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

2130 lines
60 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1996.
  5. //
  6. // File: alsup.cxx
  7. //
  8. // Contents: CAccessList support functions
  9. //
  10. // Classes:
  11. //
  12. // History: 06-Nov-96 MacM Created
  13. //
  14. //--------------------------------------------------------------------
  15. #include <aclpch.hxx>
  16. #pragma hdrstop
  17. #include <alsup.hxx>
  18. #include <netlib.h>
  19. #include <seopaque.h>
  20. #include <sertlp.h>
  21. #include <martaevt.h>
  22. #include <ntprov.hxx>
  23. #include <strings.h>
  24. DWORD
  25. InitializeEvents(void);
  26. //+---------------------------------------------------------------------------
  27. //
  28. // Function: GetOrderTypeForAccessEntry
  29. //
  30. // Synopsis: Determines the "order" type of entry given the node
  31. // information
  32. //
  33. // Arguments: [pwszProperty] -- The property this entry is
  34. // associated with
  35. // [pAE] -- The entry to check
  36. // [SeInfo] -- Type of node this is supposed to
  37. // be
  38. //
  39. // Returns: The type of the node. This is a bitmask flag of the types
  40. // ACCLIST_DENIED through ACCLIST_PROP_ALLOWED
  41. //
  42. // Notes:
  43. //
  44. //----------------------------------------------------------------------------
  45. ULONG GetOrderTypeForAccessEntry(IN PWSTR pwszProperty,
  46. IN PACTRL_ACCESS_ENTRY pAE,
  47. IN SECURITY_INFORMATION SeInfo)
  48. {
  49. ULONG Type = 0;
  50. //
  51. // First, check the simple cases (like audit or invalid)
  52. //
  53. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  54. {
  55. if(FLAG_ON(pAE->fAccessFlags,
  56. ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE))
  57. {
  58. Type = ACCLIST_AUDIT;
  59. }
  60. }
  61. else
  62. {
  63. if(!FLAG_ON(pAE->fAccessFlags,
  64. ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) &&
  65. FLAG_ON(pAE->fAccessFlags,
  66. ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED))
  67. {
  68. Type = ACCLIST_UNKOWN_ENTRY;
  69. }
  70. else
  71. {
  72. Type = ACCLIST_AUDIT;
  73. }
  74. }
  75. if(Type == 0)
  76. {
  77. if(pwszProperty == NULL && pAE->lpInheritProperty == NULL)
  78. {
  79. Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  80. ACCLIST_DENIED :
  81. ACCLIST_ALLOWED;
  82. }
  83. else if(pwszProperty == NULL)
  84. {
  85. Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  86. ACCLIST_OBJ_DENIED :
  87. ACCLIST_PROP_ALLOWED;
  88. }
  89. else
  90. {
  91. Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  92. ACCLIST_OBJ_DENIED :
  93. ACCLIST_OBJ_ALLOWED;
  94. }
  95. //
  96. // See if it's inherited. If it is, and we don't have a level
  97. // flag, assume it's level 1 and mark it as such
  98. //
  99. if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY) &&
  100. !FLAG_ON(pAE->Inheritance,
  101. INHERITED_PARENT | INHERITED_GRANDPARENT))
  102. {
  103. pAE->Inheritance |= INHERITED_PARENT;
  104. }
  105. }
  106. return(Type);
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // Function: OrderListBySid
  111. //
  112. // Synopsis: Orders an acclist_cnode list by sid. The order would be:
  113. // Everyone
  114. // Well known groups
  115. // Groups
  116. // Users
  117. // Anyone else
  118. //
  119. // Arguments: [pList] -- List of the nodes to sort
  120. // [iStart] -- Where to start in the list
  121. // [iLen] -- Number of nodes in the list
  122. //
  123. // Returns: ERROR_SUCCESS -- Success
  124. //
  125. // Notes:
  126. //
  127. //----------------------------------------------------------------------------
  128. ULONG OrderListBySid(IN PACCLIST_CNODE pList,
  129. IN ULONG iStart,
  130. IN ULONG iLen)
  131. {
  132. DWORD dwErr = ERROR_SUCCESS;
  133. return(dwErr);
  134. }
  135. //
  136. // Local functions
  137. //
  138. //+---------------------------------------------------------------------------
  139. //
  140. // Function: DelAcclistNode
  141. //
  142. // Synopsis: Deletes an ACCLIST_NODE that's kept in the _AccList. This is
  143. // used by the CSList
  144. //
  145. // Arguments: [IN pvNode] -- Node to delete
  146. //
  147. // Returns: VOID
  148. //
  149. //----------------------------------------------------------------------------
  150. void DelAcclistNode(PVOID pvNode)
  151. {
  152. PACCLIST_NODE pNode = (PACCLIST_NODE)pvNode;
  153. AccFree(pNode->pAccessList);
  154. AccFree(pNode->pAuditList);
  155. AccFree(pNode->pwszProperty);
  156. AccFree(pNode);
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Function: DelTrusteeNode
  161. //
  162. // Synopsis: Deletes an TRUSTEE_NODE that's kept in the _TrusteeList.
  163. // This is used by the CSList
  164. //
  165. // Arguments: [IN pvNode] -- Node to delete
  166. //
  167. // Returns: VOID
  168. //
  169. //----------------------------------------------------------------------------
  170. void DelTrusteeNode(PVOID pvNode)
  171. {
  172. acDebugOut((DEB_TRACE_ACC, "IN DelTrusteeNode\n"));
  173. PTRUSTEE_NODE pNode = (PTRUSTEE_NODE)pvNode;
  174. if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_SID))
  175. {
  176. AccFree(pNode->pSid);
  177. }
  178. if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_NAME))
  179. {
  180. AccFree(pNode->pwszTrusteeName);
  181. AccFree(pNode->pwszDomainName);
  182. }
  183. else if(FLAG_ON(pNode->fFlags, TRUSTEE_DELETE_DOMAIN))
  184. {
  185. AccFree(pNode->pwszDomainName);
  186. }
  187. AccFree(pNode);
  188. acDebugOut((DEB_TRACE_ACC, "Out DelTrusteeNode\n"));
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // Function: CompInheritProps
  193. //
  194. // Synopsis: Compare the given property name to the PIPROP_IN_BUFF stuct
  195. //
  196. // Arguments: [IN pvTrustee] -- Trustee to look for
  197. // [IN pvNode2] -- 2nd node to compare
  198. //
  199. // Returns: TRUE -- Nodes equal
  200. // FALSE -- Nodes not equal
  201. //
  202. //----------------------------------------------------------------------------
  203. BOOL CompInheritProps(IN PVOID pvInheritProp,
  204. IN PVOID pvNode2)
  205. {
  206. BOOL fRet = FALSE;
  207. PIPROP_IN_BUFF pPIB = (PIPROP_IN_BUFF)pvNode2;
  208. if(pvInheritProp != NULL)
  209. {
  210. if(_wcsicmp((PWSTR)pvInheritProp, (PWSTR)(pPIB->pwszIProp)) == 0)
  211. {
  212. fRet = TRUE;
  213. }
  214. }
  215. return(fRet);
  216. }
  217. //+---------------------------------------------------------------------------
  218. //
  219. // Function: CompTrustees
  220. //
  221. // Synopsis: Compare two TRUSTEE_NODES. Used by _TrusteeList.
  222. //
  223. // Arguments: [IN pvTrustee] -- Trustee to look for
  224. // [IN pvNode2] -- 2nd node to compare
  225. //
  226. // Returns: TRUE -- Nodes equal
  227. // FALSE -- Nodes not equal
  228. //
  229. //----------------------------------------------------------------------------
  230. BOOL CompTrustees(IN PVOID pvTrustee,
  231. IN PVOID pvTrustee2)
  232. {
  233. PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee;
  234. TRUSTEE_NODE TrusteeNode;
  235. BOOL Result = FALSE;
  236. memset( &TrusteeNode, 0, sizeof( TrusteeNode ) );
  237. memcpy( &TrusteeNode.Trustee, pvTrustee2, sizeof( TRUSTEE ) );
  238. Result = CompTrusteeToTrusteeNode(pvTrustee, &TrusteeNode);
  239. if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_SID))
  240. {
  241. AccFree(TrusteeNode.pSid);
  242. }
  243. if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_NAME))
  244. {
  245. AccFree(TrusteeNode.pwszTrusteeName);
  246. AccFree(TrusteeNode.pwszDomainName);
  247. TrusteeNode.pwszDomainName = NULL;
  248. }
  249. if(FLAG_ON(TrusteeNode.fFlags, TRUSTEE_DELETE_DOMAIN))
  250. {
  251. AccFree(TrusteeNode.pwszDomainName);
  252. }
  253. return(Result);
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Function: CompTrusteeToTrusteeNode
  258. //
  259. // Synopsis: Compare two trustees for equality
  260. //
  261. // Arguments: [IN pvTrustee] -- Trustee to look for
  262. // [IN pvNode2] -- 2nd node to compare
  263. //
  264. // Returns: TRUE -- Nodes equal
  265. // FALSE -- Nodes not equal
  266. //
  267. //----------------------------------------------------------------------------
  268. BOOL CompTrusteeToTrusteeNode(IN PVOID pvTrustee,
  269. IN PVOID pvNode2)
  270. {
  271. PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee;
  272. PTRUSTEE_NODE pNode2 = (PTRUSTEE_NODE)pvNode2;
  273. DWORD dwErr = ERROR_SUCCESS;
  274. BOOL fMatch = FALSE;
  275. if(pTrustee->MultipleTrusteeOperation ==
  276. pNode2->Trustee.MultipleTrusteeOperation)
  277. {
  278. //
  279. // Ok, first compare the base trustee information...
  280. //
  281. if(pTrustee->TrusteeForm != pNode2->Trustee.TrusteeForm)
  282. {
  283. //
  284. // We don't have matching information, so we'll have to look
  285. // it up.
  286. //
  287. ULONG fOptions = 0;
  288. if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
  289. {
  290. fOptions = TRUSTEE_OPT_NAME;
  291. }
  292. else
  293. {
  294. fOptions = TRUSTEE_OPT_SID;
  295. }
  296. dwErr = LookupTrusteeNodeInformation(NULL,
  297. pNode2,
  298. fOptions);
  299. }
  300. //
  301. // Now, do the comparrisons
  302. //
  303. if(dwErr == ERROR_SUCCESS)
  304. {
  305. //
  306. // Now, compare the trustees
  307. //
  308. if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
  309. {
  310. if(_wcsicmp(pTrustee->ptstrName,
  311. pNode2->pwszTrusteeName ?
  312. pNode2->pwszTrusteeName :
  313. pNode2->Trustee.ptstrName) == 0)
  314. {
  315. fMatch = TRUE;
  316. }
  317. }
  318. else
  319. {
  320. if(pTrustee->ptstrName == NULL ||
  321. (pNode2->Trustee.ptstrName == NULL && pNode2->pSid == NULL))
  322. {
  323. fMatch = FALSE;
  324. }
  325. else
  326. {
  327. fMatch = RtlEqualSid((PSID)(pTrustee->ptstrName),
  328. (PSID)(pNode2->pSid ?
  329. pNode2->pSid :
  330. pNode2->Trustee.ptstrName));
  331. }
  332. }
  333. }
  334. //
  335. // Now, if that worked, look for the multiple trustee case
  336. //
  337. if(fMatch == TRUE &&
  338. pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
  339. {
  340. fMatch = CompTrusteeToTrusteeNode(pTrustee->pMultipleTrustee,
  341. pNode2->pImpersonate);
  342. }
  343. }
  344. return(fMatch);
  345. }
  346. //+---------------------------------------------------------------------------
  347. //
  348. // Function: DoPropertiesMatch
  349. //
  350. // Synopsis: Determines if 2 properties are equal. It takes into account
  351. // the possibility of a NULL property.
  352. //
  353. // Arguments: [IN pwszProp1] -- 1st property to compare
  354. // [IN pwszProp2] -- 2nd property to compare
  355. //
  356. // Returns: TRUE -- Properties are equal
  357. // FALSE -- Properties are not equal
  358. //
  359. //----------------------------------------------------------------------------
  360. BOOL DoPropertiesMatch(IN PWSTR pwszProp1,
  361. IN PWSTR pwszProp2)
  362. {
  363. BOOL fReturn = FALSE;
  364. if(pwszProp1 == NULL || pwszProp2 == NULL)
  365. {
  366. if(pwszProp1 == pwszProp2)
  367. {
  368. fReturn = TRUE;
  369. }
  370. }
  371. else
  372. {
  373. if(_wcsicmp(pwszProp1, pwszProp2) == 0)
  374. {
  375. fReturn = TRUE;
  376. }
  377. }
  378. return(fReturn);
  379. }
  380. //+---------------------------------------------------------------------------
  381. //
  382. // Function: CompProps
  383. //
  384. // Synopsis: Compare an ACCLIST_NODE to a property
  385. //
  386. // Arguments: [IN pvProp] -- Property string
  387. // [IN pvNode] -- Node to compare
  388. //
  389. // Returns: TRUE -- Nodes equal
  390. // FALSE -- Nodes not equal
  391. //
  392. //----------------------------------------------------------------------------
  393. BOOL CompProps(IN PVOID pvProp,
  394. IN PVOID pvNode)
  395. {
  396. PACCLIST_NODE pAN = (PACCLIST_NODE)pvNode;
  397. return(DoPropertiesMatch((PWSTR)pvProp, pAN->pwszProperty));
  398. }
  399. //+---------------------------------------------------------------------------
  400. //
  401. // Function: CompGuids
  402. //
  403. // Synopsis: Compare an ACCLIST_ATOACCESS structure to a guid
  404. //
  405. // Arguments: [IN pvGuid] -- Guid
  406. // [IN pvNode] -- Node to compare
  407. //
  408. // Returns: TRUE -- Nodes equal
  409. // FALSE -- Nodes not equal
  410. //
  411. //----------------------------------------------------------------------------
  412. BOOL CompGuids(IN PVOID pvGuid,
  413. IN PVOID pvNode)
  414. {
  415. PACCLIST_ATOACCESS pAA = (PACCLIST_ATOACCESS)pvNode;
  416. GUID *pGuid = (GUID *)pvGuid;
  417. if(pGuid == NULL && pAA->pGuid == NULL)
  418. {
  419. return(TRUE);
  420. }
  421. else if(pGuid == NULL || pAA->pGuid == NULL)
  422. {
  423. return(FALSE);
  424. }
  425. return((BOOL)!memcmp(pGuid, pAA->pGuid, sizeof(GUID)));
  426. }
  427. //+---------------------------------------------------------------------------
  428. //
  429. // Function: LookupTrusteeNodeInformation
  430. //
  431. // Synopsis: Looks up the appropriate trustee information. This involves
  432. // either looking up the trustees sid or name, depending on
  433. // the options
  434. //
  435. // Arguments: [pwszServer] -- Name of server to lookup information on
  436. // [pTrusteeNode] -- Trustee to lookup the information
  437. // for
  438. // [fOptions] -- What information to lookup
  439. //
  440. // Returns: ERROR_SUCCESS -- Success
  441. //
  442. // Notes:
  443. //
  444. //----------------------------------------------------------------------------
  445. DWORD LookupTrusteeNodeInformation(IN PWSTR pwszServer,
  446. IN PTRUSTEE_NODE pTrusteeNode,
  447. IN ULONG fOptions)
  448. {
  449. DWORD dwErr = ERROR_SUCCESS;
  450. SID_NAME_USE SidType = SidTypeUnknown;
  451. //
  452. // Need to make sure we have the SID
  453. //
  454. if(FLAG_ON(fOptions, TRUSTEE_OPT_SID))
  455. {
  456. //
  457. // Make sure we have the sids
  458. //
  459. if(pTrusteeNode->pSid == NULL)
  460. {
  461. dwErr = AccctrlLookupSid(pwszServer,
  462. pTrusteeNode->Trustee.ptstrName,
  463. TRUE,
  464. &(pTrusteeNode->pSid),
  465. &SidType);
  466. if(dwErr == ERROR_SUCCESS)
  467. {
  468. pTrusteeNode->fFlags |= TRUSTEE_DELETE_SID;
  469. }
  470. }
  471. }
  472. //
  473. // Ok, we need to have the name
  474. //
  475. if(dwErr == ERROR_SUCCESS && FLAG_ON(fOptions, TRUSTEE_OPT_NAME))
  476. {
  477. //
  478. // Make sure we have the name
  479. //
  480. if(pTrusteeNode->pwszTrusteeName == NULL)
  481. {
  482. dwErr = AccctrlLookupName(pwszServer,
  483. pTrusteeNode->pSid,
  484. TRUE,
  485. &(pTrusteeNode->pwszTrusteeName),
  486. &SidType);
  487. if(dwErr == ERROR_SUCCESS)
  488. {
  489. pTrusteeNode->fFlags |= TRUSTEE_DELETE_NAME;
  490. }
  491. }
  492. }
  493. //
  494. // Then, take care of our sid type
  495. //
  496. if(dwErr == ERROR_SUCCESS && pTrusteeNode->SidType == SidTypeUnknown)
  497. {
  498. pTrusteeNode->SidType = SidType;
  499. if(SidType == SidTypeUnknown)
  500. {
  501. pTrusteeNode->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  502. }
  503. else
  504. {
  505. pTrusteeNode->Trustee.TrusteeType = (TRUSTEE_TYPE)(SidType);
  506. }
  507. }
  508. return(dwErr);
  509. }
  510. //+---------------------------------------------------------------------------
  511. //
  512. // Function: GetATypeForEntry
  513. //
  514. // Synopsis: Determines the type of entry given the node information
  515. //
  516. // Arguments: [pwszProperty] -- The property this entry is
  517. // associated with
  518. // [pAE] -- The entry to check
  519. // [SeInfo] -- Type of node this is supposed to
  520. // be
  521. //
  522. // Returns: The type of the node
  523. //
  524. // Notes:
  525. //
  526. //----------------------------------------------------------------------------
  527. ACC_ACLBLD_TYPE GetATypeForEntry(IN PWSTR pwszProperty,
  528. IN PACTRL_ACCESS_ENTRY pAE,
  529. IN SECURITY_INFORMATION SeInfo)
  530. {
  531. ACC_ACLBLD_TYPE AType = AAT_DENIED;
  532. //
  533. // First, check the simple cases (like audit or invalid)
  534. //
  535. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  536. {
  537. if(FLAG_ON(pAE->fAccessFlags,
  538. ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE))
  539. {
  540. AType = AAT_INVALID;
  541. }
  542. }
  543. else
  544. {
  545. if(!FLAG_ON(pAE->fAccessFlags,
  546. ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) &&
  547. FLAG_ON(pAE->fAccessFlags,
  548. ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED))
  549. {
  550. AType = AAT_INVALID;
  551. }
  552. else
  553. {
  554. AType = AAT_AUDIT;
  555. }
  556. }
  557. if(AType == 0)
  558. {
  559. if(pwszProperty == NULL && pAE->lpInheritProperty == NULL)
  560. {
  561. AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  562. AAT_DENIED :
  563. AAT_ALLOWED;
  564. }
  565. else if(pwszProperty == NULL)
  566. {
  567. AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  568. AAT_OBJ_DENIED :
  569. AAT_PROP_ALLOWED;
  570. }
  571. else
  572. {
  573. AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ?
  574. AAT_OBJ_DENIED :
  575. AAT_OBJ_ALLOWED;
  576. }
  577. //
  578. // See if it's inherited
  579. //
  580. if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY))
  581. {
  582. AType =(ACC_ACLBLD_TYPE)
  583. ((ULONG)AType + ((ULONG)AAT_IDENIED - (ULONG)AAT_DENIED));
  584. }
  585. }
  586. return(AType);
  587. }
  588. //+---------------------------------------------------------------------------
  589. //
  590. // Function: CNodeCompare
  591. //
  592. // Synopsis: Used by CSList class. Used to determine if 2 acclist_cnodes are
  593. // identical, based upon the property
  594. //
  595. // Arguments: [pv1] -- 1st node
  596. // [pv2] -- 2nd node
  597. //
  598. // Returns: 0 on equality
  599. // non-0 otherwise
  600. //
  601. // Notes:
  602. //
  603. //----------------------------------------------------------------------------
  604. int __cdecl CNodeCompare(const void *pv1, const void *pv2)
  605. {
  606. PACCLIST_CNODE pCN1 = (PACCLIST_CNODE)pv1;
  607. PACCLIST_CNODE pCN2 = (PACCLIST_CNODE)pv2;
  608. if(pCN1->pONode->pwszProperty == NULL)
  609. {
  610. return(-1);
  611. }
  612. if(pCN2->pONode->pwszProperty == NULL)
  613. {
  614. return(1);
  615. }
  616. return(_wcsicmp(pCN1->pONode->pwszProperty, pCN2->pONode->pwszProperty));
  617. }
  618. //+---------------------------------------------------------------------------
  619. //
  620. // Function: CompAndMarkCompressNode
  621. //
  622. // Synopsis: Used by CSList class. Used to determine if 2 nodes can be
  623. // compressed into one. If so, the first node has its access
  624. // flag marked with a bit signifying it can be compressed. See
  625. // below for the definition of what it means to be compressible
  626. //
  627. // Arguments: [pvAE] -- New node
  628. // [pvNode] -- Node already existing in list
  629. //
  630. // Returns: 0 on equality
  631. // non-0 otherwise
  632. //
  633. // Notes:
  634. //
  635. //----------------------------------------------------------------------------
  636. BOOL CompAndMarkCompressNode(IN PVOID pvAE,
  637. IN PVOID pvNode)
  638. {
  639. PACTRL_ACCESS_ENTRY pAE1 = (PACTRL_ACCESS_ENTRY)pvAE;
  640. PACTRL_ACCESS_ENTRY pAE2 = (PACTRL_ACCESS_ENTRY)pvNode;
  641. //
  642. // We will consider nodes identical iff:
  643. // They match trustee, inheritance, and access flags exactly and the
  644. // inherit property or (along with the rest of the above):
  645. // - Both nodes are inherited and one is marked l1 inherited and the
  646. // other is not marked at all, or neither node is inherited
  647. // and the inheritance is identical or the inheritance is different
  648. // but the access masks are the same
  649. // - fAccessFlags indicates that combining this 2 nodes will still
  650. // yield an audit node.
  651. //
  652. if(CompTrustees(&pAE1->Trustee,&pAE2->Trustee) == TRUE &&
  653. //
  654. // Check the inheritance
  655. //
  656. (pAE1->Inheritance == pAE2->Inheritance ||
  657. (pAE1->Inheritance & ~INHERITED_PARENT) ==
  658. (pAE2->Inheritance & ~INHERITED_PARENT) ||
  659. (!FLAG_ON(pAE1->Inheritance, INHERITED_ACCESS_ENTRY) &&
  660. !FLAG_ON(pAE2->Inheritance, INHERITED_ACCESS_ENTRY)&&
  661. (pAE1->Inheritance != 0 && pAE2->Inheritance != 0) &&
  662. (pAE1->Access) == pAE2->Access)) &&
  663. //
  664. // Check the access
  665. //
  666. (((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) ==
  667. ( pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS ) ||
  668. (((((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) |
  669. (pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS)) &
  670. ~(ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) == 0))) &&
  671. pAE1->Access == pAE2->Access) &&
  672. //
  673. // Check the properties
  674. //
  675. DoPropertiesMatch(pAE1->lpInheritProperty,
  676. pAE2->lpInheritProperty) == TRUE)
  677. {
  678. pAE1->fAccessFlags |= ACCLIST_COMPRESS;
  679. return(TRUE);
  680. }
  681. return(FALSE);
  682. }
  683. //+---------------------------------------------------------------------------
  684. //
  685. // Function: GetNodeForProperty
  686. //
  687. // Synopsis: This function will lookup the existing list node for the given
  688. // property. If the node doesn't exist, it will be created and
  689. // inserted into the list
  690. //
  691. // Arguments: [List] -- List to examine
  692. // [pwszProperty] -- The property to look for
  693. // [ppNode] -- Where the found or inserted node is
  694. // returned
  695. //
  696. // Returns: ERROR_SUCCESS -- Success
  697. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  698. //
  699. // Notes:
  700. //
  701. //----------------------------------------------------------------------------
  702. DWORD GetNodeForProperty(CSList& List,
  703. PWSTR pwszProperty,
  704. PACCLIST_NODE *ppNode)
  705. {
  706. DWORD dwErr = ERROR_SUCCESS;
  707. PACCLIST_NODE pAccNode = (PACCLIST_NODE)List.Find(pwszProperty,
  708. CompProps);
  709. if(pAccNode == NULL)
  710. {
  711. //
  712. // Doesn't exist. We'll have to add it...
  713. //
  714. pAccNode = (PACCLIST_NODE)AccAlloc(sizeof(ACCLIST_NODE));
  715. if(pAccNode == NULL)
  716. {
  717. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  718. }
  719. else
  720. {
  721. if(pwszProperty != NULL)
  722. {
  723. ACC_ALLOC_AND_COPY_STRINGW(pwszProperty,
  724. pAccNode->pwszProperty,
  725. dwErr);
  726. }
  727. if(dwErr == ERROR_SUCCESS)
  728. {
  729. dwErr = List.Insert((PVOID)pAccNode);
  730. if(dwErr != ERROR_SUCCESS)
  731. {
  732. AccFree(pAccNode->pwszProperty);
  733. AccFree(pAccNode);
  734. }
  735. }
  736. else
  737. {
  738. AccFree(pAccNode);
  739. pAccNode = 0;
  740. }
  741. }
  742. }
  743. *ppNode = pAccNode;
  744. return(dwErr);
  745. }
  746. VOID
  747. FreeAToAccessStruct(PVOID pv)
  748. {
  749. ((PACCLIST_ATOACCESS)pv)->AceList.FreeList((FreeFunc)AccFree);
  750. AccFree(pv);
  751. }
  752. //+---------------------------------------------------------------------------
  753. //
  754. // Function: GetNodeForGuid
  755. //
  756. // Synopsis: Finds the node in the given list based upon the guid. If the
  757. // node doesn't exist, it is inserted
  758. //
  759. // Arguments: [List] -- List to examine
  760. // [pGuid] -- The guid to look for
  761. // [ppNode] -- Where the found or inserted node is
  762. // returned
  763. //
  764. // Returns: ERROR_SUCCESS -- Success
  765. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  766. //
  767. // Notes:
  768. //
  769. //----------------------------------------------------------------------------
  770. DWORD GetNodeForGuid(CSList& List,
  771. GUID *pGuid,
  772. PACCLIST_ATOACCESS *ppNode)
  773. {
  774. DWORD dwErr = ERROR_SUCCESS;
  775. List.Init((FreeFunc)FreeAToAccessStruct);
  776. PACCLIST_ATOACCESS pNode = (PACCLIST_ATOACCESS)List.Find(pGuid,
  777. CompGuids);
  778. if(pNode == NULL)
  779. {
  780. //
  781. // Doesn't exist. We'll have to add it...
  782. //
  783. pNode = (PACCLIST_ATOACCESS)AccAlloc(sizeof(ACCLIST_ATOACCESS));
  784. if(pNode == NULL)
  785. {
  786. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  787. }
  788. else
  789. {
  790. pNode->AceList.Init((FreeFunc)AccFree);
  791. if(pGuid != NULL)
  792. {
  793. pNode->pGuid = (GUID *)AccAlloc(sizeof(GUID));
  794. if(pNode->pGuid == NULL)
  795. {
  796. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  797. AccFree(pNode);
  798. pNode = 0;
  799. }
  800. else
  801. {
  802. memcpy(pNode->pGuid,
  803. pGuid,
  804. sizeof(GUID));
  805. }
  806. }
  807. if(dwErr == ERROR_SUCCESS)
  808. {
  809. dwErr = List.Insert((PVOID)pNode);
  810. if(dwErr != ERROR_SUCCESS)
  811. {
  812. AccFree(pNode->pGuid);
  813. AccFree(pNode);
  814. }
  815. }
  816. }
  817. }
  818. *ppNode = pNode;
  819. return(dwErr);
  820. }
  821. //+---------------------------------------------------------------------------
  822. //
  823. // Function: InsertAtoANode
  824. //
  825. // Synopsis: Inserts an access to ace node into the list.
  826. //
  827. // Arguments: [List] -- List to insert in
  828. // [pProperty] -- Property to match
  829. // [pAce] -- Ace to be inserted
  830. // [fInherit] -- Inheritance flags
  831. //
  832. // Returns: ERROR_SUCCESS -- Success
  833. // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
  834. //
  835. // Notes:
  836. //
  837. //----------------------------------------------------------------------------
  838. DWORD InsertAtoANode(CSList& List,
  839. GUID *pProperty,
  840. PACE_HEADER pAce,
  841. ULONG fInherit)
  842. {
  843. DWORD dwErr = ERROR_SUCCESS;
  844. PACCLIST_ATOANODE pAANode =
  845. (PACCLIST_ATOANODE)AccAlloc(sizeof(ACCLIST_ATOANODE));
  846. if(pAANode == NULL)
  847. {
  848. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  849. }
  850. else
  851. {
  852. pAANode->pAce = pAce;
  853. pAANode->fInherit = fInherit;
  854. PACCLIST_ATOACCESS pParent;
  855. dwErr = GetNodeForGuid(List,
  856. pProperty,
  857. &pParent);
  858. if(dwErr == ERROR_SUCCESS)
  859. {
  860. dwErr = pParent->AceList.Insert((PVOID)pAANode);
  861. }
  862. if(dwErr != ERROR_SUCCESS)
  863. {
  864. AccFree(pAANode);
  865. }
  866. }
  867. return(dwErr);
  868. }
  869. //+---------------------------------------------------------------------------
  870. //
  871. // Function: AceToAccessEntry
  872. //
  873. // Synopsis: Converts an ACE into an access entry
  874. //
  875. // Arguments: [pAce] -- Ace to convert
  876. // [fInheritLevel] -- What inheritance level (effective,
  877. // parent inherit, etc) are we at
  878. // [ObjType] -- Type of object we're dealing with
  879. // [pAE] -- Already existing access entry to
  880. // initialize
  881. //
  882. // Returns: ERROR_SUCCESS -- Success
  883. // ERROR_INVALID_ACL -- A bad ace type was encountered
  884. //
  885. // Notes:
  886. //
  887. //----------------------------------------------------------------------------
  888. DWORD AceToAccessEntry(PACE_HEADER pAce,
  889. ULONG fInheritLevel,
  890. SE_OBJECT_TYPE ObjType,
  891. IN MARTA_KERNEL_TYPE KernelObjectType,
  892. PACTRL_ACCESS_ENTRY pAE)
  893. {
  894. DWORD dwErr = ERROR_SUCCESS;
  895. //
  896. // Go ahead and initialize the node
  897. //
  898. BOOL fIsImpersonate = FALSE;
  899. BOOL fIsExtendedAce = FALSE;
  900. //
  901. // Ok, now lets try to figure out what type of ACE this is, so we can
  902. // do the neccessary mapping into the provider rights
  903. //
  904. switch(pAce->AceType)
  905. {
  906. case ACCESS_ALLOWED_ACE_TYPE:
  907. pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED;
  908. break;
  909. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  910. pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED;
  911. fIsExtendedAce = TRUE;
  912. break;
  913. //
  914. // Currently unsupported
  915. //
  916. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  917. pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED;
  918. fIsImpersonate = TRUE;
  919. dwErr = ERROR_INVALID_ACL;
  920. break;
  921. case ACCESS_DENIED_ACE_TYPE:
  922. pAE->fAccessFlags = ACTRL_ACCESS_DENIED;
  923. break;
  924. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  925. pAE->fAccessFlags = ACTRL_ACCESS_DENIED;
  926. fIsExtendedAce = TRUE;
  927. break;
  928. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  929. pAE->fAccessFlags = 0;
  930. if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG))
  931. {
  932. pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS;
  933. }
  934. if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG))
  935. {
  936. pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE;
  937. }
  938. fIsExtendedAce = TRUE;
  939. break;
  940. case SYSTEM_AUDIT_ACE_TYPE:
  941. pAE->fAccessFlags = 0;
  942. if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG))
  943. {
  944. pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS;
  945. }
  946. if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG))
  947. {
  948. pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE;
  949. }
  950. break;
  951. default:
  952. dwErr = ERROR_INVALID_ACL;
  953. break;
  954. }
  955. if(dwErr == ERROR_SUCCESS)
  956. {
  957. //
  958. // Pull what we can from the ace header
  959. //
  960. pAE->Inheritance = (INHERIT_FLAGS)( pAce->AceFlags & VALID_INHERIT_FLAGS );
  961. pAE->Inheritance |= fInheritLevel;
  962. PSID pSid = NULL;
  963. ACCESS_MASK AccessMask = 0;
  964. if(fIsImpersonate == FALSE)
  965. {
  966. if(fIsExtendedAce == TRUE)
  967. {
  968. pSid = RtlObjectAceSid(pAce);
  969. AccessMask = ((PKNOWN_OBJECT_ACE)pAce)->Mask;
  970. }
  971. else
  972. {
  973. pSid = &((PKNOWN_ACE)pAce)->SidStart;
  974. AccessMask = ((PKNOWN_ACE)pAce)->Mask;
  975. }
  976. }
  977. else
  978. {
  979. if(fIsExtendedAce == TRUE)
  980. {
  981. dwErr = ERROR_INVALID_ACL;
  982. }
  983. else
  984. {
  985. pSid =
  986. (PSID)Add2Ptr(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart,
  987. RtlLengthSid(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart));
  988. AccessMask = ((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->Mask;
  989. }
  990. }
  991. //
  992. // Build the trustee
  993. //
  994. pAE->Trustee.pMultipleTrustee = NULL;
  995. pAE->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  996. pAE->Trustee.TrusteeForm = TRUSTEE_IS_SID;
  997. pAE->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  998. pAE->Trustee.ptstrName = (LPWSTR)pSid;
  999. //
  1000. // Convert our access
  1001. //
  1002. AccConvertAccessMaskToActrlAccess(AccessMask,
  1003. ObjType,
  1004. KernelObjectType,
  1005. pAE);
  1006. //
  1007. // Deal with the inheritance property...
  1008. //
  1009. if(fIsExtendedAce == TRUE)
  1010. {
  1011. PACCESS_ALLOWED_OBJECT_ACE pExAce =
  1012. (PACCESS_ALLOWED_OBJECT_ACE)pAce;
  1013. if(FLAG_ON(pExAce->Flags,
  1014. ACE_INHERITED_OBJECT_TYPE_PRESENT))
  1015. {
  1016. PWSTR StrUuid;
  1017. dwErr = UuidToString(RtlObjectAceInheritedObjectType(pAce),
  1018. &StrUuid );
  1019. //
  1020. // The calling functions expect a buffer allocated with AccAlloc
  1021. //
  1022. if(dwErr == ERROR_SUCCESS)
  1023. {
  1024. ACC_ALLOC_AND_COPY_STRINGW(StrUuid, (PWSTR)pAE->lpInheritProperty, dwErr);
  1025. RpcStringFree(&StrUuid);
  1026. }
  1027. }
  1028. }
  1029. else
  1030. {
  1031. pAE->lpInheritProperty = NULL;
  1032. }
  1033. }
  1034. if(dwErr != ERROR_SUCCESS)
  1035. {
  1036. if(pAE->lpInheritProperty != NULL)
  1037. {
  1038. AccFree((PWSTR)pAE->lpInheritProperty);
  1039. }
  1040. }
  1041. return(dwErr);
  1042. }
  1043. //+---------------------------------------------------------------------------
  1044. //
  1045. // Function: ConvertToAutoInheritSD
  1046. //
  1047. // Synopsis: Determines the inheritance necessary for the current security
  1048. // descriptor given the parent security descriptor
  1049. //
  1050. // Arguments: [IN pCurrentSD] -- The security descriptor to
  1051. // update
  1052. // [IN pParentSD] -- The parent security descriptor
  1053. // [IN fIsContainer] -- Does the Sec. Desc. refer to
  1054. // a container?
  1055. // [IN pGenericMapping] -- Generic mapping to apply
  1056. // [OUT ppNewSD] -- Where the new SD is returned
  1057. //
  1058. // Returns: ERROR_SUCCESS -- Success
  1059. //
  1060. // Notes: The returned security descriptor must be freed via a call to
  1061. // DestroyPrivateObjectSecurity
  1062. //
  1063. //----------------------------------------------------------------------------
  1064. DWORD
  1065. ConvertToAutoInheritSD(IN PSECURITY_DESCRIPTOR pParentSD,
  1066. IN PSECURITY_DESCRIPTOR pCurrentSD,
  1067. IN BOOL fIsContainer,
  1068. IN PGENERIC_MAPPING pGenericMapping,
  1069. OUT PSECURITY_DESCRIPTOR *ppNewSD)
  1070. {
  1071. DWORD dwErr = ERROR_SUCCESS;
  1072. SECURITY_DESCRIPTOR_CONTROL OldControl;
  1073. //
  1074. // Turn off the inherited bits, so we can always do the
  1075. // necessary inheritance checks. This is because we don't know if some
  1076. // downlevel process came in and messed with one of our security
  1077. // descriptors, and left is in a hosed state
  1078. //
  1079. OldControl = ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control;
  1080. ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control &=
  1081. ~(SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED);
  1082. #ifdef DBG
  1083. if(pParentSD != NULL)
  1084. {
  1085. ASSERT(IsValidSecurityDescriptor(pParentSD));
  1086. DebugDumpSD("CTAIPOS ParentSD", pParentSD);
  1087. }
  1088. ASSERT(IsValidSecurityDescriptor(pCurrentSD));
  1089. DebugDumpSD("CTAIPOS CurrentSD", pCurrentSD);
  1090. #endif
  1091. if(ConvertToAutoInheritPrivateObjectSecurity(pParentSD,
  1092. pCurrentSD,
  1093. ppNewSD,
  1094. NULL,
  1095. fIsContainer != 0,
  1096. pGenericMapping) == FALSE)
  1097. {
  1098. dwErr = GetLastError();
  1099. }
  1100. #ifdef DBG
  1101. else
  1102. {
  1103. ASSERT(IsValidSecurityDescriptor(*ppNewSD));
  1104. DebugDumpSD("CTAIPOS NewSD", *ppNewSD);
  1105. }
  1106. #endif
  1107. ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control = OldControl;
  1108. return(dwErr);
  1109. }
  1110. //+---------------------------------------------------------------------------
  1111. //
  1112. // Function: MakeSDAbsolute
  1113. //
  1114. // Synopsis: Allocates a new security descriptor and makes an absolute copy
  1115. // of the supplied SD
  1116. //
  1117. // Arguments: [IN pOriginalSD] -- The security descriptor to
  1118. // convert
  1119. // [IN SeInfo] -- SD components to care about
  1120. // [IN *ppNewSD] -- Where the new SD is returned
  1121. // [IN pOwnerToAdd] -- OPTIONAL. Owner SID to add to
  1122. // absolute SD.
  1123. // [IN pGroupToAdd] -- OPTIONAL. Group SID to add to
  1124. // absolute SD.
  1125. //
  1126. // Returns: ERROR_SUCCESS -- Success
  1127. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation falied
  1128. //
  1129. // Notes: The returned security descriptor must be freed via a call to
  1130. // AccFree
  1131. //
  1132. //----------------------------------------------------------------------------
  1133. DWORD
  1134. MakeSDAbsolute(IN PSECURITY_DESCRIPTOR pOriginalSD,
  1135. IN SECURITY_INFORMATION SeInfo,
  1136. OUT PSECURITY_DESCRIPTOR *ppNewSD,
  1137. IN PSID pOwnerToAdd,
  1138. IN PSID pGroupToAdd)
  1139. {
  1140. DWORD dwErr = ERROR_SUCCESS;
  1141. BOOL fDAclPresent = FALSE;
  1142. BOOL fSAclPresent = FALSE;
  1143. BOOL fDAclDef = FALSE, fSAclDef = FALSE;
  1144. BOOL fOwnerDef = FALSE, fGroupDef = FALSE;
  1145. PACL pDAcl = NULL, pSAcl = NULL;
  1146. PSID pOwner = NULL, pGroup = NULL;
  1147. ULONG cSize = 0;
  1148. //
  1149. // First, get the info out of the current SD
  1150. //
  1151. if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION))
  1152. {
  1153. if(GetSecurityDescriptorDacl(pOriginalSD, &fDAclPresent, &pDAcl, &fDAclDef) == FALSE)
  1154. {
  1155. dwErr = GetLastError();
  1156. }
  1157. else
  1158. {
  1159. if(pDAcl != NULL)
  1160. {
  1161. cSize += pDAcl->AclSize;
  1162. }
  1163. }
  1164. }
  1165. if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION))
  1166. {
  1167. if(GetSecurityDescriptorSacl(pOriginalSD, &fSAclPresent, &pSAcl, &fSAclDef) == FALSE)
  1168. {
  1169. dwErr = GetLastError();
  1170. }
  1171. else
  1172. {
  1173. if(pSAcl != NULL)
  1174. {
  1175. cSize += pSAcl->AclSize;
  1176. }
  1177. }
  1178. }
  1179. if(pOwnerToAdd != NULL)
  1180. {
  1181. pOwner = pOwnerToAdd;
  1182. }
  1183. else
  1184. {
  1185. if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION))
  1186. {
  1187. if(GetSecurityDescriptorOwner(pOriginalSD, &pOwner, &fOwnerDef) == FALSE)
  1188. {
  1189. dwErr = GetLastError();
  1190. }
  1191. }
  1192. }
  1193. if(pGroupToAdd != NULL)
  1194. {
  1195. pGroup = pGroupToAdd;
  1196. }
  1197. else
  1198. {
  1199. if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION))
  1200. {
  1201. if(GetSecurityDescriptorGroup(pOriginalSD, &pGroup, &fGroupDef) == FALSE)
  1202. {
  1203. dwErr = GetLastError();
  1204. }
  1205. }
  1206. }
  1207. if(pOwner != NULL)
  1208. {
  1209. cSize += RtlLengthSid(pOwner);
  1210. }
  1211. if(pGroup != NULL)
  1212. {
  1213. cSize += RtlLengthSid(pGroup);
  1214. }
  1215. if(dwErr == ERROR_SUCCESS)
  1216. {
  1217. //
  1218. // Allocate the buffer...
  1219. //
  1220. PBYTE pBuff = (PBYTE)AccAlloc(cSize + sizeof(SECURITY_DESCRIPTOR));
  1221. if(pBuff == NULL)
  1222. {
  1223. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1224. }
  1225. else
  1226. {
  1227. //
  1228. // Start copying in the existing items...
  1229. //
  1230. DWORD cLen;
  1231. PBYTE pbEndOBuf = pBuff + cSize + sizeof(SECURITY_DESCRIPTOR);
  1232. if(pOwner != NULL)
  1233. {
  1234. cLen = RtlLengthSid(pOwner);
  1235. pbEndOBuf -= cLen;
  1236. RtlCopyMemory(pbEndOBuf, pOwner, cLen);
  1237. pOwner = (PSID)pbEndOBuf;
  1238. }
  1239. if(pGroup != NULL)
  1240. {
  1241. cLen = RtlLengthSid(pGroup);
  1242. pbEndOBuf -= cLen;
  1243. RtlCopyMemory(pbEndOBuf, pGroup, cLen);
  1244. pGroup = (PSID)pbEndOBuf;
  1245. }
  1246. if(pDAcl != NULL)
  1247. {
  1248. pbEndOBuf -= pDAcl->AclSize;
  1249. RtlCopyMemory(pbEndOBuf, pDAcl, pDAcl->AclSize);
  1250. pDAcl = (PACL)pbEndOBuf;
  1251. }
  1252. if(pSAcl != NULL)
  1253. {
  1254. pbEndOBuf -= pSAcl->AclSize;
  1255. RtlCopyMemory(pbEndOBuf, pSAcl, pSAcl->AclSize);
  1256. pSAcl = (PACL)pbEndOBuf;
  1257. }
  1258. //
  1259. // Ok, now build it...
  1260. //
  1261. *ppNewSD = (PSECURITY_DESCRIPTOR)pBuff;
  1262. if(InitializeSecurityDescriptor(*ppNewSD, SECURITY_DESCRIPTOR_REVISION) == FALSE)
  1263. {
  1264. dwErr = GetLastError();
  1265. }
  1266. if(dwErr == ERROR_SUCCESS && fDAclPresent == TRUE)
  1267. {
  1268. if(SetSecurityDescriptorDacl(*ppNewSD, TRUE, pDAcl, fDAclDef) == FALSE)
  1269. {
  1270. dwErr = GetLastError();
  1271. }
  1272. }
  1273. if(dwErr == ERROR_SUCCESS && fSAclPresent == TRUE)
  1274. {
  1275. if(SetSecurityDescriptorSacl(*ppNewSD, TRUE, pSAcl, fSAclDef) == FALSE)
  1276. {
  1277. dwErr = GetLastError();
  1278. }
  1279. }
  1280. if(dwErr == ERROR_SUCCESS && pOwner != NULL)
  1281. {
  1282. if(SetSecurityDescriptorOwner(*ppNewSD, pOwner, fOwnerDef) == FALSE)
  1283. {
  1284. dwErr = GetLastError();
  1285. }
  1286. }
  1287. if(dwErr == ERROR_SUCCESS && pGroup != NULL)
  1288. {
  1289. if(SetSecurityDescriptorGroup(*ppNewSD, pGroup, fGroupDef) == FALSE)
  1290. {
  1291. dwErr = GetLastError();
  1292. }
  1293. }
  1294. //
  1295. // Set the new control bits to look like the old ones (minus the selfrel flag, of
  1296. // course...
  1297. //
  1298. if(dwErr == ERROR_SUCCESS)
  1299. {
  1300. RtlpPropagateControlBits((PISECURITY_DESCRIPTOR)*ppNewSD,
  1301. (PISECURITY_DESCRIPTOR)pOriginalSD,
  1302. ~SE_SELF_RELATIVE );
  1303. }
  1304. if(dwErr != ERROR_SUCCESS)
  1305. {
  1306. AccFree(*ppNewSD);
  1307. *ppNewSD = NULL;
  1308. }
  1309. }
  1310. }
  1311. return(dwErr);
  1312. }
  1313. //+---------------------------------------------------------------------------
  1314. //
  1315. // Function: EqualSecurityDescriptors
  1316. //
  1317. // Synopsis: Determines if 2 security descriptors are identical. It does
  1318. // this by comparing control fields, owner/group, and sids.
  1319. //
  1320. // Arguments: [IN pSD1] -- 1st SD to compare
  1321. // [IN pSD2] -- 2nd SD to compare
  1322. //
  1323. // Returns: TRUE -- They are identical
  1324. // FALSE -- They are not identical
  1325. //
  1326. //
  1327. //----------------------------------------------------------------------------
  1328. BOOL
  1329. EqualSecurityDescriptors(IN PSECURITY_DESCRIPTOR pSD1,
  1330. IN PSECURITY_DESCRIPTOR pSD2)
  1331. {
  1332. BOOL fRet = TRUE;
  1333. SECURITY_DESCRIPTOR *pS1 = (SECURITY_DESCRIPTOR *)pSD1;
  1334. SECURITY_DESCRIPTOR *pS2 = (SECURITY_DESCRIPTOR *)pSD2;
  1335. if(pS1->Control != pS2->Control)
  1336. {
  1337. return(FALSE);
  1338. }
  1339. PACL pA1, pA2;
  1340. //
  1341. // Dacl
  1342. //
  1343. pA1 = RtlpDaclAddrSecurityDescriptor(pS1);
  1344. pA2 = RtlpDaclAddrSecurityDescriptor(pS2);
  1345. if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL))
  1346. {
  1347. return(FALSE);
  1348. }
  1349. if(pA1 != NULL)
  1350. {
  1351. if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize)))
  1352. {
  1353. return(FALSE);
  1354. }
  1355. }
  1356. //
  1357. // Sacl
  1358. //
  1359. pA1 = RtlpSaclAddrSecurityDescriptor(pS1);
  1360. pA2 = RtlpSaclAddrSecurityDescriptor(pS2);
  1361. if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL))
  1362. {
  1363. return(FALSE);
  1364. }
  1365. if(pA1 != NULL)
  1366. {
  1367. if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize)))
  1368. {
  1369. return(FALSE);
  1370. }
  1371. }
  1372. //
  1373. // Group
  1374. //
  1375. PSID pSid1, pSid2;
  1376. pSid1 = RtlpGroupAddrSecurityDescriptor(pS1);
  1377. pSid2 = RtlpGroupAddrSecurityDescriptor(pS2);
  1378. if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL))
  1379. {
  1380. return(FALSE);
  1381. }
  1382. if(pSid1 != NULL)
  1383. {
  1384. if(!RtlEqualSid(pSid1, pSid2))
  1385. {
  1386. return(FALSE);
  1387. }
  1388. }
  1389. //
  1390. // Owner
  1391. //
  1392. pSid1 = RtlpOwnerAddrSecurityDescriptor(pS1);
  1393. pSid2 = RtlpOwnerAddrSecurityDescriptor(pS2);
  1394. if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL))
  1395. {
  1396. return(FALSE);
  1397. }
  1398. if(pSid1 != NULL)
  1399. {
  1400. if(!RtlEqualSid(pSid1, pSid2))
  1401. {
  1402. return(FALSE);
  1403. }
  1404. }
  1405. acDebugOut((DEB_TRACE, "Nodes 0x%lx and 0x%lx are equal!\n", pSD1, pSD2));
  1406. #ifdef DBG
  1407. DebugDumpSD("SD1", pSD1);
  1408. DebugDumpSD("SD2", pSD2);
  1409. #endif
  1410. return(TRUE);
  1411. }
  1412. //+---------------------------------------------------------------------------
  1413. //
  1414. // Function: InsertPropagationFailureEntry
  1415. //
  1416. // Synopsis: Adds a propagation failure entry to the list of items
  1417. // to be written to the event log
  1418. //
  1419. // Arguments: [IN LogList] -- Reference to the log list
  1420. // [IN ErrorCode] -- Error of propagation
  1421. // [IN Protected] -- Flags determining whether the dacl
  1422. // or sacl was protected
  1423. // [IN pwszPath] -- Path that expierneced the error
  1424. //
  1425. // Returns: ERROR_SUCCESS -- Success
  1426. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  1427. //
  1428. //
  1429. //----------------------------------------------------------------------------
  1430. DWORD
  1431. InsertPropagationFailureEntry( IN CSList& LogList,
  1432. IN ULONG ErrorCode,
  1433. IN ULONG Protected,
  1434. IN PWSTR pwszPath)
  1435. {
  1436. DWORD dwErr = ERROR_SUCCESS;
  1437. PACCESS_PROP_LOG_ENTRY pEntry = NULL;
  1438. pEntry = (PACCESS_PROP_LOG_ENTRY)AccAlloc(sizeof(ACCESS_PROP_LOG_ENTRY));
  1439. if(pEntry == NULL)
  1440. {
  1441. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1442. }
  1443. else
  1444. {
  1445. ACC_ALLOC_AND_COPY_STRINGW(pwszPath, pEntry->pwszPath, dwErr );
  1446. if(pwszPath == NULL)
  1447. {
  1448. AccFree(pEntry);
  1449. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1450. }
  1451. else
  1452. {
  1453. pEntry->Protected = Protected;
  1454. pEntry->Error = ErrorCode;
  1455. dwErr = LogList.Insert(pEntry);
  1456. if(dwErr != ERROR_SUCCESS)
  1457. {
  1458. FreePropagationFailureListEntry(pEntry);
  1459. }
  1460. }
  1461. }
  1462. return(dwErr);
  1463. }
  1464. //+---------------------------------------------------------------------------
  1465. //
  1466. // Function: FreePropagationFailureListEntry
  1467. //
  1468. // Synopsis: Frees the propagation failure list
  1469. //
  1470. // Arguments: [IN LogList] -- Reference to the log list
  1471. //
  1472. // Returns: VOID
  1473. //
  1474. //
  1475. //----------------------------------------------------------------------------
  1476. VOID
  1477. FreePropagationFailureListEntry(IN PVOID Entry)
  1478. {
  1479. PACCESS_PROP_LOG_ENTRY pLogEntry = (PACCESS_PROP_LOG_ENTRY)Entry;
  1480. AccFree(pLogEntry->pwszPath);
  1481. AccFree(pLogEntry);
  1482. }
  1483. //+---------------------------------------------------------------------------
  1484. //
  1485. // Function: WritePropagationFailureList
  1486. //
  1487. // Synopsis: Logs the propagation failures to the event log
  1488. //
  1489. // Arguments: [IN EventType] -- Type of event to log:
  1490. // registry or filesystem
  1491. // [IN LogList] -- Reference to the log list
  1492. // [IN hToken] -- Current process/thread token
  1493. //
  1494. // Returns: ERROR_SUCCESS -- Success
  1495. // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
  1496. //
  1497. //----------------------------------------------------------------------------
  1498. DWORD
  1499. WritePropagationFailureList(IN ULONG EventType,
  1500. IN CSList& LogList,
  1501. IN HANDLE hToken)
  1502. {
  1503. DWORD dwErr = ERROR_SUCCESS;
  1504. HANDLE hEventlog = NULL;
  1505. TOKEN_USER *UserInfo;
  1506. ULONG InfoSize, StrCount, i;
  1507. PSID pSid = NULL;
  1508. BYTE Buffer[ 7 * sizeof( ULONG ) + sizeof( TOKEN_USER ) ], *pBuff = NULL;
  1509. WCHAR ErrorNumberBuffer[25];
  1510. WCHAR wszErrorBuffer[ 256];
  1511. PWSTR pwszStringBuffer = NULL, pwszCurrent;
  1512. PACCESS_PROP_LOG_ENTRY pLogEntry;
  1513. ULONG ProtectedValue;
  1514. if(LogList.QueryCount() == 0)
  1515. {
  1516. return(dwErr);
  1517. }
  1518. //
  1519. // Get the user sid
  1520. //
  1521. if(GetTokenInformation(hToken,
  1522. TokenUser,
  1523. (PVOID)&Buffer,
  1524. sizeof(Buffer),
  1525. &InfoSize ) == FALSE )
  1526. {
  1527. dwErr = GetLastError();
  1528. if(dwErr == ERROR_INSUFFICIENT_BUFFER)
  1529. {
  1530. pBuff = (PBYTE)AccAlloc( InfoSize );
  1531. if(pBuff == NULL)
  1532. {
  1533. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1534. }
  1535. else
  1536. {
  1537. if(GetTokenInformation(hToken,
  1538. TokenUser,
  1539. (PVOID)pBuff,
  1540. InfoSize,
  1541. &InfoSize ) == FALSE )
  1542. {
  1543. dwErr = GetLastError();
  1544. }
  1545. else
  1546. {
  1547. dwErr = ERROR_SUCCESS;
  1548. }
  1549. }
  1550. }
  1551. }
  1552. else
  1553. {
  1554. pBuff = Buffer;
  1555. }
  1556. if(dwErr == ERROR_SUCCESS)
  1557. {
  1558. UserInfo = ( PTOKEN_USER )pBuff;
  1559. pSid = UserInfo->User.Sid;
  1560. }
  1561. //
  1562. // Build the list of paths and associated error codes
  1563. // The format of the buffer is [tab][path] [error][cr/lf]
  1564. //
  1565. if(dwErr == ERROR_SUCCESS)
  1566. {
  1567. InfoSize = 1;
  1568. LogList.Reset();
  1569. pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData();
  1570. for(; pLogEntry;)
  1571. {
  1572. InfoSize += 1 + wcslen( pLogEntry->pwszPath ) + 5;
  1573. //
  1574. // Determine the size of the buffer for the error message
  1575. //
  1576. if(pLogEntry->Protected)
  1577. {
  1578. switch(pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED))
  1579. {
  1580. case SE_DACL_PROTECTED | SE_SACL_PROTECTED:
  1581. ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED;
  1582. break;
  1583. case SE_DACL_PROTECTED:
  1584. ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED;
  1585. break;
  1586. case SE_SACL_PROTECTED:
  1587. ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED;
  1588. break;
  1589. default:
  1590. ProtectedValue = 0;
  1591. break;
  1592. }
  1593. if (LoadString(ghDll,
  1594. ProtectedValue,
  1595. wszErrorBuffer,
  1596. sizeof( wszErrorBuffer ) / sizeof( WCHAR )) == 0)
  1597. {
  1598. dwErr = GetLastError();
  1599. break;
  1600. }
  1601. }
  1602. else
  1603. {
  1604. if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  1605. NULL,
  1606. pLogEntry->Error,
  1607. MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  1608. wszErrorBuffer,
  1609. 256,
  1610. NULL ) == 0 )
  1611. {
  1612. dwErr = GetLastError();
  1613. break;
  1614. }
  1615. }
  1616. InfoSize += wcslen( wszErrorBuffer );
  1617. pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData();
  1618. }
  1619. //
  1620. // Now, allocate the buffer
  1621. //
  1622. if(dwErr == ERROR_SUCCESS)
  1623. {
  1624. pwszStringBuffer = (PWSTR)AccAlloc(( InfoSize + 1 ) * sizeof( WCHAR ));
  1625. if(pwszStringBuffer == NULL)
  1626. {
  1627. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1628. }
  1629. else
  1630. {
  1631. LogList.Reset();
  1632. pwszCurrent = pwszStringBuffer;
  1633. pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData();
  1634. for(; pLogEntry;)
  1635. {
  1636. if(pLogEntry->Protected == 0 )
  1637. {
  1638. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  1639. NULL,
  1640. pLogEntry->Error,
  1641. MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  1642. wszErrorBuffer,
  1643. 256,
  1644. NULL );
  1645. }
  1646. else
  1647. {
  1648. switch( pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED))
  1649. {
  1650. case SE_DACL_PROTECTED | SE_SACL_PROTECTED:
  1651. ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED;
  1652. break;
  1653. case SE_DACL_PROTECTED:
  1654. ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED;
  1655. break;
  1656. case SE_SACL_PROTECTED:
  1657. ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED;
  1658. break;
  1659. default:
  1660. ProtectedValue = 0;
  1661. break;
  1662. }
  1663. LoadString(ghDll,
  1664. ProtectedValue,
  1665. wszErrorBuffer,
  1666. sizeof( wszErrorBuffer ) / sizeof( WCHAR ));
  1667. }
  1668. InfoSize = swprintf( pwszCurrent,
  1669. L"\r\n\t%ws\t\t%ws",
  1670. pLogEntry->pwszPath,
  1671. wszErrorBuffer );
  1672. pwszCurrent += InfoSize;
  1673. pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData();
  1674. }
  1675. }
  1676. }
  1677. }
  1678. //
  1679. // Write to the event log
  1680. //
  1681. if(dwErr == ERROR_SUCCESS)
  1682. {
  1683. dwErr = InitializeEvents();
  1684. if(dwErr == ERROR_SUCCESS)
  1685. {
  1686. hEventlog = RegisterEventSource( NULL, L"AclPropagation" );
  1687. if(hEventlog == NULL)
  1688. {
  1689. dwErr = GetLastError();
  1690. if(dwErr == RPC_S_UNKNOWN_IF)
  1691. {
  1692. acDebugOut(( DEB_ERROR, "Eventlog service not started!\n" ));
  1693. dwErr = ERROR_SUCCESS;
  1694. }
  1695. }
  1696. else
  1697. {
  1698. if( ReportEvent(hEventlog,
  1699. EVENTLOG_INFORMATION_TYPE,
  1700. CATEGORY_NTMARTA,
  1701. EventType,
  1702. pSid,
  1703. 1,
  1704. 0,
  1705. (LPCTSTR *)&pwszStringBuffer,
  1706. NULL ) == FALSE )
  1707. {
  1708. dwErr = GetLastError();
  1709. }
  1710. DeregisterEventSource(hEventlog);
  1711. }
  1712. }
  1713. }
  1714. if(pBuff != Buffer)
  1715. {
  1716. AccFree(pBuff);
  1717. }
  1718. if ((dwErr != ERROR_SUCCESS) && (pwszStringBuffer != NULL))
  1719. {
  1720. AccFree(pwszStringBuffer);
  1721. }
  1722. return(dwErr);
  1723. }
  1724. //+---------------------------------------------------------------------------
  1725. //
  1726. // Function: InitializeEvents
  1727. //
  1728. // Synopsis: Sets the registry values to enable NTMARTA to act as an event source
  1729. //
  1730. // Arguments: void
  1731. //
  1732. // Returns: ERROR_SUCCESS -- Success
  1733. //
  1734. //----------------------------------------------------------------------------
  1735. DWORD
  1736. InitializeEvents(void)
  1737. {
  1738. HKEY hKey;
  1739. DWORD dwErr, disp;
  1740. dwErr = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  1741. TEXT("System\\CurrentControlSet\\Services\\EventLog\\Application\\AclPropagation"),
  1742. 0,
  1743. TEXT(""),
  1744. REG_OPTION_NON_VOLATILE,
  1745. KEY_WRITE,
  1746. NULL,
  1747. &hKey,
  1748. &disp);
  1749. if(dwErr != ERROR_SUCCESS)
  1750. {
  1751. return(dwErr);
  1752. }
  1753. if (disp == REG_CREATED_NEW_KEY)
  1754. {
  1755. RegSetValueEx( hKey,
  1756. TEXT("EventMessageFile"),
  1757. 0,
  1758. REG_EXPAND_SZ,
  1759. (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"),
  1760. sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) );
  1761. RegSetValueEx( hKey,
  1762. TEXT("CategoryMessageFile"),
  1763. 0,
  1764. REG_EXPAND_SZ,
  1765. (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"),
  1766. sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) );
  1767. disp = EVENTLOG_ERROR_TYPE |
  1768. EVENTLOG_WARNING_TYPE |
  1769. EVENTLOG_INFORMATION_TYPE ;
  1770. RegSetValueEx( hKey,
  1771. TEXT("TypesSupported"),
  1772. 0,
  1773. REG_DWORD,
  1774. (PBYTE) &disp,
  1775. sizeof(DWORD) );
  1776. disp = CATEGORY_MAX_CATEGORY - 1;
  1777. RegSetValueEx( hKey,
  1778. TEXT("CategoryCount"),
  1779. 0,
  1780. REG_DWORD,
  1781. (PBYTE) &disp,
  1782. sizeof(DWORD) );
  1783. }
  1784. RegCloseKey(hKey);
  1785. return(dwErr);
  1786. }
  1787. //+---------------------------------------------------------------------------
  1788. //
  1789. // Function: SetAccessListLookupServer
  1790. //
  1791. // Synopsis: Sets the name of the server to lookup the names/sids on for
  1792. // the given path
  1793. //
  1794. // Arguments: [IN pwszPath] -- Path to get the server name for
  1795. // [IN AccessList] -- Reference to CAccessList class that
  1796. // needs the server name
  1797. //
  1798. // Returns: ERROR_SUCCESS -- Success
  1799. //
  1800. //----------------------------------------------------------------------------
  1801. DWORD SetAccessListLookupServer(IN PWSTR pwszPath,
  1802. IN CAccessList &AccessList )
  1803. {
  1804. DWORD dwErr = ERROR_SUCCESS;
  1805. PWSTR pwszServer, pwszSep;
  1806. if( pwszPath && IS_UNC_PATH( pwszPath, wcslen( pwszPath ) ) )
  1807. {
  1808. pwszServer = pwszPath + 2;
  1809. pwszSep = wcschr(pwszServer, L'\\');
  1810. if(pwszSep)
  1811. {
  1812. *pwszSep = UNICODE_NULL;
  1813. }
  1814. dwErr = AccessList.SetLookupServer(pwszServer);
  1815. if(pwszSep)
  1816. {
  1817. *pwszSep = L'\\';
  1818. }
  1819. }
  1820. return(dwErr);
  1821. }