Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3415 lines
99 KiB

  1. //******************************************************************************
  2. //
  3. // Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
  4. //
  5. // File: ChkAcc.cpp
  6. //
  7. // Description: RSOP Security functions
  8. //
  9. // History: 31-Jul-99 leonardm Created
  10. //
  11. //******************************************************************************
  12. #include "uenv.h"
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <Windows.h>
  17. #include <DsGetDC.h>
  18. #include "ChkAcc.h"
  19. #include "smartptr.h"
  20. #include "RsopUtil.h"
  21. #include "RsopDbg.h"
  22. CDebug dbgAccessCheck( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon",
  23. L"ChkAccDebugLevel",
  24. L"ChkAcc.log",
  25. L"ChkAcc.bak",
  26. TRUE );
  27. #undef dbg
  28. #define dbg dbgAccessCheck
  29. //******************************************************************************
  30. //
  31. // Class: CSid
  32. //
  33. // Description: Objects of this class encapsulate and simplify manipulation of
  34. // SIDs for the purposes of access control checks.
  35. //
  36. // History: 7/30/99 leonardm Created.
  37. //
  38. //******************************************************************************
  39. class CSid
  40. {
  41. private:
  42. bool m_bState; // Flag to indicate whether the object is currently
  43. // associated with a valid SID.
  44. PSID m_pSid; // Pointer to the SID encapsulated by thi class.
  45. CWString m_sUser; // User name
  46. CWString m_sDomain; // Domain where the user account resides.
  47. CWString m_sComputer; // Computer in the domain where the user account exists
  48. CWString m_sSidString; // String representation of the encapsulated SID.
  49. SID_NAME_USE m_eUse; // SID type.
  50. public:
  51. //
  52. // Overloaded constructors
  53. //
  54. CSid() : m_bState(false), m_pSid(NULL), m_eUse(SidTypeUnknown){}
  55. CSid(const PSID pSid, const WCHAR* szComputer = NULL ) :
  56. m_bState(false),
  57. m_pSid(NULL),
  58. m_eUse(SidTypeUnknown)
  59. {
  60. Initialize(pSid, szComputer);
  61. }
  62. CSid(const WCHAR* szUser, const WCHAR* szComputer = NULL ) :
  63. m_bState(false),
  64. m_pSid(NULL),
  65. m_eUse(SidTypeUnknown)
  66. {
  67. Initialize(szUser, szComputer);
  68. }
  69. CSid(const CSid& otherSid) :
  70. m_bState(false),
  71. m_pSid(NULL),
  72. m_eUse(SidTypeUnknown)
  73. {
  74. Initialize(otherSid.User(), otherSid.Computer());
  75. }
  76. ~CSid()
  77. {
  78. Reset();
  79. }
  80. //
  81. // Attempts to initialize an object of this class by associating it with
  82. // an existing user represented in the SID pointed to by pSid.
  83. //
  84. bool Initialize(PSID pSid, const WCHAR* szComputer = NULL);
  85. //
  86. // Attempts to initialize an object of this class by associating it with
  87. // an existing user represented by szUser.
  88. //
  89. bool Initialize(const WCHAR* szUser, const WCHAR* szComputer = NULL);
  90. //
  91. // Indicates whether this object is currently associated with a valid user.
  92. //
  93. bool IsValid() const{ return m_bState; }
  94. //
  95. // Overload of assignment operator. Copies one CSid to another.
  96. // After a this call two objects encapsulate the same SID.
  97. // However, each owns its own memory. So the destructor of
  98. // one object can be called without invalidating resources used by the other.
  99. //
  100. CSid& operator = (CSid otherSid);
  101. //
  102. // Overload of assignment operator. Initializes
  103. // the current object with an existing SID.
  104. //
  105. CSid& operator = (PSID pSid);
  106. //
  107. // Returns a pointer to the SID encapsulated by this object.
  108. //
  109. PSID GetSidPtr() const{ return m_pSid; }
  110. //
  111. // Returns the name of the user associated with this object.
  112. //
  113. const WCHAR* User() const{ return m_sUser; }
  114. //
  115. // Returns the name of the computer used to Initialize this object with a user.
  116. //
  117. const WCHAR* Computer() const{ return m_sComputer; }
  118. //
  119. // Returns the name of the domain of which the user is a member.
  120. //
  121. const WCHAR* Domain() const{ return m_sDomain; }
  122. //
  123. // Returns a the SID associated with object in
  124. // a string format suitable for display
  125. //
  126. const WCHAR* SidString() const{ return m_sSidString; }
  127. //
  128. // Returns the type as it was found in the SID associated
  129. // with this object during processing of Initialize.
  130. //
  131. SID_NAME_USE SidType() const{ return m_eUse; }
  132. //
  133. // Breaks the association of this object with an exisitng SID. Releases
  134. // memory allocate during Initialize and set the internal state to Invalid.
  135. // This call is safe even if the object is not initialized.
  136. //
  137. void Reset();
  138. };
  139. //******************************************************************************
  140. //
  141. // Function: CSid::Initialize
  142. //
  143. // Description: Attempts to initialize an object of this class by associating it with
  144. // an existing user represented in the SID pointed to by pSid.
  145. //
  146. // Parameters: - pSid: Pointer to an exisitng SID. The memory pointed to
  147. // by this parameter may be released after a call to
  148. // this function since objects of this class allocate
  149. // and release their own memory for the associated SID.
  150. // - szComputer: Pointer to a string naming the computer where the
  151. // lookup of the account is to take place. If NULL, the
  152. // curent computer is used.
  153. //
  154. // Return: true on success. false otherwise.
  155. //
  156. // History: 7/30/99 leonardm Created.
  157. //
  158. //******************************************************************************
  159. bool CSid::Initialize(const PSID pSid, const WCHAR* szComputer/* = NULL */)
  160. {
  161. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CSid::Initialize - Entering...");
  162. Reset();
  163. if(!IsValidSid(pSid))
  164. {
  165. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - IsValidSid returned false!");
  166. return m_bState;
  167. }
  168. m_pSid = new BYTE[GetLengthSid(pSid)];
  169. if(!m_pSid)
  170. {
  171. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - call to new failed!");
  172. return m_bState;
  173. }
  174. BOOL bRes = CopySid(GetLengthSid(pSid), m_pSid, pSid);
  175. if(!bRes)
  176. {
  177. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - Call to CopySid returned FALSE!");
  178. Reset();
  179. return m_bState;
  180. }
  181. DWORD cbUser = 0;
  182. DWORD cbDomain = 0;
  183. LookupAccountSid(szComputer, m_pSid, NULL, &cbUser, NULL, &cbDomain, &m_eUse);
  184. if(cbUser && cbDomain)
  185. {
  186. XPtrST<WCHAR>xpszUser = new WCHAR[cbUser];
  187. if(!xpszUser)
  188. {
  189. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - call to new failed!");
  190. Reset();
  191. return m_bState;
  192. }
  193. XPtrST<WCHAR>xpszDomain = new WCHAR[cbDomain];
  194. if(!xpszDomain)
  195. {
  196. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - call to new failed!");
  197. Reset();
  198. return m_bState;
  199. }
  200. bRes = LookupAccountSid(szComputer, m_pSid, xpszUser, &cbUser, xpszDomain, &cbDomain, &m_eUse);
  201. if(!bRes)
  202. {
  203. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - call to LookupAccountSid returned FALSE!");
  204. Reset();
  205. return m_bState;
  206. }
  207. m_sUser = xpszUser;
  208. if(!m_sUser.ValidString())
  209. {
  210. Reset();
  211. return m_bState;
  212. }
  213. m_sDomain = xpszDomain;
  214. if(!m_sDomain.ValidString())
  215. {
  216. Reset();
  217. return m_bState;
  218. }
  219. XPtrLF<WCHAR>szSidString = NULL;
  220. BOOL bRes = ConvertSidToStringSid(m_pSid, &szSidString);
  221. if(!bRes)
  222. {
  223. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CSid::Initialize - call to ConvertSidToStringSid returned false!");
  224. Reset();
  225. return m_bState;
  226. }
  227. m_sSidString = szSidString;
  228. if(!m_sSidString.ValidString())
  229. {
  230. Reset();
  231. return m_bState;
  232. }
  233. m_bState = true;
  234. }
  235. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CSid::Initialize - Leaving successfully.");
  236. return m_bState;
  237. }
  238. //******************************************************************************
  239. //
  240. // Function: CSid::Initialize
  241. //
  242. // Description: Attempts to initialize an object of this class by associating it with
  243. // an existing user represented by szUser.
  244. //
  245. // Parameters: - szUser: Name of an existing user.
  246. // - szComputer: Pointer to a string naming the computer where the
  247. // lookup of the account is to take place. If NULL, the
  248. // curent computer is used.
  249. //
  250. // Return: true on success. false otherwise.
  251. //
  252. // History: 7/30/99 leonardm Created.
  253. //
  254. //******************************************************************************
  255. bool CSid::Initialize(const WCHAR* szUser, const WCHAR* szComputer/* = NULL */)
  256. {
  257. Reset();
  258. if(!szUser)
  259. {
  260. return m_bState;
  261. }
  262. m_sUser = szUser;
  263. if(!m_sUser.ValidString())
  264. {
  265. Reset();
  266. return m_bState;
  267. }
  268. m_sComputer = szComputer ? szComputer : L"";
  269. if(!m_sComputer.ValidString())
  270. {
  271. Reset();
  272. return m_bState;
  273. }
  274. DWORD cSid = 0;
  275. DWORD cDomain = 0;
  276. LookupAccountName(szComputer, szUser, NULL, &cSid, NULL, &cDomain, &m_eUse);
  277. if(cSid && cDomain)
  278. {
  279. m_pSid = new BYTE[cSid];
  280. if(!m_pSid)
  281. {
  282. Reset();
  283. return m_bState;
  284. }
  285. XPtrST<WCHAR>xpszDomain = new WCHAR[cDomain];
  286. if(!xpszDomain)
  287. {
  288. Reset();
  289. return m_bState;
  290. }
  291. BOOL bRes = LookupAccountName(szComputer, szUser, m_pSid, &cSid, xpszDomain, &cDomain, &m_eUse);
  292. if(!bRes)
  293. {
  294. Reset();
  295. return m_bState;
  296. }
  297. m_sDomain = xpszDomain;
  298. if(!m_sDomain.ValidString())
  299. {
  300. Reset();
  301. return m_bState;
  302. }
  303. XPtrLF<WCHAR>szSidString = NULL;
  304. bRes = ConvertSidToStringSid(m_pSid, &szSidString);
  305. if(!bRes)
  306. {
  307. Reset();
  308. return m_bState;
  309. }
  310. m_sSidString = szSidString;
  311. if(!m_sSidString.ValidString())
  312. {
  313. Reset();
  314. return m_bState;
  315. }
  316. m_bState = true;
  317. }
  318. return m_bState;
  319. }
  320. //******************************************************************************
  321. //
  322. // Function: Reset
  323. //
  324. // Description: Breaks the association of this object with an exisitng SID. Releases
  325. // memory allocate during Initialize and set the internal state to Invalid.
  326. // This call is safe even if the object is not initialized.
  327. //
  328. // Parameters: None.
  329. //
  330. // Return:
  331. //
  332. // History: 7/30/99 leonardm Created.
  333. //
  334. //******************************************************************************
  335. void CSid::Reset()
  336. {
  337. delete[] (BYTE*)m_pSid;
  338. m_pSid = NULL;
  339. m_sUser = m_sDomain = m_sComputer = m_sSidString = L"";
  340. m_eUse = SidTypeUnknown;
  341. m_bState = false;
  342. }
  343. //******************************************************************************
  344. //
  345. // Function: operator =
  346. //
  347. // Description: Overload of assignment operator. Copies one CSid to another.
  348. // After a this call two objects encapsulate the same SID.
  349. // However, each owns its own memory. So the destructor of
  350. // one object can be called without invalidating resources used by the other.
  351. //
  352. // Parameters: - otherSid: The CSid whose value is to be copied.
  353. //
  354. // Return: A reference to the object on which the call is invoked.
  355. //
  356. // History: 7/30/99 leonardm Created.
  357. //
  358. //******************************************************************************
  359. CSid& CSid::operator = (CSid otherSid)
  360. {
  361. if(this == &otherSid)
  362. {
  363. return *this;
  364. }
  365. Reset();
  366. if(!IsValidSid(otherSid.GetSidPtr()))
  367. {
  368. return *this;
  369. }
  370. Initialize(otherSid.User(), otherSid.Computer());
  371. return *this;
  372. }
  373. //******************************************************************************
  374. //
  375. // Function: operator =
  376. //
  377. // Description: Overload of assignment operator. Initializes the current object with
  378. // an existing SID.
  379. //
  380. // Parameters: - otherSid: The CSid whose value is to be copied.
  381. //
  382. // Return: A reference to the object on which the call is invoked.
  383. //
  384. // History: 7/30/99 leonardm Created.
  385. //
  386. //******************************************************************************
  387. CSid& CSid::operator = (PSID pSid)
  388. {
  389. Reset();
  390. if(!IsValidSid(pSid))
  391. {
  392. return *this;
  393. }
  394. Initialize(pSid);
  395. return *this;
  396. }
  397. //******************************************************************************
  398. //
  399. // Structure: CTLink
  400. //
  401. // Description:
  402. //
  403. // History: 8/02/99 leonardm Created.
  404. //
  405. //******************************************************************************
  406. template<typename T> struct CTLink
  407. {
  408. T* m_pData;
  409. CTLink* m_pNext;
  410. CTLink* m_pPrev;
  411. CTLink(T* pData) : m_pData(pData), m_pNext(NULL), m_pPrev(NULL){}
  412. ~CTLink()
  413. {
  414. delete m_pData;
  415. }
  416. };
  417. //******************************************************************************
  418. //
  419. // Structure: CRsopToken
  420. //
  421. // Description: This reprents a pseudo-token containing an arbitrary
  422. // combination of SIDs which
  423. // can be used to check access to objects protected with security descriptors.
  424. //
  425. // History: 7/30/99 leonardm Created.
  426. //
  427. //******************************************************************************
  428. struct CRsopToken
  429. {
  430. CTLink<CSid>* m_pSidsHead;
  431. CTLink<CSid>* m_pSidsTail;
  432. //
  433. // Default constructor. Constructs an object with no sids. Access checks
  434. // against an CRsopToken with no SIDs will always fail; even on objects
  435. // with no DACL.
  436. //
  437. CRsopToken() : m_pSidsHead(NULL), m_pSidsTail(NULL) {}
  438. //
  439. // Destructor. Releases the memory pointed
  440. // to by each of the elements of m_pSidsHead.
  441. //
  442. ~CRsopToken();
  443. //
  444. // Adds a CSid to this object. The client of this class allocates the memory
  445. // for the CSid and this class releases the memory in the destructor.
  446. //
  447. HRESULT AddSid(CSid* pSid);
  448. };
  449. //******************************************************************************
  450. //
  451. // Function: CRsopToken::~CRsopToken
  452. //
  453. // Description: Destructor. Releases the memory pointed to by each of the elements of
  454. // m_pSidsHead.
  455. //
  456. // Parameters: None.
  457. //
  458. // Return: N/A
  459. //
  460. // History: 7/30/99 leonardm Created.
  461. //
  462. //******************************************************************************
  463. CRsopToken::~CRsopToken()
  464. {
  465. CTLink<CSid>* pLinkIterator = m_pSidsHead;
  466. while(pLinkIterator)
  467. {
  468. CTLink<CSid>* pLinkToDelete = pLinkIterator;
  469. pLinkIterator = pLinkIterator->m_pNext;
  470. delete pLinkToDelete;
  471. }
  472. }
  473. //******************************************************************************
  474. //
  475. // Function: CRsopToken::AddSid
  476. //
  477. // Description: Adds a CSid to this object. The client of this class allocates the
  478. // memory for the CSid and this class releases the memory in the destructor.
  479. //
  480. // Parameters: - pSid: A pointer to a CSid. The memory pointed to by pSid will be released by
  481. // in the destructor.
  482. //
  483. // Return: On success it returns S_OK.
  484. // On failure it returns E_OUTOFMEMORY.
  485. //
  486. // History: 7/30/99 leonardm Created.
  487. //
  488. //******************************************************************************
  489. HRESULT CRsopToken::AddSid(CSid* pSid)
  490. {
  491. //
  492. // first check if the Sid is already in there
  493. //
  494. for(CTLink<CSid>* pTraverseLink = m_pSidsHead; pTraverseLink; pTraverseLink = pTraverseLink->m_pNext)
  495. {
  496. //
  497. // If one of the SIDs in the RsopToken matches
  498. // this Sid, return
  499. //
  500. if (EqualSid(pSid->GetSidPtr(), pTraverseLink->m_pData->GetSidPtr()))
  501. return S_OK;
  502. }
  503. //
  504. // Allocate a new link using the pSid passed in.
  505. //
  506. CTLink<CSid>* pLink = new CTLink<CSid>(pSid);
  507. if(!pLink)
  508. {
  509. return E_OUTOFMEMORY;
  510. }
  511. if(!m_pSidsHead)
  512. {
  513. m_pSidsHead = pLink;
  514. }
  515. else
  516. {
  517. m_pSidsTail->m_pNext = pLink;
  518. }
  519. m_pSidsTail = pLink;
  520. return S_OK;
  521. }
  522. //******************************************************************************
  523. //
  524. // Function: GetUserInfo
  525. //
  526. // Description:
  527. //
  528. // Parameters:
  529. //
  530. // Return: S_OK if successful. An HRESULT error code on failure.
  531. //
  532. // History: 8/7/99 leonardm Created.
  533. //
  534. //******************************************************************************
  535. HRESULT GetUserInfo(const CWString& sUser,
  536. CWString& sUserName,
  537. CWString& sUserDomain,
  538. CWString& sUserDC)
  539. {
  540. if(!sUser.ValidString())
  541. {
  542. return E_FAIL;
  543. }
  544. NET_API_STATUS status;
  545. XPtrST<WCHAR>xpUserName = NULL;
  546. XPtrST<WCHAR>xpUserDomain = NULL;
  547. size_t len = sUser.length();
  548. WCHAR* backslashPos = wcschr(sUser, L'\\');
  549. if(backslashPos)
  550. {
  551. size_t index = backslashPos - sUser;
  552. xpUserDomain = new WCHAR[index + 1];
  553. if(!xpUserDomain )
  554. {
  555. return E_OUTOFMEMORY;
  556. }
  557. wcsncpy(xpUserDomain, sUser, index);
  558. xpUserDomain[index] = L'\0';
  559. xpUserName = new WCHAR[len - index];
  560. if(!xpUserName)
  561. {
  562. return E_OUTOFMEMORY;
  563. }
  564. wcsncpy(xpUserName, backslashPos + 1, len - index - 1);
  565. xpUserName[len - index - 1] = L'\0';
  566. }
  567. sUserName = xpUserName ? CWString(xpUserName) : sUser;
  568. if(!sUserName.ValidString())
  569. {
  570. return E_FAIL;
  571. }
  572. if(xpUserDomain)
  573. {
  574. // Use supplied domain.
  575. sUserDomain = xpUserDomain;
  576. }
  577. else
  578. {
  579. // Use current domain
  580. WKSTA_INFO_100* pWkstaInfo = NULL;
  581. status = NetWkstaGetInfo(NULL,100,(LPBYTE*)&pWkstaInfo);
  582. if(status != NERR_Success)
  583. {
  584. return E_FAIL;
  585. }
  586. sUserDomain = pWkstaInfo->wki100_langroup;
  587. NetApiBufferFree(pWkstaInfo);
  588. }
  589. if(!sUserDomain.ValidString())
  590. {
  591. return E_FAIL;
  592. }
  593. PDOMAIN_CONTROLLER_INFO pDCInfo = 0;
  594. DWORD dwError = DsGetDcName(0,
  595. sUserDomain,
  596. 0,
  597. 0,
  598. 0,
  599. &pDCInfo );
  600. if ( dwError != NO_ERROR )
  601. {
  602. return HRESULT_FROM_WIN32( dwError );
  603. }
  604. sUserDC = pDCInfo->DomainControllerName;
  605. NetApiBufferFree(pDCInfo);
  606. if ( !sUserDC.ValidString() )
  607. {
  608. return E_FAIL;
  609. }
  610. return S_OK;
  611. }
  612. //******************************************************************************
  613. //
  614. // Function: AddSpecialGroup
  615. //
  616. // Description:
  617. //
  618. // Parameters:
  619. //
  620. // Return: S_OK if successful. An HRESULT error code on failure.
  621. //
  622. // History: 8/7/99 leonardm Created.
  623. //
  624. //******************************************************************************
  625. HRESULT AddSpecialGroup(PRSOPTOKEN pRsopToken, PSID pSid)
  626. {
  627. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  628. XPtrST<CSid> xpCSid = new CSid(pSid);
  629. if(!xpCSid)
  630. {
  631. return E_OUTOFMEMORY;
  632. }
  633. if(!xpCSid->IsValid())
  634. {
  635. return E_FAIL;
  636. }
  637. HRESULT hr = pToken->AddSid(xpCSid);
  638. if(FAILED(hr))
  639. {
  640. return hr;
  641. }
  642. xpCSid.Acquire();
  643. return S_OK;
  644. }
  645. //******************************************************************************
  646. //
  647. // Function: AddSpecialGroups
  648. //
  649. // Description:
  650. //
  651. // Parameters:
  652. //
  653. // Return: S_OK if successful. An HRESULT error code on failure.
  654. //
  655. // History: 8/7/99 leonardm Created.
  656. //
  657. //******************************************************************************
  658. HRESULT AddSpecialGroups(PRSOPTOKEN pRsopToken )
  659. {
  660. BOOL bRes;
  661. PSID pSid;
  662. HRESULT hr;
  663. //
  664. // Everyone
  665. //
  666. SID_IDENTIFIER_AUTHORITY IdentifierAuthority_World = SECURITY_WORLD_SID_AUTHORITY;
  667. bRes = AllocateAndInitializeSid(&IdentifierAuthority_World, 1,
  668. SECURITY_WORLD_RID,
  669. 0, 0, 0, 0, 0, 0, 0,
  670. &pSid);
  671. if(!bRes)
  672. {
  673. DWORD dwLastError = GetLastError();
  674. return E_FAIL;
  675. }
  676. hr = AddSpecialGroup(pRsopToken, pSid);
  677. FreeSid(pSid);
  678. if(FAILED(hr))
  679. {
  680. return hr;
  681. }
  682. //
  683. // Authenticated users
  684. //
  685. SID_IDENTIFIER_AUTHORITY IdentifierAuthority_NT = SECURITY_NT_AUTHORITY;
  686. bRes = AllocateAndInitializeSid(&IdentifierAuthority_NT, 1,
  687. SECURITY_AUTHENTICATED_USER_RID,
  688. 0, 0, 0, 0, 0, 0, 0,
  689. &pSid);
  690. if(!bRes)
  691. {
  692. DWORD dwLastError = GetLastError();
  693. return E_FAIL;
  694. }
  695. hr = AddSpecialGroup(pRsopToken, pSid);
  696. FreeSid(pSid);
  697. if(FAILED(hr))
  698. {
  699. return hr;
  700. }
  701. return S_OK;
  702. }
  703. //******************************************************************************
  704. //
  705. // Function: AddGlobalGroups
  706. //
  707. // Description:
  708. //
  709. // Parameters:
  710. //
  711. // Return: S_OK if successful. An HRESULT error code on failure.
  712. //
  713. // History: 8/7/99 leonardm Created.
  714. //
  715. //******************************************************************************
  716. HRESULT AddGlobalGroups(const CWString& sUserName,
  717. const CWString& sUserDC,
  718. PRSOPTOKEN pRsopToken)
  719. {
  720. if(!sUserName.ValidString())
  721. {
  722. return E_FAIL;
  723. }
  724. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  725. BYTE* pBuffer = NULL;
  726. DWORD dwEntriesread;
  727. DWORD dwTotalentries;
  728. NET_API_STATUS result = NetUserGetGroups( sUserDC,
  729. sUserName,
  730. 0,
  731. &pBuffer,
  732. MAX_PREFERRED_LENGTH,
  733. &dwEntriesread,
  734. &dwTotalentries);
  735. if(result != NERR_Success)
  736. {
  737. return HRESULT_FROM_WIN32(result);
  738. }
  739. HRESULT hr = S_OK;
  740. GROUP_USERS_INFO_0* pGui = (GROUP_USERS_INFO_0*)pBuffer;
  741. XPtrST<CSid> xpCSid;
  742. for(DWORD dwi = 0; dwi < dwEntriesread; dwi++)
  743. {
  744. xpCSid = new CSid((pGui[dwi]).grui0_name);
  745. if(!xpCSid)
  746. {
  747. hr = E_OUTOFMEMORY;
  748. break;
  749. }
  750. if(!xpCSid->IsValid())
  751. {
  752. hr = E_FAIL;
  753. break;
  754. }
  755. hr = pToken->AddSid(xpCSid);
  756. if(FAILED(hr))
  757. {
  758. break;
  759. }
  760. xpCSid.Acquire();
  761. }
  762. NetApiBufferFree(pBuffer);
  763. return hr;
  764. }
  765. //******************************************************************************
  766. //
  767. // Function: AddLocalGroups
  768. //
  769. // Description:
  770. //
  771. // Parameters:
  772. //
  773. // Return: S_OK if successful. An HRESULT error code on failure.
  774. //
  775. //
  776. //******************************************************************************
  777. HRESULT AddLocalGroups(const CWString& sUserName,
  778. const CWString& sUserDC,
  779. PRSOPTOKEN pRsopToken)
  780. {
  781. if(!sUserName.ValidString())
  782. {
  783. return E_FAIL;
  784. }
  785. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  786. BYTE* pBuffer = NULL;
  787. DWORD dwEntriesread;
  788. DWORD dwTotalentries;
  789. NET_API_STATUS result = NetUserGetLocalGroups(
  790. sUserDC,
  791. sUserName,
  792. 0,
  793. LG_INCLUDE_INDIRECT,
  794. &pBuffer,
  795. MAX_PREFERRED_LENGTH,
  796. &dwEntriesread,
  797. &dwTotalentries);
  798. if(result != NERR_Success)
  799. {
  800. HRESULT_FROM_WIN32(result);
  801. }
  802. HRESULT hr = S_OK;
  803. LPLOCALGROUP_USERS_INFO_0 pLui = (LPLOCALGROUP_USERS_INFO_0)pBuffer;
  804. XPtrST<CSid> xpCSid;
  805. for(DWORD dwi = 0; dwi < dwEntriesread; dwi++)
  806. {
  807. xpCSid = new CSid((pLui[dwi]).lgrui0_name);
  808. if(!xpCSid)
  809. {
  810. hr = E_OUTOFMEMORY;
  811. break;
  812. }
  813. if(!xpCSid->IsValid())
  814. {
  815. hr = E_FAIL;
  816. break;
  817. }
  818. hr = pToken->AddSid(xpCSid);
  819. if(FAILED(hr))
  820. {
  821. break;
  822. }
  823. xpCSid.Acquire();
  824. }
  825. NetApiBufferFree(pBuffer);
  826. return hr;
  827. }
  828. //******************************************************************************
  829. //
  830. // Function: ExpandGroup
  831. //
  832. // Description: Expands a given group by expanding to include all the member subgroups etc..
  833. //
  834. // Parameters: - pRsopToken: Rsop token
  835. // hAuthz: A pointer to the Authz resource manager
  836. // (that we are using to expand the grps)
  837. // pCSid: Sid of the group
  838. //
  839. //
  840. // Return: S_OK if successful. An HRESULT error code on failure.
  841. //
  842. //******************************************************************************
  843. HRESULT ExpandGroup(CRsopToken *pRsopToken, AUTHZ_RESOURCE_MANAGER_HANDLE hAuthz,
  844. CSid *pCSid )
  845. {
  846. AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzContext=0;
  847. LUID luid = {0};
  848. HRESULT hrRet = S_OK;
  849. DWORD dwSize=0;
  850. XPtrLF<TOKEN_GROUPS> xGrps;
  851. XPtrST<CSid> xpCSid;
  852. if (!AuthzInitializeContextFromSid(0,
  853. pCSid->GetSidPtr(),
  854. hAuthz,
  855. NULL,
  856. luid, // we are not using it
  857. NULL,
  858. &hAuthzContext)) {
  859. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AuthzInitializeContextFromSid failed. Error - %d", GetLastError());
  860. hrRet = HRESULT_FROM_WIN32(GetLastError());
  861. goto Exit;
  862. }
  863. //
  864. // Now get the list of expanded sids
  865. // find the size first
  866. //
  867. if (!AuthzGetInformationFromContext(hAuthzContext,
  868. AuthzContextInfoGroupsSids,
  869. NULL,
  870. &dwSize,
  871. 0)) {
  872. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  873. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AuthzGetInformationFromContext failed. Error - %d", GetLastError());
  874. hrRet = HRESULT_FROM_WIN32(GetLastError());
  875. goto Exit;
  876. }
  877. }
  878. xGrps = (PTOKEN_GROUPS)LocalAlloc(LPTR, dwSize);
  879. if (!xGrps) {
  880. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - Couldn't allocate memory for the token grps. Error - %d", GetLastError());
  881. hrRet = HRESULT_FROM_WIN32(GetLastError());
  882. goto Exit;
  883. }
  884. if (!AuthzGetInformationFromContext(hAuthzContext,
  885. AuthzContextInfoGroupsSids,
  886. dwSize,
  887. &dwSize,
  888. xGrps)) {
  889. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AuthzGetInformationFromContext(2) failed. Error - %d", GetLastError());
  890. hrRet = HRESULT_FROM_WIN32(GetLastError());
  891. goto Exit;
  892. }
  893. for (DWORD i = 0; i < xGrps->GroupCount; i++) {
  894. xpCSid = new CSid(xGrps->Groups[i].Sid, NULL);
  895. if (!xpCSid) {
  896. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - couldn't allocate memory(2). Error - %d", GetLastError());
  897. hrRet = HRESULT_FROM_WIN32(GetLastError());
  898. goto Exit;
  899. }
  900. hrRet = pRsopToken->AddSid(xpCSid);
  901. if(FAILED(hrRet)) {
  902. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AddSid failed. Error - 0x%x", hrRet);
  903. goto Exit;
  904. }
  905. xpCSid.Acquire();
  906. }
  907. hrRet = S_OK;
  908. Exit:
  909. if (hAuthzContext)
  910. AuthzFreeContext(hAuthzContext);
  911. return hrRet;
  912. }
  913. //******************************************************************************
  914. //
  915. // Function: RsopCreateToken
  916. //
  917. // Description: Creates a pseudo-token using an exisitng user or machine account plus
  918. // the accounts of which that user is currently a member of.
  919. // The returned pseudo-token can be used subsequently in call
  920. // to other RSOP security functions to check access to
  921. // objects protected by security descriptors.
  922. //
  923. // Parameters: - szaccountName: Pointer to a user or machine account name.
  924. // - psaUserSecurityGroups: Pointer ta SAFEARRAY of BSTRs representing
  925. // security groups.
  926. // If NULL, then all the current security groups for the
  927. // szaccountName are added to the RsopToken.
  928. // If not NULL but pointing to an empty array,
  929. // only the szaccountName is added to the RsopToken.
  930. // - ppRsopToken: Address of a PRSOPTOKEN that receives the newly
  931. // created pseudo-token
  932. //
  933. //
  934. // Return: S_OK if successful. An HRESULT error code on failure.
  935. //
  936. // History: 8/7/99 leonardm Created.
  937. //
  938. //******************************************************************************
  939. HRESULT RsopCreateToken(WCHAR* szAccountName,
  940. SAFEARRAY* psaUserSecurityGroups,
  941. PRSOPTOKEN* ppRsopToken )
  942. {
  943. dbg.Initialize( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon",
  944. L"ChkAccDebugLevel",
  945. L"ChkAcc.log",
  946. L"ChkAcc.bak");
  947. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopCreateToken - Entering...");
  948. HRESULT hr = E_FAIL;
  949. //
  950. // Instantiate a new CRsopToken
  951. //
  952. *ppRsopToken = NULL;
  953. XPtrST<CRsopToken>xpRsopToken = new CRsopToken();
  954. if(!xpRsopToken)
  955. {
  956. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - Operator new returned NULL. Creation of a CRsopToken failed.");
  957. return E_OUTOFMEMORY;
  958. }
  959. //
  960. // Add to the new CRsopToken a CSid corresponding to the
  961. // principal represented by parameter szAccountName. For
  962. // dummy target the szAccountName will be null.
  963. //
  964. XPtrST<CSid>xpCSid;
  965. if ( szAccountName )
  966. {
  967. xpCSid = new CSid(szAccountName);
  968. if(!xpCSid)
  969. {
  970. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - Operator new returned NULL. Creation of a CSid failed.");
  971. return E_OUTOFMEMORY;
  972. }
  973. if(!xpCSid->IsValid())
  974. {
  975. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - Call to CSid::IsValid failed.");
  976. return E_FAIL;
  977. }
  978. hr = xpRsopToken->AddSid(xpCSid);
  979. if(FAILED(hr))
  980. {
  981. return hr;
  982. }
  983. xpCSid.Acquire();
  984. }
  985. //
  986. // If the parameter is NULL, that means we are to add the security
  987. // groups to which the user currently belongs.
  988. //
  989. if(!psaUserSecurityGroups)
  990. {
  991. if (szAccountName) {
  992. CWString sUser = szAccountName;
  993. CWString sUserName;
  994. CWString sUserDomain;
  995. CWString sUserDC;
  996. hr = GetUserInfo(sUser, sUserName, sUserDomain, sUserDC);
  997. if(FAILED(hr))
  998. {
  999. return hr;
  1000. }
  1001. /* for cross domain cases this fails
  1002. //
  1003. // Get Global group membership
  1004. //
  1005. hr = AddGlobalGroups(sUserName, sUserDC, xpRsopToken);
  1006. if(FAILED(hr))
  1007. {
  1008. return hr;
  1009. }
  1010. */
  1011. hr = AddLocalGroups(sUserName, sUserDC, xpRsopToken);
  1012. if(FAILED(hr))
  1013. {
  1014. return hr;
  1015. }
  1016. //
  1017. // Universal groups across domains cannot be retrieved by
  1018. // NetUserGetGroups but can be fetched by authz functions.
  1019. //
  1020. xpCSid = new CSid(szAccountName);
  1021. AUTHZ_RESOURCE_MANAGER_HANDLE hAuthz;
  1022. if (!AuthzInitializeResourceManager(NULL,
  1023. NULL,
  1024. NULL,
  1025. NULL,
  1026. 0,
  1027. &hAuthz)) {
  1028. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AuthzInitializeResourceManager failed. Error - %d", GetLastError());
  1029. return HRESULT_FROM_WIN32(GetLastError());
  1030. }
  1031. HRESULT hr = ExpandGroup(xpRsopToken, hAuthz, xpCSid);
  1032. if (FAILED(hr)) {
  1033. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - ExpandGrp failed for user. Error - 0x%x", hr);
  1034. AuthzFreeResourceManager(hAuthz);
  1035. return hr;
  1036. }
  1037. AuthzFreeResourceManager(hAuthz);
  1038. // xpCSid will be freed automatically.
  1039. }
  1040. }
  1041. //
  1042. // Otherwise, we add only those groups named in the SAFERARRAY.
  1043. //
  1044. else
  1045. {
  1046. BSTR* pbstr;
  1047. AUTHZ_RESOURCE_MANAGER_HANDLE hAuthz;
  1048. if (!AuthzInitializeResourceManager(NULL,
  1049. NULL,
  1050. NULL,
  1051. NULL,
  1052. 0,
  1053. &hAuthz)) {
  1054. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - AuthzInitializeResourceManager failed. Error - %d", GetLastError());
  1055. return HRESULT_FROM_WIN32(GetLastError());
  1056. }
  1057. // Get a pointer to the elements of the array.
  1058. HRESULT hr = SafeArrayAccessData(psaUserSecurityGroups, (void**)&pbstr);
  1059. if(FAILED(hr))
  1060. {
  1061. AuthzFreeResourceManager(hAuthz);
  1062. return hr;
  1063. }
  1064. int count = psaUserSecurityGroups->rgsabound[0].cElements;
  1065. for (int i = 0; i < count; i++)
  1066. {
  1067. xpCSid = new CSid(pbstr[i]);
  1068. if(!xpCSid)
  1069. {
  1070. AuthzFreeResourceManager(hAuthz);
  1071. SafeArrayUnaccessData(psaUserSecurityGroups);
  1072. return E_OUTOFMEMORY;
  1073. }
  1074. if(!xpCSid->IsValid())
  1075. {
  1076. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - %s is invalid", pbstr[i]);
  1077. AuthzFreeResourceManager(hAuthz);
  1078. SafeArrayUnaccessData(psaUserSecurityGroups);
  1079. return HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  1080. }
  1081. HRESULT hr = ExpandGroup(xpRsopToken, hAuthz, xpCSid);
  1082. if (FAILED(hr)) {
  1083. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopCreateToken - ExpandGrp failed. Error - 0x%x", hr);
  1084. AuthzFreeResourceManager(hAuthz);
  1085. SafeArrayUnaccessData(psaUserSecurityGroups);
  1086. return hr;
  1087. }
  1088. hr = xpRsopToken->AddSid(xpCSid);
  1089. if(FAILED(hr))
  1090. {
  1091. AuthzFreeResourceManager(hAuthz);
  1092. SafeArrayUnaccessData(psaUserSecurityGroups);
  1093. return hr;
  1094. }
  1095. xpCSid.Acquire();
  1096. }
  1097. AuthzFreeResourceManager(hAuthz);
  1098. SafeArrayUnaccessData(psaUserSecurityGroups);
  1099. }
  1100. hr = AddSpecialGroups(xpRsopToken);
  1101. if(FAILED(hr))
  1102. {
  1103. return hr;
  1104. }
  1105. *ppRsopToken = xpRsopToken;
  1106. xpRsopToken.Acquire();
  1107. return S_OK;
  1108. }
  1109. //******************************************************************************
  1110. //
  1111. // Function: RsopDeleteToken
  1112. //
  1113. // Description: Destroys a pseudo-token previously created by any of the overloaded
  1114. // forms of RSOPCreateRsopToken
  1115. //
  1116. // Parameters: - pRsopToken: Pointer to a valid PRSOPTOKEN
  1117. //
  1118. // Return: S_OK on success. An HRESULT error code on failure.
  1119. //
  1120. // History: 7/30/99 leonardm Created.
  1121. //
  1122. //******************************************************************************
  1123. HRESULT RsopDeleteToken(PRSOPTOKEN pRsopToken)
  1124. {
  1125. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  1126. delete pToken;
  1127. return S_OK;
  1128. }
  1129. //******************************************************************************
  1130. //
  1131. // Function: GetAceSid
  1132. //
  1133. // Description:
  1134. //
  1135. // Parameters:
  1136. //
  1137. // Return:
  1138. //
  1139. // History: 10/19/99 leonardm Created.
  1140. //
  1141. //******************************************************************************
  1142. PISID GetAceSid(PACE_HEADER pAceHeader)
  1143. {
  1144. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - Entering.");
  1145. //
  1146. // Check for invalid argument
  1147. //
  1148. if(!pAceHeader)
  1149. {
  1150. dbg.Msg(DEBUG_MESSAGE_WARNING, L"GetAceSid - Invalid parameter: pAceHeader is NULL");
  1151. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - Leaving.");
  1152. return NULL;
  1153. }
  1154. PISID pSid = NULL;
  1155. PACCESS_ALLOWED_ACE pACCESS_ALLOWED_ACE;
  1156. PACCESS_ALLOWED_OBJECT_ACE pACCESS_ALLOWED_OBJECT_ACE;
  1157. PACCESS_DENIED_ACE pACCESS_DENIED_ACE;
  1158. PACCESS_DENIED_OBJECT_ACE pACCESS_DENIED_OBJECT_ACE;
  1159. //
  1160. // Cast the ACE header to the appropriate ACE type based on the 'Acetype' member of the
  1161. // ACE header.
  1162. //
  1163. switch(pAceHeader->AceType)
  1164. {
  1165. case ACCESS_ALLOWED_ACE_TYPE:
  1166. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - ACE type: ACCESS_ALLOWED_ACE_TYPE");
  1167. pACCESS_ALLOWED_ACE = reinterpret_cast<PACCESS_ALLOWED_ACE>(pAceHeader);
  1168. pSid = reinterpret_cast<PISID>(&(pACCESS_ALLOWED_ACE->SidStart));
  1169. break;
  1170. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1171. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - ACE type: ACCESS_ALLOWED_OBJECT_ACE_TYPE");
  1172. pACCESS_ALLOWED_OBJECT_ACE = reinterpret_cast<PACCESS_ALLOWED_OBJECT_ACE>(pAceHeader);
  1173. if( (pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT) &&
  1174. (pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT))
  1175. {
  1176. //
  1177. // If both ACE_OBJECT_TYPE_PRESENT and ACE_INHERITED_OBJECT_TYPE_PRESENT are set in
  1178. // the ACE flags, the SID starts at the offset specified by 'SidStart'.
  1179. //
  1180. pSid = reinterpret_cast<PISID>(&(pACCESS_ALLOWED_OBJECT_ACE->SidStart));
  1181. }
  1182. else if((pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT) ||
  1183. (pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT))
  1184. {
  1185. //
  1186. // If either ACE_OBJECT_TYPE_PRESENT or ACE_INHERITED_OBJECT_TYPE_PRESENT is set in
  1187. // the ACE flags, the SID starts at the offset specified by 'InheritedObjectType'.
  1188. //
  1189. pSid = reinterpret_cast<PISID>(&(pACCESS_ALLOWED_OBJECT_ACE->InheritedObjectType));
  1190. }
  1191. else
  1192. {
  1193. //
  1194. // If neither ACE_OBJECT_TYPE_PRESENT nor ACE_INHERITED_OBJECT_TYPE_PRESENT is set in
  1195. // the ACE flags, the SID starts at the offset specified by 'ObjectType'.
  1196. //
  1197. pSid = reinterpret_cast<PISID>(&(pACCESS_ALLOWED_OBJECT_ACE->ObjectType));
  1198. }
  1199. break;
  1200. case ACCESS_DENIED_ACE_TYPE:
  1201. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - ACE type: ACCESS_DENIED_ACE_TYPE");
  1202. pACCESS_DENIED_ACE = reinterpret_cast<PACCESS_DENIED_ACE>(pAceHeader);
  1203. pSid = reinterpret_cast<PISID>(&(pACCESS_DENIED_ACE->SidStart));
  1204. break;
  1205. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1206. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - ACE type: ACCESS_DENIED_OBJECT_ACE_TYPE");
  1207. pACCESS_DENIED_OBJECT_ACE = reinterpret_cast<PACCESS_DENIED_OBJECT_ACE>(pAceHeader);
  1208. if( (pACCESS_DENIED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT) &&
  1209. (pACCESS_DENIED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT))
  1210. {
  1211. //
  1212. // If both ACE_OBJECT_TYPE_PRESENT and ACE_INHERITED_OBJECT_TYPE_PRESENT are set in
  1213. // the ACE flags, the SID starts at the offset specified by 'SidStart'.
  1214. //
  1215. pSid = reinterpret_cast<PISID>(&(pACCESS_DENIED_OBJECT_ACE->SidStart));
  1216. }
  1217. else if((pACCESS_DENIED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT) ||
  1218. (pACCESS_DENIED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT))
  1219. {
  1220. //
  1221. // If either ACE_OBJECT_TYPE_PRESENT or ACE_INHERITED_OBJECT_TYPE_PRESENT is set in
  1222. // the ACE flags, the SID starts at the offset specified by 'InheritedObjectType'.
  1223. //
  1224. pSid = reinterpret_cast<PISID>(&(pACCESS_DENIED_OBJECT_ACE->InheritedObjectType));
  1225. }
  1226. else
  1227. {
  1228. //
  1229. // If neither ACE_OBJECT_TYPE_PRESENT nor ACE_INHERITED_OBJECT_TYPE_PRESENT is set in
  1230. // the ACE flags, the SID starts at the offset specified by 'ObjectType'.
  1231. //
  1232. pSid = reinterpret_cast<PISID>(&(pACCESS_DENIED_OBJECT_ACE->ObjectType));
  1233. }
  1234. break;
  1235. default:
  1236. dbg.Msg(DEBUG_MESSAGE_WARNING, L"GetAceSid - Unexpected ACE type found. Type: 0x%08X", pAceHeader->AceType);
  1237. break;
  1238. }
  1239. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"GetAceSid - Leaving.");
  1240. return pSid;
  1241. }
  1242. //******************************************************************************
  1243. //
  1244. // Function: CheckAceApplies
  1245. //
  1246. // Description:
  1247. //
  1248. // Parameters:
  1249. //
  1250. // Return: S_OK on success. An HRESULT error code on failure.
  1251. //
  1252. // History: 8/8/99 leonardm Created.
  1253. //
  1254. //******************************************************************************
  1255. HRESULT CheckAceApplies(PACE_HEADER pAceHeader, PRSOPTOKEN pRsopToken, bool* pbAceApplies)
  1256. {
  1257. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - Entering.");
  1258. //
  1259. // Get the SID from the ACE associated with this Ace Header.
  1260. //
  1261. PISID pSid = GetAceSid(pAceHeader);
  1262. if(!pSid)
  1263. {
  1264. dbg.Msg(DEBUG_MESSAGE_WARNING, L"CheckAceApplies - GetAceSid failed.");
  1265. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - Leaving.");
  1266. return E_FAIL;
  1267. }
  1268. *pbAceApplies = false;
  1269. //
  1270. // Compare the SID from the ACE with all the SIDs in the RsopToken.
  1271. //
  1272. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  1273. for(CTLink<CSid>* pLink = pToken->m_pSidsHead; pLink; pLink = pLink->m_pNext)
  1274. {
  1275. //
  1276. // If one of the SIDs in the RsopToken matches
  1277. // the SID in the ACE, this ACE applies.
  1278. //
  1279. if(EqualSid(pSid, pLink->m_pData->GetSidPtr()))
  1280. {
  1281. *pbAceApplies = true;
  1282. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - One of the SIDs in the RsopToken matches the SID in the ACE. The ACE applies.");
  1283. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - Leaving.");
  1284. return S_OK;
  1285. }
  1286. }
  1287. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - None of the SIDs in the RsopToken matches the SID in the ACE. The ACE does not apply.");
  1288. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"CheckAceApplies - Leaving.");
  1289. return S_OK;
  1290. }
  1291. //******************************************************************************
  1292. const DWORD MAX_PERM_BITS=25;
  1293. //******************************************************************************
  1294. enum EPermission{ PERMISSION_DENIED, PERMISSION_ALLOWED, PERMISSION_NOT_SET};
  1295. //******************************************************************************
  1296. //
  1297. // Class: CSubObjectPerm
  1298. //
  1299. // Description:
  1300. //
  1301. // History: 11/09/99 leonardm Created.
  1302. //
  1303. //******************************************************************************
  1304. class CSubObjectPerm
  1305. {
  1306. private:
  1307. CTLink<GUID>* m_pGuidsHead;
  1308. CTLink<GUID>* m_pGuidsTail;
  1309. EPermission permissionBits[MAX_PERM_BITS];
  1310. public:
  1311. CSubObjectPerm();
  1312. ~CSubObjectPerm();
  1313. HRESULT AddGuid(GUID* pGuid);
  1314. void ProcessAceMask(DWORD dwMask, EPermission permission, GUID* pGuid);
  1315. DWORD GetAccumulatedPermissions();
  1316. bool AnyDenied();
  1317. };
  1318. //******************************************************************************
  1319. //
  1320. // Function: CSubObjectPerm::CSubObjectPerm
  1321. //
  1322. // Description:
  1323. //
  1324. // Parameters:
  1325. //
  1326. // Return:
  1327. //
  1328. // History: 11/09/99 leonardm Created.
  1329. //
  1330. //******************************************************************************
  1331. CSubObjectPerm::CSubObjectPerm() : m_pGuidsHead(NULL), m_pGuidsTail(NULL)
  1332. {
  1333. for (int i = 0; i < MAX_PERM_BITS; i++)
  1334. {
  1335. permissionBits[i] = PERMISSION_NOT_SET;
  1336. }
  1337. }
  1338. //******************************************************************************
  1339. //
  1340. // Function: CSubObjectPerm::~CSubObjectPerm
  1341. //
  1342. // Description:
  1343. //
  1344. // Parameters:
  1345. //
  1346. // Return:
  1347. //
  1348. // History: 11/09/99 leonardm Created.
  1349. //
  1350. //******************************************************************************
  1351. CSubObjectPerm::~CSubObjectPerm()
  1352. {
  1353. CTLink<GUID>* pLinkIterator = m_pGuidsHead;
  1354. while(pLinkIterator)
  1355. {
  1356. CTLink<GUID>* pLinkToDelete = pLinkIterator;
  1357. pLinkIterator = pLinkIterator->m_pNext;
  1358. delete pLinkToDelete;
  1359. }
  1360. }
  1361. //******************************************************************************
  1362. //
  1363. // Function: CSubObjectPerm::AddGuid
  1364. //
  1365. // Description:
  1366. //
  1367. // Parameters:
  1368. //
  1369. // Return:
  1370. //
  1371. // History: 11/09/99 leonardm Created.
  1372. //
  1373. //******************************************************************************
  1374. HRESULT CSubObjectPerm::AddGuid(GUID* pGuid)
  1375. {
  1376. CTLink<GUID>* pLink = new CTLink<GUID>(pGuid);
  1377. if(!pLink)
  1378. {
  1379. return E_OUTOFMEMORY;
  1380. }
  1381. if(!m_pGuidsHead)
  1382. {
  1383. m_pGuidsHead = pLink;
  1384. }
  1385. else
  1386. {
  1387. m_pGuidsTail->m_pNext = pLink;
  1388. }
  1389. m_pGuidsTail = pLink;
  1390. return S_OK;
  1391. }
  1392. //******************************************************************************
  1393. //
  1394. // Function: CSubObjectPerm::ProcessAceMask
  1395. //
  1396. // Description:
  1397. //
  1398. // Parameters:
  1399. //
  1400. // Return:
  1401. //
  1402. // History: 11/09/99 leonardm Created.
  1403. //
  1404. //******************************************************************************
  1405. void CSubObjectPerm::ProcessAceMask(DWORD dwMask, EPermission permission, GUID* pGuid)
  1406. {
  1407. bool bAceApplies = false;
  1408. if(!pGuid)
  1409. {
  1410. bAceApplies = true;
  1411. }
  1412. else if(pGuid && m_pGuidsHead)
  1413. {
  1414. CTLink<GUID>* pLinkIterator = m_pGuidsHead;
  1415. while(pLinkIterator)
  1416. {
  1417. if(*(pLinkIterator->m_pData) == *pGuid)
  1418. {
  1419. bAceApplies = true;
  1420. break;
  1421. }
  1422. pLinkIterator = pLinkIterator->m_pNext;
  1423. }
  1424. }
  1425. if(bAceApplies)
  1426. {
  1427. DWORD dwTemp = 0x00000001;
  1428. for(int i = 0; i < MAX_PERM_BITS; i++)
  1429. {
  1430. if((dwMask & dwTemp) && (permissionBits[i] == PERMISSION_NOT_SET))
  1431. {
  1432. permissionBits[i] = permission;
  1433. }
  1434. dwTemp <<= 1;
  1435. }
  1436. }
  1437. }
  1438. //******************************************************************************
  1439. //
  1440. // Function: CSubObjectPerm::AccumulatedPermissions
  1441. //
  1442. // Description:
  1443. //
  1444. // Parameters:
  1445. //
  1446. // Return:
  1447. //
  1448. // History: 11/09/99 leonardm Created.
  1449. //
  1450. //******************************************************************************
  1451. DWORD CSubObjectPerm::GetAccumulatedPermissions()
  1452. {
  1453. DWORD dwAccumulatedPermissions = 0;
  1454. for(int i = MAX_PERM_BITS - 1; i >= 0; i--)
  1455. {
  1456. dwAccumulatedPermissions <<= 1;
  1457. if(permissionBits[i] == PERMISSION_ALLOWED)
  1458. {
  1459. dwAccumulatedPermissions |= 0x00000001;
  1460. }
  1461. }
  1462. return dwAccumulatedPermissions;
  1463. }
  1464. //******************************************************************************
  1465. //
  1466. // Function: CSubObjectPerm::AnyDenied
  1467. //
  1468. // Description:
  1469. //
  1470. // Parameters:
  1471. //
  1472. // Return:
  1473. //
  1474. // History: 11/09/99 leonardm Created.
  1475. //
  1476. //******************************************************************************
  1477. bool CSubObjectPerm::AnyDenied()
  1478. {
  1479. for(int i = 0; i < MAX_PERM_BITS; i++)
  1480. {
  1481. if(permissionBits[i] == PERMISSION_DENIED)
  1482. {
  1483. return true;
  1484. }
  1485. }
  1486. return false;
  1487. }
  1488. //******************************************************************************
  1489. //
  1490. // Struct: CDSObject
  1491. //
  1492. // Description:
  1493. //
  1494. //
  1495. // History: 10/25/99 leonardm Created.
  1496. //
  1497. //******************************************************************************
  1498. struct CDSObject
  1499. {
  1500. DWORD m_dwLevel;
  1501. GUID* m_pGuid;
  1502. CDSObject() : m_pGuid(NULL){}
  1503. ~CDSObject()
  1504. {
  1505. delete m_pGuid;
  1506. }
  1507. };
  1508. //******************************************************************************
  1509. //
  1510. // Class: CAccumulatedPermissions
  1511. //
  1512. // Description:
  1513. //
  1514. //
  1515. // History: 10/25/99 leonardm Created.
  1516. //
  1517. //******************************************************************************
  1518. class CAccumulatedPermissions
  1519. {
  1520. CTLink<CSubObjectPerm>* m_pSubObjectsHead;
  1521. CTLink<CSubObjectPerm>* m_pSubObjectsTail;
  1522. CTLink<CDSObject>* m_pDSObjectsHead;
  1523. CTLink<CDSObject>* m_pDSObjectsTail;
  1524. bool m_bInitialized;
  1525. public:
  1526. CAccumulatedPermissions(POBJECT_TYPE_LIST pObjectTypeList,
  1527. DWORD ObjectTypeListLength);
  1528. ~CAccumulatedPermissions();
  1529. void ProcessAceMask(DWORD dwMask, EPermission permission, GUID* pGuid);
  1530. DWORD GetAccumulatedPermissions();
  1531. bool AnyDenied();
  1532. bool Initialized(){return m_bInitialized;}
  1533. };
  1534. //******************************************************************************
  1535. //
  1536. // Function: CAccumulatedPermissions::CAccumulatedPermissions
  1537. //
  1538. // Description:
  1539. //
  1540. // Parameters:
  1541. //
  1542. // Return:
  1543. //
  1544. // History: 10/25/99 leonardm Created.
  1545. //
  1546. //******************************************************************************
  1547. CAccumulatedPermissions::CAccumulatedPermissions( POBJECT_TYPE_LIST pObjectTypeList,
  1548. DWORD ObjectTypeListLength) :
  1549. m_pSubObjectsHead(NULL),
  1550. m_pSubObjectsTail(NULL),
  1551. m_bInitialized(false),
  1552. m_pDSObjectsHead(NULL),
  1553. m_pDSObjectsTail(NULL)
  1554. {
  1555. if(!pObjectTypeList || ObjectTypeListLength == 0)
  1556. {
  1557. XPtrST<CSubObjectPerm>xpSubObjectPerm = new CSubObjectPerm;
  1558. if(!xpSubObjectPerm)
  1559. {
  1560. return;
  1561. }
  1562. m_pSubObjectsHead = new CTLink<CSubObjectPerm>(xpSubObjectPerm);
  1563. if(!m_pSubObjectsHead)
  1564. {
  1565. return;
  1566. }
  1567. xpSubObjectPerm.Acquire();
  1568. m_pSubObjectsTail = m_pSubObjectsHead;
  1569. m_bInitialized = true;
  1570. return;
  1571. }
  1572. DWORD dwCurrentLevel;
  1573. for(DWORD i = 0; i < ObjectTypeListLength; i++)
  1574. {
  1575. if( i==0 )
  1576. {
  1577. //
  1578. // This assumes that the first element in the list of
  1579. // OBJECT_TYPEs pointed to by pObjectTypeList is at
  1580. // level ACCESS_OBJECT_GUID.
  1581. //
  1582. dwCurrentLevel = pObjectTypeList[i].Level;
  1583. XPtrST<CDSObject>xpDSObject = new CDSObject;
  1584. if(!xpDSObject)
  1585. {
  1586. return;
  1587. }
  1588. XPtrST<GUID>xpGuid = new GUID(*(pObjectTypeList[i].ObjectType));
  1589. if(!xpGuid)
  1590. {
  1591. return;
  1592. }
  1593. m_pDSObjectsHead = new CTLink<CDSObject>(xpDSObject);
  1594. if(!m_pDSObjectsHead)
  1595. {
  1596. return;
  1597. }
  1598. xpDSObject.Acquire();
  1599. m_pDSObjectsHead->m_pData->m_pGuid = xpGuid.Acquire();
  1600. m_pDSObjectsHead->m_pData->m_dwLevel = pObjectTypeList[i].Level;
  1601. m_pDSObjectsTail = m_pDSObjectsHead;
  1602. continue;
  1603. }
  1604. else if(pObjectTypeList[i].Level > dwCurrentLevel)
  1605. {
  1606. dwCurrentLevel = pObjectTypeList[i].Level;
  1607. XPtrST<CDSObject> xpDSObject = new CDSObject;
  1608. if(!xpDSObject)
  1609. {
  1610. return;
  1611. }
  1612. XPtrST<GUID>xpGuid = new GUID(*(pObjectTypeList[i].ObjectType));
  1613. if(!xpGuid)
  1614. {
  1615. return;
  1616. }
  1617. CTLink<CDSObject>* pDSObjectLink = new CTLink<CDSObject>(xpDSObject);
  1618. if(!pDSObjectLink)
  1619. {
  1620. return;
  1621. }
  1622. xpDSObject.Acquire();
  1623. pDSObjectLink->m_pData->m_pGuid = xpGuid.Acquire();
  1624. pDSObjectLink->m_pData->m_dwLevel = pObjectTypeList[i].Level;
  1625. pDSObjectLink->m_pPrev = m_pDSObjectsTail;
  1626. m_pDSObjectsTail->m_pNext = pDSObjectLink;
  1627. m_pDSObjectsTail = pDSObjectLink;
  1628. }
  1629. else
  1630. {
  1631. XPtrST<CSubObjectPerm>xpSubObjectPerm = new CSubObjectPerm;
  1632. if(!xpSubObjectPerm)
  1633. {
  1634. return;
  1635. }
  1636. CTLink<CSubObjectPerm>* pSubObjectLink = new CTLink<CSubObjectPerm>(xpSubObjectPerm);
  1637. if(!pSubObjectLink)
  1638. {
  1639. return;
  1640. }
  1641. xpSubObjectPerm.Acquire();
  1642. CTLink<CDSObject>* pLinkIterator = m_pDSObjectsHead;
  1643. while(pLinkIterator)
  1644. {
  1645. XPtrST<GUID>xpGuid = new GUID(*(pLinkIterator->m_pData->m_pGuid));
  1646. if(!xpGuid)
  1647. {
  1648. delete pSubObjectLink;
  1649. return;
  1650. }
  1651. if(FAILED(pSubObjectLink->m_pData->AddGuid(xpGuid)))
  1652. {
  1653. delete pSubObjectLink;
  1654. return;
  1655. }
  1656. xpGuid.Acquire();
  1657. pLinkIterator = pLinkIterator->m_pNext;
  1658. }
  1659. if(!m_pSubObjectsHead)
  1660. {
  1661. m_pSubObjectsHead = pSubObjectLink;
  1662. }
  1663. else
  1664. {
  1665. m_pSubObjectsTail->m_pNext = pSubObjectLink;
  1666. }
  1667. m_pSubObjectsTail = pSubObjectLink;
  1668. pLinkIterator = m_pDSObjectsTail;
  1669. if(pLinkIterator)
  1670. {
  1671. while(pLinkIterator->m_pData->m_dwLevel >= pObjectTypeList[i].Level)
  1672. {
  1673. CTLink<CDSObject>* pLinkToDelete = pLinkIterator;
  1674. pLinkIterator = pLinkIterator->m_pPrev;
  1675. delete pLinkToDelete;
  1676. m_pDSObjectsTail = pLinkIterator;
  1677. if(m_pDSObjectsTail)
  1678. {
  1679. m_pDSObjectsTail->m_pNext = NULL;
  1680. }
  1681. }
  1682. }
  1683. XPtrST<CDSObject>xpDSObject = new CDSObject;
  1684. if(!xpDSObject)
  1685. {
  1686. return;
  1687. }
  1688. XPtrST<GUID>xpGuid = new GUID(*(pObjectTypeList[i].ObjectType));
  1689. if(!xpGuid)
  1690. {
  1691. return;
  1692. }
  1693. CTLink<CDSObject>* pLink = new CTLink<CDSObject>(xpDSObject);
  1694. if(!pLink)
  1695. {
  1696. return;
  1697. }
  1698. xpDSObject.Acquire();
  1699. pLink->m_pData->m_pGuid = xpGuid.Acquire();
  1700. pLink->m_pData->m_dwLevel = pObjectTypeList[i].Level;
  1701. pLink->m_pPrev = m_pDSObjectsTail;
  1702. m_pDSObjectsTail->m_pNext = pLink;
  1703. m_pDSObjectsTail = pLink;
  1704. }
  1705. }
  1706. CTLink<CDSObject>* pLinkIterator = m_pDSObjectsHead;
  1707. if(pLinkIterator)
  1708. {
  1709. XPtrST<CSubObjectPerm>xpSubObject = new CSubObjectPerm;
  1710. if(!xpSubObject)
  1711. {
  1712. return;
  1713. }
  1714. CTLink<CSubObjectPerm>* pSubObjectLink = new CTLink<CSubObjectPerm>(xpSubObject);
  1715. if(!pSubObjectLink)
  1716. {
  1717. return;
  1718. }
  1719. xpSubObject.Acquire();
  1720. while(pLinkIterator)
  1721. {
  1722. XPtrST<GUID>xpGuid = new GUID(*(pLinkIterator->m_pData->m_pGuid));
  1723. if(!xpGuid)
  1724. {
  1725. delete pSubObjectLink;
  1726. return;
  1727. }
  1728. if(FAILED(pSubObjectLink->m_pData->AddGuid(xpGuid)))
  1729. {
  1730. delete pSubObjectLink;
  1731. return;
  1732. }
  1733. xpGuid.Acquire();
  1734. pLinkIterator = pLinkIterator->m_pNext;
  1735. }
  1736. if(!m_pSubObjectsHead)
  1737. {
  1738. m_pSubObjectsHead = pSubObjectLink;
  1739. }
  1740. else
  1741. {
  1742. m_pSubObjectsTail->m_pNext = pSubObjectLink;
  1743. }
  1744. m_pSubObjectsTail = pSubObjectLink;
  1745. }
  1746. pLinkIterator = m_pDSObjectsHead;
  1747. while(pLinkIterator)
  1748. {
  1749. CTLink<CDSObject>* pLinkToDelete = pLinkIterator;
  1750. pLinkIterator = pLinkIterator->m_pNext;
  1751. delete pLinkToDelete;
  1752. }
  1753. m_pDSObjectsHead = m_pDSObjectsTail = NULL;
  1754. m_bInitialized = true;
  1755. }
  1756. //******************************************************************************
  1757. //
  1758. // Function: CAccumulatedPermissions::~CAccumulatedPermissions
  1759. //
  1760. // Description:
  1761. //
  1762. // Parameters:
  1763. //
  1764. // Return:
  1765. //
  1766. // History: 10/25/99 leonardm Created.
  1767. //
  1768. //******************************************************************************
  1769. CAccumulatedPermissions::~CAccumulatedPermissions()
  1770. {
  1771. CTLink<CSubObjectPerm>* pSubObjectLinkIterator = m_pSubObjectsHead;
  1772. while(pSubObjectLinkIterator)
  1773. {
  1774. CTLink<CSubObjectPerm>* pSubObjectLinkToDelete = pSubObjectLinkIterator;
  1775. pSubObjectLinkIterator = pSubObjectLinkIterator->m_pNext;
  1776. delete pSubObjectLinkToDelete;
  1777. }
  1778. CTLink<CDSObject>* pDSObjectLinkIterator = m_pDSObjectsHead;
  1779. while(pDSObjectLinkIterator)
  1780. {
  1781. CTLink<CDSObject>* pDSObjectLinkToDelete = pDSObjectLinkIterator;
  1782. pDSObjectLinkIterator = pDSObjectLinkIterator->m_pNext;
  1783. delete pDSObjectLinkToDelete;
  1784. }
  1785. }
  1786. //******************************************************************************
  1787. //
  1788. // Function: CAccumulatedPermissions::ProcessAceMask
  1789. //
  1790. // Description:
  1791. //
  1792. // Parameters:
  1793. //
  1794. // Return:
  1795. //
  1796. // History: 8/8/99 leonardm Created.
  1797. //
  1798. //******************************************************************************
  1799. void CAccumulatedPermissions::ProcessAceMask(DWORD dwMask, EPermission permission, GUID* pGuid)
  1800. {
  1801. CTLink<CSubObjectPerm>* pLinkIterator = m_pSubObjectsHead;
  1802. while(pLinkIterator)
  1803. {
  1804. pLinkIterator->m_pData->ProcessAceMask(dwMask, permission, pGuid);
  1805. pLinkIterator = pLinkIterator->m_pNext;
  1806. }
  1807. }
  1808. //******************************************************************************
  1809. //
  1810. // Function: CAccumulatedPermissions::AccumulatedPermissions
  1811. //
  1812. // Description:
  1813. //
  1814. // Parameters:
  1815. //
  1816. // Return:
  1817. //
  1818. // History: 8/8/99 leonardm Created.
  1819. //
  1820. //******************************************************************************
  1821. DWORD CAccumulatedPermissions::GetAccumulatedPermissions()
  1822. {
  1823. DWORD dwAccumulatedPermissions = 0x01FFFFFF;
  1824. CTLink<CSubObjectPerm>* pLinkIterator = m_pSubObjectsHead;
  1825. while(pLinkIterator)
  1826. {
  1827. dwAccumulatedPermissions &= pLinkIterator->m_pData->GetAccumulatedPermissions();
  1828. pLinkIterator = pLinkIterator->m_pNext;
  1829. }
  1830. return dwAccumulatedPermissions;
  1831. }
  1832. //******************************************************************************
  1833. //
  1834. // Function: CAccumulatedPermissions::AnyDenied
  1835. //
  1836. // Description:
  1837. //
  1838. // Parameters:
  1839. //
  1840. // Return:
  1841. //
  1842. // History: 8/8/99 leonardm Created.
  1843. //
  1844. //******************************************************************************
  1845. bool CAccumulatedPermissions::AnyDenied()
  1846. {
  1847. CTLink<CSubObjectPerm>* pLinkIterator = m_pSubObjectsHead;
  1848. while(pLinkIterator)
  1849. {
  1850. if(pLinkIterator->m_pData->AnyDenied())
  1851. {
  1852. return true;
  1853. }
  1854. pLinkIterator = pLinkIterator->m_pNext;
  1855. }
  1856. return false;
  1857. }
  1858. //******************************************************************************
  1859. //
  1860. // Function: LogGuid
  1861. //
  1862. // Description:
  1863. //
  1864. // Parameters:
  1865. //
  1866. // Return: void
  1867. //
  1868. // History: 10/26/99 leonardm Created.
  1869. //
  1870. //******************************************************************************
  1871. void LogGuid(GUID& guid)
  1872. {
  1873. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogGuid - Entering.");
  1874. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogGuid - {0x%08x 0x%04x 0x%04x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x}",
  1875. guid.Data1,
  1876. guid.Data2,
  1877. guid.Data3,
  1878. guid.Data4[0],
  1879. guid.Data4[1],
  1880. guid.Data4[2],
  1881. guid.Data4[3],
  1882. guid.Data4[4],
  1883. guid.Data4[5],
  1884. guid.Data4[6],
  1885. guid.Data4[7]);
  1886. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogGuid - (%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x)",
  1887. guid.Data1,
  1888. guid.Data2,
  1889. guid.Data3,
  1890. guid.Data4[0],
  1891. guid.Data4[1],
  1892. guid.Data4[2],
  1893. guid.Data4[3],
  1894. guid.Data4[4],
  1895. guid.Data4[5],
  1896. guid.Data4[6],
  1897. guid.Data4[7]);
  1898. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogGuid - Leaving.");
  1899. }
  1900. //******************************************************************************
  1901. //
  1902. // Function: LogSid
  1903. //
  1904. // Description:
  1905. //
  1906. // Parameters:
  1907. //
  1908. // Return: void
  1909. //
  1910. // History: 10/26/99 leonardm Created.
  1911. //
  1912. //******************************************************************************
  1913. void LogSid(PSID pSid)
  1914. {
  1915. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Entering.");
  1916. XPtrST<CSid>xpCSid = new CSid(pSid);
  1917. if(!xpCSid)
  1918. {
  1919. dbg.Msg(DEBUG_MESSAGE_WARNING, L"LogSid - Call to operator new failed.");
  1920. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Leaving.");
  1921. return;
  1922. }
  1923. if(!(xpCSid->IsValid()))
  1924. {
  1925. dbg.Msg(DEBUG_MESSAGE_WARNING, L"LogSid - call to CSid::IsValid returned false.");
  1926. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Leaving.");
  1927. return;
  1928. }
  1929. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid string: %s.", xpCSid->SidString());
  1930. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid User: %s.", xpCSid->User());
  1931. if(xpCSid->SidType() == SidTypeUser)
  1932. {
  1933. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeUser.");
  1934. }
  1935. else if(xpCSid->SidType() == SidTypeGroup)
  1936. {
  1937. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeGroup.");
  1938. }
  1939. else if(xpCSid->SidType() == SidTypeDomain)
  1940. {
  1941. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeDomain.");
  1942. }
  1943. else if(xpCSid->SidType() == SidTypeAlias)
  1944. {
  1945. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeAlias.");
  1946. }
  1947. else if(xpCSid->SidType() == SidTypeWellKnownGroup)
  1948. {
  1949. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeWellKnownGroup.");
  1950. }
  1951. else if(xpCSid->SidType() == SidTypeDeletedAccount)
  1952. {
  1953. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeDeletedAccount.");
  1954. }
  1955. else if(xpCSid->SidType() == SidTypeInvalid)
  1956. {
  1957. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeInvalid.");
  1958. }
  1959. else if(xpCSid->SidType() == SidTypeUnknown)
  1960. {
  1961. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeUnknown.");
  1962. }
  1963. else if(xpCSid->SidType() == SidTypeComputer)
  1964. {
  1965. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid type: SidTypeComputer.");
  1966. }
  1967. else
  1968. {
  1969. dbg.Msg(DEBUG_MESSAGE_WARNING, L"LogSid - Sid type: UNKNOWN SID type.");
  1970. }
  1971. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid Domain: %s.", xpCSid->Domain());
  1972. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Sid Computer: %s.", xpCSid->Computer());
  1973. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogSid - Leaving.");
  1974. }
  1975. //******************************************************************************
  1976. //
  1977. // Function: LogAce
  1978. //
  1979. // Description:
  1980. //
  1981. // Parameters:
  1982. //
  1983. // Return: void
  1984. //
  1985. // History: 10/26/99 leonardm Created.
  1986. //
  1987. //******************************************************************************
  1988. void LogAce(PACE_HEADER pAceHeader)
  1989. {
  1990. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Entering.");
  1991. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - AceType = 0x%08X.", pAceHeader->AceType);
  1992. PACCESS_ALLOWED_ACE pACCESS_ALLOWED_ACE = NULL;
  1993. PACCESS_ALLOWED_OBJECT_ACE pACCESS_ALLOWED_OBJECT_ACE = NULL;
  1994. PACCESS_DENIED_ACE pACCESS_DENIED_ACE = NULL;
  1995. PACCESS_DENIED_OBJECT_ACE pACCESS_DENIED_OBJECT_ACE = NULL;
  1996. PSYSTEM_AUDIT_ACE pSYSTEM_AUDIT_ACE = NULL;
  1997. PSYSTEM_AUDIT_OBJECT_ACE pSYSTEM_AUDIT_OBJECT_ACE = NULL;
  1998. PSYSTEM_ALARM_ACE pSYSTEM_ALARM_ACE = NULL;
  1999. PSYSTEM_ALARM_OBJECT_ACE pSYSTEM_ALARM_OBJECT_ACE = NULL;
  2000. switch(pAceHeader->AceType)
  2001. {
  2002. case ACCESS_ALLOWED_ACE_TYPE:
  2003. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: ACCESS_ALLOWED_ACE_TYPE");
  2004. pACCESS_ALLOWED_ACE = reinterpret_cast<PACCESS_ALLOWED_ACE>(pAceHeader);
  2005. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pACCESS_ALLOWED_ACE->Mask);
  2006. break;
  2007. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  2008. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: ACCESS_ALLOWED_OBJECT_ACE_TYPE");
  2009. pACCESS_ALLOWED_OBJECT_ACE = reinterpret_cast<PACCESS_ALLOWED_OBJECT_ACE>(pAceHeader);
  2010. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pACCESS_ALLOWED_OBJECT_ACE->Mask);
  2011. if(pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2012. {
  2013. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_OBJECT_TYPE_PRESENT.");
  2014. LogGuid(pACCESS_ALLOWED_OBJECT_ACE->ObjectType);
  2015. }
  2016. if(pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  2017. {
  2018. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_INHERITED_OBJECT_TYPE_PRESENT.");
  2019. LogGuid(pACCESS_ALLOWED_OBJECT_ACE->InheritedObjectType);
  2020. }
  2021. break;
  2022. case ACCESS_DENIED_ACE_TYPE:
  2023. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: ACCESS_DENIED_ACE_TYPE");
  2024. pACCESS_DENIED_ACE = reinterpret_cast<PACCESS_DENIED_ACE>(pAceHeader);
  2025. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pACCESS_DENIED_ACE->Mask);
  2026. break;
  2027. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  2028. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: ACCESS_DENIED_OBJECT_ACE_TYPE");
  2029. pACCESS_DENIED_OBJECT_ACE = reinterpret_cast<PACCESS_DENIED_OBJECT_ACE>(pAceHeader);
  2030. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pACCESS_DENIED_OBJECT_ACE->Mask);
  2031. if(pACCESS_DENIED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2032. {
  2033. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_OBJECT_TYPE_PRESENT.");
  2034. LogGuid(pACCESS_DENIED_OBJECT_ACE->ObjectType);
  2035. }
  2036. if(pACCESS_DENIED_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  2037. {
  2038. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_INHERITED_OBJECT_TYPE_PRESENT.");
  2039. LogGuid(pACCESS_DENIED_OBJECT_ACE->InheritedObjectType);
  2040. }
  2041. break;
  2042. case SYSTEM_AUDIT_ACE_TYPE:
  2043. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: SYSTEM_AUDIT_ACE_TYPE");
  2044. pSYSTEM_AUDIT_ACE = reinterpret_cast<PSYSTEM_AUDIT_ACE>(pAceHeader);
  2045. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pSYSTEM_AUDIT_ACE->Mask);
  2046. break;
  2047. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  2048. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: SYSTEM_AUDIT_OBJECT_ACE_TYPE");
  2049. pSYSTEM_AUDIT_OBJECT_ACE = reinterpret_cast<PSYSTEM_AUDIT_OBJECT_ACE>(pAceHeader);
  2050. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pSYSTEM_AUDIT_OBJECT_ACE->Mask);
  2051. if(pSYSTEM_AUDIT_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2052. {
  2053. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_OBJECT_TYPE_PRESENT.");
  2054. LogGuid(pSYSTEM_AUDIT_OBJECT_ACE->ObjectType);
  2055. }
  2056. if(pSYSTEM_AUDIT_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  2057. {
  2058. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_INHERITED_OBJECT_TYPE_PRESENT.");
  2059. LogGuid(pSYSTEM_AUDIT_OBJECT_ACE->InheritedObjectType);
  2060. }
  2061. break;
  2062. case SYSTEM_ALARM_ACE_TYPE:
  2063. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: SYSTEM_ALARM_ACE_TYPE");
  2064. pSYSTEM_ALARM_ACE = reinterpret_cast<PSYSTEM_ALARM_ACE>(pAceHeader);
  2065. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pSYSTEM_ALARM_ACE->Mask);
  2066. break;
  2067. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  2068. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE type: SYSTEM_ALARM_OBJECT_ACE_TYPE");
  2069. pSYSTEM_ALARM_OBJECT_ACE = reinterpret_cast<PSYSTEM_ALARM_OBJECT_ACE>(pAceHeader);
  2070. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - ACE Mask: 0x%08X", pSYSTEM_ALARM_OBJECT_ACE->Mask);
  2071. if(pSYSTEM_ALARM_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2072. {
  2073. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_OBJECT_TYPE_PRESENT.");
  2074. LogGuid(pSYSTEM_ALARM_OBJECT_ACE->ObjectType);
  2075. }
  2076. if(pSYSTEM_ALARM_OBJECT_ACE->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  2077. {
  2078. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Flag is on: ACE_INHERITED_OBJECT_TYPE_PRESENT.");
  2079. LogGuid(pSYSTEM_ALARM_OBJECT_ACE->InheritedObjectType);
  2080. }
  2081. break;
  2082. default:
  2083. dbg.Msg(DEBUG_MESSAGE_WARNING, L"LogAce - ACE type: UNKNOWN ACE type.");
  2084. break;
  2085. }
  2086. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - AceFlags = 0x%08X.", pAceHeader->AceFlags);
  2087. if(pAceHeader->AceFlags & OBJECT_INHERIT_ACE)
  2088. {
  2089. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: OBJECT_INHERIT_ACE.");
  2090. }
  2091. if(pAceHeader->AceFlags & CONTAINER_INHERIT_ACE)
  2092. {
  2093. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: CONTAINER_INHERIT_ACE.");
  2094. }
  2095. if(pAceHeader->AceFlags & NO_PROPAGATE_INHERIT_ACE)
  2096. {
  2097. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: NO_PROPAGATE_INHERIT_ACE.");
  2098. }
  2099. if(pAceHeader->AceFlags & INHERIT_ONLY_ACE)
  2100. {
  2101. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: INHERIT_ONLY_ACE.");
  2102. }
  2103. if(pAceHeader->AceFlags & INHERITED_ACE)
  2104. {
  2105. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: INHERITED_ACE.");
  2106. }
  2107. if(pAceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
  2108. {
  2109. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: SUCCESSFUL_ACCESS_ACE_FLAG.");
  2110. }
  2111. if(pAceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG)
  2112. {
  2113. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - The Following ACE header flag is on: FAILED_ACCESS_ACE_FLAG.");
  2114. }
  2115. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - AceSize = 0x%08X.", pAceHeader->AceSize);
  2116. PISID pSid = GetAceSid(pAceHeader);
  2117. if(!pSid)
  2118. {
  2119. dbg.Msg(DEBUG_MESSAGE_WARNING, L"LogAce - Call to GetAceSid failed.");
  2120. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Leaving.");
  2121. return;
  2122. }
  2123. LogSid(pSid);
  2124. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"LogAce - Leaving.");
  2125. }
  2126. //******************************************************************************
  2127. //
  2128. // Function: ProcessAce
  2129. //
  2130. // Description:
  2131. //
  2132. // Parameters:
  2133. //
  2134. // Return: S_OK on success. An HRESULT error code on failure.
  2135. //
  2136. // History: 8/8/99 leonardm Created.
  2137. //
  2138. //******************************************************************************
  2139. HRESULT ProcessAce( PACE_HEADER pAceHeader,
  2140. PRSOPTOKEN pRsopToken,
  2141. POBJECT_TYPE_LIST pObjectTypeList,
  2142. DWORD ObjectTypeListLength,
  2143. DWORD dwDesiredAccessMask,
  2144. CAccumulatedPermissions& accumulatedPermissions,
  2145. bool* pbAccessExplicitlyDenied)
  2146. {
  2147. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Entering.");
  2148. //
  2149. // Check parameters.
  2150. //
  2151. if( !pAceHeader || !pRsopToken ||
  2152. (ObjectTypeListLength && !pObjectTypeList) ||
  2153. !pbAccessExplicitlyDenied)
  2154. {
  2155. dbg.Msg(DEBUG_MESSAGE_WARNING, L"ProcessAce - Invalid argument(s).");
  2156. return E_FAIL;
  2157. }
  2158. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Desired Access Mask: 0x%08X.", dwDesiredAccessMask);
  2159. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2160. {
  2161. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Desired Access Mask == MAXIMUM_ALLOWED.");
  2162. }
  2163. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Accumulated Permissions BEFORE Processing Ace: 0x%08X.", accumulatedPermissions.GetAccumulatedPermissions());
  2164. //
  2165. // Log ACE information
  2166. //
  2167. LogAce(pAceHeader);
  2168. *pbAccessExplicitlyDenied = false;
  2169. //
  2170. // ACEs with INHERIT_ONLY_ACE flag do no control access to the current object.
  2171. // Therefore, we ignore them.
  2172. //
  2173. if(pAceHeader->AceFlags & INHERIT_ONLY_ACE)
  2174. {
  2175. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Found ACE with INHERIT_ONLY_ACE flag. Ace does not apply.");
  2176. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Leaving.");
  2177. return S_OK;
  2178. }
  2179. //
  2180. // If this ACE does not reference any of the SIDs contained in the RsopToken,
  2181. // we ignore it.
  2182. //
  2183. bool bAceApplies;
  2184. HRESULT hr = CheckAceApplies(pAceHeader, pRsopToken, &bAceApplies);
  2185. if(FAILED(hr))
  2186. {
  2187. dbg.Msg(DEBUG_MESSAGE_WARNING, L"ProcessAce - CheckAceApplies failed. Return code: 0x%08X", hr);
  2188. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Leaving.");
  2189. return hr;
  2190. }
  2191. if(!bAceApplies)
  2192. {
  2193. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE does not apply.");
  2194. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Leaving.");
  2195. return S_OK;
  2196. }
  2197. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE aplies.");
  2198. PACCESS_ALLOWED_ACE pACCESS_ALLOWED_ACE;
  2199. PACCESS_ALLOWED_OBJECT_ACE pACCESS_ALLOWED_OBJECT_ACE;
  2200. PACCESS_DENIED_ACE pACCESS_DENIED_ACE;
  2201. PACCESS_DENIED_OBJECT_ACE pACCESS_DENIED_OBJECT_ACE;
  2202. DWORD i;
  2203. DWORD dwMask;
  2204. switch(pAceHeader->AceType)
  2205. {
  2206. case ACCESS_ALLOWED_ACE_TYPE:
  2207. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE type: ACCESS_ALLOWED_ACE_TYPE");
  2208. pACCESS_ALLOWED_ACE = reinterpret_cast<PACCESS_ALLOWED_ACE>(pAceHeader);
  2209. //
  2210. // If the requested access is MAXIMUM_ALLOWED, consider all bits in the Mask
  2211. // controlled by this ACE.
  2212. // Otherwise, consider only those bits that are also specified in the
  2213. // desired access mask.
  2214. //
  2215. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2216. {
  2217. dwMask = pACCESS_ALLOWED_ACE->Mask;
  2218. }
  2219. else
  2220. {
  2221. dwMask = dwDesiredAccessMask & pACCESS_ALLOWED_ACE->Mask;
  2222. }
  2223. accumulatedPermissions.ProcessAceMask( dwMask,
  2224. PERMISSION_ALLOWED,
  2225. NULL);
  2226. break;
  2227. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  2228. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE type: ACCESS_ALLOWED_OBJECT_ACE_TYPE");
  2229. pACCESS_ALLOWED_OBJECT_ACE = reinterpret_cast<PACCESS_ALLOWED_OBJECT_ACE>(pAceHeader);
  2230. //
  2231. // We have chosen to process only those object ACEs that have
  2232. // the flag ACE_OBJECT_TYPE_PRESENT set.
  2233. //
  2234. if(pACCESS_ALLOWED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2235. {
  2236. //
  2237. // Notice that if this function is invoked with no
  2238. // ObjectTypeList, object ACEs are disregarded.
  2239. //
  2240. for(i = 0; i < ObjectTypeListLength; i++)
  2241. {
  2242. POBJECT_TYPE_LIST pObjectType = &(pObjectTypeList[i]);
  2243. if(*(pObjectType->ObjectType) == pACCESS_ALLOWED_OBJECT_ACE->ObjectType)
  2244. {
  2245. //
  2246. // If the requested access is MAXIMUM_ALLOWED, consider all bits in the Mask
  2247. // controlled by this ACE.
  2248. // Otherwise, consider only those bits that are also specified in the
  2249. // desired access mask.
  2250. //
  2251. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2252. {
  2253. dwMask = pACCESS_ALLOWED_OBJECT_ACE->Mask;
  2254. }
  2255. else
  2256. {
  2257. dwMask = dwDesiredAccessMask & pACCESS_ALLOWED_OBJECT_ACE->Mask;
  2258. }
  2259. accumulatedPermissions.ProcessAceMask( dwMask,
  2260. PERMISSION_ALLOWED,
  2261. &(pACCESS_ALLOWED_OBJECT_ACE->ObjectType));
  2262. break;
  2263. }
  2264. }
  2265. }
  2266. break;
  2267. case ACCESS_DENIED_ACE_TYPE:
  2268. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE type: ACCESS_DENIED_ACE_TYPE");
  2269. pACCESS_DENIED_ACE = reinterpret_cast<PACCESS_DENIED_ACE>(pAceHeader);
  2270. //
  2271. // If the requested access is MAXIMUM_ALLOWED, consider all bits in the Mask
  2272. // controlled by this ACE.
  2273. // Otherwise, consider only those bits that are also specified in the
  2274. // desired access mask.
  2275. //
  2276. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2277. {
  2278. dwMask = pACCESS_DENIED_ACE->Mask;
  2279. }
  2280. else
  2281. {
  2282. dwMask = dwDesiredAccessMask & pACCESS_DENIED_ACE->Mask;
  2283. }
  2284. accumulatedPermissions.ProcessAceMask( dwMask,
  2285. PERMISSION_DENIED,
  2286. NULL);
  2287. if(dwDesiredAccessMask != MAXIMUM_ALLOWED)
  2288. {
  2289. if(accumulatedPermissions.AnyDenied())
  2290. {
  2291. *pbAccessExplicitlyDenied = true;
  2292. }
  2293. }
  2294. break;
  2295. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  2296. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - ACE type: ACCESS_DENIED_OBJECT_ACE_TYPE");
  2297. pACCESS_DENIED_OBJECT_ACE = reinterpret_cast<PACCESS_DENIED_OBJECT_ACE>(pAceHeader);
  2298. //
  2299. // We have chosen to process only those object ACEs that have
  2300. // the flag ACE_OBJECT_TYPE_PRESENT set.
  2301. //
  2302. if(pACCESS_DENIED_OBJECT_ACE->Flags & ACE_OBJECT_TYPE_PRESENT)
  2303. {
  2304. //
  2305. // Notice that if this function is invoked with no
  2306. // ObjectTypeList, object ACEs are disregarded.
  2307. //
  2308. for(i = 0; i < ObjectTypeListLength; i++)
  2309. {
  2310. POBJECT_TYPE_LIST pObjectType = &(pObjectTypeList[i]);
  2311. if(*(pObjectType->ObjectType) == pACCESS_DENIED_OBJECT_ACE->ObjectType)
  2312. {
  2313. //
  2314. // If the requested access is MAXIMUM_ALLOWED, consider all bits in the Mask
  2315. // controlled by this ACE.
  2316. // Otherwise, consider only those bits that are also specified in the
  2317. // desired access mask.
  2318. //
  2319. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2320. {
  2321. dwMask = pACCESS_DENIED_OBJECT_ACE->Mask;
  2322. }
  2323. else
  2324. {
  2325. dwMask = dwDesiredAccessMask & pACCESS_DENIED_OBJECT_ACE->Mask;
  2326. }
  2327. accumulatedPermissions.ProcessAceMask( dwMask,
  2328. PERMISSION_DENIED,
  2329. &(pACCESS_DENIED_OBJECT_ACE->ObjectType));
  2330. if(dwDesiredAccessMask != MAXIMUM_ALLOWED)
  2331. {
  2332. if(accumulatedPermissions.AnyDenied())
  2333. {
  2334. *pbAccessExplicitlyDenied = true;
  2335. }
  2336. }
  2337. break;
  2338. }
  2339. }
  2340. }
  2341. break;
  2342. default:
  2343. dbg.Msg(DEBUG_MESSAGE_WARNING, L"ProcessAce - Unexpected ACE type found in ACE header. Type: 0x%08x", pAceHeader->AceType);
  2344. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Leaving.");
  2345. return E_FAIL;
  2346. break;
  2347. }
  2348. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Accumulated Permissions AFTER Processing Ace: 0x%08X.", accumulatedPermissions.GetAccumulatedPermissions());
  2349. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"ProcessAce - Leaving.");
  2350. return S_OK;
  2351. }
  2352. //******************************************************************************
  2353. //
  2354. // Function: RsopAccessCheckByType
  2355. //
  2356. // Description:
  2357. //
  2358. // Parameters: - pSecurityDescriptor,
  2359. // - pPrincipalSelfSid:
  2360. // - pRsopToken:
  2361. // - dwDesiredAccessMask:
  2362. // - pObjectTypeList:
  2363. // - ObjectTypeListLength:
  2364. // - pGenericMapping:
  2365. // - pPrivilegeSet:
  2366. // - pdwPrivilegeSetLength:
  2367. // - pdwGrantedAccessMask:
  2368. // - pbAccessStatus:
  2369. //
  2370. // Return: S_OK on success. An HRESULT error code on failure.
  2371. //
  2372. // History: 7/30/99 leonardm Created.
  2373. //
  2374. //******************************************************************************
  2375. HRESULT RsopAccessCheckByType( PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2376. PSID pPrincipalSelfSid,
  2377. PRSOPTOKEN pRsopToken,
  2378. DWORD dwDesiredAccessMask,
  2379. POBJECT_TYPE_LIST pObjectTypeList,
  2380. DWORD ObjectTypeListLength,
  2381. PGENERIC_MAPPING pGenericMapping,
  2382. PPRIVILEGE_SET pPrivilegeSet,
  2383. LPDWORD pdwPrivilegeSetLength,
  2384. LPDWORD pdwGrantedAccessMask,
  2385. LPBOOL pbAccessStatus)
  2386. {
  2387. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Entering.");
  2388. //
  2389. // Check arguments.
  2390. //
  2391. if( !pSecurityDescriptor |
  2392. !IsValidSecurityDescriptor(pSecurityDescriptor) |
  2393. !pRsopToken |
  2394. !pGenericMapping |
  2395. !pdwGrantedAccessMask |
  2396. !pbAccessStatus)
  2397. {
  2398. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopAccessCheckByType - Function invoked with invalid arguments.");
  2399. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2400. return E_INVALIDARG;
  2401. }
  2402. //
  2403. // Get the DACL from the Security Descriptor
  2404. //
  2405. BOOL bDaclPresent;
  2406. PACL pDacl;
  2407. BOOL bDaclDefaulted;
  2408. if(!GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted))
  2409. {
  2410. DWORD dwLastError = GetLastError();
  2411. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopAccessCheckByType - GetSecurityDescriptorDacl failed. GetLastError=0x%08X", dwLastError);
  2412. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2413. return E_FAIL;
  2414. }
  2415. //
  2416. // Map generic rights specified in dwDesiredAccessMask to standard
  2417. // and specific rights.
  2418. // This is necessary because the ACEs in the DACL specify standard
  2419. // and specific rights only.
  2420. //
  2421. if(dwDesiredAccessMask != MAXIMUM_ALLOWED)
  2422. {
  2423. MapGenericMask(&dwDesiredAccessMask, pGenericMapping);
  2424. }
  2425. //
  2426. // If no DACL is present (as indicated by bDaclPresent) in the security descriptor,
  2427. // or if it present (as indicated by bDaclPresent) but it is a NULL DACL
  2428. // the object implicitly grants all access.
  2429. //
  2430. if(!bDaclPresent || pDacl == NULL)
  2431. {
  2432. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2433. {
  2434. *pdwGrantedAccessMask = pGenericMapping->GenericAll |
  2435. pGenericMapping->GenericExecute |
  2436. pGenericMapping->GenericRead |
  2437. pGenericMapping->GenericWrite;
  2438. }
  2439. else
  2440. {
  2441. *pdwGrantedAccessMask = dwDesiredAccessMask;
  2442. }
  2443. *pbAccessStatus = TRUE;
  2444. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - No DACL present. All access is granted.");
  2445. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2446. return S_OK;
  2447. }
  2448. DWORD dwAceCount = pDacl->AceCount;
  2449. //
  2450. // If the DACL is present but it is empty,
  2451. // the object implicitly denies access to everyone.
  2452. //
  2453. if(!dwAceCount)
  2454. {
  2455. *pdwGrantedAccessMask = 0;
  2456. *pbAccessStatus = FALSE;
  2457. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - The DACL is present but it is empty. All access is denied.");
  2458. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2459. return S_OK;
  2460. }
  2461. //
  2462. // At this point we have an array of ACES structures
  2463. //
  2464. // If the desired access is different from MAXIMUM_ALLOWED,
  2465. // inspect them until one of the following happens:
  2466. //
  2467. // 1. An ACE is found which explicitly denies one of the requested
  2468. // access rights. In this case checking stops immediately and
  2469. // access is (explicitly) denied.
  2470. //
  2471. // 2. All the requested accesses are explicitly granted by one or
  2472. // more ACEs. In this case checking stops immediately and
  2473. // access is (explicitly) allowed.
  2474. //
  2475. //
  2476. // 3. All the ACEs have been inspected inspected and there is at least
  2477. // one requested access right that has not been explicitly allowed.
  2478. // In this case, access is (implicitly) denied.
  2479. //
  2480. // If the desired access is MAXIMUM_ALLOWED, inspect all the ACEs.
  2481. //
  2482. PISID pSid;
  2483. BYTE* pByte;
  2484. CAccumulatedPermissions accumulatedPermissions( pObjectTypeList, ObjectTypeListLength);
  2485. if(!accumulatedPermissions.Initialized())
  2486. {
  2487. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopAccessCheckByType - CAccumulatedPermissions failed to initialize.");
  2488. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2489. return E_FAIL;
  2490. }
  2491. *pdwGrantedAccessMask = 0;
  2492. *pbAccessStatus = FALSE;
  2493. //
  2494. // Log SID information contained in the RsopToken.
  2495. //
  2496. CRsopToken* pToken = static_cast<CRsopToken*>(pRsopToken);
  2497. for(CTLink<CSid>* pLink = pToken->m_pSidsHead; pLink; pLink = pLink->m_pNext)
  2498. {
  2499. LogSid(pLink->m_pData->GetSidPtr());
  2500. }
  2501. //
  2502. // The first ACE immediately follows the DACL structure. We don't know up front
  2503. // the type of ACE so we get the ACE header which has a format common to all
  2504. // ACE types.
  2505. //
  2506. PACE_HEADER pAceHeader = reinterpret_cast<PACE_HEADER>(pDacl+1);
  2507. for(DWORD i=0; i<dwAceCount; i++)
  2508. {
  2509. bool bAccessExplicitlyDenied;
  2510. HRESULT hr = ProcessAce(pAceHeader,
  2511. pRsopToken,
  2512. pObjectTypeList,
  2513. ObjectTypeListLength,
  2514. dwDesiredAccessMask,
  2515. accumulatedPermissions,
  2516. &bAccessExplicitlyDenied);
  2517. if(FAILED(hr))
  2518. {
  2519. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopAccessCheckByType - ProcessAce failed. Return code: 0x%08X", hr);
  2520. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2521. return hr;
  2522. }
  2523. //
  2524. // If, this ACE explicitly denies any of the requested access rights,
  2525. // stop immediately. Access is denied.
  2526. // ProcessAce will never set this variable to true when dwDesiredAccessMask
  2527. // is MAXIMUM_ALLOWED.
  2528. //
  2529. if(bAccessExplicitlyDenied)
  2530. {
  2531. *pdwGrantedAccessMask = 0;
  2532. *pbAccessStatus = FALSE;
  2533. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - An ACE explicitly denies any of the requested access rights. Access is denied.");
  2534. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2535. return S_OK;
  2536. }
  2537. //
  2538. // If, after processing this ACE all requested access rights have been granted,
  2539. // stop immediately. Access is granted.
  2540. //
  2541. DWORD dwAccumulatedPermissions = accumulatedPermissions.GetAccumulatedPermissions();
  2542. if((dwDesiredAccessMask != MAXIMUM_ALLOWED) && (dwAccumulatedPermissions == dwDesiredAccessMask))
  2543. {
  2544. *pdwGrantedAccessMask = dwDesiredAccessMask;
  2545. *pbAccessStatus = TRUE;
  2546. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - dwDesiredAccessMask != MAXIMUM_ALLOWED && dwAccumulatedPermissions == dwDesiredAccessMask. Access is granted.");
  2547. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2548. return S_OK;
  2549. }
  2550. //
  2551. // Otherwise, point to the next ACE.
  2552. //
  2553. pAceHeader = reinterpret_cast<PACE_HEADER>(reinterpret_cast<BYTE*>(pAceHeader) + pAceHeader->AceSize);
  2554. }
  2555. if(dwDesiredAccessMask == MAXIMUM_ALLOWED)
  2556. {
  2557. *pdwGrantedAccessMask = accumulatedPermissions.GetAccumulatedPermissions();
  2558. *pbAccessStatus = *pdwGrantedAccessMask ? TRUE : FALSE;
  2559. }
  2560. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopAccessCheckByType - Leaving.");
  2561. return S_OK;
  2562. }
  2563. //******************************************************************************
  2564. //
  2565. // Function: RsopFileAccessCheck
  2566. //
  2567. // Description: Determines whether the security descriptor pointed to by pSecurityDescriptor
  2568. // grants the set of file access rights specified in dwDesiredAccessMask
  2569. // to the client identified by the RSOPTOKEN pointed to by pRsopToken.
  2570. //
  2571. // Parameters: - pszFileName: Pointer to an existing filename.
  2572. // - pRsopToken: Pointer to a valid RSOPTOKEN against which access
  2573. // is to be checked.
  2574. // - dwDesiredAccessMask: Mask of requested generic and/or standard and/or specific access rights,
  2575. // - pdwGrantedAccessMask: On success, if pbAccessStatus is true, it contains
  2576. // the mask of standard and specific rights granted.
  2577. // If pbAccessStatus is false, it is set to 0.
  2578. // On failure, it is not modified.
  2579. // - pbAccessStatus: On success, indicates wether the requested set
  2580. // of access rights was granted.
  2581. // On failure, it is not modified
  2582. //
  2583. // Return: S_OK on success. An HRESULT error code on failure.
  2584. //
  2585. // History: 7/30/99 leonardm Created.
  2586. //
  2587. //******************************************************************************
  2588. HRESULT RsopFileAccessCheck(LPTSTR pszFileName,
  2589. PRSOPTOKEN pRsopToken,
  2590. DWORD dwDesiredAccessMask,
  2591. LPDWORD pdwGrantedAccessMask,
  2592. LPBOOL pbAccessStatus)
  2593. {
  2594. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Entering.");
  2595. //
  2596. // Check for invalid arguments.
  2597. //
  2598. if( !pszFileName |!pRsopToken | !pdwGrantedAccessMask | !pbAccessStatus)
  2599. {
  2600. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopFileAccessCheck - Function called with invalid parameters.");
  2601. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Leaving.");
  2602. return E_INVALIDARG;
  2603. }
  2604. //
  2605. // Attempt to get a handle with READ_CONTROL access right that can be used to
  2606. // read the security descriptor.
  2607. //
  2608. XHandle hFile = CreateFile( pszFileName,
  2609. READ_CONTROL,
  2610. FILE_SHARE_READ|FILE_SHARE_WRITE,
  2611. NULL,
  2612. OPEN_EXISTING,
  2613. 0,
  2614. NULL);
  2615. if(hFile == INVALID_HANDLE_VALUE)
  2616. {
  2617. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopFileAccessCheck - Call to CreateFile failed. Filename: %s. Last error: 0x%08X", pszFileName, GetLastError());
  2618. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Leaving.");
  2619. return E_FAIL;
  2620. }
  2621. //
  2622. // Use the handle to get the security descriptor with only the DACL in it.
  2623. //
  2624. PACL pDacl;
  2625. XPtrLF<SECURITY_DESCRIPTOR>xpSecurityDescriptor = NULL;
  2626. DWORD status = GetSecurityInfo( hFile,
  2627. SE_FILE_OBJECT,
  2628. DACL_SECURITY_INFORMATION,
  2629. NULL,
  2630. NULL,
  2631. &pDacl,
  2632. NULL,
  2633. reinterpret_cast<void**>(&xpSecurityDescriptor));
  2634. if(status != ERROR_SUCCESS)
  2635. {
  2636. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopFileAccessCheck - Call to GetSecurityInfo failed. Return: 0x%08X", status);
  2637. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Leaving.");
  2638. return E_FAIL;
  2639. }
  2640. //
  2641. // This will be used by RSOPAccessCheckByType to map generic rights specified in
  2642. // dwDesiredAccessMask to standard and specific rights.
  2643. //
  2644. GENERIC_MAPPING FileGenericMapping;
  2645. FileGenericMapping.GenericRead = FILE_GENERIC_READ;
  2646. FileGenericMapping.GenericWrite = FILE_GENERIC_WRITE;
  2647. FileGenericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
  2648. FileGenericMapping.GenericAll = FILE_ALL_ACCESS;
  2649. //
  2650. // Call RsopAccessCheckByType to do the actual checking.
  2651. //
  2652. HRESULT hr = RsopAccessCheckByType( xpSecurityDescriptor,
  2653. NULL,
  2654. pRsopToken,
  2655. dwDesiredAccessMask,
  2656. NULL,
  2657. 0,
  2658. &FileGenericMapping,
  2659. NULL,
  2660. 0,
  2661. pdwGrantedAccessMask,
  2662. pbAccessStatus);
  2663. if(SUCCEEDED(hr))
  2664. {
  2665. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Leaving successfully.");
  2666. }
  2667. else
  2668. {
  2669. dbg.Msg(DEBUG_MESSAGE_WARNING, L"RsopFileAccessCheck - Call to RsopAccessCheckByType failed. Return: 0x%08X", hr);
  2670. dbg.Msg(DEBUG_MESSAGE_VERBOSE, L"RsopFileAccessCheck - Leaving.");
  2671. }
  2672. return hr;
  2673. }
  2674. //******************************************************************************
  2675. //
  2676. // Function: RsopSidsFromToken
  2677. //
  2678. // Description: Returns all the sids in the token
  2679. //
  2680. // Parameters: pRsopToken -- an rsop token from which to obtain sids
  2681. // ppGroups -- a pointer to the address of a TOKEN_GROUPS structure
  2682. // that will be allocated by this function and will contain
  2683. // references to the sids. The caller should free this
  2684. // pointer with LocalFree -- this will also free all memory
  2685. // referenced by the structure.
  2686. //
  2687. // Return: S_OK on success. An HRESULT error code on failure.
  2688. //
  2689. //
  2690. //******************************************************************************
  2691. HRESULT RsopSidsFromToken(PRSOPTOKEN pRsopToken,
  2692. PTOKEN_GROUPS* ppGroups)
  2693. {
  2694. HRESULT hr;
  2695. CRsopToken* pToken;
  2696. //
  2697. // Initializations
  2698. //
  2699. hr = S_OK;
  2700. *ppGroups = NULL;
  2701. pToken = (CRsopToken*) pRsopToken;
  2702. //
  2703. // First, determine the number of groups and the size
  2704. // needed for each sid
  2705. //
  2706. CTLink<CSid>* pCurrent;
  2707. DWORD cbSize;
  2708. DWORD cGroups;
  2709. cbSize = 0;
  2710. cGroups = 0;
  2711. //
  2712. // Iterate through each sid, adding its size to the total
  2713. // needed to store the sids
  2714. //
  2715. for ( pCurrent = pToken->m_pSidsHead;
  2716. pCurrent;
  2717. pCurrent = pCurrent->m_pNext)
  2718. {
  2719. cbSize += RtlLengthSid(pCurrent->m_pData->GetSidPtr());
  2720. cGroups++;
  2721. }
  2722. //
  2723. // Add in the size of the fixed portion of the return structure.
  2724. // Note that the fixed portion of the structure already has
  2725. // space for one group, so we exclude that group from the amount
  2726. // neeeded to allocate if we are allocating at least one group
  2727. //
  2728. cbSize += sizeof(TOKEN_GROUPS) + (sizeof(SID_AND_ATTRIBUTES) *
  2729. (cGroups - (cGroups ? 1 : 0)));
  2730. //
  2731. // Now allocate space for the groups
  2732. //
  2733. *ppGroups = (PTOKEN_GROUPS) LocalAlloc( LPTR, cbSize );
  2734. if ( !*ppGroups )
  2735. {
  2736. return E_OUTOFMEMORY;
  2737. }
  2738. //
  2739. // Set the count member of the structure
  2740. //
  2741. (*ppGroups)->GroupCount = cGroups;
  2742. //
  2743. // If there are groups, copy the sids
  2744. //
  2745. if ( 0 != cGroups )
  2746. {
  2747. PSID pCurrentSid;
  2748. PSID_AND_ATTRIBUTES pCurrentGroup;
  2749. //
  2750. // Set the current sid to an offset past the
  2751. // array of SID_AND_ATTRIBUTE structures that
  2752. // represents each group
  2753. //
  2754. pCurrentSid = &((*ppGroups)->Groups[cGroups]);
  2755. //
  2756. // Set the current group to the first SID_AND_ATTRIBUTE structure
  2757. //
  2758. pCurrentGroup = (PSID_AND_ATTRIBUTES) &((*ppGroups)->Groups);
  2759. //
  2760. // We have no information in the rsop token regarding
  2761. // the attributes, so we clear this member
  2762. //
  2763. pCurrentGroup->Attributes = 0;
  2764. //
  2765. // Iterate through each group and copy it
  2766. //
  2767. for (pCurrent = pToken->m_pSidsHead;
  2768. pCurrent;
  2769. pCurrent = pCurrent->m_pNext)
  2770. {
  2771. DWORD cbSid;
  2772. NTSTATUS Status;
  2773. //
  2774. // Determine the length of the source sid
  2775. //
  2776. cbSid = RtlLengthSid(pCurrent->m_pData->GetSidPtr());
  2777. //
  2778. // Copy the source sid to the current sid
  2779. //
  2780. Status = RtlCopySid(
  2781. cbSid,
  2782. pCurrentSid,
  2783. pCurrent->m_pData->GetSidPtr());
  2784. //
  2785. // Check for errors
  2786. //
  2787. if (STATUS_SUCCESS != Status)
  2788. {
  2789. hr = HRESULT_FROM_WIN32(Status);
  2790. break;
  2791. }
  2792. //
  2793. // Set the current group's sid reference to the
  2794. // current sid
  2795. //
  2796. pCurrentGroup->Sid = pCurrentSid;
  2797. //
  2798. // Move our current sid offset forward by the length of
  2799. // the current sid. Move our group reference forward as well.
  2800. //
  2801. pCurrentSid = (PSID) (((BYTE*) pCurrentSid) + cbSid);
  2802. pCurrentGroup++;
  2803. }
  2804. }
  2805. //
  2806. // Free any memory on failure and remove
  2807. // any reference to it
  2808. //
  2809. if (FAILED(hr))
  2810. {
  2811. LocalFree(*ppGroups);
  2812. *ppGroups = NULL;
  2813. }
  2814. return hr;
  2815. }