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.

4506 lines
150 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: acclist.cxx
  7. //
  8. // Contents: Class implementation of the CAccessList class
  9. //
  10. // Classes: CAccessList
  11. //
  12. // History: 28-Jul-96 MacM Created
  13. //
  14. //--------------------------------------------------------------------
  15. #include <aclpch.hxx>
  16. #pragma hdrstop
  17. #include <alsup.hxx>
  18. #include <seopaque.h>
  19. #include <sertlp.h>
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Member: CAcccessList::CAccessList, public
  23. //
  24. // Synopsis: Constructor for the class
  25. //
  26. // Arguments: None
  27. //
  28. // Returns: Void
  29. //
  30. //----------------------------------------------------------------------------
  31. CAccessList::CAccessList() :
  32. _AccList(DelAcclistNode),
  33. _TrusteeList (DelTrusteeNode),
  34. _pGroup (NULL),
  35. _pOwner (NULL),
  36. _fSDValid (FALSE),
  37. _fFreeSD (FALSE),
  38. _pSD (NULL),
  39. _cSDSize (0),
  40. _fDAclFlags (0),
  41. _fSAclFlags (0),
  42. _ObjType (SE_UNKNOWN_OBJECT_TYPE),
  43. _pLDAP (NULL),
  44. _pwszDsPathReference (NULL),
  45. _pwszLookupServer (NULL)
  46. {
  47. acDebugOut((DEB_TRACE_ACC, "In - out CAccessList::CAccessList\n"));
  48. }
  49. //+---------------------------------------------------------------------------
  50. //
  51. // Member: CAccessList::~CAccessList, public
  52. //
  53. // Synopsis: Destructor for the class
  54. //
  55. // Arguments: None
  56. //
  57. // Returns: Void
  58. //
  59. //----------------------------------------------------------------------------
  60. CAccessList::~CAccessList()
  61. {
  62. acDebugOut((DEB_TRACE_ACC, "In - out CAccessList::~CAccessList\n"));
  63. AccFree(_pGroup);
  64. AccFree(_pOwner);
  65. if(_fFreeSD == TRUE)
  66. {
  67. AccFree(_pSD);
  68. }
  69. AccFree(_pwszLookupServer);
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Member: CAccessList::AddSD, public
  74. //
  75. // Synopsis: Adds a new security descriptor to the list. It converts the
  76. // acls into an access list
  77. //
  78. // Arguments: [IN pSD] -- The information about the security
  79. // descriptor
  80. // [IN SeInfo] -- SecurityInfo
  81. // [IN pwszProperty] Property name
  82. //
  83. // Returns: ERROR_SUCCESS -- Success
  84. //
  85. //----------------------------------------------------------------------------
  86. DWORD CAccessList::AddSD(IN PSECURITY_DESCRIPTOR pSD,
  87. IN SECURITY_INFORMATION SeInfo,
  88. IN PWSTR pwszProperty,
  89. IN BOOL fAddAll)
  90. {
  91. acDebugOut((DEB_TRACE_ACC, "In CAccessList::AddSD\n"));
  92. DWORD dwErr = ERROR_SUCCESS;
  93. PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR)pSD;
  94. dwErr = AddAcl(RtlpDaclAddrSecurityDescriptor(pISD),
  95. RtlpSaclAddrSecurityDescriptor(pISD),
  96. RtlpOwnerAddrSecurityDescriptor(pISD),
  97. RtlpGroupAddrSecurityDescriptor(pISD),
  98. SeInfo,
  99. pwszProperty,
  100. fAddAll,
  101. pISD->Control);
  102. acDebugOut((DEB_TRACE_ACC, "Out CAccessList::AddSD: 0x%lx\n", dwErr));
  103. return(dwErr);
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Member: CAccessList::AddAcl, public
  108. //
  109. // Synopsis: Adds a new acl to the list. It converts the acls into an
  110. // access list
  111. //
  112. // Arguments: [IN pDAcl] -- The DAcl to add
  113. // [IN pSAcl] -- The SAcl to add
  114. // [IN SeInfo] -- SecurityInfo
  115. // [IN pwszProperty] Property name
  116. //
  117. // Returns: ERROR_SUCCESS -- Success
  118. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  119. //
  120. //----------------------------------------------------------------------------
  121. DWORD CAccessList::AddAcl(IN PACL pDAcl,
  122. IN PACL pSAcl,
  123. IN PSID pOwner,
  124. IN PSID pGroup,
  125. IN SECURITY_INFORMATION SeInfo,
  126. IN PWSTR pwszProperty,
  127. IN BOOL fAddAll,
  128. IN ULONG fControl)
  129. {
  130. acDebugOut((DEB_TRACE_ACC, "In CAccessList::AddAcl: 0x%lx\n", pDAcl));
  131. DWORD dwErr = ERROR_SUCCESS;
  132. _fSDValid = FALSE;
  133. //
  134. // If no parameters are given, just return success
  135. //
  136. if(SeInfo == 0)
  137. {
  138. return(ERROR_SUCCESS);
  139. }
  140. //
  141. // Ok, save off the group and owner if they exist
  142. //
  143. if(FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION))
  144. {
  145. if(pOwner == NULL || RtlValidSid((PSID)pOwner) == FALSE)
  146. {
  147. dwErr = ERROR_INVALID_OWNER;
  148. }
  149. else
  150. {
  151. ACC_ALLOC_AND_COPY_SID(pOwner, _pOwner, dwErr);
  152. }
  153. }
  154. if(FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION))
  155. {
  156. if(pGroup == NULL || RtlValidSid((PSID)pGroup) == FALSE)
  157. {
  158. dwErr = ERROR_INVALID_PRIMARY_GROUP;
  159. }
  160. else
  161. {
  162. ACC_ALLOC_AND_COPY_SID(pGroup, _pGroup, dwErr);
  163. }
  164. }
  165. //
  166. // Otherwise, we'll start processing them...
  167. //
  168. if(dwErr == ERROR_SUCCESS &&
  169. FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  170. {
  171. dwErr = ConvertAclToAccess(DACL_SECURITY_INFORMATION,
  172. pDAcl,
  173. pwszProperty,
  174. fAddAll,
  175. (BOOL)FLAG_ON(fControl, SE_DACL_PROTECTED));
  176. }
  177. if(dwErr == ERROR_SUCCESS &&
  178. FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION))
  179. {
  180. dwErr = ConvertAclToAccess(SACL_SECURITY_INFORMATION,
  181. pSAcl,
  182. pwszProperty,
  183. fAddAll,
  184. (BOOL)FLAG_ON(fControl, SE_SACL_PROTECTED));
  185. }
  186. acDebugOut((DEB_TRACE_ACC, "Out CAccessList::AddAcl: %lu\n", dwErr));
  187. return(dwErr);
  188. }
  189. //+---------------------------------------------------------------------------
  190. //
  191. // Member: CAccessList::RemoveTrusteeFromAccess, public
  192. //
  193. // Synopsis: This method goes through and removes any explicit entries from
  194. // an access list for the given trustee.
  195. //
  196. // Arguments: [IN SeInfo] -- Type of access list to operate on
  197. // [IN pTrustee] -- Trustee to remove
  198. // [IN pwszProperty] -- If present, this is the property to
  199. // revoke the access on
  200. //
  201. // Returns: ERROR_SUCCESS -- Success
  202. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  203. //
  204. // Notes:
  205. //
  206. //----------------------------------------------------------------------------
  207. DWORD CAccessList::RemoveTrusteeFromAccess(IN SECURITY_INFORMATION SeInfo,
  208. IN PTRUSTEE pTrustee,
  209. IN PWSTR pwszProperty OPTIONAL)
  210. {
  211. acDebugOut((DEB_TRACE_ACC,"In CAccessList::RemoveTrusteeFromAccess\n"));
  212. DWORD dwErr = ERROR_SUCCESS;
  213. BOOL PropertiesMatch = FALSE;
  214. GUID Guid;
  215. PWSTR pwszNewPropertyName, pwszSourceName;
  216. //
  217. // Now, we'll simply process all of the lists, and remove any of the
  218. // specified entries
  219. //
  220. _fSDValid = FALSE;
  221. //
  222. // Enumerate through the list
  223. //
  224. _AccList.Reset();
  225. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.NextData();
  226. while(pAccNode != NULL && dwErr == ERROR_SUCCESS)
  227. {
  228. PropertiesMatch = DoPropertiesMatch(pAccNode->pwszProperty, pwszProperty);
  229. if(PropertiesMatch == FALSE && pwszProperty != NULL && pAccNode->pwszProperty != NULL)
  230. {
  231. //
  232. // See if we should convert one to/from a guid and then
  233. // compare it again
  234. //
  235. dwErr = UuidFromString(pwszProperty, &Guid);
  236. if(dwErr == ERROR_SUCCESS)
  237. {
  238. pwszSourceName = pAccNode->pwszProperty;
  239. }
  240. else
  241. {
  242. dwErr = UuidFromString(pAccNode->pwszProperty, &Guid);
  243. if(dwErr == ERROR_SUCCESS)
  244. {
  245. pwszSourceName = pwszProperty;
  246. }
  247. }
  248. if(dwErr == ERROR_SUCCESS)
  249. {
  250. dwErr = AccctrlLookupIdName(_pLDAP,
  251. _pwszDsPathReference,
  252. &Guid,
  253. FALSE,
  254. FALSE,
  255. &pwszNewPropertyName);
  256. if(dwErr == ERROR_SUCCESS)
  257. {
  258. PropertiesMatch = DoPropertiesMatch(pwszSourceName,
  259. pwszNewPropertyName);
  260. }
  261. }
  262. }
  263. if(PropertiesMatch)
  264. {
  265. //
  266. // Get the list we need
  267. //
  268. PACTRL_ACCESS_ENTRY_LIST pList = SeInfo == DACL_SECURITY_INFORMATION ?
  269. pAccNode->pAccessList :
  270. pAccNode->pAuditList;
  271. if(pList != NULL)
  272. {
  273. //
  274. // Now, process it...
  275. //
  276. ULONG cRemoved = 0;
  277. for(ULONG iIndex = 0;
  278. iIndex < pList->cEntries && dwErr == ERROR_SUCCESS;
  279. iIndex++)
  280. {
  281. BOOL fMatch = FALSE;
  282. dwErr = DoTrusteesMatch(_pwszLookupServer,
  283. pTrustee,
  284. &(pList->pAccessList[iIndex].Trustee),
  285. &fMatch);
  286. if(dwErr == ERROR_SUCCESS && fMatch == TRUE)
  287. {
  288. cRemoved++;
  289. //
  290. // Indicate that this node is to be removed by setting the
  291. // access flags to 0xFFFFFFFF
  292. //
  293. pList->pAccessList[iIndex].Access = 0xFFFFFFFF;
  294. }
  295. }
  296. //
  297. // Now, see if we need to do anything...
  298. //
  299. if(dwErr == ERROR_SUCCESS && cRemoved != 0)
  300. {
  301. PACTRL_ACCESS_ENTRY_LIST pNew;
  302. dwErr = ShrinkList(pList,
  303. cRemoved,
  304. &pNew);
  305. if(dwErr == ERROR_SUCCESS)
  306. {
  307. //
  308. // Finally, replace what is there with our new one
  309. //
  310. if(SeInfo == DACL_SECURITY_INFORMATION)
  311. {
  312. CHECK_HEAP
  313. AccFree(pAccNode->pAccessList);
  314. pAccNode->pAccessList = pNew;
  315. if(pNew == NULL)
  316. {
  317. pAccNode->SeInfo &= ~DACL_SECURITY_INFORMATION;
  318. }
  319. }
  320. else
  321. {
  322. AccFree(pAccNode->pAuditList);
  323. pAccNode->pAuditList = pNew;
  324. if(pNew == NULL)
  325. {
  326. pAccNode->SeInfo &= ~SACL_SECURITY_INFORMATION;
  327. }
  328. }
  329. }
  330. }
  331. }
  332. }
  333. pAccNode = (PACCLIST_NODE)_AccList.NextData();
  334. }
  335. acDebugOut((DEB_TRACE_ACC,
  336. "Out CAccessList::RemoveTrusteeFromAccess: %lu\n", dwErr));
  337. return(dwErr);
  338. }
  339. //+---------------------------------------------------------------------------
  340. //
  341. // Member: CAccessList::ConvertAclToAccess, private
  342. //
  343. // Synopsis: Converts the given dacl/sacl to an ACCLIST_NODE format
  344. //
  345. // Arguments: [IN SeInfo] -- What type of ACL this is
  346. // [IN pAcl] -- The Acl to convert
  347. //
  348. // Returns: ERROR_SUCCESS -- Success
  349. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  350. // ERROR_INVALID_ACL -- ACL came in as downlevel
  351. //
  352. //----------------------------------------------------------------------------
  353. DWORD CAccessList::ConvertAclToAccess(IN SECURITY_INFORMATION SeInfo,
  354. IN PACL pAcl,
  355. IN PWSTR pwszProperty,
  356. IN BOOL fAddAll,
  357. IN BOOL fProtected)
  358. {
  359. acDebugOut((DEB_TRACE_ACC, "In CAccessList::ConvertAclToAccess\n"));
  360. DWORD dwErr = ERROR_SUCCESS;
  361. CSList AceList((FreeFunc)AccFree);
  362. ACL EmptyAcl;
  363. // CSList AceList((FreeFunc)DebugFree);
  364. //
  365. // Check for the case where we're setting a NULL acl. If it's a NULL SACL, turn
  366. // it into an empty one.
  367. //
  368. if(pAcl == NULL && FLAG_ON(SeInfo,SACL_SECURITY_INFORMATION))
  369. {
  370. EmptyAcl.AclRevision = ACL_REVISION;
  371. EmptyAcl.Sbz1 = 0;
  372. EmptyAcl.AclSize = sizeof( ACL );
  373. EmptyAcl.AceCount = 0;
  374. EmptyAcl.Sbz2 = 0;
  375. pAcl = &EmptyAcl;
  376. }
  377. if(pAcl == NULL)
  378. {
  379. //
  380. // Ok, find the node for this property
  381. //
  382. PACCLIST_NODE pAccNode;
  383. dwErr = GetNodeForProperty(_AccList,
  384. pwszProperty,
  385. &pAccNode);
  386. if(dwErr == ERROR_SUCCESS)
  387. {
  388. //
  389. // We'll fill in the information now
  390. //
  391. pAccNode->SeInfo |= SeInfo;
  392. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  393. {
  394. pAccNode->pAccessList = NULL;
  395. if(fProtected)
  396. {
  397. pAccNode->fState |= ACCLIST_DACL_PROTECTED;
  398. }
  399. }
  400. else
  401. {
  402. pAccNode->pAuditList = NULL;
  403. if(fProtected)
  404. {
  405. pAccNode->fState |= ACCLIST_SACL_PROTECTED;
  406. }
  407. }
  408. }
  409. }
  410. else
  411. {
  412. //
  413. // Ok, we've got a valid acl list, so we'll process it...
  414. //
  415. //
  416. // Basically, we'll save off our flags...
  417. //
  418. SeInfo == DACL_SECURITY_INFORMATION ?
  419. _fDAclFlags = pAcl->Sbz1 :
  420. _fSAclFlags = pAcl->Sbz1;
  421. ULONG rgInheritFlags[] = {0,
  422. INHERITED_PARENT,
  423. INHERITED_GRANDPARENT};
  424. //
  425. // We need to keep track of the changes in denied/allowed pairs,
  426. // so that we can determine between the inherited and parent
  427. // inherited aces are, so that we can mark our new entries
  428. //
  429. ULONG iIFIndex = 0;
  430. ULONG PrevIn = 0;
  431. BOOL fPrevAllowed = FALSE;
  432. //
  433. // Ok, now we'll simply process each of the entries in the list
  434. //
  435. PACE_HEADER pAceHeader = (PACE_HEADER)FirstAce(pAcl);
  436. for(ULONG iAce = 0;
  437. iAce < pAcl->AceCount && dwErr == ERROR_SUCCESS;
  438. iAce++, pAceHeader = (PACE_HEADER)NextAce(pAceHeader))
  439. {
  440. BOOL fThisAllowed = FALSE;
  441. BOOL fIsExtendedAce = FALSE;
  442. GUID PropID;
  443. GUID *pPropID = NULL;
  444. //
  445. // Ok, now lets try to figure out what type of ACE this is, so we can
  446. // do the neccessary mapping into the provider rights
  447. //
  448. switch(pAceHeader->AceType)
  449. {
  450. case ACCESS_ALLOWED_ACE_TYPE:
  451. fThisAllowed = TRUE;
  452. break;
  453. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  454. fThisAllowed = TRUE;
  455. fIsExtendedAce = TRUE;
  456. break;
  457. //
  458. // Currently unsupported
  459. //
  460. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  461. dwErr = ERROR_INVALID_ACL;
  462. break;
  463. case ACCESS_DENIED_ACE_TYPE:
  464. break;
  465. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  466. fIsExtendedAce = TRUE;
  467. break;
  468. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  469. fIsExtendedAce = TRUE;
  470. fThisAllowed = TRUE;
  471. break;
  472. case SYSTEM_AUDIT_ACE_TYPE:
  473. fThisAllowed = TRUE;
  474. break;
  475. default:
  476. dwErr = ERROR_INVALID_ACL;
  477. break;
  478. }
  479. LPGUID pProp = NULL;
  480. if(dwErr == ERROR_SUCCESS)
  481. {
  482. if(fIsExtendedAce == TRUE)
  483. {
  484. PACCESS_ALLOWED_OBJECT_ACE pExAce =
  485. (PACCESS_ALLOWED_OBJECT_ACE)pAceHeader;
  486. if(FLAG_ON(pExAce->Flags,ACE_OBJECT_TYPE_PRESENT))
  487. {
  488. pProp = RtlObjectAceObjectType(pAceHeader);
  489. }
  490. }
  491. //
  492. // Pull what we can from the ace header
  493. //
  494. if((fThisAllowed == FALSE && fPrevAllowed == TRUE) ||
  495. (FLAG_ON(pAceHeader->AceFlags,INHERITED_ACE) &&
  496. PrevIn == 0))
  497. {
  498. iIFIndex++;
  499. ASSERT(iIFIndex < sizeof(rgInheritFlags) / sizeof(ULONG));
  500. if(iIFIndex >= sizeof(rgInheritFlags) / sizeof(ULONG))
  501. {
  502. dwErr = ERROR_INVALID_ACL;
  503. }
  504. PrevIn = pAceHeader->AceFlags;
  505. }
  506. else
  507. {
  508. PrevIn = pAceHeader->AceFlags;
  509. }
  510. dwErr = InsertAtoANode(AceList,
  511. pProp,
  512. pAceHeader,
  513. rgInheritFlags[iIFIndex]);
  514. }
  515. }
  516. }
  517. //
  518. // Ok, now we'll turn it into PACTRL_ACCESS structure, and call our
  519. // add access routine
  520. //
  521. if(dwErr == ERROR_SUCCESS)
  522. {
  523. ACTRL_ACCESS Access;
  524. Access.cEntries = 0;
  525. PACTRL_PROPERTY_ENTRY pAPE = (PACTRL_PROPERTY_ENTRY)
  526. AccAlloc(max( AceList.QueryCount(), 1 ) * sizeof(ACTRL_PROPERTY_ENTRY));
  527. if(pAPE == NULL)
  528. {
  529. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  530. }
  531. else
  532. {
  533. Access.cEntries = AceList.QueryCount();
  534. Access.pPropertyAccessList = pAPE;
  535. //
  536. // Now, start filling them in...
  537. //
  538. AceList.Reset();
  539. for(ULONG i = 0; i < Access.cEntries; i++)
  540. {
  541. if(fProtected)
  542. {
  543. pAPE[i].fListFlags = ACTRL_ACCESS_PROTECTED;
  544. }
  545. PACCLIST_ATOACCESS pAToA = (PACCLIST_ATOACCESS)AceList.NextData();
  546. if(pAToA->pGuid != NULL)
  547. {
  548. dwErr = AccctrlLookupIdName(_pLDAP,
  549. _pwszDsPathReference,
  550. pAToA->pGuid,
  551. TRUE,
  552. FALSE, // avoid object GUIDs
  553. (PWSTR *)&pAPE[i].lpProperty);
  554. }
  555. if(dwErr == ERROR_SUCCESS)
  556. {
  557. pAPE[i].pAccessEntryList = (PACTRL_ACCESS_ENTRY_LIST)
  558. AccAlloc(sizeof(ACTRL_ACCESS_ENTRY_LIST));
  559. if(pAPE[i].pAccessEntryList == NULL)
  560. {
  561. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  562. }
  563. }
  564. if(dwErr == ERROR_SUCCESS)
  565. {
  566. pAPE[i].pAccessEntryList->cEntries =
  567. pAToA->AceList.QueryCount();
  568. pAPE[i].pAccessEntryList->pAccessList =
  569. (PACTRL_ACCESS_ENTRY)AccAlloc(
  570. pAPE[i].pAccessEntryList->cEntries *
  571. sizeof(ACTRL_ACCESS_ENTRY));
  572. if(pAPE[i].pAccessEntryList->pAccessList == NULL)
  573. {
  574. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  575. }
  576. else
  577. {
  578. PACTRL_ACCESS_ENTRY pAEL =
  579. pAPE[i].pAccessEntryList->pAccessList;
  580. pAToA->AceList.Reset();
  581. for(ULONG j = 0;
  582. j < pAPE[i].pAccessEntryList->cEntries &&
  583. dwErr == ERROR_SUCCESS;
  584. j++)
  585. {
  586. PACCLIST_ATOANODE pNode = (PACCLIST_ATOANODE)
  587. pAToA->AceList.NextData();
  588. dwErr = AceToAccessEntry(pNode->pAce,
  589. pNode->fInherit,
  590. _ObjType,
  591. _KernelObjectType,
  592. &(pAEL[j]));
  593. }
  594. }
  595. }
  596. }
  597. //
  598. // Handle the empty case...
  599. //
  600. if ( Access.cEntries == 0 && pAcl != NULL ) {
  601. Access.cEntries = 1;
  602. pAPE->pAccessEntryList = (PACTRL_ACCESS_ENTRY_LIST)
  603. AccAlloc(sizeof(ACTRL_ACCESS_ENTRY_LIST));
  604. if(pAPE->pAccessEntryList == NULL)
  605. {
  606. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  607. }
  608. else
  609. {
  610. pAPE->pAccessEntryList->cEntries = 0;
  611. pAPE->pAccessEntryList->pAccessList = NULL;
  612. if(fProtected)
  613. {
  614. pAPE->fListFlags = ACTRL_ACCESS_PROTECTED;
  615. }
  616. }
  617. }
  618. //
  619. // If all of that worked, add it...
  620. //
  621. if(dwErr == ERROR_SUCCESS)
  622. {
  623. dwErr = AddAccessLists(SeInfo,
  624. &Access,
  625. TRUE);
  626. }
  627. //
  628. // Regardless of success or failure, delete all memory
  629. //
  630. for(i = 0; i < Access.cEntries; i++)
  631. {
  632. AccFree((PWSTR *)Access.pPropertyAccessList[i].lpProperty);
  633. if(Access.pPropertyAccessList[i].pAccessEntryList != NULL)
  634. {
  635. for(ULONG j = 0;
  636. j < Access.pPropertyAccessList[i].
  637. pAccessEntryList->cEntries;
  638. j++)
  639. {
  640. if(Access.pPropertyAccessList[i].pAccessEntryList->pAccessList != NULL )
  641. {
  642. AccFree(Access.pPropertyAccessList[i].
  643. pAccessEntryList->pAccessList[j].lpInheritProperty);
  644. }
  645. }
  646. AccFree(Access.pPropertyAccessList[i].
  647. pAccessEntryList->pAccessList);
  648. AccFree(Access.pPropertyAccessList[i].pAccessEntryList);
  649. }
  650. }
  651. AccFree(Access.pPropertyAccessList);
  652. }
  653. }
  654. acDebugOut((DEB_TRACE_ACC,
  655. "Out CAccessList::ConvertAclToAccess: %lu\n",
  656. dwErr));
  657. return(dwErr);
  658. }
  659. //+---------------------------------------------------------------------------
  660. //
  661. // Member: CAccessList::MarshalAccessList, private
  662. //
  663. // Synopsis: Marshals the information specified by SeInfo into a single
  664. // buffer
  665. //
  666. // Arguments: [IN SeInfo] -- Type of info to marshal
  667. // [OUT ppAList] -- Where the information is
  668. // returned
  669. //
  670. // Returns: ERROR_SUCCESS -- Success
  671. // ERRROR_NOT_ENOUGH_MEMORY-- A memory allocation failed
  672. //
  673. // Notes: Memory is allocated as a block via a AccAlloc call and
  674. // should be freed with a AccFree call
  675. //
  676. // SeInfo can only contain a SINGLE information value
  677. //
  678. //----------------------------------------------------------------------------
  679. DWORD CAccessList::MarshalAccessList(IN SECURITY_INFORMATION SeInfo,
  680. OUT PACTRL_ACCESSW *ppAList)
  681. {
  682. acDebugOut((DEB_TRACE_ACC,"In qCAccessList::MarshalAccessList\n"));
  683. DWORD dwErr = ERROR_SUCCESS;
  684. PACCLIST_CNODE pCNode = NULL;
  685. ULONG cItems = 0;
  686. ASSERT( SeInfo == DACL_SECURITY_INFORMATION || SeInfo == SACL_SECURITY_INFORMATION );
  687. //
  688. // First, compress the list...
  689. //
  690. dwErr = CompressList(SeInfo,
  691. &pCNode,
  692. &cItems);
  693. //
  694. // Then, we need to get the size of the memory block we need to allocate
  695. //
  696. DWORD cSize = 0;
  697. DWORD cAEs = 0;
  698. PBYTE pbEndOBuff = NULL;
  699. ULONG cUsed = 0;
  700. ULONG i = 0;
  701. CSList TrusteesToMarshal(NULL);
  702. CSList InheritPropsToMarshal((FreeFunc)LocalFree);
  703. // CSList InheritPropsToMarshal((FreeFunc)DebugFree);
  704. for(i = 0; i < cItems && dwErr == ERROR_SUCCESS; i++)
  705. {
  706. //
  707. // Get the list we need
  708. //
  709. ULONG cEnts = pCNode[i].cExp + pCNode[i].cL1Inherit +
  710. pCNode[i].cL2Inherit;
  711. if(pCNode[i].pList != NULL)
  712. {
  713. cUsed++;
  714. cSize += sizeof(ACTRL_ACCESS_ENTRY) * cEnts;
  715. if ((SeInfo == DACL_SECURITY_INFORMATION ?
  716. pCNode[ i ].pONode->pAccessList->pAccessList : pCNode[ i ].pONode->pAuditList->pAccessList) == NULL )
  717. {
  718. pCNode[i].Empty = TRUE;
  719. }
  720. //
  721. // Finally, go through and figure out what trustees we'll need to
  722. // marshal
  723. //
  724. for(ULONG iIndex = 0;
  725. iIndex < cEnts && dwErr == ERROR_SUCCESS && pCNode[i].Empty == FALSE;
  726. iIndex++)
  727. {
  728. dwErr = TrusteesToMarshal.InsertIfUnique(
  729. &(pCNode[i].pList[iIndex].Trustee),
  730. CompTrustees);
  731. if(dwErr == ERROR_SUCCESS &&
  732. pCNode[i].pList[iIndex].Trustee.MultipleTrusteeOperation ==
  733. TRUSTEE_IS_IMPERSONATE)
  734. {
  735. dwErr = TrusteesToMarshal.InsertIfUnique(
  736. pCNode[i].pList[iIndex].Trustee.pMultipleTrustee,
  737. CompTrustees);
  738. }
  739. //
  740. // Now, see if we have any inheritable properties to add
  741. //
  742. if(dwErr == ERROR_SUCCESS)
  743. {
  744. if(pCNode[i].pList[iIndex].lpInheritProperty != NULL &&
  745. InheritPropsToMarshal.Find(
  746. (PVOID)pCNode[i].pList[iIndex].lpInheritProperty,
  747. CompInheritProps) == NULL)
  748. {
  749. PIPROP_IN_BUFF pPIB =
  750. (PIPROP_IN_BUFF)AccAlloc(sizeof(IPROP_IN_BUFF));
  751. if(pPIB == NULL)
  752. {
  753. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  754. }
  755. else
  756. {
  757. pPIB->pwszIProp = (LPWSTR)
  758. pCNode[i].pList[iIndex].lpInheritProperty;
  759. dwErr = InheritPropsToMarshal.Insert((PVOID)pPIB);
  760. if(dwErr != ERROR_SUCCESS)
  761. {
  762. AccFree(pPIB);
  763. }
  764. else
  765. {
  766. cSize +=
  767. SIZE_PWSTR(pCNode[i].pList[iIndex].
  768. lpInheritProperty);
  769. }
  770. }
  771. }
  772. }
  773. }
  774. }
  775. else
  776. {
  777. cUsed++;
  778. }
  779. //
  780. // Also, add in the property size
  781. //
  782. cSize += SIZE_PWSTR(pCNode[i].pONode->pwszProperty);
  783. }
  784. if(dwErr == ERROR_SUCCESS)
  785. {
  786. TrusteesToMarshal.Reset();
  787. PTRUSTEE pTrustee = (PTRUSTEE)TrusteesToMarshal.NextData();
  788. while(pTrustee != NULL)
  789. {
  790. if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
  791. {
  792. cSize += SIZE_PWSTR(pTrustee->ptstrName);
  793. }
  794. else
  795. {
  796. PTRUSTEE_NODE pTN = NULL;
  797. dwErr = GetTrusteeNode(pTrustee,
  798. TRUSTEE_OPT_NOTHING,
  799. &pTN);
  800. cSize += SIZE_PWSTR(pTN->pwszTrusteeName);
  801. }
  802. if(pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
  803. {
  804. cSize += sizeof(TRUSTEE);
  805. }
  806. pTrustee = (PTRUSTEE)TrusteesToMarshal.NextData();
  807. }
  808. }
  809. if(dwErr == ERROR_SUCCESS)
  810. {
  811. //
  812. // Now, all that we have is the size of the entries and the strings.
  813. // We now need to add the size of our structures...
  814. //
  815. cSize += sizeof(PACTRL_ACCESSW) +
  816. (cUsed * sizeof(ACTRL_PROPERTY_ENTRY)) +
  817. (cUsed * sizeof(ACTRL_ACCESS_ENTRY)) +
  818. sizeof(ACTRL_ACCESS_ENTRY_LIST);
  819. acDebugOut((DEB_TRACE_ACC, "Total size needed: %lu\n", cSize));
  820. //
  821. // Now, we'll allocate it, and start filling it in
  822. //
  823. *ppAList = (PACTRL_ACCESSW)AccAlloc(cSize);
  824. if(*ppAList == NULL)
  825. {
  826. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  827. }
  828. else
  829. {
  830. //
  831. // Now, we'll have to through first and add the property and
  832. // names to the end of the block. We need to do this before
  833. // adding the individual entries, so that as we go through and
  834. // add each access entry, we can point the trustee to the
  835. // proper place
  836. //
  837. pbEndOBuff = (PBYTE)*ppAList + cSize;
  838. //
  839. // First, process all of the property names
  840. //
  841. for(i = 0; i < cItems; i++)
  842. {
  843. //
  844. // If we don't have a property name, set it to NULL
  845. //
  846. if(pCNode[i].pONode->pwszProperty == NULL)
  847. {
  848. pCNode[i].pONode->pwszPropInBuff = NULL;
  849. }
  850. else
  851. {
  852. ULONG cLen = SIZE_PWSTR(pCNode[i].pONode->pwszProperty);
  853. pbEndOBuff -= cLen;
  854. memcpy(pbEndOBuff,
  855. pCNode[i].pONode->pwszProperty,
  856. cLen);
  857. pCNode[i].pONode->pwszPropInBuff = (PWSTR)pbEndOBuff;
  858. }
  859. }
  860. if(dwErr == ERROR_SUCCESS)
  861. {
  862. TrusteesToMarshal.Reset();
  863. PTRUSTEE pTrustee = (PTRUSTEE)TrusteesToMarshal.NextData();
  864. while(pTrustee != NULL)
  865. {
  866. PTRUSTEE_NODE pTN = NULL;
  867. dwErr = GetTrusteeNode(pTrustee,
  868. TRUSTEE_OPT_NOTHING,
  869. &pTN);
  870. ULONG cLen = SIZE_PWSTR(pTN->pwszTrusteeName);
  871. pbEndOBuff -= cLen;
  872. memcpy(pbEndOBuff,
  873. pTN->pwszTrusteeName,
  874. cLen);
  875. pTN->pwszTrusteeInBuff = (PWSTR)pbEndOBuff;
  876. pTrustee = (PTRUSTEE)TrusteesToMarshal.NextData();
  877. }
  878. }
  879. if(dwErr == ERROR_SUCCESS)
  880. {
  881. InheritPropsToMarshal.Reset();
  882. PIPROP_IN_BUFF pPIB =
  883. (PIPROP_IN_BUFF)InheritPropsToMarshal.NextData();
  884. while(pPIB != NULL)
  885. {
  886. ULONG cLen = SIZE_PWSTR(pPIB->pwszIProp);
  887. pbEndOBuff -= cLen;
  888. memcpy(pbEndOBuff,
  889. pPIB->pwszIProp,
  890. cLen);
  891. pPIB->pwszIPropInBuff = (PWSTR)pbEndOBuff;
  892. pPIB = (PIPROP_IN_BUFF)InheritPropsToMarshal.NextData();
  893. }
  894. }
  895. //
  896. // Ok, now we'll start processing everything else... This
  897. // begins by setting our count
  898. //
  899. (*ppAList)->cEntries = cUsed;
  900. PBYTE pCurrBuff = (PBYTE)*ppAList + sizeof(ACTRL_PROPERTY_ENTRY);;
  901. if((*ppAList)->cEntries != 0)
  902. {
  903. (*ppAList)->pPropertyAccessList =
  904. (PACTRL_PROPERTY_ENTRYW)pCurrBuff;
  905. pCurrBuff += (*ppAList)->cEntries * sizeof(ACTRL_PROPERTY_ENTRY);
  906. }
  907. else
  908. {
  909. (*ppAList)->pPropertyAccessList = NULL;
  910. }
  911. //
  912. // Go through and set our property entry list correctly
  913. //
  914. ULONG iProp = 0; // Property list index
  915. for(i = 0; i < cItems && cUsed != 0; i++)
  916. {
  917. BOOL fNullAcl = FALSE;
  918. if(FLAG_ON(SeInfo,DACL_SECURITY_INFORMATION))
  919. {
  920. if(FLAG_ON(pCNode[i].pONode->fState, ACCLIST_DACL_PROTECTED) ||
  921. FLAG_ON(_fDAclFlags, ACCLIST_DACL_PROTECTED) )
  922. {
  923. (*ppAList)->pPropertyAccessList[iProp].fListFlags =
  924. ACTRL_ACCESS_PROTECTED;
  925. }
  926. }
  927. if(FLAG_ON(SeInfo,SACL_SECURITY_INFORMATION))
  928. {
  929. if(FLAG_ON(pCNode[i].pONode->fState, ACCLIST_SACL_PROTECTED) ||
  930. FLAG_ON(_fSAclFlags, ACCLIST_SACL_PROTECTED) )
  931. {
  932. (*ppAList)->pPropertyAccessList[iProp].fListFlags =
  933. ACTRL_ACCESS_PROTECTED;
  934. }
  935. }
  936. if(pCNode[i].pList == NULL)
  937. {
  938. fNullAcl = TRUE;
  939. }
  940. //
  941. // Set our prop pointer
  942. //
  943. (*ppAList)->pPropertyAccessList[iProp].lpProperty =
  944. pCNode[i].pONode->pwszPropInBuff;
  945. if(fNullAcl == TRUE)
  946. {
  947. (*ppAList)->pPropertyAccessList[iProp].pAccessEntryList = NULL;
  948. }
  949. else
  950. {
  951. (*ppAList)->pPropertyAccessList[iProp].pAccessEntryList =
  952. (PACTRL_ACCESS_ENTRY_LIST)pCurrBuff;
  953. if(pCNode[i].pList != NULL)
  954. {
  955. pCurrBuff +=
  956. (sizeof(ACTRL_ACCESS_ENTRY_LIST));
  957. }
  958. }
  959. iProp++;
  960. }
  961. //
  962. // Ok, now we'll actually go through and build the individual
  963. // lists
  964. //
  965. iProp = 0;
  966. if((*ppAList)->pPropertyAccessList != NULL)
  967. {
  968. pCurrBuff =
  969. (PBYTE)(*ppAList)->pPropertyAccessList[iProp].pAccessEntryList;
  970. pCurrBuff +=
  971. (cUsed * sizeof(ACTRL_ACCESS_ENTRY_LIST));
  972. }
  973. for(i = 0; i < cItems && dwErr == ERROR_SUCCESS; i++)
  974. {
  975. //
  976. // Get the list we need
  977. //
  978. if(pCNode[i].pList != NULL &&
  979. (*ppAList)->pPropertyAccessList[iProp].pAccessEntryList != NULL)
  980. {
  981. PACTRL_ACCESS_ENTRY_LIST pAEL =
  982. (*ppAList)->pPropertyAccessList[iProp].pAccessEntryList;
  983. pAEL->cEntries = pCNode[i].cExp + pCNode[i].cL1Inherit +
  984. pCNode[i].cL2Inherit;
  985. if( !pCNode[i].Empty )
  986. {
  987. pAEL->pAccessList = (PACTRL_ACCESS_ENTRY)pCurrBuff;
  988. pCurrBuff += (sizeof(ACTRL_ACCESS_ENTRY) * pAEL->cEntries);
  989. }
  990. else
  991. {
  992. pAEL->pAccessList = NULL;
  993. pAEL->cEntries = 0;
  994. }
  995. //
  996. // Copy the node and adjust our trustee
  997. //
  998. for(ULONG iIndex = 0; iIndex < pAEL->cEntries && !pCNode[i].Empty; iIndex++)
  999. {
  1000. //
  1001. // Make sure we strip any of our internal flags info
  1002. //
  1003. pAEL->pAccessList[iIndex].fAccessFlags =
  1004. pCNode[i].pList[iIndex].fAccessFlags &
  1005. ~ACCLIST_VALID_TYPE_FLAGS;
  1006. pAEL->pAccessList[iIndex].Access =
  1007. pCNode[i].pList[iIndex].Access;
  1008. pAEL->pAccessList[iIndex].ProvSpecificAccess =
  1009. pCNode[i].pList[iIndex].ProvSpecificAccess;
  1010. pAEL->pAccessList[iIndex].Inheritance =
  1011. pCNode[i].pList[iIndex].Inheritance;
  1012. if(pCNode[i].pList[iIndex].lpInheritProperty != NULL)
  1013. {
  1014. PIPROP_IN_BUFF pPIB =
  1015. (PIPROP_IN_BUFF)InheritPropsToMarshal.Find(
  1016. (PVOID)pCNode[i].pList[iIndex].
  1017. lpInheritProperty,
  1018. CompInheritProps);
  1019. ASSERT(pPIB != NULL);
  1020. pAEL->pAccessList[iIndex].lpInheritProperty =
  1021. pPIB->pwszIPropInBuff;
  1022. }
  1023. //
  1024. // Now, we only have to adjust our trustee
  1025. //
  1026. PTRUSTEE pTrustee = &(pCNode[i].pList[iIndex].Trustee);
  1027. PTRUSTEE_NODE pTN = NULL;
  1028. dwErr = GetTrusteeNode(pTrustee,
  1029. TRUSTEE_OPT_NOTHING,
  1030. &pTN);
  1031. if(dwErr == ERROR_SUCCESS)
  1032. {
  1033. //
  1034. // We'll add the trustee now...
  1035. //
  1036. pAEL->pAccessList[iIndex].Trustee.pMultipleTrustee =
  1037. NULL;
  1038. pAEL->pAccessList[iIndex].Trustee.MultipleTrusteeOperation =
  1039. NO_MULTIPLE_TRUSTEE;
  1040. pAEL->pAccessList[iIndex].Trustee.TrusteeForm =
  1041. TRUSTEE_IS_NAME;
  1042. pAEL->pAccessList[iIndex].Trustee.TrusteeType =
  1043. pTN->Trustee.TrusteeType;
  1044. pAEL->pAccessList[iIndex].Trustee.ptstrName =
  1045. pTN->pwszTrusteeInBuff;
  1046. if(pTN->pImpersonate != NULL)
  1047. {
  1048. //
  1049. // Ok, 2 things to do: adjust our current trustee
  1050. // state and add the new one
  1051. //
  1052. pAEL->pAccessList[iIndex].Trustee.
  1053. MultipleTrusteeOperation =
  1054. TRUSTEE_IS_IMPERSONATE;
  1055. pTrustee = pAEL->pAccessList[iIndex].Trustee.
  1056. pMultipleTrustee;
  1057. pbEndOBuff -= sizeof(TRUSTEE);
  1058. pTrustee = (PTRUSTEE)pbEndOBuff;
  1059. pTrustee->MultipleTrusteeOperation =
  1060. NO_MULTIPLE_TRUSTEE;
  1061. pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
  1062. pTrustee->TrusteeType = TRUSTEE_IS_USER;
  1063. pTrustee->ptstrName =
  1064. pTN->pImpersonate->pwszTrusteeInBuff;
  1065. }
  1066. }
  1067. else
  1068. {
  1069. break;
  1070. }
  1071. }
  1072. iProp++;
  1073. }
  1074. }
  1075. //
  1076. // Free our memory if something failed
  1077. //
  1078. if(dwErr != ERROR_SUCCESS)
  1079. {
  1080. AccFree(*ppAList);
  1081. *ppAList = NULL;
  1082. }
  1083. }
  1084. }
  1085. FreeCompressedList(pCNode,
  1086. cItems);
  1087. acDebugOut((DEB_TRACE_ACC,
  1088. "Out CAccessList::MarshalAccessList: %lu\n", dwErr));
  1089. return(dwErr);
  1090. }
  1091. //+---------------------------------------------------------------------------
  1092. //
  1093. // Member: CAccessList::MarshalAccessLists, public
  1094. //
  1095. // Synopsis: Returns the requested lists in single buffer form. Each
  1096. // access or audit list is returned seperately.
  1097. //
  1098. // Arguments: [IN SeInfo] -- Type of info requested
  1099. // [OUT ppAccess] -- Where the ACCESS list is
  1100. // returned if requested
  1101. // [OUT ppAudit] -- Where the AUDIT list is
  1102. // returned if requested
  1103. //
  1104. // Returns: ERROR_SUCCESS -- Success
  1105. //
  1106. // Notes:
  1107. //
  1108. //----------------------------------------------------------------------------
  1109. DWORD CAccessList::MarshalAccessLists(IN SECURITY_INFORMATION SeInfo,
  1110. OUT PACTRL_ACCESS *ppAccess,
  1111. OUT PACTRL_AUDIT *ppAudit)
  1112. {
  1113. acDebugOut((DEB_TRACE_ACC,"In CAccessList::MarshalAccessLists\n"));
  1114. DWORD dwErr = ERROR_SUCCESS;
  1115. if(FLAG_ON(SeInfo,DACL_SECURITY_INFORMATION))
  1116. {
  1117. dwErr = MarshalAccessList(DACL_SECURITY_INFORMATION,
  1118. ppAccess);
  1119. }
  1120. if(dwErr == ERROR_SUCCESS &&
  1121. FLAG_ON(SeInfo,SACL_SECURITY_INFORMATION))
  1122. {
  1123. dwErr = MarshalAccessList(SACL_SECURITY_INFORMATION,
  1124. ppAudit);
  1125. //
  1126. // If it failed and we allocated our Access list, make sure to free it
  1127. //
  1128. if(dwErr != ERROR_SUCCESS &&
  1129. FLAG_ON(SeInfo,DACL_SECURITY_INFORMATION))
  1130. {
  1131. AccFree(*ppAccess);
  1132. }
  1133. }
  1134. acDebugOut((DEB_TRACE_ACC,
  1135. "Out CAccessList::MarshalAccessLists: %lu\n", dwErr));
  1136. return(dwErr);
  1137. }
  1138. //+---------------------------------------------------------------------------
  1139. //
  1140. // Member: CAccessList::GetTrusteeNode, private
  1141. //
  1142. // Synopsis: Returns a pointer to a TRUSTEE_NODE for the given
  1143. // trustee. The flags indicate what information about the
  1144. // trustee needs to be present in the node. If the trustee
  1145. // does not already exist in the list, it will be added
  1146. //
  1147. // Arguments: [IN pTrustee] -- Trustee to find
  1148. // [IN fNodeOptions] -- Information that needs to be
  1149. // present in the node
  1150. // [OUT ppTrusteeNode] -- Where the node pointer is returned
  1151. //
  1152. // Returns: ERROR_SUCCESS -- Success
  1153. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  1154. //
  1155. // Notes:
  1156. //
  1157. //----------------------------------------------------------------------------
  1158. DWORD CAccessList::GetTrusteeNode(IN PTRUSTEE pTrustee,
  1159. IN ULONG fNodeOptions,
  1160. OUT PTRUSTEE_NODE *ppTrusteeNode)
  1161. {
  1162. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GetTrusteeNode\n"));
  1163. DWORD dwErr = ERROR_SUCCESS;
  1164. //
  1165. // If we're doing an insert, we'll always want to create the name
  1166. //
  1167. if(FLAG_ON(fNodeOptions, TRUSTEE_OPT_INSERT_ONLY))
  1168. {
  1169. fNodeOptions |= TRUSTEE_OPT_NAME;
  1170. }
  1171. //
  1172. // First, see if it exists in our list...
  1173. //
  1174. PTRUSTEE_NODE pTrusteeNode =
  1175. (PTRUSTEE_NODE)_TrusteeList.Find((PVOID)pTrustee,
  1176. CompTrusteeToTrusteeNode);
  1177. if(pTrusteeNode == NULL)
  1178. {
  1179. //
  1180. // Ok, we'll have to create one...
  1181. //
  1182. pTrusteeNode = (PTRUSTEE_NODE)AccAlloc(sizeof(TRUSTEE_NODE));
  1183. if(pTrusteeNode == NULL)
  1184. {
  1185. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1186. }
  1187. else
  1188. {
  1189. memcpy(&(pTrusteeNode->Trustee),
  1190. pTrustee,
  1191. sizeof(TRUSTEE));
  1192. pTrusteeNode->SidType = SidTypeUnknown;
  1193. //
  1194. // Copy off whatever information we need
  1195. //
  1196. if(dwErr == ERROR_SUCCESS)
  1197. {
  1198. if(pTrustee->TrusteeForm == TRUSTEE_IS_SID)
  1199. {
  1200. if(RtlValidSid((PSID)pTrustee->ptstrName))
  1201. {
  1202. DWORD cSidSize =
  1203. RtlLengthSid((PSID)pTrustee->ptstrName);
  1204. pTrusteeNode->pSid = (PSID)AccAlloc(cSidSize);
  1205. if(pTrusteeNode->pSid == NULL)
  1206. {
  1207. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1208. }
  1209. else
  1210. {
  1211. memcpy(pTrusteeNode->pSid,
  1212. (PSID)pTrustee->ptstrName,
  1213. cSidSize);
  1214. pTrusteeNode->Trustee.ptstrName =
  1215. (PWSTR)pTrusteeNode->pSid;
  1216. pTrusteeNode->fFlags |= TRUSTEE_DELETE_SID;
  1217. }
  1218. }
  1219. else
  1220. {
  1221. dwErr = ERROR_INVALID_SID;
  1222. }
  1223. }
  1224. else
  1225. {
  1226. pTrusteeNode->pwszTrusteeName =
  1227. (PWSTR)AccAlloc(SIZE_PWSTR(pTrustee->ptstrName));
  1228. if(pTrusteeNode->pwszTrusteeName == NULL)
  1229. {
  1230. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1231. }
  1232. else
  1233. {
  1234. wcscpy(pTrusteeNode->pwszTrusteeName,
  1235. pTrustee->ptstrName);
  1236. pTrusteeNode->Trustee.ptstrName =
  1237. pTrusteeNode->pwszTrusteeName;
  1238. pTrusteeNode->fFlags |= TRUSTEE_DELETE_NAME;
  1239. }
  1240. }
  1241. }
  1242. //
  1243. // See if we need to insert an impersonate node as well
  1244. //
  1245. if(dwErr == ERROR_SUCCESS)
  1246. {
  1247. if(pTrustee->MultipleTrusteeOperation ==
  1248. TRUSTEE_IS_IMPERSONATE)
  1249. {
  1250. if(pTrustee->pMultipleTrustee == NULL)
  1251. {
  1252. dwErr = ERROR_INVALID_PARAMETER;
  1253. }
  1254. else
  1255. {
  1256. PTRUSTEE_NODE pImpersonate;
  1257. dwErr = GetTrusteeNode(pTrustee->pMultipleTrustee,
  1258. fNodeOptions,
  1259. &pImpersonate);
  1260. if(dwErr == ERROR_SUCCESS)
  1261. {
  1262. pTrusteeNode->pImpersonate = pImpersonate;
  1263. }
  1264. }
  1265. }
  1266. }
  1267. //
  1268. // Finally, insert it in the list
  1269. //
  1270. if(dwErr == ERROR_SUCCESS)
  1271. {
  1272. dwErr = _TrusteeList.Insert((PVOID)pTrusteeNode);
  1273. }
  1274. //
  1275. // If something went wrong, cleanup
  1276. //
  1277. if(dwErr != ERROR_SUCCESS)
  1278. {
  1279. DelTrusteeNode(pTrusteeNode);
  1280. }
  1281. }
  1282. }
  1283. //
  1284. // Increment our use count if we were inserting
  1285. //
  1286. if(dwErr == ERROR_SUCCESS &&
  1287. FLAG_ON(fNodeOptions, TRUSTEE_OPT_INSERT_ONLY))
  1288. {
  1289. pTrusteeNode->cUseCount++;
  1290. }
  1291. //
  1292. // Now, if that worked, we'll need to make sure we have all the info
  1293. // we need...
  1294. //
  1295. if(dwErr == ERROR_SUCCESS)
  1296. {
  1297. //
  1298. // Now, if we don't have our sid type, we'll go ahead and determine it
  1299. //
  1300. if(pTrusteeNode->SidType == SidTypeUnknown)
  1301. {
  1302. //
  1303. // We'll do this by turning on the appropriate flag
  1304. //
  1305. if(pTrusteeNode->Trustee.TrusteeForm == TRUSTEE_IS_SID)
  1306. {
  1307. fNodeOptions |= TRUSTEE_OPT_NAME;
  1308. }
  1309. else
  1310. {
  1311. fNodeOptions |= TRUSTEE_OPT_SID;
  1312. }
  1313. }
  1314. dwErr = LookupTrusteeNodeInformation(_pwszLookupServer,
  1315. pTrusteeNode,
  1316. fNodeOptions);
  1317. //
  1318. // Finally, if that worked, and we have a compound trustee, do the
  1319. // child
  1320. //
  1321. if(dwErr == ERROR_SUCCESS && pTrusteeNode->pImpersonate != NULL)
  1322. {
  1323. dwErr = GetTrusteeNode(&(pTrusteeNode->pImpersonate->Trustee),
  1324. fNodeOptions,
  1325. &(pTrusteeNode->pImpersonate));
  1326. }
  1327. }
  1328. //
  1329. // If it all worked, return the new information
  1330. //
  1331. if(dwErr == ERROR_SUCCESS)
  1332. {
  1333. ASSERT(pTrusteeNode->Trustee.ptstrName == pTrusteeNode->pSid ||
  1334. pTrusteeNode->Trustee.ptstrName == pTrusteeNode->pwszTrusteeName);
  1335. if(ppTrusteeNode != NULL)
  1336. {
  1337. *ppTrusteeNode = pTrusteeNode;
  1338. }
  1339. }
  1340. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::GetTrusteeNode: %lu\n", dwErr));
  1341. return(dwErr);
  1342. }
  1343. //+---------------------------------------------------------------------------
  1344. //
  1345. // Member: CAccessList::AddAccessLists, private
  1346. //
  1347. // Synopsis:
  1348. //
  1349. // Arguments: [IN pTrustee] -- Trustee to find
  1350. // [IN fNodeOptions] -- Information that needs to be
  1351. // present in the node
  1352. // [OUT ppTrusteeNode] -- Where the node pointer is returned
  1353. //
  1354. // Returns: ERROR_SUCCESS -- Success
  1355. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  1356. //
  1357. // Notes:
  1358. //
  1359. //----------------------------------------------------------------------------
  1360. DWORD CAccessList::AddAccessLists(IN SECURITY_INFORMATION SeInfo,
  1361. IN PACTRL_ACCESSW pAdd,
  1362. IN BOOL fMerge,
  1363. IN BOOL fOldStyleMerge)
  1364. {
  1365. DWORD dwErr = ERROR_SUCCESS;
  1366. acDebugOut((DEB_TRACE_ACC,
  1367. "In CAccessList::AddAccessLists (%ws)\n",
  1368. fMerge == TRUE ? L"Merge" : L"NoMerge"));
  1369. //
  1370. // If NULL parameters are given, just return success
  1371. //
  1372. if(SeInfo == 0)
  1373. {
  1374. return(ERROR_SUCCESS);
  1375. }
  1376. //
  1377. // Handle the empty list case
  1378. //
  1379. ACTRL_ACCESSW NullAccess;
  1380. ACTRL_PROPERTY_ENTRY EmptyPropList;
  1381. ACTRL_ACCESS_ENTRY_LIST EmptyAccessList;
  1382. if(pAdd == NULL)
  1383. {
  1384. //
  1385. // We don't allow NULL sacls, only empty ones
  1386. //
  1387. if(FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION))
  1388. {
  1389. NullAccess.cEntries = 1;
  1390. NullAccess.pPropertyAccessList = &EmptyPropList;
  1391. memset(&EmptyPropList,0,sizeof(EmptyPropList));
  1392. EmptyPropList.pAccessEntryList = &EmptyAccessList;
  1393. memset(&EmptyAccessList,0,sizeof(EmptyAccessList));
  1394. }
  1395. else
  1396. {
  1397. NullAccess.cEntries = 0;
  1398. NullAccess.pPropertyAccessList = NULL;
  1399. }
  1400. pAdd = &NullAccess;
  1401. }
  1402. if(pAdd->cEntries != 0 && pAdd->pPropertyAccessList == NULL)
  1403. {
  1404. return(ERROR_INVALID_PARAMETER);
  1405. }
  1406. else
  1407. {
  1408. _fSDValid = FALSE;
  1409. }
  1410. //
  1411. // If we're doing an old style merge, make sure we remove all of the
  1412. // existing entries for these trustees
  1413. //
  1414. if(fOldStyleMerge == TRUE)
  1415. {
  1416. dwErr = RevokeTrusteeAccess(SeInfo,
  1417. pAdd,
  1418. NULL);
  1419. }
  1420. //
  1421. // If we're doing a set, we'll have to go through and remove any entries
  1422. // that would be replaced before we go through and add the new entries
  1423. // This is because our input list can have multiple lists that deal
  1424. // with the same property, so a set applied then has disasterous results
  1425. //
  1426. ULONG iIndex = 0;
  1427. while(fMerge == FALSE && iIndex < pAdd->cEntries)
  1428. {
  1429. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.Find((PVOID)
  1430. (pAdd->cEntries == 0 ?
  1431. NULL :
  1432. pAdd->pPropertyAccessList
  1433. [iIndex].lpProperty),
  1434. CompProps);
  1435. if(pAccNode != NULL)
  1436. {
  1437. if(SeInfo == DACL_SECURITY_INFORMATION)
  1438. {
  1439. FreeAEList(pAccNode->pAccessList);
  1440. pAccNode->pAccessList = NULL;
  1441. pAccNode->fState &= ~ACCLIST_DACL_PROTECTED;
  1442. }
  1443. else
  1444. {
  1445. FreeAEList(pAccNode->pAuditList);
  1446. pAccNode->fState &= ~ACCLIST_SACL_PROTECTED;
  1447. pAccNode->pAuditList = NULL;
  1448. }
  1449. }
  1450. iIndex++;
  1451. }
  1452. //
  1453. // We have to do this in a while loop, so we handle the empty access list
  1454. // properly without having to duplicate a bunch o' code
  1455. //
  1456. iIndex = 0;
  1457. while(dwErr == ERROR_SUCCESS)
  1458. {
  1459. //
  1460. // Ok, first, we need to find the matching property...
  1461. //
  1462. PACCLIST_NODE pAccNode;
  1463. dwErr = GetNodeForProperty(_AccList,
  1464. (PWSTR)(pAdd->cEntries == 0 ?
  1465. NULL :
  1466. pAdd->pPropertyAccessList
  1467. [iIndex].lpProperty),
  1468. &pAccNode);
  1469. if(dwErr != ERROR_SUCCESS)
  1470. {
  1471. break;
  1472. }
  1473. //
  1474. // Otherwise, we'll figure out what we're doing...
  1475. //
  1476. PACTRL_ACCESS_ENTRY_LIST pList =
  1477. SeInfo == DACL_SECURITY_INFORMATION ?
  1478. pAccNode->pAccessList :
  1479. pAccNode->pAuditList;
  1480. pAccNode->SeInfo |= SeInfo;
  1481. if(pAdd->cEntries && FLAG_ON(pAdd->pPropertyAccessList[iIndex].fListFlags, ACTRL_ACCESS_PROTECTED))
  1482. {
  1483. SeInfo == DACL_SECURITY_INFORMATION ?
  1484. _fDAclFlags |= ACCLIST_DACL_PROTECTED :
  1485. _fSAclFlags |= ACCLIST_SACL_PROTECTED;
  1486. }
  1487. //
  1488. // Ok, we can quit now if we have an empty list
  1489. //
  1490. if( pAdd->cEntries == 0 ||
  1491. pAdd->pPropertyAccessList[iIndex].pAccessEntryList == NULL )
  1492. {
  1493. break;
  1494. }
  1495. //
  1496. // Validate that the list is correct
  1497. //
  1498. if(pAdd->cEntries &&
  1499. pAdd->pPropertyAccessList[iIndex].pAccessEntryList->cEntries != 0 &&
  1500. pAdd->pPropertyAccessList[iIndex].pAccessEntryList->pAccessList == NULL)
  1501. {
  1502. dwErr = ERROR_INVALID_PARAMETER;
  1503. break;
  1504. }
  1505. //
  1506. // Save our flags
  1507. //
  1508. SeInfo == DACL_SECURITY_INFORMATION ?
  1509. _fDAclFlags |= pAdd->pPropertyAccessList[iIndex].fListFlags :
  1510. _fSAclFlags |= pAdd->pPropertyAccessList[iIndex].fListFlags;
  1511. //
  1512. // Now, we'll have to generate a new list
  1513. //
  1514. ULONG cSize = 0;
  1515. if(pAdd->pPropertyAccessList[iIndex].pAccessEntryList != NULL)
  1516. {
  1517. cSize += pAdd->pPropertyAccessList[iIndex].pAccessEntryList->cEntries;
  1518. }
  1519. if(pList != NULL)
  1520. {
  1521. cSize += pList->cEntries;
  1522. }
  1523. PACTRL_ACCESS_ENTRY_LIST pNew = (PACTRL_ACCESS_ENTRY_LIST)AccAlloc(
  1524. sizeof(ACTRL_ACCESS_ENTRY_LIST) +
  1525. (cSize * sizeof(ACTRL_ACCESS_ENTRY)));
  1526. if(pNew == NULL)
  1527. {
  1528. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1529. break;
  1530. }
  1531. //
  1532. // Otherwise, we'll add all the new denieds, followed by the old
  1533. // denieds, then the new accesses, followed by the old accesses
  1534. //
  1535. ULONG iNewIndex = 0;
  1536. ULONG cNewCopy = 0;
  1537. ULONG cOldCopy = 0;
  1538. pNew->pAccessList = (PACTRL_ACCESS_ENTRY)((PBYTE)pNew +
  1539. sizeof(ACTRL_ACCESS_ENTRY_LIST));
  1540. if ( pAdd->pPropertyAccessList[iIndex].pAccessEntryList->pAccessList == NULL ) {
  1541. pNew->cEntries = 0;
  1542. pNew->pAccessList = NULL;
  1543. SeInfo == DACL_SECURITY_INFORMATION ?
  1544. pAccNode->pAccessList = pNew :
  1545. pAccNode->pAuditList = pNew;
  1546. break;
  1547. }
  1548. //
  1549. // Count the new denieds
  1550. //
  1551. for(ULONG iCnt = 0;
  1552. pAdd->pPropertyAccessList[iIndex].pAccessEntryList != NULL &&
  1553. iCnt < pAdd->pPropertyAccessList[iIndex].pAccessEntryList->cEntries;
  1554. iCnt++)
  1555. {
  1556. if(FLAG_ON(pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1557. pAccessList[iCnt].fAccessFlags,
  1558. ACTRL_ACCESS_DENIED))
  1559. {
  1560. cNewCopy++;
  1561. }
  1562. else
  1563. {
  1564. break;
  1565. }
  1566. }
  1567. //
  1568. // Now, the old denieds
  1569. //
  1570. if(pList != NULL)
  1571. {
  1572. for(iCnt = 0;
  1573. iCnt < pList->cEntries;
  1574. iCnt++)
  1575. {
  1576. if(FLAG_ON(pList->pAccessList[iCnt].fAccessFlags,
  1577. ACTRL_ACCESS_DENIED))
  1578. {
  1579. cOldCopy++;
  1580. }
  1581. else
  1582. {
  1583. break;
  1584. }
  1585. }
  1586. }
  1587. //
  1588. // Excellent.. Now, a series of copies
  1589. //
  1590. if(cNewCopy != 0)
  1591. {
  1592. for(iCnt = 0; iCnt < cNewCopy && dwErr == ERROR_SUCCESS; iCnt++)
  1593. {
  1594. if(SeInfo == DACL_SECURITY_INFORMATION)
  1595. {
  1596. if(!(FLAG_ON(pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1597. pAccessList[iCnt].fAccessFlags,ACTRL_ACCESS_DENIED) ||
  1598. FLAG_ON(pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1599. pAccessList[iCnt].fAccessFlags,ACTRL_ACCESS_ALLOWED)))
  1600. {
  1601. dwErr = ERROR_INVALID_ACL;
  1602. break;
  1603. }
  1604. }
  1605. else
  1606. {
  1607. if(!(FLAG_ON(pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1608. pAccessList[iCnt].fAccessFlags,ACTRL_AUDIT_SUCCESS) ||
  1609. FLAG_ON(pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1610. pAccessList[iCnt].fAccessFlags,ACTRL_AUDIT_FAILURE)))
  1611. {
  1612. dwErr = ERROR_INVALID_ACL;
  1613. break;
  1614. }
  1615. }
  1616. dwErr = CopyAccessEntry(&(pNew->pAccessList[iNewIndex]),
  1617. &(pAdd->pPropertyAccessList[iIndex].
  1618. pAccessEntryList->pAccessList[iCnt]));
  1619. iNewIndex++;
  1620. }
  1621. pNew->cEntries += cNewCopy;
  1622. }
  1623. if(cOldCopy != 0)
  1624. {
  1625. memcpy(&(pNew->pAccessList[iNewIndex]),
  1626. pList->pAccessList,
  1627. cOldCopy * sizeof(ACTRL_ACCESS_ENTRY));
  1628. iNewIndex += cOldCopy;
  1629. pNew->cEntries += cOldCopy;
  1630. }
  1631. //
  1632. // Then, copy the alloweds...
  1633. //
  1634. for(iCnt = cNewCopy;
  1635. dwErr == ERROR_SUCCESS &&
  1636. pAdd->pPropertyAccessList[iIndex].pAccessEntryList != NULL &&
  1637. iCnt < pAdd->pPropertyAccessList[iIndex].pAccessEntryList->cEntries;
  1638. iCnt++)
  1639. {
  1640. ULONG fAccessFlag = pAdd->pPropertyAccessList[iIndex].pAccessEntryList->
  1641. pAccessList[iCnt].fAccessFlags;
  1642. if(fAccessFlag != ACTRL_ACCESS_ALLOWED &&
  1643. fAccessFlag != ACTRL_ACCESS_DENIED &&
  1644. (fAccessFlag & ~(ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)))
  1645. {
  1646. dwErr = ERROR_INVALID_FLAGS;
  1647. break;
  1648. }
  1649. if(SeInfo == DACL_SECURITY_INFORMATION)
  1650. {
  1651. if(!(FLAG_ON(fAccessFlag,ACTRL_ACCESS_DENIED) ||
  1652. FLAG_ON(fAccessFlag,ACTRL_ACCESS_ALLOWED)))
  1653. {
  1654. dwErr = ERROR_INVALID_ACL;
  1655. break;
  1656. }
  1657. }
  1658. else
  1659. {
  1660. if(!(FLAG_ON(fAccessFlag,ACTRL_AUDIT_SUCCESS) ||
  1661. FLAG_ON(fAccessFlag,ACTRL_AUDIT_FAILURE)))
  1662. {
  1663. dwErr = ERROR_INVALID_ACL;
  1664. break;
  1665. }
  1666. }
  1667. if(fAccessFlag == ACTRL_ACCESS_DENIED)
  1668. {
  1669. dwErr = ERROR_INVALID_ACL;
  1670. break;
  1671. }
  1672. dwErr = CopyAccessEntry(&(pNew->pAccessList[iNewIndex]),
  1673. &(pAdd->pPropertyAccessList[iIndex].
  1674. pAccessEntryList->pAccessList[iCnt]));
  1675. iNewIndex++;
  1676. pNew->cEntries++;
  1677. }
  1678. if(dwErr == ERROR_SUCCESS &&
  1679. pList != NULL && pList->cEntries - cOldCopy > 0)
  1680. {
  1681. memcpy(&(pNew->pAccessList[iNewIndex]),
  1682. &pList->pAccessList[cOldCopy],
  1683. (pList->cEntries - cOldCopy) * sizeof(ACTRL_ACCESS_ENTRY));
  1684. iNewIndex += cOldCopy;
  1685. pNew->cEntries += (pList->cEntries - cOldCopy);
  1686. }
  1687. //
  1688. // Now, if we got this far, we'll set it back in our list
  1689. //
  1690. if(dwErr == ERROR_SUCCESS)
  1691. {
  1692. SeInfo == DACL_SECURITY_INFORMATION ?
  1693. pAccNode->pAccessList = pNew :
  1694. pAccNode->pAuditList = pNew;
  1695. if(FLAG_ON(pAdd->pPropertyAccessList[iIndex].fListFlags, ACTRL_ACCESS_PROTECTED))
  1696. {
  1697. pAccNode->fState |= (SeInfo == DACL_SECURITY_INFORMATION ?
  1698. ACCLIST_DACL_PROTECTED :
  1699. ACCLIST_SACL_PROTECTED);
  1700. }
  1701. }
  1702. else
  1703. {
  1704. AccFree(pNew);
  1705. }
  1706. iIndex++;
  1707. if(iIndex >= pAdd->cEntries)
  1708. {
  1709. break;
  1710. }
  1711. }
  1712. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::AddAccessLists: %lu\n", dwErr));
  1713. return(dwErr);
  1714. }
  1715. //+---------------------------------------------------------------------------
  1716. //
  1717. // Member: CAccessList::GetExplicitAccess, public
  1718. //
  1719. // Synopsis: Determines the explicit access for a given trustee. This
  1720. // includes group membership lookup
  1721. //
  1722. // Arguments: [IN pTrustee] -- Trustee to check the access for
  1723. // [IN pwszProperty] -- Property to get access for
  1724. // [OUT pDeniedMask] -- Where the denied mask is returned
  1725. // [OUT pAllowedMask] -- Where the allowed mask is returned
  1726. //
  1727. // Returns: ERROR_SUCCESS -- Success
  1728. //
  1729. // Notes:
  1730. //
  1731. //----------------------------------------------------------------------------
  1732. DWORD CAccessList::GetExplicitAccess(IN PTRUSTEE pTrustee,
  1733. IN PWSTR pwszProperty,
  1734. OUT PULONG pDeniedMask,
  1735. OUT PULONG pAllowedMask)
  1736. {
  1737. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GetExplicitAccess\n"));
  1738. DWORD dwErr = ERROR_SUCCESS;
  1739. BOOL PropertiesMatch = FALSE;
  1740. GUID Guid;
  1741. PWSTR pwszNewPropertyName, pwszSourceName;
  1742. //
  1743. // Ok, first, get the specified access list for our property
  1744. //
  1745. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.Find((PVOID)pwszProperty,
  1746. CompProps);
  1747. if(pAccNode == NULL)
  1748. {
  1749. //
  1750. // If that failed, lets see if we can translate it from a guid to a string
  1751. //
  1752. //
  1753. // See if we should convert one to/from a guid and then
  1754. // compare it again
  1755. //
  1756. dwErr = UuidFromString(pwszProperty, &Guid);
  1757. if(dwErr == ERROR_SUCCESS)
  1758. {
  1759. dwErr = AccctrlLookupIdName(_pLDAP,
  1760. _pwszDsPathReference,
  1761. &Guid,
  1762. FALSE,
  1763. FALSE,
  1764. &pwszNewPropertyName);
  1765. if(dwErr == ERROR_SUCCESS)
  1766. {
  1767. pAccNode = (PACCLIST_NODE)_AccList.Find((PVOID)pwszNewPropertyName,
  1768. CompProps);
  1769. }
  1770. }
  1771. //
  1772. // Whoops... No such property...
  1773. //
  1774. if(pAccNode == NULL)
  1775. {
  1776. dwErr = ERROR_UNKNOWN_PROPERTY;
  1777. }
  1778. }
  1779. if(pAccNode != NULL)
  1780. {
  1781. PACTRL_ACCESS_ENTRY_LIST pList = pAccNode->pAccessList;
  1782. if(pList == NULL)
  1783. {
  1784. *pDeniedMask = 0;
  1785. *pAllowedMask = 0xFFFFFFFF;
  1786. }
  1787. else if(pList->cEntries == 0)
  1788. {
  1789. *pDeniedMask = 0xFFFFFFFF;
  1790. *pAllowedMask = 0;
  1791. }
  1792. else
  1793. {
  1794. //
  1795. // Now, we'll process each one of the entries, and build our masks
  1796. //
  1797. *pDeniedMask = 0;
  1798. *pAllowedMask = 0;
  1799. //
  1800. // Add our trustee, so we get our information
  1801. //
  1802. PTRUSTEE_NODE pTNode;
  1803. dwErr = GetTrusteeNode(pTrustee,
  1804. TRUSTEE_OPT_SID,
  1805. &pTNode);
  1806. if(dwErr == ERROR_SUCCESS)
  1807. {
  1808. CMemberCheck MemberCheck(pTNode);
  1809. dwErr = MemberCheck.Init();
  1810. //
  1811. // Now, we'll just go
  1812. //
  1813. for(ULONG iIndex = 0;
  1814. iIndex < pList->cEntries && dwErr == ERROR_SUCCESS;
  1815. iIndex++)
  1816. {
  1817. if(!(pList->pAccessList[iIndex].Inheritance & INHERIT_ONLY_ACE))
  1818. {
  1819. PTRUSTEE_NODE pATNode;
  1820. dwErr = GetTrusteeNode(&(pList->pAccessList[iIndex].Trustee),
  1821. TRUSTEE_OPT_SID,
  1822. &pATNode);
  1823. if(dwErr == ERROR_SUCCESS)
  1824. {
  1825. BOOL fAddMask;
  1826. dwErr = MemberCheck.IsMemberOf(pATNode,
  1827. &fAddMask);
  1828. if(dwErr == ERROR_SUCCESS && fAddMask == TRUE)
  1829. {
  1830. //
  1831. // Great, then we'll simply or in the bits
  1832. //
  1833. if(pList->pAccessList[iIndex].fAccessFlags ==
  1834. ACTRL_ACCESS_ALLOWED)
  1835. {
  1836. *pAllowedMask |= pList->pAccessList[iIndex].Access;
  1837. }
  1838. else
  1839. {
  1840. *pDeniedMask |= pList->pAccessList[iIndex].Access;
  1841. }
  1842. }
  1843. }
  1844. }
  1845. }
  1846. }
  1847. }
  1848. }
  1849. acDebugOut((DEB_TRACE_ACC,
  1850. "Out CAccessList::GetExplicitAccess: %lu\n",
  1851. dwErr));
  1852. return(dwErr);
  1853. }
  1854. //+---------------------------------------------------------------------------
  1855. //
  1856. // Member: CAccessList::GetExplicitAudits, public
  1857. //
  1858. // Synopsis: Determines the explicit audits for a given trustee. This
  1859. // includes group membership lookup
  1860. //
  1861. // Arguments: [IN pTrustee] -- Trustee to check the access for
  1862. // [IN pwszProperty] -- Property to get access for
  1863. // [OUT pSuccessMask] -- Where the successful audit mask
  1864. // is returned
  1865. // [OUT pFailureMask] -- Where the failed audit mask is
  1866. // returned
  1867. //
  1868. // Returns: ERROR_SUCCESS -- Success
  1869. //
  1870. // Notes:
  1871. //
  1872. //----------------------------------------------------------------------------
  1873. DWORD CAccessList::GetExplicitAudits(IN PTRUSTEE pTrustee,
  1874. IN PWSTR pwszProperty,
  1875. OUT PULONG pSuccessMask,
  1876. OUT PULONG pFailureMask)
  1877. {
  1878. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GetExplicitAudits\n"));
  1879. DWORD dwErr = ERROR_SUCCESS;
  1880. //
  1881. // Ok, first, get the specified access list for our property
  1882. //
  1883. //
  1884. // Ok, first, get the specified access list for our property
  1885. //
  1886. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.Find((PVOID)pwszProperty,
  1887. CompProps);
  1888. if(pAccNode == NULL)
  1889. {
  1890. //
  1891. // Whoops... No such property...
  1892. //
  1893. dwErr = ERROR_INVALID_PARAMETER;
  1894. }
  1895. else
  1896. {
  1897. PACTRL_ACCESS_ENTRY_LIST pList = pAccNode->pAuditList;
  1898. if(pList == NULL)
  1899. {
  1900. *pSuccessMask = 0;
  1901. *pFailureMask = 0;
  1902. }
  1903. else if(pList->cEntries == 0)
  1904. {
  1905. *pSuccessMask = 0;
  1906. *pFailureMask = 0;
  1907. }
  1908. else
  1909. {
  1910. //
  1911. // Now, we'll process each one of the entries, and build our masks
  1912. //
  1913. *pSuccessMask = 0;
  1914. *pFailureMask = 0;
  1915. //
  1916. // Add our trustee, so we get our information
  1917. //
  1918. PTRUSTEE_NODE pTNode;
  1919. dwErr = GetTrusteeNode(pTrustee,
  1920. TRUSTEE_OPT_SID,
  1921. &pTNode);
  1922. if(dwErr == ERROR_SUCCESS)
  1923. {
  1924. CMemberCheck MemberCheck(pTNode);
  1925. dwErr = MemberCheck.Init();
  1926. //
  1927. // Now, we'll just go
  1928. //
  1929. for(ULONG iIndex = 0;
  1930. iIndex < pList->cEntries && dwErr == ERROR_SUCCESS;
  1931. iIndex++)
  1932. {
  1933. PTRUSTEE_NODE pATNode;
  1934. dwErr = GetTrusteeNode(&(pList->pAccessList[iIndex].Trustee),
  1935. TRUSTEE_OPT_SID,
  1936. &pATNode);
  1937. if(dwErr == ERROR_SUCCESS)
  1938. {
  1939. BOOL fAddMask;
  1940. dwErr = MemberCheck.IsMemberOf(pATNode,
  1941. &fAddMask);
  1942. if(dwErr == ERROR_SUCCESS && fAddMask == TRUE)
  1943. {
  1944. //
  1945. // Great, then we'll simply or in the bits
  1946. //
  1947. if(pList->pAccessList[iIndex].fAccessFlags ==
  1948. ACTRL_AUDIT_SUCCESS)
  1949. {
  1950. *pSuccessMask |= AccessMaskForAccessEntry(
  1951. &(pList->pAccessList[iIndex]),
  1952. _ObjType);
  1953. }
  1954. if(pList->pAccessList[iIndex].fAccessFlags ==
  1955. ACTRL_AUDIT_FAILURE)
  1956. {
  1957. *pFailureMask |= AccessMaskForAccessEntry(
  1958. &(pList->pAccessList[iIndex]),
  1959. _ObjType);
  1960. }
  1961. }
  1962. }
  1963. }
  1964. }
  1965. }
  1966. }
  1967. acDebugOut((DEB_TRACE_ACC,
  1968. "Out CAccessList::GetExplicitAudits: %lu\n",
  1969. dwErr));
  1970. return(dwErr);
  1971. }
  1972. //+---------------------------------------------------------------------------
  1973. //
  1974. // Member: CAccessList::CopyAccessEntry, private
  1975. //
  1976. // Synopsis: Copies one access entry to another
  1977. //
  1978. // Arguments: [IN pNewEntry] -- Entry to be copied to
  1979. // [IN pOldEntry] -- Entry to copy from
  1980. //
  1981. // Returns: ERROR_SUCCESS -- Success
  1982. //
  1983. // Notes: pNewEntry must already exist
  1984. //
  1985. //----------------------------------------------------------------------------
  1986. DWORD CAccessList::CopyAccessEntry(IN PACTRL_ACCESS_ENTRY pNewEntry,
  1987. IN PACTRL_ACCESS_ENTRY pOldEntry)
  1988. {
  1989. acDebugOut((DEB_TRACE_ACC,"In CAccessList::CopyAccessEntry\n"));
  1990. DWORD dwErr = ERROR_SUCCESS;
  1991. //
  1992. // First, copy the members
  1993. //
  1994. memcpy(pNewEntry,
  1995. pOldEntry,
  1996. sizeof(ACTRL_ACCESS_ENTRY));
  1997. //
  1998. // We'll have to NULL out the inherit property on the given entry,
  1999. // since we only share it, and we don't want to prematurely delete it
  2000. //
  2001. pOldEntry->lpInheritProperty = NULL;
  2002. //
  2003. // Then, adjust the trustee
  2004. //
  2005. PTRUSTEE_NODE pTNode;
  2006. dwErr = GetTrusteeNode(&(pOldEntry->Trustee),
  2007. TRUSTEE_OPT_NOTHING,
  2008. &pTNode);
  2009. if(dwErr == ERROR_SUCCESS)
  2010. {
  2011. PWSTR pwszNewTrustee;
  2012. if(pOldEntry->Trustee.TrusteeForm == TRUSTEE_IS_SID)
  2013. {
  2014. acDebugOut((DEB_TRACE_ACC,
  2015. "Transfered %p\n",
  2016. pTNode->pSid));
  2017. pwszNewTrustee = (PWSTR)pTNode->pSid;
  2018. }
  2019. else
  2020. {
  2021. pwszNewTrustee = pTNode->pwszTrusteeName;
  2022. acDebugOut((DEB_TRACE_ACC,
  2023. "Transfered %ws\n",
  2024. pwszNewTrustee));
  2025. }
  2026. pNewEntry->Trustee.ptstrName = pwszNewTrustee;
  2027. }
  2028. acDebugOut((DEB_TRACE_ACC,
  2029. "Out CAccessList::CopyAccessEntry: %lu\n",
  2030. dwErr));
  2031. return(dwErr);
  2032. }
  2033. //+---------------------------------------------------------------------------
  2034. //
  2035. // Member: CAccessList::GrowInheritedAces, private
  2036. //
  2037. // Synopsis: Expands inherited aces of a DS Object. This will actually
  2038. // add the appropriate access entries
  2039. //
  2040. // Arguments: None
  2041. //
  2042. // Returns: ERROR_SUCCESS -- Success
  2043. // ERROR_INVALID_DATA -- The root access list was not
  2044. // loaded
  2045. //
  2046. // Notes:
  2047. //
  2048. //----------------------------------------------------------------------------
  2049. DWORD CAccessList::GrowInheritedAces()
  2050. {
  2051. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GrowInheritedAces\n"));
  2052. DWORD dwErr = ERROR_SUCCESS;
  2053. if(_ObjType != SE_DS_OBJECT && _ObjType != SE_DS_OBJECT_ALL)
  2054. {
  2055. acDebugOut((DEB_TRACE_ACC,
  2056. "Out CAccessList::GrowInheritedAces: %lu\n",
  2057. dwErr));
  2058. return(dwErr);
  2059. }
  2060. //
  2061. // Ok, find the node whose property is NULL
  2062. //
  2063. PACCLIST_NODE pNode = (PACCLIST_NODE)_AccList.Find(NULL,
  2064. CompProps);
  2065. if(pNode == NULL)
  2066. {
  2067. //
  2068. // If we haven't loaded the root, so we're screwed
  2069. //
  2070. dwErr = ERROR_INVALID_DATA;
  2071. }
  2072. if(dwErr == ERROR_SUCCESS && _AccList.QueryCount() > 1)
  2073. {
  2074. PACTRL_ACCESS_ENTRYW *ppAccInherit = NULL;
  2075. PACTRL_ACCESS_ENTRYW *ppAudInherit = NULL;
  2076. ULONG cAud = 0;
  2077. ULONG cAcc = 0;
  2078. PACTRL_ACCESS_ENTRY_LIST pILists[2];
  2079. PACTRL_ACCESS_ENTRY **ppInheritList[2];
  2080. PULONG pulCounts[2];
  2081. pILists[0] = pNode->pAccessList;
  2082. ppInheritList[0] = &ppAccInherit;
  2083. pulCounts[0] = &cAcc;
  2084. pILists[1] = pNode->pAuditList;
  2085. ppInheritList[1] = &ppAudInherit;
  2086. pulCounts[1] = &cAud;
  2087. //
  2088. // Now, build the lists
  2089. //
  2090. for(ULONG iIndex = 0;
  2091. iIndex < 2 && dwErr == ERROR_SUCCESS;
  2092. iIndex++)
  2093. {
  2094. //
  2095. // Skip empty lists
  2096. //
  2097. if(pILists[iIndex] == NULL)
  2098. {
  2099. continue;
  2100. }
  2101. for(ULONG iItems = 0; iItems < pILists[iIndex]->cEntries; iItems++)
  2102. {
  2103. if(FLAG_ON(pILists[iIndex]->pAccessList[iItems].Inheritance,
  2104. VALID_INHERIT_FLAGS))
  2105. {
  2106. (*pulCounts[iIndex])++;
  2107. }
  2108. }
  2109. //
  2110. // Now, we'll do an allocation, and repeat the operation, doing
  2111. // the assignment
  2112. //
  2113. *ppInheritList[iIndex] = (PACTRL_ACCESS_ENTRY *)
  2114. AccAlloc(sizeof(PACTRL_ACCESS_ENTRY) * *pulCounts[iIndex]);
  2115. if(*ppInheritList[iIndex] == NULL)
  2116. {
  2117. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2118. break;
  2119. }
  2120. ULONG iInherit = 0;
  2121. for(iItems = 0; iItems < pILists[iIndex]->cEntries; iItems++)
  2122. {
  2123. if(FLAG_ON(pILists[iIndex]->pAccessList[iItems].Inheritance,
  2124. VALID_INHERIT_FLAGS))
  2125. {
  2126. (*ppInheritList)[iIndex][iInherit] =
  2127. &(pILists[iIndex]->pAccessList[iItems]);
  2128. }
  2129. }
  2130. }
  2131. _AccList.Reset();
  2132. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.NextData();
  2133. //
  2134. // We'll do this for both the access and audit lists
  2135. //
  2136. while(pAccNode != NULL && dwErr == ERROR_SUCCESS)
  2137. {
  2138. if(pAccNode->pwszProperty == NULL)
  2139. {
  2140. PACTRL_ACCESS_ENTRY_LIST *ppLists[2];
  2141. ppLists[0] = &(pAccNode->pAccessList);
  2142. ppLists[1] = &(pAccNode->pAuditList);
  2143. for(ULONG iList = 0;
  2144. iList < 2 && dwErr == ERROR_SUCCESS;
  2145. iList++)
  2146. {
  2147. //
  2148. // Skip empty lists
  2149. //
  2150. if(ppLists[iList] == NULL ||
  2151. (*ppInheritList)[iList] == NULL)
  2152. {
  2153. continue;
  2154. }
  2155. //
  2156. // We'll build an AList and then do a merge
  2157. //
  2158. ACTRL_ACCESS_ENTRY_LIST AEL;
  2159. AEL.cEntries = *pulCounts[iList];
  2160. AEL.pAccessList = **ppInheritList[iList];
  2161. ACTRL_PROPERTY_ENTRY PEntry;
  2162. PEntry.lpProperty = pAccNode->pwszProperty;
  2163. PEntry.pAccessEntryList = &AEL;
  2164. ACTRL_ACCESSW AList;
  2165. AList.cEntries = 1;
  2166. AList.pPropertyAccessList = &PEntry;
  2167. dwErr = AddAccessLists(iList == 0 ?
  2168. DACL_SECURITY_INFORMATION :
  2169. SACL_SECURITY_INFORMATION,
  2170. &AList,
  2171. TRUE);
  2172. if(dwErr != ERROR_SUCCESS)
  2173. {
  2174. break;
  2175. }
  2176. }
  2177. }
  2178. pAccNode = (PACCLIST_NODE)_AccList.NextData();
  2179. }
  2180. //
  2181. // Finally, free our memory
  2182. //
  2183. for(iIndex = 0; iIndex < 2; iIndex++)
  2184. {
  2185. AccFree(*ppInheritList[iIndex]);;
  2186. }
  2187. }
  2188. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::GrowInheritedAces: %lu\n",
  2189. dwErr));
  2190. return(dwErr);
  2191. }
  2192. //+---------------------------------------------------------------------------
  2193. //
  2194. // Member: CAccessList::CollapseInheritedAces, private
  2195. //
  2196. // Synopsis: The inverse of the above function. Goes through the lists
  2197. // and collapses the inherited access entries for a DS object
  2198. //
  2199. // Arguments: None
  2200. //
  2201. // Returns: ERROR_SUCCESS -- Success
  2202. //
  2203. // Notes:
  2204. //
  2205. //----------------------------------------------------------------------------
  2206. DWORD CAccessList::CollapseInheritedAces()
  2207. {
  2208. acDebugOut((DEB_TRACE_ACC,"In CAccessList::CollapseInheritedAces\n"));
  2209. DWORD dwErr = ERROR_SUCCESS;
  2210. if(_ObjType != SE_DS_OBJECT && _ObjType != SE_DS_OBJECT_ALL)
  2211. {
  2212. acDebugOut((DEB_TRACE_ACC,
  2213. "Out CAccessList::CollapseInheritedAces: %lu\n",
  2214. dwErr));
  2215. return(dwErr);
  2216. }
  2217. //
  2218. // Now, we'll process all the items EXCEPT the root. (We only collapse
  2219. // on properties)
  2220. //
  2221. _AccList.Reset();
  2222. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.NextData();
  2223. //
  2224. // We'll do this for both the access and audit lists
  2225. //
  2226. while(pAccNode != NULL && dwErr == ERROR_SUCCESS)
  2227. {
  2228. if(pAccNode->pwszProperty == NULL)
  2229. {
  2230. PACTRL_ACCESS_ENTRY_LIST *ppLists[2];
  2231. ULONG cLists = 0;
  2232. if(pAccNode->pAccessList != NULL)
  2233. {
  2234. ppLists[cLists++] = &(pAccNode->pAccessList);
  2235. }
  2236. if(pAccNode->pAuditList != NULL)
  2237. {
  2238. ppLists[cLists++] = &(pAccNode->pAuditList);
  2239. }
  2240. for(ULONG iList = 0;
  2241. iList < cLists && dwErr == ERROR_SUCCESS;
  2242. iList++)
  2243. {
  2244. ULONG cRemoved = 0;
  2245. for(ULONG iIndex = 0;
  2246. iIndex < (*ppLists)[iList]->cEntries;
  2247. iIndex++)
  2248. {
  2249. if(FLAG_ON((*ppLists)[iList]->pAccessList[iIndex].
  2250. Inheritance,
  2251. INHERITED_ACE))
  2252. {
  2253. (*ppLists)[iList]->pAccessList[iIndex].Access =
  2254. 0xFFFFFFFF;
  2255. cRemoved++;
  2256. }
  2257. }
  2258. if(dwErr == ERROR_SUCCESS && cRemoved != 0)
  2259. {
  2260. PACTRL_ACCESS_ENTRY_LIST pNew;
  2261. dwErr = ShrinkList((*ppLists)[iList],
  2262. cRemoved,
  2263. &pNew);
  2264. if(dwErr == ERROR_SUCCESS)
  2265. {
  2266. AccFree((*ppLists)[iList]);
  2267. (*ppLists)[iList] = pNew;
  2268. }
  2269. }
  2270. }
  2271. }
  2272. pAccNode = (PACCLIST_NODE)_AccList.NextData();
  2273. }
  2274. acDebugOut((DEB_TRACE_ACC,
  2275. "Out CAccessList::CollapseInheritedAces: %lu\n",
  2276. dwErr));
  2277. return(dwErr);
  2278. }
  2279. //+---------------------------------------------------------------------------
  2280. //
  2281. // Member: CAccessList::ShrinkList, private
  2282. //
  2283. // Synopsis: Shrinks the given list. This goes through and removes any
  2284. // nodes that have been marked as "deleted", as indicated by the
  2285. // access mask.
  2286. //
  2287. // Arguments: [IN pOldList] -- List to shrink
  2288. // [IN cRemoved] -- Number of items to be removed
  2289. // [OUT ppNewList] -- Where the "shrunk" list is
  2290. // returned
  2291. //
  2292. // Returns: ERROR_SUCCESS -- Success
  2293. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  2294. //
  2295. // Notes:
  2296. //
  2297. //----------------------------------------------------------------------------
  2298. DWORD CAccessList::ShrinkList(IN PACTRL_ACCESS_ENTRY_LIST pOldList,
  2299. IN ULONG cRemoved,
  2300. IN PACTRL_ACCESS_ENTRY_LIST *ppNewList)
  2301. {
  2302. acDebugOut((DEB_TRACE_ACC,"In CAccessList::ShrinkList\n"));
  2303. DWORD dwErr = ERROR_SUCCESS;
  2304. //
  2305. // Ok, we'll process the list, and repackage it...
  2306. //
  2307. PACTRL_ACCESS_ENTRY_LIST pNew = (PACTRL_ACCESS_ENTRY_LIST)
  2308. AccAlloc(sizeof(ACTRL_ACCESS_ENTRY_LIST) +
  2309. ((pOldList->cEntries - cRemoved) *
  2310. sizeof(ACTRL_ACCESS_ENTRY)));
  2311. if(pNew == NULL)
  2312. {
  2313. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2314. }
  2315. else
  2316. {
  2317. pNew->pAccessList = (PACTRL_ACCESS_ENTRY)((PBYTE)pNew +
  2318. sizeof(ACTRL_ACCESS_ENTRY_LIST));
  2319. //
  2320. // Now, copy the ones that we still want to keep over
  2321. //
  2322. ULONG iNew = 0;
  2323. ULONG Removed = 0;
  2324. for(ULONG iIndex = 0; iIndex < pOldList->cEntries; iIndex++)
  2325. {
  2326. if(pOldList->pAccessList[iIndex].Access != 0xFFFFFFFF)
  2327. {
  2328. memcpy(&(pNew->pAccessList[iNew]),
  2329. &(pOldList->pAccessList[iIndex]),
  2330. sizeof(ACTRL_ACCESS_ENTRY));
  2331. iNew++;
  2332. }
  2333. else
  2334. {
  2335. //
  2336. // Remove the trustee from the list
  2337. //
  2338. dwErr = RemoveTrustee(&(pOldList->pAccessList[iIndex].Trustee));
  2339. Removed++;
  2340. }
  2341. }
  2342. //
  2343. // If we've removed all of the entries, remove the item as well...
  2344. //
  2345. if(iNew == 0 && Removed > 0 )
  2346. {
  2347. AccFree( pNew );
  2348. *ppNewList = NULL;
  2349. }
  2350. else
  2351. {
  2352. pNew->cEntries = iNew;
  2353. *ppNewList = pNew;
  2354. }
  2355. }
  2356. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::ShrinkList: %lu\n",
  2357. dwErr));
  2358. return(dwErr);
  2359. }
  2360. //+---------------------------------------------------------------------------
  2361. //
  2362. // Member: CAccessList::BuildSDForAccessList, public
  2363. //
  2364. // Synopsis: Builds a security descriptor for the loaded access lists
  2365. //
  2366. // Arguments: [OUT ppSD] -- Where the built security
  2367. // descriptor is returned
  2368. // [OUT pSeInfo] -- Where the SeInfo corresponding
  2369. // to the Security Descriptor is
  2370. // returned
  2371. // [IN fFlags] -- Flags that govern the lifetime
  2372. // of the SD. It controls whether
  2373. // the class deletes the SD or not
  2374. //
  2375. // Returns: ERROR_SUCCESS -- Success
  2376. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  2377. //
  2378. // Notes:
  2379. //
  2380. //----------------------------------------------------------------------------
  2381. DWORD CAccessList::BuildSDForAccessList(OUT PSECURITY_DESCRIPTOR *ppSD,
  2382. OUT PSECURITY_INFORMATION pSeInfo,
  2383. IN ULONG fFlags)
  2384. {
  2385. acDebugOut((DEB_TRACE_ACC,"In CAccessList::BuildSDForAccessList\n"));
  2386. DWORD dwErr = ERROR_SUCCESS;
  2387. //
  2388. // If our current SD is valid, simply return it...
  2389. //
  2390. if(_fSDValid == TRUE)
  2391. {
  2392. *ppSD = _pSD;
  2393. *pSeInfo = _SeInfo;
  2394. acDebugOut((DEB_TRACE_ACC,
  2395. "Out CAccessList::BuildSDForAccessList: 0\n"));
  2396. return(dwErr);
  2397. }
  2398. else
  2399. {
  2400. AccFree(_pSD);
  2401. _pSD = NULL;
  2402. _fFreeSD = FALSE;
  2403. _cSDSize = 0;
  2404. }
  2405. if(FLAG_ON(fFlags,ACCLIST_SD_NOFREE))
  2406. {
  2407. _fFreeSD = FALSE;
  2408. }
  2409. else
  2410. {
  2411. _fFreeSD = TRUE;
  2412. }
  2413. UCHAR AclRevision = ACL_REVISION2;
  2414. if(_ObjType == SE_DS_OBJECT || _ObjType == SE_DS_OBJECT_ALL)
  2415. {
  2416. AclRevision = ACL_REVISION_DS;
  2417. }
  2418. PACCLIST_CNODE pCDAcl = NULL;
  2419. PACCLIST_CNODE pCSAcl = NULL;
  2420. ULONG cDAcls = 0;
  2421. ULONG cSAcls = 0;
  2422. ULONG cDAclSize = 0;
  2423. ULONG cSAclSize = 0;
  2424. dwErr = CompressList(DACL_SECURITY_INFORMATION,
  2425. &pCDAcl,
  2426. &cDAcls);
  2427. if(dwErr == ERROR_SUCCESS)
  2428. {
  2429. if(cDAcls != 0)
  2430. {
  2431. *pSeInfo = DACL_SECURITY_INFORMATION;
  2432. }
  2433. else
  2434. {
  2435. *pSeInfo = 0;
  2436. }
  2437. dwErr = CompressList(SACL_SECURITY_INFORMATION,
  2438. &pCSAcl,
  2439. &cSAcls);
  2440. if(dwErr == ERROR_SUCCESS && cSAcls != 0)
  2441. {
  2442. *pSeInfo |= SACL_SECURITY_INFORMATION;
  2443. }
  2444. }
  2445. //
  2446. // Now, go through and size the DACL and SACL
  2447. //
  2448. if(dwErr == ERROR_SUCCESS)
  2449. {
  2450. dwErr = SizeCompressedListAsAcl(pCDAcl,
  2451. cDAcls,
  2452. &cDAclSize,
  2453. FALSE);
  2454. if(dwErr == ERROR_SUCCESS)
  2455. {
  2456. dwErr = SizeCompressedListAsAcl(pCSAcl,
  2457. cSAcls,
  2458. &cSAclSize,
  2459. TRUE);
  2460. }
  2461. }
  2462. //
  2463. // If all that worked, add in our security descriptor size and owner/group
  2464. //
  2465. ULONG cSize = 0;
  2466. if(dwErr == ERROR_SUCCESS)
  2467. {
  2468. cSize = cDAclSize + cSAclSize;
  2469. cSize += sizeof(SECURITY_DESCRIPTOR);
  2470. //
  2471. // Owner and group
  2472. //
  2473. if(_pOwner != NULL)
  2474. {
  2475. cSize += RtlLengthSid(_pOwner);
  2476. *pSeInfo |= OWNER_SECURITY_INFORMATION;
  2477. }
  2478. if(_pGroup != NULL)
  2479. {
  2480. cSize += RtlLengthSid(_pGroup);
  2481. *pSeInfo |= GROUP_SECURITY_INFORMATION;
  2482. }
  2483. if(FLAG_ON(fFlags, ACCLIST_SD_DS_STYLE))
  2484. {
  2485. cSize += sizeof(ULONG);
  2486. }
  2487. }
  2488. //
  2489. // If that worked, then we'll allocate for the security descriptor.
  2490. // We allocate in a block, so we can free it in another routine later
  2491. //
  2492. BOOL fProtected=FALSE;
  2493. PSECURITY_DESCRIPTOR pSD;
  2494. if(dwErr == ERROR_SUCCESS)
  2495. {
  2496. pSD = (PSECURITY_DESCRIPTOR)AccAlloc(cSize);
  2497. if(pSD == NULL)
  2498. {
  2499. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2500. }
  2501. else
  2502. {
  2503. PBYTE pbEndOBuff = (PBYTE)pSD + cSize;
  2504. if(FLAG_ON(fFlags, ACCLIST_SD_DS_STYLE))
  2505. {
  2506. pSD = (PSECURITY_DESCRIPTOR)((PBYTE)pSD + sizeof(ULONG));
  2507. }
  2508. _cSDSize = cSize;
  2509. //
  2510. // First, build an absolute SD
  2511. //
  2512. if(InitializeSecurityDescriptor(pSD,
  2513. SECURITY_DESCRIPTOR_REVISION) ==
  2514. FALSE)
  2515. {
  2516. dwErr = GetLastError();
  2517. }
  2518. //
  2519. // First, set the owner
  2520. //
  2521. if(dwErr == ERROR_SUCCESS && _pOwner != NULL)
  2522. {
  2523. PSID pOwner = (PSID)(pbEndOBuff - RtlLengthSid(_pOwner));
  2524. RtlCopySid((ULONG)(pbEndOBuff - (PBYTE)pOwner),
  2525. pOwner,
  2526. _pOwner);
  2527. pbEndOBuff = (PBYTE)pOwner;
  2528. if(SetSecurityDescriptorOwner(pSD,
  2529. pOwner,
  2530. FALSE) == FALSE)
  2531. {
  2532. dwErr = GetLastError();
  2533. }
  2534. }
  2535. //
  2536. // Next, try our hand with the group
  2537. //
  2538. if(dwErr == ERROR_SUCCESS && _pGroup != NULL)
  2539. {
  2540. PSID pGroup = (PSID)(pbEndOBuff - RtlLengthSid(_pGroup));
  2541. RtlCopySid((ULONG)(pbEndOBuff - (PBYTE)pGroup),
  2542. pGroup,
  2543. _pGroup);
  2544. pbEndOBuff = (PBYTE)pGroup;
  2545. if(SetSecurityDescriptorGroup(pSD,
  2546. pGroup,
  2547. FALSE) == FALSE)
  2548. {
  2549. dwErr = GetLastError();
  2550. }
  2551. }
  2552. //
  2553. // Ok, then the DACL
  2554. //
  2555. if(dwErr == ERROR_SUCCESS && cDAclSize != 0)
  2556. {
  2557. PACL pAcl = (PACL)(pbEndOBuff - cDAclSize);
  2558. pAcl->AclRevision = AclRevision;
  2559. pAcl->Sbz1 = (BYTE)_fDAclFlags;
  2560. pAcl->AclSize = (USHORT)cDAclSize;
  2561. pAcl->AceCount = 0;
  2562. if(cDAclSize > sizeof(ACL))
  2563. {
  2564. dwErr = BuildAcl(pCDAcl,
  2565. cDAcls,
  2566. pAcl,
  2567. DACL_SECURITY_INFORMATION,
  2568. &fProtected);
  2569. #if DBG
  2570. if(dwErr == ERROR_SUCCESS)
  2571. {
  2572. DWORD cChk = 0;
  2573. PKNOWN_ACE pAce = (PKNOWN_ACE)FirstAce(pAcl);
  2574. for(ULONG z = 0; z < pAcl->AceCount; z++)
  2575. {
  2576. cChk += (DWORD)pAce->Header.AceSize;
  2577. pAce = (PKNOWN_ACE)NextAce(pAce);
  2578. }
  2579. cChk += sizeof(ACL);
  2580. ASSERT(cChk == cDAclSize);
  2581. }
  2582. #endif
  2583. }
  2584. else
  2585. {
  2586. if( FLAG_ON(_fDAclFlags, ACCLIST_DACL_PROTECTED ))
  2587. {
  2588. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_DACL_PROTECTED;
  2589. }
  2590. }
  2591. pbEndOBuff = (PBYTE)pAcl;
  2592. if(dwErr == ERROR_SUCCESS)
  2593. {
  2594. if(SetSecurityDescriptorDacl(pSD,
  2595. TRUE,
  2596. pAcl,
  2597. FALSE) == FALSE)
  2598. {
  2599. dwErr = GetLastError();
  2600. }
  2601. if(dwErr == ERROR_SUCCESS && fProtected == TRUE)
  2602. {
  2603. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_DACL_PROTECTED;
  2604. }
  2605. }
  2606. }
  2607. else
  2608. {
  2609. if( cDAclSize == 0 && FLAG_ON(_fDAclFlags,ACCLIST_DACL_PROTECTED ))
  2610. {
  2611. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_DACL_PROTECTED;
  2612. }
  2613. if ( FLAG_ON( *pSeInfo, DACL_SECURITY_INFORMATION ) )
  2614. {
  2615. ((SECURITY_DESCRIPTOR *) pSD)->Dacl = NULL;
  2616. ((SECURITY_DESCRIPTOR *) pSD)->Control |= SE_DACL_PRESENT;
  2617. }
  2618. }
  2619. //
  2620. // Finally, the SACL
  2621. //
  2622. fProtected=FALSE;
  2623. if(dwErr == ERROR_SUCCESS && cSAclSize != 0)
  2624. {
  2625. PACL pAcl = (PACL)(pbEndOBuff - cSAclSize);
  2626. pAcl->AclRevision = AclRevision;
  2627. pAcl->Sbz1 = (BYTE)_fSAclFlags;
  2628. pAcl->AclSize = (USHORT)cSAclSize;
  2629. pAcl->AceCount = 0;
  2630. if(cSAclSize > sizeof(ACL))
  2631. {
  2632. dwErr = BuildAcl(pCSAcl,
  2633. cSAcls,
  2634. pAcl,
  2635. SACL_SECURITY_INFORMATION,
  2636. &fProtected);
  2637. }
  2638. else
  2639. {
  2640. if( FLAG_ON(_fSAclFlags,ACCLIST_SACL_PROTECTED ))
  2641. {
  2642. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_SACL_PROTECTED;
  2643. }
  2644. }
  2645. pbEndOBuff = (PBYTE)pAcl;
  2646. if(dwErr == ERROR_SUCCESS)
  2647. {
  2648. if(SetSecurityDescriptorSacl(pSD,
  2649. TRUE,
  2650. pAcl,
  2651. FALSE) == FALSE)
  2652. {
  2653. dwErr = GetLastError();
  2654. }
  2655. if(dwErr == ERROR_SUCCESS && fProtected == TRUE)
  2656. {
  2657. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_SACL_PROTECTED;
  2658. }
  2659. }
  2660. }
  2661. else
  2662. {
  2663. if( cSAclSize == 0 && FLAG_ON(_fSAclFlags, ACCLIST_SACL_PROTECTED ))
  2664. {
  2665. ((SECURITY_DESCRIPTOR *)pSD)->Control |= SE_SACL_PROTECTED;
  2666. }
  2667. if ( FLAG_ON( *pSeInfo, SACL_SECURITY_INFORMATION ) )
  2668. {
  2669. if(SetSecurityDescriptorSacl(pSD,
  2670. TRUE,
  2671. NULL,
  2672. FALSE) == FALSE)
  2673. {
  2674. dwErr = GetLastError();
  2675. }
  2676. }
  2677. }
  2678. #if DBG
  2679. if(dwErr == ERROR_SUCCESS)
  2680. {
  2681. ASSERT(pbEndOBuff == (PBYTE)pSD + sizeof(SECURITY_DESCRIPTOR));
  2682. acDebugOut((DEB_TRACE_ACC,"pbEndOBuff: 0x%lx\n", pbEndOBuff));
  2683. acDebugOut((DEB_TRACE_ACC,"pSD: 0x%lx\n",
  2684. (PBYTE)pSD + sizeof(SECURITY_DESCRIPTOR)));
  2685. }
  2686. #endif
  2687. //
  2688. // Great.. Now if all of that worked, we'll convert it to
  2689. // an absolute format if necessary, or
  2690. //
  2691. if(dwErr == ERROR_SUCCESS)
  2692. {
  2693. if(FLAG_ON(fFlags,ACCLIST_SD_ABSOK))
  2694. {
  2695. *ppSD = pSD;
  2696. }
  2697. else
  2698. {
  2699. //
  2700. // We'll need to make this self relative
  2701. //
  2702. ULONG cNewSDSize = 0;
  2703. MakeSelfRelativeSD(pSD,
  2704. NULL,
  2705. &cNewSDSize);
  2706. ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
  2707. if(FLAG_ON(fFlags,ACCLIST_SD_DS_STYLE))
  2708. {
  2709. cNewSDSize += sizeof(ULONG);
  2710. }
  2711. *ppSD = (PSECURITY_DESCRIPTOR)AccAlloc(cNewSDSize);
  2712. if(*ppSD == NULL)
  2713. {
  2714. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2715. }
  2716. else
  2717. {
  2718. if(FLAG_ON(fFlags,ACCLIST_SD_DS_STYLE))
  2719. {
  2720. *ppSD = (PSECURITY_DESCRIPTOR)
  2721. ((PBYTE)*ppSD + sizeof(ULONG));
  2722. }
  2723. _cSDSize = cNewSDSize;
  2724. if(MakeSelfRelativeSD(pSD,
  2725. *ppSD,
  2726. &cNewSDSize) == FALSE)
  2727. {
  2728. dwErr = GetLastError();
  2729. }
  2730. else
  2731. {
  2732. if(FLAG_ON(fFlags, ACCLIST_SD_DS_STYLE))
  2733. {
  2734. pSD = (PSECURITY_DESCRIPTOR)((PBYTE)pSD - sizeof(ULONG));
  2735. }
  2736. //
  2737. // It all worked, so free our initial sd
  2738. //
  2739. AccFree(pSD);
  2740. }
  2741. }
  2742. }
  2743. }
  2744. if(dwErr != ERROR_SUCCESS)
  2745. {
  2746. if(FLAG_ON(fFlags, ACCLIST_SD_DS_STYLE))
  2747. {
  2748. pSD = (PSECURITY_DESCRIPTOR)((PBYTE)pSD - sizeof(ULONG));
  2749. }
  2750. AccFree(pSD);
  2751. }
  2752. }
  2753. }
  2754. //
  2755. // Save and return our security information
  2756. //
  2757. if(dwErr == ERROR_SUCCESS)
  2758. {
  2759. _pSD = *ppSD;
  2760. _SeInfo = *pSeInfo;
  2761. }
  2762. //
  2763. // Set our flags properly
  2764. //
  2765. if(dwErr == ERROR_SUCCESS)
  2766. {
  2767. if(FLAG_ON(*pSeInfo, DACL_SECURITY_INFORMATION))
  2768. {
  2769. ((PISECURITY_DESCRIPTOR)_pSD)->Control |=
  2770. SE_DACL_AUTO_INHERIT_REQ;
  2771. }
  2772. if(FLAG_ON(*pSeInfo, SACL_SECURITY_INFORMATION))
  2773. {
  2774. ((PISECURITY_DESCRIPTOR)_pSD)->Control |=
  2775. SE_SACL_AUTO_INHERIT_REQ;
  2776. }
  2777. if(FLAG_ON(fFlags,ACCLIST_SD_DS_STYLE))
  2778. {
  2779. PULONG pSE = (PULONG)((PBYTE)*ppSD - sizeof(ULONG));
  2780. *pSE = *pSeInfo;
  2781. *ppSD = (PSECURITY_DESCRIPTOR)pSE;
  2782. }
  2783. }
  2784. FreeCompressedList(pCDAcl, cDAcls);
  2785. FreeCompressedList(pCSAcl, cSAcls);
  2786. if(dwErr != ERROR_SUCCESS)
  2787. {
  2788. _fFreeSD = FALSE;
  2789. }
  2790. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::BuildSDForAccessList: %lu\n",
  2791. dwErr));
  2792. return(dwErr);
  2793. }
  2794. //+---------------------------------------------------------------------------
  2795. //
  2796. // Member: CAccessList::AddOwnerGroup, public
  2797. //
  2798. // Synopsis: Adds an owner and or group to the class
  2799. //
  2800. // Arguments: [IN SeInfo] -- Add owner or group?
  2801. // [IN pOwner] -- Owner to add
  2802. // [IN pGroup] -- Group to add
  2803. //
  2804. // Returns: ERROR_SUCCESS -- Success
  2805. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  2806. //
  2807. // Notes:
  2808. //
  2809. //----------------------------------------------------------------------------
  2810. DWORD CAccessList::AddOwnerGroup(IN SECURITY_INFORMATION SeInfo,
  2811. IN PTRUSTEE pOwner,
  2812. IN PTRUSTEE pGroup)
  2813. {
  2814. acDebugOut((DEB_TRACE_ACC,"In CAccessList::AddOwnerGroup\n"));
  2815. DWORD dwErr = ERROR_SUCCESS;
  2816. SID_NAME_USE SidType;
  2817. //
  2818. // Basically, we'll simply add them in..
  2819. //
  2820. if(FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION))
  2821. {
  2822. if(pOwner->TrusteeForm == TRUSTEE_IS_SID)
  2823. {
  2824. if(RtlValidSid((PSID)pOwner->ptstrName) == FALSE)
  2825. {
  2826. dwErr = ERROR_INVALID_PARAMETER;
  2827. }
  2828. else
  2829. {
  2830. ACC_ALLOC_AND_COPY_SID((PSID)pOwner->ptstrName,_pOwner, dwErr);
  2831. }
  2832. }
  2833. else
  2834. {
  2835. dwErr = AccctrlLookupSid(_pwszLookupServer,
  2836. pOwner->ptstrName,
  2837. TRUE,
  2838. &_pOwner,
  2839. &SidType);
  2840. }
  2841. }
  2842. if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION))
  2843. {
  2844. if(pGroup->TrusteeForm == TRUSTEE_IS_SID)
  2845. {
  2846. if(RtlValidSid((PSID)pGroup->ptstrName) == FALSE)
  2847. {
  2848. dwErr = ERROR_INVALID_PARAMETER;
  2849. }
  2850. else
  2851. {
  2852. ACC_ALLOC_AND_COPY_SID((PSID)pGroup->ptstrName,_pGroup, dwErr);
  2853. }
  2854. }
  2855. else
  2856. {
  2857. dwErr = AccctrlLookupSid(_pwszLookupServer,
  2858. pGroup->ptstrName,
  2859. TRUE,
  2860. &_pGroup,
  2861. &SidType);
  2862. }
  2863. }
  2864. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::AddOwnerGroup: %lu\n",
  2865. dwErr));
  2866. return(dwErr);
  2867. }
  2868. //+---------------------------------------------------------------------------
  2869. //
  2870. // Member: CAccessList::GetSDSidAsTrustee, public
  2871. //
  2872. // Synopsis: Returns the specified owner/group as a trustee...
  2873. //
  2874. // Arguments: [IN SeInfo] -- Get owner or group?
  2875. // [OUT ppTrustee] -- Where the trustee is returned
  2876. //
  2877. // Returns: ERROR_SUCCESS -- Success
  2878. //
  2879. // Notes:
  2880. //
  2881. //----------------------------------------------------------------------------
  2882. DWORD CAccessList::GetSDSidAsTrustee(IN SECURITY_INFORMATION SeInfo,
  2883. OUT PTRUSTEE *ppTrustee)
  2884. {
  2885. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GetSDSidAsTrustee\n"));
  2886. DWORD dwErr = ERROR_SUCCESS;
  2887. PSID pSid;
  2888. if(FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION))
  2889. {
  2890. pSid = _pGroup;
  2891. }
  2892. else
  2893. {
  2894. pSid = _pOwner;
  2895. }
  2896. dwErr = AccLookupAccountTrustee(_pwszLookupServer,
  2897. pSid,
  2898. ppTrustee);
  2899. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::GetSDSidAsTrustee: %lu\n",
  2900. dwErr));
  2901. return(dwErr);
  2902. }
  2903. //+---------------------------------------------------------------------------
  2904. //
  2905. // Member: CAccessList::GetExplicitEntries, public
  2906. //
  2907. // Synopsis: Returns a list of explicit entries for the given trustee.
  2908. // This will lookup group membership
  2909. //
  2910. // Arguments: [IN pTrustee] -- Trustee to lookup
  2911. // [IN pwszProperty] -- Property to worry about
  2912. // [IN SeInfo] -- Look for access or audit list
  2913. // [OUT pcEntries] -- Where the count of items is
  2914. // returned.
  2915. // [OUT ppAEList] -- Where the explicit entry list is
  2916. // returned
  2917. //
  2918. // Returns: ERROR_SUCCESS -- Success
  2919. //
  2920. // Notes:
  2921. //
  2922. //----------------------------------------------------------------------------
  2923. DWORD CAccessList::GetExplicitEntries(IN PTRUSTEE pTrustee,
  2924. IN PWSTR pwszProperty,
  2925. IN SECURITY_INFORMATION SeInfo,
  2926. OUT PULONG pcEntries,
  2927. OUT PACTRL_ACCESS_ENTRYW *ppAEList)
  2928. {
  2929. acDebugOut((DEB_TRACE_ACC,"In CAccessList::GetExplicitEntries\n"));
  2930. DWORD dwErr = ERROR_SUCCESS;
  2931. //
  2932. // Ok, first, get the specified access list for our property
  2933. //
  2934. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.Find((PVOID)pwszProperty,
  2935. CompProps);
  2936. if(pAccNode == NULL)
  2937. {
  2938. //
  2939. // Whoops... No such property...
  2940. //
  2941. dwErr = ERROR_INVALID_PARAMETER;
  2942. }
  2943. else
  2944. {
  2945. PACTRL_ACCESS_ENTRY_LIST pList = pAccNode->pAccessList;
  2946. if(pList != NULL)
  2947. {
  2948. //
  2949. // Now, we'll process each one of the entries, and build our masks
  2950. //
  2951. CSList MemberList(NULL);
  2952. //
  2953. // Add our trustee, so we get our information
  2954. //
  2955. PTRUSTEE_NODE pTNode;
  2956. dwErr = GetTrusteeNode(pTrustee,
  2957. TRUSTEE_OPT_SID,
  2958. &pTNode);
  2959. if(dwErr == ERROR_SUCCESS)
  2960. {
  2961. CMemberCheck MemberCheck(pTNode);
  2962. dwErr = MemberCheck.Init();
  2963. //
  2964. // Now, we'll just go
  2965. //
  2966. for(ULONG iIndex = 0;
  2967. iIndex < pList->cEntries && dwErr == ERROR_SUCCESS;
  2968. iIndex++)
  2969. {
  2970. PTRUSTEE_NODE pATNode;
  2971. dwErr = GetTrusteeNode(
  2972. &(pList->pAccessList[iIndex].Trustee),
  2973. TRUSTEE_OPT_SID,
  2974. &pATNode);
  2975. if(dwErr == ERROR_SUCCESS)
  2976. {
  2977. BOOL fAddMask;
  2978. dwErr = MemberCheck.IsMemberOf(pATNode,
  2979. &fAddMask);
  2980. if(dwErr == ERROR_SUCCESS && fAddMask == TRUE)
  2981. {
  2982. dwErr = MemberList.Insert((PVOID)
  2983. &pList->pAccessList[iIndex]);
  2984. }
  2985. }
  2986. }
  2987. }
  2988. //
  2989. // Ok, if we have everything, build our list
  2990. //
  2991. if(dwErr == ERROR_SUCCESS)
  2992. {
  2993. *pcEntries = 0;
  2994. if(MemberList.QueryCount() == 0)
  2995. {
  2996. *ppAEList = NULL;
  2997. }
  2998. else
  2999. {
  3000. dwErr = GetTrusteeNode(pTrustee,
  3001. TRUSTEE_OPT_NAME,
  3002. &pTNode);
  3003. if(dwErr == ERROR_SUCCESS)
  3004. {
  3005. ULONG cSize = SIZE_PWSTR(pTNode->pwszTrusteeName);
  3006. cSize += MemberList.QueryCount() *
  3007. sizeof(ACTRL_ACCESS_ENTRY);
  3008. *ppAEList = (PACTRL_ACCESS_ENTRY)AccAlloc(cSize);
  3009. if(*ppAEList == NULL)
  3010. {
  3011. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  3012. }
  3013. else
  3014. {
  3015. PWSTR pwszTrustee = (PWSTR)((PBYTE)(*ppAEList) +
  3016. (MemberList.QueryCount() *
  3017. sizeof(ACTRL_ACCESS_ENTRY)));
  3018. wcscpy(pwszTrustee,
  3019. pTNode->pwszTrusteeName);
  3020. //
  3021. // Now, copy the rest of the information
  3022. //
  3023. MemberList.Reset();
  3024. PACTRL_ACCESS_ENTRY pCurrent =
  3025. (PACTRL_ACCESS_ENTRY)MemberList.NextData();
  3026. while(pCurrent != NULL)
  3027. {
  3028. memcpy(&((*ppAEList)[*pcEntries]),
  3029. pCurrent,
  3030. sizeof(ACTRL_ACCESS_ENTRY));
  3031. //
  3032. // Then, adjust the trustee...
  3033. //
  3034. (*ppAEList)[*pcEntries].Trustee.TrusteeType =
  3035. pTrustee->TrusteeType;
  3036. (*ppAEList)[*pcEntries].Trustee.TrusteeForm =
  3037. TRUSTEE_IS_NAME;
  3038. (*ppAEList)[*pcEntries].Trustee.ptstrName =
  3039. pwszTrustee;
  3040. pCurrent =
  3041. (PACTRL_ACCESS_ENTRY)MemberList.NextData();
  3042. (*pcEntries)++;
  3043. }
  3044. }
  3045. }
  3046. }
  3047. }
  3048. }
  3049. }
  3050. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::GetExplicitEntries: %lu\n",
  3051. dwErr));
  3052. return(dwErr);
  3053. }
  3054. //+---------------------------------------------------------------------------
  3055. //
  3056. // Member: CAccessList::RevokeTrusteeAccess, public
  3057. //
  3058. // Synopsis: Removes any explicit entries that exist for the named
  3059. // trustees
  3060. //
  3061. // Arguments: [IN SeInfo] -- Whether to process the access and
  3062. // or audit list
  3063. // [IN pSrcList] -- Trustee information list to
  3064. // process
  3065. // [IN pwszProperty] -- Optional property to do the revoke for
  3066. //
  3067. // Returns: ERROR_SUCCESS -- Success
  3068. //
  3069. // Notes:
  3070. //
  3071. //----------------------------------------------------------------------------
  3072. DWORD CAccessList::RevokeTrusteeAccess(IN SECURITY_INFORMATION SeInfo,
  3073. IN PACTRL_ACCESSW pSrcList,
  3074. IN PWSTR pwszProperty OPTIONAL)
  3075. {
  3076. DWORD dwErr = ERROR_SUCCESS;
  3077. acDebugOut((DEB_TRACE_ACC,"In CAccessList::RevokeTrusteeAccess\n"));
  3078. CSList TrusteeList(NULL);
  3079. //
  3080. // First, generate a list of all of the passed in trustees
  3081. //
  3082. for(ULONG iAcc = 0;
  3083. iAcc < pSrcList->cEntries && dwErr == ERROR_SUCCESS;
  3084. iAcc++)
  3085. {
  3086. PACTRL_ACCESS_ENTRY_LIST pAEL =
  3087. pSrcList->pPropertyAccessList[iAcc].pAccessEntryList;
  3088. //
  3089. // Then the access entry strings
  3090. //
  3091. for(ULONG iEntry = 0;
  3092. pAEL && iEntry < pAEL->cEntries && dwErr == ERROR_SUCCESS;
  3093. iEntry++)
  3094. {
  3095. dwErr = TrusteeList.InsertIfUnique(
  3096. (PVOID)&(pAEL->pAccessList[iEntry].Trustee),
  3097. CompTrustees);
  3098. }
  3099. }
  3100. //
  3101. // Ok, now if that worked, we have a list of trustees... We'll simply
  3102. // go through and revoke them all from our current list before
  3103. // continuing
  3104. //
  3105. TrusteeList.Reset();
  3106. PTRUSTEE pTrustee = (PTRUSTEE)TrusteeList.NextData();
  3107. while(pTrustee != NULL && dwErr == ERROR_SUCCESS)
  3108. {
  3109. TRUSTEE TempTrustee;
  3110. TempTrustee.TrusteeForm = TRUSTEE_IS_SID;
  3111. TempTrustee.ptstrName = NULL;
  3112. //
  3113. // If we have a domain relative name, we'll look the name as a sid
  3114. //
  3115. if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME && wcschr(pTrustee->ptstrName, L'\\') == NULL)
  3116. {
  3117. SID_NAME_USE Type;
  3118. dwErr = AccctrlLookupSid(_pwszLookupServer,
  3119. pTrustee->ptstrName,
  3120. TRUE,
  3121. (PSID *)&(TempTrustee.ptstrName),
  3122. &Type);
  3123. if(dwErr == ERROR_SUCCESS)
  3124. {
  3125. pTrustee = &TempTrustee;
  3126. }
  3127. }
  3128. if(dwErr == ERROR_SUCCESS)
  3129. {
  3130. dwErr = RemoveTrusteeFromAccess(SeInfo,
  3131. pTrustee,
  3132. pwszProperty);
  3133. }
  3134. AccFree(TempTrustee.ptstrName);
  3135. pTrustee = (PTRUSTEE)TrusteeList.NextData();
  3136. }
  3137. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::GetExplicitEntries: %lu\n",
  3138. dwErr));
  3139. return(dwErr);
  3140. }
  3141. //+---------------------------------------------------------------------------
  3142. //
  3143. // Member: CAccessList::CompressList, private
  3144. //
  3145. // Synopsis:
  3146. //
  3147. // Arguments: [] -- Whether to process the access and
  3148. // or audit list
  3149. // [] -- Trustee information list to
  3150. // process
  3151. //
  3152. // Returns: ERROR_SUCCESS -- Success
  3153. //
  3154. // Notes:
  3155. //
  3156. //----------------------------------------------------------------------------
  3157. DWORD CAccessList::CompressList(IN SECURITY_INFORMATION SeInfo,
  3158. OUT PACCLIST_CNODE *ppList,
  3159. OUT PULONG pcItems)
  3160. {
  3161. DWORD dwErr = ERROR_SUCCESS;
  3162. acDebugOut((DEB_TRACE_ACC,"In CAccessList::CompressList\n"));
  3163. BOOL fEmpty = FALSE;
  3164. //
  3165. // Ok, first, we'll have to go through and determine how many items there
  3166. // are
  3167. //
  3168. *pcItems = 0;
  3169. *ppList = 0;
  3170. _AccList.Reset();
  3171. PACCLIST_NODE pAccNode = (PACCLIST_NODE)_AccList.NextData();
  3172. while(pAccNode != NULL)
  3173. {
  3174. if(FLAG_ON(pAccNode->SeInfo, SeInfo))
  3175. {
  3176. (*pcItems)++;
  3177. }
  3178. pAccNode = (PACCLIST_NODE)_AccList.NextData();
  3179. }
  3180. //
  3181. // Now, do some allocations
  3182. //
  3183. if(*pcItems != 0)
  3184. {
  3185. *ppList = (PACCLIST_CNODE)AccAlloc(sizeof(ACCLIST_CNODE) * *pcItems);
  3186. if(*ppList == NULL)
  3187. {
  3188. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  3189. }
  3190. else
  3191. {
  3192. _AccList.Reset();
  3193. ULONG i = 0;
  3194. while(i < *pcItems )
  3195. {
  3196. pAccNode = (PACCLIST_NODE)_AccList.NextData();
  3197. if(FLAG_ON(pAccNode->SeInfo, SeInfo))
  3198. {
  3199. (*ppList)[i++].pONode = pAccNode;
  3200. }
  3201. }
  3202. //
  3203. // Now, sort the list based upon the property name
  3204. //
  3205. qsort(*ppList,
  3206. *pcItems,
  3207. sizeof(ACCLIST_CNODE),
  3208. CNodeCompare);
  3209. //
  3210. // Now, start processing them all...
  3211. //
  3212. for(i = 0; i < *pcItems; i++)
  3213. {
  3214. PACCLIST_CNODE pCN = &(*ppList)[i];
  3215. PACTRL_ACCESS_ENTRY_LIST pList =
  3216. SeInfo == DACL_SECURITY_INFORMATION ?
  3217. pCN->pONode->pAccessList :
  3218. pCN->pONode->pAuditList;
  3219. if(pList == NULL)
  3220. {
  3221. continue;
  3222. }
  3223. if(pList->cEntries == 0)
  3224. {
  3225. fEmpty = TRUE;
  3226. (*ppList)[i].Empty = TRUE;
  3227. pList->pAccessList = NULL;
  3228. }
  3229. else
  3230. {
  3231. fEmpty = FALSE;
  3232. }
  3233. //
  3234. // Go through and build some temprorary lists for each
  3235. // type.
  3236. //
  3237. CSList ExpList(NULL);
  3238. CSList L1List(NULL);
  3239. CSList L2List(NULL);
  3240. //
  3241. // We'll go through each entry and add it to our
  3242. // proper list. We'll also check for entries to
  3243. // collapse here as well. We'll do this by having our
  3244. // node comparrison routine mark the new access entry with
  3245. // a special bit if it finds a match
  3246. //
  3247. for(ULONG j = 0; j < pList->cEntries && !fEmpty; j++)
  3248. {
  3249. //
  3250. // Mark our ordering information
  3251. //
  3252. pList->pAccessList[j].fAccessFlags |=
  3253. GetOrderTypeForAccessEntry(
  3254. (*ppList)[i].pONode->pwszProperty,
  3255. &pList->pAccessList[j],
  3256. SeInfo);
  3257. if(FLAG_ON(pList->pAccessList[j].Inheritance,
  3258. INHERITED_GRANDPARENT))
  3259. {
  3260. dwErr = L2List.InsertIfUnique(
  3261. &(pList->pAccessList[j]),
  3262. CompAndMarkCompressNode);
  3263. }
  3264. else if(FLAG_ON(pList->pAccessList[j].Inheritance,
  3265. INHERITED_PARENT) ||
  3266. FLAG_ON(pList->pAccessList[j].Inheritance,
  3267. INHERITED_ACCESS_ENTRY))
  3268. {
  3269. dwErr = L1List.InsertIfUnique(
  3270. &(pList->pAccessList[j]),
  3271. CompAndMarkCompressNode);
  3272. }
  3273. else
  3274. {
  3275. dwErr = ExpList.InsertIfUnique(
  3276. &(pList->pAccessList[j]),
  3277. CompAndMarkCompressNode);
  3278. }
  3279. if(dwErr != ERROR_SUCCESS)
  3280. {
  3281. break;
  3282. }
  3283. } // for(j = 0; j < pList->cEntries; j++)
  3284. if ( fEmpty ) {
  3285. dwErr = ExpList.Insert( &(pList->pAccessList));
  3286. }
  3287. //
  3288. // Ok, now we are read to actually build our new list
  3289. //
  3290. ULONG cUsed = ExpList.QueryCount() + L1List.QueryCount() +
  3291. L2List.QueryCount();
  3292. ULONG cCompressed = pList->cEntries - cUsed;
  3293. if(dwErr == ERROR_SUCCESS)
  3294. {
  3295. pCN->pList = (PACTRL_ACCESS_ENTRY)AccAlloc(
  3296. sizeof(ACTRL_ACCESS_ENTRY) * cUsed);
  3297. if(pCN->pList == NULL)
  3298. {
  3299. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  3300. }
  3301. else
  3302. {
  3303. //
  3304. // Start processing them all...
  3305. //
  3306. ULONG iIndex = 0;
  3307. ULONG cComp;
  3308. pCN->cExp = ExpList.QueryCount();
  3309. pCN->cL1Inherit = L1List.QueryCount();
  3310. pCN->cL2Inherit = L2List.QueryCount();
  3311. if(pCN->cExp != 0)
  3312. {
  3313. dwErr = AddSubList(pCN,
  3314. ExpList,
  3315. iIndex);
  3316. }
  3317. if(dwErr == ERROR_SUCCESS && pCN->cL1Inherit != 0)
  3318. {
  3319. iIndex += pCN->cExp;
  3320. dwErr = AddSubList(pCN,
  3321. L1List,
  3322. iIndex);
  3323. }
  3324. if(dwErr == ERROR_SUCCESS && pCN->cL2Inherit != 0)
  3325. {
  3326. iIndex += pCN->cL1Inherit;
  3327. dwErr = AddSubList(pCN,
  3328. L2List,
  3329. iIndex);
  3330. }
  3331. //
  3332. // If that worked, we'll see about compressing
  3333. //
  3334. if(dwErr == ERROR_SUCCESS && cCompressed > 0)
  3335. {
  3336. for(j = 0;
  3337. j < pList->cEntries && cCompressed > 0;
  3338. j++)
  3339. {
  3340. if(FLAG_ON(pList->pAccessList[j].fAccessFlags,
  3341. ACCLIST_COMPRESS))
  3342. {
  3343. for(ULONG k = 0; k < cUsed; k++)
  3344. {
  3345. if(CompAndMarkCompressNode(
  3346. &(pList->pAccessList[j]),
  3347. &(pCN->pList[k])) == TRUE)
  3348. {
  3349. pList->pAccessList[j].fAccessFlags &=
  3350. ~ACCLIST_COMPRESS;
  3351. pCN->pList[k].fAccessFlags |=
  3352. pList->pAccessList[j].fAccessFlags;
  3353. pCN->pList[k].Access |=
  3354. pList->pAccessList[j].Access;
  3355. pCN->pList[k].Inheritance |=
  3356. pList->pAccessList[j].Inheritance;
  3357. pCN->pList[k].ProvSpecificAccess |=
  3358. pList->pAccessList[j].ProvSpecificAccess;
  3359. }
  3360. }
  3361. }
  3362. }
  3363. }
  3364. }
  3365. }
  3366. if(dwErr != ERROR_SUCCESS && cCompressed > 0)
  3367. {
  3368. //
  3369. // We'll have to go through and undo any compress
  3370. // bits we may have set
  3371. //
  3372. for(ULONG k = 0; k < j; k++)
  3373. {
  3374. pList->pAccessList[j].fAccessFlags &=
  3375. ~ACCLIST_COMPRESS;
  3376. }
  3377. }
  3378. }
  3379. }
  3380. if(dwErr != ERROR_SUCCESS)
  3381. {
  3382. FreeCompressedList(*ppList,
  3383. *pcItems);
  3384. *ppList = 0;
  3385. }
  3386. //
  3387. // Handle the special case of the non-zero, empty list
  3388. //
  3389. else if(fEmpty == TRUE)
  3390. {
  3391. (*ppList)[0].cExp = 1;
  3392. }
  3393. }
  3394. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::CompressList: %lu\n",
  3395. dwErr));
  3396. return(dwErr);
  3397. }
  3398. //+---------------------------------------------------------------------------
  3399. //
  3400. // Member: CAccessList::CompressList, private
  3401. //
  3402. // Synopsis:
  3403. //
  3404. // Arguments: [] -- Whether to process the access and
  3405. // or audit list
  3406. // [] -- Trustee information list to
  3407. // process
  3408. //
  3409. // Returns: ERROR_SUCCESS -- Success
  3410. //
  3411. // Notes:
  3412. //
  3413. //----------------------------------------------------------------------------
  3414. VOID CAccessList::FreeCompressedList(IN PACCLIST_CNODE pList,
  3415. IN ULONG cItems)
  3416. {
  3417. acDebugOut((DEB_TRACE_ACC,"In CAccessList::FreeCompressedList\n"));
  3418. if(pList != NULL)
  3419. {
  3420. for(ULONG i = 0; i < cItems; i++)
  3421. {
  3422. if(pList[i].pList == NULL)
  3423. {
  3424. break;
  3425. }
  3426. else
  3427. {
  3428. AccFree(pList[i].pList);
  3429. }
  3430. }
  3431. AccFree(pList);
  3432. }
  3433. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::FreeCompressedList\n"));
  3434. }
  3435. //+---------------------------------------------------------------------------
  3436. //
  3437. // Member: CAccessList::AddSubList, private
  3438. //
  3439. // Synopsis:
  3440. //
  3441. // Arguments: [] -- Whether to process the access and
  3442. // or audit list
  3443. // [] -- Trustee information list to
  3444. // process
  3445. //
  3446. // Returns: ERROR_SUCCESS -- Success
  3447. //
  3448. // Notes:
  3449. //
  3450. //----------------------------------------------------------------------------
  3451. DWORD CAccessList::AddSubList(IN PACCLIST_CNODE pCList,
  3452. IN CSList& TempList,
  3453. IN ULONG iStart)
  3454. {
  3455. DWORD dwErr = ERROR_SUCCESS;
  3456. acDebugOut((DEB_TRACE_ACC,"In CAccessList::AddSubList\n"));
  3457. if ( pCList->Empty ) {
  3458. return( dwErr );
  3459. }
  3460. //
  3461. // First, we copy all of the list entries
  3462. //
  3463. TempList.Reset();
  3464. PACTRL_ACCESS_ENTRY pAE = (PACTRL_ACCESS_ENTRY)TempList.NextData();
  3465. ULONG i = iStart;
  3466. while(pAE != NULL)
  3467. {
  3468. memcpy(&(pCList->pList[i]), pAE, sizeof(ACTRL_ACCESS_ENTRY));
  3469. i++;
  3470. pAE = (PACTRL_ACCESS_ENTRY)TempList.NextData();
  3471. }
  3472. //
  3473. // Now, order them...
  3474. //
  3475. dwErr = OrderListBySid(pCList,
  3476. iStart,
  3477. TempList.QueryCount());
  3478. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::AddSubList: %lu\n", dwErr));
  3479. return(dwErr);
  3480. }
  3481. //+---------------------------------------------------------------------------
  3482. //
  3483. // Member: CAccessList::CompressList, private
  3484. //
  3485. // Synopsis:
  3486. //
  3487. // Arguments: [] -- Whether to process the access and
  3488. // or audit list
  3489. // [] -- Trustee information list to
  3490. // process
  3491. //
  3492. // Returns: ERROR_SUCCESS -- Success
  3493. //
  3494. // Notes:
  3495. //
  3496. //----------------------------------------------------------------------------
  3497. DWORD CAccessList::SizeCompressedListAsAcl(IN PACCLIST_CNODE pList,
  3498. IN ULONG cItems,
  3499. OUT PULONG pcSize,
  3500. IN BOOL fForceNullToEmpty)
  3501. {
  3502. DWORD dwErr = ERROR_SUCCESS;
  3503. acDebugOut((DEB_TRACE_ACC,"In CAccessList::SizeCompressedListAsAcl\n"));
  3504. ULONG cTotalEnts = 0;
  3505. BOOL Empty = FALSE;
  3506. *pcSize = 0;
  3507. for(ULONG i = 0; i < cItems; i++)
  3508. {
  3509. ULONG cEnts = pList[i].cExp + pList[i].cL1Inherit + pList[i].cL2Inherit;
  3510. cTotalEnts += cEnts;
  3511. for(ULONG j = 0; j < cEnts; j++)
  3512. {
  3513. BOOL fObjectAce = FALSE;
  3514. if(pList[i].pONode->pwszProperty != NULL)
  3515. {
  3516. (*pcSize) += sizeof(GUID);
  3517. fObjectAce = TRUE;
  3518. }
  3519. if(pList[i].pList == NULL || pList[i].Empty == TRUE)
  3520. {
  3521. continue;
  3522. }
  3523. if(pList[i].pList[j].lpInheritProperty != NULL)
  3524. {
  3525. (*pcSize) += sizeof(GUID);
  3526. fObjectAce = TRUE;
  3527. }
  3528. //
  3529. // Find the trustee for this node
  3530. //
  3531. PTRUSTEE_NODE pTN = NULL;
  3532. dwErr = GetTrusteeNode(&(pList[i].pList[j].Trustee),
  3533. TRUSTEE_OPT_SID,
  3534. &pTN);
  3535. if(dwErr == ERROR_SUCCESS)
  3536. {
  3537. //
  3538. // Then, add in the SID
  3539. //
  3540. (*pcSize) += RtlLengthSid(pTN->pSid) - sizeof(ULONG);
  3541. if(pTN->pImpersonate != NULL)
  3542. {
  3543. (*pcSize) += RtlLengthSid(pTN->pSid);
  3544. }
  3545. }
  3546. else
  3547. {
  3548. break;
  3549. }
  3550. //
  3551. // Then, add the size of the ACE
  3552. //
  3553. if(pTN->pImpersonate != NULL)
  3554. {
  3555. if(fObjectAce == FALSE)
  3556. {
  3557. (*pcSize) += sizeof(KNOWN_COMPOUND_ACE);
  3558. }
  3559. else
  3560. {
  3561. dwErr = ERROR_INVALID_PARAMETER;
  3562. }
  3563. }
  3564. else
  3565. {
  3566. if(fObjectAce == TRUE)
  3567. {
  3568. (*pcSize) += sizeof(KNOWN_OBJECT_ACE);
  3569. }
  3570. else
  3571. {
  3572. (*pcSize) += sizeof(KNOWN_ACE);
  3573. }
  3574. }
  3575. }
  3576. if(cEnts == 0 && fForceNullToEmpty == TRUE)
  3577. {
  3578. Empty = TRUE;
  3579. }
  3580. }
  3581. if(cTotalEnts != 0 || Empty == TRUE)
  3582. {
  3583. (*pcSize) += sizeof(ACL);
  3584. }
  3585. acDebugOut((DEB_TRACE_ACC,
  3586. "Out CAccessList::SizeCompressedListAsAcl: %lu\n",
  3587. dwErr));
  3588. return(dwErr);
  3589. }
  3590. //+---------------------------------------------------------------------------
  3591. //
  3592. // Member: CAccessList::BuildAcl, private
  3593. //
  3594. // Synopsis: The method will build an acl out of the individual access entries
  3595. //
  3596. // Arguments: [pList] -- List of entries in compressed form
  3597. // [cItems] -- Number of items in the list
  3598. // [pAcl] -- Acl to fill in
  3599. // [SeInfo] -- Building DACL or SACL
  3600. // [pfProtected] -- If TRUE, the acl should be protected
  3601. //
  3602. // Returns: ERROR_SUCCESS -- Success
  3603. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  3604. //
  3605. // Notes:
  3606. //
  3607. //----------------------------------------------------------------------------
  3608. DWORD CAccessList::BuildAcl(IN PACCLIST_CNODE pList,
  3609. IN ULONG cItems,
  3610. IN PACL pAcl,
  3611. IN SECURITY_INFORMATION SeInfo,
  3612. OUT BOOL *pfProtected)
  3613. {
  3614. acDebugOut((DEB_TRACE_ACC,"In CAccessList::BuildAcl\n"));
  3615. DWORD dwErr = ERROR_SUCCESS;
  3616. BOOL fIsSacl = FALSE;
  3617. PULONG pIList = (PULONG)AccAlloc(cItems * sizeof(ULONG));
  3618. if(pIList == NULL)
  3619. {
  3620. return(ERROR_NOT_ENOUGH_MEMORY);
  3621. }
  3622. //
  3623. // Ok, now we'll process this list several times, so we get entries
  3624. // in the following order:
  3625. //
  3626. // ACCESS_DENIED_ACE on the object
  3627. // ACCESS_DENIED_OBJECT_ACE
  3628. // ACCESS_ALLOWED_ACE on the object
  3629. // ACCESS_ALLOWED_OBJECT_ACE on an object
  3630. // ACCESS_ALLOWED_OBJECT_ACE on a property set
  3631. // ACCESS_ALLOWED_OBJECT_ACE on a property
  3632. //
  3633. //
  3634. // List of entry attributes we're looking for
  3635. //
  3636. ULONG EntryAttribs[] = {ACCLIST_DENIED,
  3637. ACCLIST_OBJ_DENIED,
  3638. ACCLIST_ALLOWED,
  3639. ACCLIST_OBJ_ALLOWED,
  3640. ACCLIST_PSET_ALLOWED,
  3641. ACCLIST_PROP_ALLOWED,
  3642. 0}; // Cover anything out of place...
  3643. //
  3644. // Process all of the items
  3645. //
  3646. *pfProtected = FALSE;
  3647. //
  3648. // We'll process the list of compressed entries each time, looking for
  3649. // entries from a different level (base, then inherited, then grandparent
  3650. // inherited
  3651. //
  3652. ULONG InheritAttribs[] = {0,
  3653. INHERITED_PARENT,
  3654. INHERITED_GRANDPARENT};
  3655. for(ULONG iInherit = 0;
  3656. iInherit < sizeof(InheritAttribs) / sizeof(ULONG) && dwErr == ERROR_SUCCESS;
  3657. iInherit++)
  3658. {
  3659. for(ULONG iEntry = 0;
  3660. iEntry < sizeof(EntryAttribs) / sizeof(ULONG) && dwErr == ERROR_SUCCESS;
  3661. iEntry++)
  3662. {
  3663. for(ULONG i = 0; i < cItems && dwErr == ERROR_SUCCESS; i++)
  3664. {
  3665. LPGUID pObjectId = NULL;
  3666. if(pList[i].pONode->pwszProperty != NULL)
  3667. {
  3668. dwErr = AccctrlLookupGuid(_pLDAP,
  3669. _pwszDsPathReference,
  3670. pList[i].pONode->pwszProperty,
  3671. FALSE,
  3672. &pObjectId);
  3673. }
  3674. //
  3675. // Process the items in the lists that match our criteria...
  3676. //
  3677. for(ULONG j = pIList[i];
  3678. j < pList[i].cExp + pList[i].cL1Inherit +
  3679. pList[i].cL2Inherit &&
  3680. dwErr == ERROR_SUCCESS;
  3681. j++)
  3682. {
  3683. if((FLAG_ON(pList[i].pList[j].Inheritance,
  3684. InheritAttribs[iInherit]) ||
  3685. InheritAttribs[iInherit] == 0 &&
  3686. !FLAG_ON(pList[i].pList[j].Inheritance,
  3687. INHERITED_PARENT | INHERITED_GRANDPARENT)) &&
  3688. (FLAG_ON(pList[i].pList[j].fAccessFlags,
  3689. EntryAttribs[iEntry]) ||
  3690. EntryAttribs[iEntry] == 0))
  3691. {
  3692. //
  3693. // Ok, we can add this in
  3694. //
  3695. dwErr = InsertEntryInAcl(&(pList[i].pList[j]),
  3696. pObjectId,
  3697. pAcl);
  3698. }
  3699. else
  3700. {
  3701. break;
  3702. }
  3703. }
  3704. pIList[i] = j;
  3705. //
  3706. // See if it's protected
  3707. //
  3708. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION) &&
  3709. FLAG_ON(pList[i].pONode->fState, ACCLIST_DACL_PROTECTED))
  3710. {
  3711. *pfProtected = TRUE;
  3712. }
  3713. if(FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION) &&
  3714. FLAG_ON(pList[i].pONode->fState, ACCLIST_SACL_PROTECTED))
  3715. {
  3716. *pfProtected = TRUE;
  3717. }
  3718. }
  3719. }
  3720. }
  3721. AccFree(pIList);
  3722. acDebugOut((DEB_TRACE_ACC,"Out CAccessList::BuildAcl: %lu\n",
  3723. dwErr));
  3724. return(dwErr);
  3725. }
  3726. //+---------------------------------------------------------------------------
  3727. //
  3728. // Member: CAccessList::InsertEntryInAcl, private
  3729. //
  3730. // Synopsis: Inserts an access entry into the acl
  3731. //
  3732. // Arguments: [pAE] -- Access entry to insert
  3733. // [pObject] -- If present, this is an object type ace
  3734. // [pAcl] -- Acl to do the insertion for
  3735. //
  3736. // Returns: ERROR_SUCCESS -- Success
  3737. // ERROR_INVALID_ACL A compound ace type was specified
  3738. //
  3739. // Notes:
  3740. //
  3741. //----------------------------------------------------------------------------
  3742. DWORD CAccessList::InsertEntryInAcl(IN PACTRL_ACCESS_ENTRY pAE,
  3743. IN GUID *pObject,
  3744. IN PACL pAcl)
  3745. {
  3746. DWORD dwErr = ERROR_SUCCESS;
  3747. LPGUID pInheritId = NULL;
  3748. BOOL fIsObjectAce = FALSE;
  3749. BOOL fIsSacl = FALSE;
  3750. if(pAE->lpInheritProperty != NULL)
  3751. {
  3752. dwErr = AccctrlLookupGuid(_pLDAP,
  3753. _pwszDsPathReference,
  3754. pAE->lpInheritProperty,
  3755. FALSE,
  3756. &pInheritId);
  3757. fIsObjectAce = TRUE;
  3758. if(dwErr != ERROR_SUCCESS)
  3759. {
  3760. return(dwErr);
  3761. }
  3762. }
  3763. if(pObject != NULL)
  3764. {
  3765. fIsObjectAce = TRUE;
  3766. }
  3767. //
  3768. // First, get the trustee
  3769. //
  3770. PTRUSTEE_NODE pTN;
  3771. dwErr = GetTrusteeNode(&(pAE->Trustee),
  3772. TRUSTEE_OPT_SID,
  3773. &pTN);
  3774. if(dwErr != ERROR_SUCCESS)
  3775. {
  3776. return(dwErr);
  3777. }
  3778. //
  3779. // Add the ace
  3780. //
  3781. ACCESS_MASK AM = AccessMaskForAccessEntry(pAE, _ObjType);
  3782. ACCESS_RIGHTS fAccess = pAE->fAccessFlags & ~ACCLIST_VALID_TYPE_FLAGS;
  3783. INHERIT_FLAGS Inherit = pAE->Inheritance & ~ACCLIST_VALID_IN_LEVEL_FLAGS;
  3784. if(dwErr == ERROR_SUCCESS)
  3785. {
  3786. if(pTN->pImpersonate == NULL)
  3787. {
  3788. if(fAccess == ACTRL_ACCESS_ALLOWED)
  3789. {
  3790. if(fIsObjectAce == TRUE)
  3791. {
  3792. if(AddAccessAllowedObjectAce(
  3793. pAcl,
  3794. ACL_REVISION4,
  3795. Inherit,
  3796. AM,
  3797. pObject,
  3798. pInheritId,
  3799. pTN->pSid) == FALSE)
  3800. {
  3801. dwErr = GetLastError();
  3802. }
  3803. }
  3804. else
  3805. {
  3806. if(AddAccessAllowedAceEx(
  3807. pAcl,
  3808. ACL_REVISION2,
  3809. Inherit,
  3810. AM,
  3811. pTN->pSid) == FALSE)
  3812. {
  3813. dwErr = GetLastError();
  3814. }
  3815. }
  3816. }
  3817. else if(fAccess == ACTRL_ACCESS_DENIED)
  3818. {
  3819. if(fIsObjectAce == TRUE)
  3820. {
  3821. if(AddAccessDeniedObjectAce(
  3822. pAcl,
  3823. ACL_REVISION4,
  3824. Inherit,
  3825. AM,
  3826. pObject,
  3827. pInheritId,
  3828. pTN->pSid) == FALSE)
  3829. {
  3830. dwErr = GetLastError();
  3831. }
  3832. }
  3833. else
  3834. {
  3835. if(AddAccessDeniedAceEx(
  3836. pAcl,
  3837. ACL_REVISION2,
  3838. Inherit,
  3839. AM,
  3840. pTN->pSid) == FALSE)
  3841. {
  3842. dwErr = GetLastError();
  3843. }
  3844. }
  3845. }
  3846. else if(FLAG_ON(fAccess,
  3847. (ACTRL_AUDIT_SUCCESS |
  3848. ACTRL_AUDIT_FAILURE)))
  3849. {
  3850. fIsSacl = TRUE;
  3851. if(fIsObjectAce == TRUE)
  3852. {
  3853. if(AddAuditAccessObjectAce(
  3854. pAcl,
  3855. ACL_REVISION4,
  3856. Inherit,
  3857. AM,
  3858. pObject,
  3859. pInheritId,
  3860. pTN->pSid,
  3861. FLAG_ON(fAccess,
  3862. ACTRL_AUDIT_SUCCESS),
  3863. FLAG_ON(fAccess,
  3864. ACTRL_AUDIT_FAILURE)) == FALSE)
  3865. {
  3866. dwErr = GetLastError();
  3867. }
  3868. }
  3869. else
  3870. {
  3871. if(AddAuditAccessAceEx(
  3872. pAcl,
  3873. ACL_REVISION2,
  3874. Inherit,
  3875. AM,
  3876. pTN->pSid,
  3877. (BOOL)FLAG_ON(fAccess,
  3878. ACTRL_AUDIT_SUCCESS),
  3879. (BOOL)FLAG_ON(fAccess,
  3880. ACTRL_AUDIT_FAILURE)) == FALSE)
  3881. {
  3882. dwErr = GetLastError();
  3883. }
  3884. }
  3885. }
  3886. else
  3887. {
  3888. dwErr = ERROR_INVALID_ACL;
  3889. }
  3890. }
  3891. else
  3892. {
  3893. #if 0
  3894. if(pAE->fAccessFlags == ACTRL_ACCESS_ALLOWED)
  3895. {
  3896. NTSTATUS Status;
  3897. if(pANList[j].pNode->pwszProperty != NULL)
  3898. {
  3899. dwErr = ERROR_INVALID_ACL;
  3900. }
  3901. else
  3902. {
  3903. Status = RtlAddCompoundAce(
  3904. pAcl,
  3905. ACL_REVISION3,
  3906. ACCESS_ALLOWED_COMPOUND_ACE_TYPE,
  3907. AM,
  3908. pTN->pSid,
  3909. pTN->pImpersonate->pSid);
  3910. }
  3911. }
  3912. else
  3913. {
  3914. dwErr = ERROR_INVALID_ACL;
  3915. }
  3916. #endif
  3917. //
  3918. // Compound aces are disabled for the PDC
  3919. //
  3920. dwErr = ERROR_INVALID_ACL;
  3921. }
  3922. }
  3923. //
  3924. // Add in our protected flag...
  3925. //
  3926. if(dwErr == ERROR_SUCCESS)
  3927. {
  3928. ULONG fFlags = fIsSacl == FALSE ?
  3929. _fDAclFlags :
  3930. _fSAclFlags;
  3931. if(FLAG_ON(fFlags,ACTRL_ACCESS_PROTECTED))
  3932. {
  3933. pAcl->Sbz1 |= fIsSacl == FALSE ?
  3934. SE_DACL_PROTECTED :
  3935. SE_SACL_PROTECTED;
  3936. }
  3937. }
  3938. return(dwErr);
  3939. }