Leaked source code of windows server 2003
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.

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