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.

5091 lines
171 KiB

  1. ////////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // Microsoft Windows //
  4. // Copyright (C) Microsoft Corporation, 1999. //
  5. // //
  6. // File: rewrite.cxx //
  7. // //
  8. // Contents: New marta rewrite functions. //
  9. // //
  10. // History: 4/99 KedarD Created //
  11. // //
  12. ////////////////////////////////////////////////////////////////////////////////
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. extern "C"
  16. {
  17. #include <stdio.h>
  18. #include <permit.h>
  19. #include <dsgetdc.h>
  20. #include <lmapibuf.h>
  21. #include <wmistr.h>
  22. #include <ntprov.hxx>
  23. #include <strings.h>
  24. #include <seopaque.h>
  25. #include <sertlp.h>
  26. #include <tables.h>
  27. }
  28. #define MARTA_DEBUG_NO 0
  29. ////////////////////////////////////////////////////////////////////////////////
  30. // //
  31. // STRUCTURES DEFINITIONS TO HOLD FUNCTION POINTERS START HERE //
  32. // //
  33. ////////////////////////////////////////////////////////////////////////////////
  34. typedef struct _MARTA_GET_FUNCTION_CONTEXT {
  35. FN_ADD_REF_CONTEXT fAddRefContext;
  36. FN_CLOSE_CONTEXT fCloseContext;
  37. FN_GET_DESIRED_ACCESS fGetDesiredAccess;
  38. FN_GET_PARENT_CONTEXT fGetParentContext;
  39. FN_GET_PROPERTIES fGetProperties;
  40. FN_GET_TYPE_PROPERTIES fGetTypeProperties;
  41. FN_OPEN_NAMED_OBJECT fOpenNamedObject;
  42. FN_OPEN_HANDLE_OBJECT fOpenHandleObject;
  43. FN_GET_RIGHTS fGetRights;
  44. } MARTA_GET_FUNCTION_CONTEXT, *PMARTA_GET_FUNCTION_CONTEXT;
  45. typedef struct _MARTA_SET_FUNCTION_CONTEXT {
  46. FN_ADD_REF_CONTEXT fAddRefContext;
  47. FN_CLOSE_CONTEXT fCloseContext;
  48. FN_FIND_FIRST fFindFirst;
  49. FN_FIND_NEXT fFindNext;
  50. FN_GET_DESIRED_ACCESS fGetDesiredAccess;
  51. FN_GET_PARENT_CONTEXT fGetParentContext;
  52. FN_GET_PROPERTIES fGetProperties;
  53. FN_GET_TYPE_PROPERTIES fGetTypeProperties;
  54. FN_GET_RIGHTS fGetRights;
  55. FN_OPEN_NAMED_OBJECT fOpenNamedObject;
  56. FN_OPEN_HANDLE_OBJECT fOpenHandleObject;
  57. FN_SET_RIGHTS fSetRights;
  58. FN_REOPEN_CONTEXT fReopenContext;
  59. FN_REOPEN_ORIG_CONTEXT fReopenOrigContext;
  60. FN_GET_NAME_FROM_CONTEXT fGetNameFromContext;
  61. } MARTA_SET_FUNCTION_CONTEXT, *PMARTA_SET_FUNCTION_CONTEXT;
  62. typedef struct _MARTA_INDEX_FUNCTION_CONTEXT {
  63. FN_OPEN_NAMED_OBJECT fOpenNamedObject;
  64. FN_CLOSE_CONTEXT fCloseContext;
  65. FN_GET_RIGHTS fGetRights;
  66. FN_GET_PARENT_NAME fGetParentName;
  67. } MARTA_INDEX_FUNCTION_CONTEXT, *PMARTA_INDEX_FUNCTION_CONTEXT;
  68. typedef struct _MARTA_RESET_FUNCTION_CONTEXT {
  69. FN_ADD_REF_CONTEXT fAddRefContext;
  70. FN_CLOSE_CONTEXT fCloseContext;
  71. FN_GET_DESIRED_ACCESS fGetDesiredAccess;
  72. FN_GET_PARENT_CONTEXT fGetParentContext;
  73. FN_GET_PROPERTIES fGetProperties;
  74. FN_GET_TYPE_PROPERTIES fGetTypeProperties;
  75. FN_OPEN_NAMED_OBJECT fOpenNamedObject;
  76. FN_GET_RIGHTS fGetRights;
  77. } MARTA_RESET_FUNCTION_CONTEXT, *PMARTA_RESET_FUNCTION_CONTEXT;
  78. ////////////////////////////////////////////////////////////////////////////////
  79. // //
  80. // MACRO DEFINITIONS START HERE //
  81. // //
  82. ////////////////////////////////////////////////////////////////////////////////
  83. #define MARTA_DACL_NOT_PROTECTED(sd, si) \
  84. (FLAG_ON((si), DACL_SECURITY_INFORMATION) && \
  85. !FLAG_ON((sd)->Control, SE_DACL_PROTECTED))
  86. #define MARTA_SACL_NOT_PROTECTED(sd, si) \
  87. (FLAG_ON((si), SACL_SECURITY_INFORMATION) && \
  88. !FLAG_ON((sd)->Control, SE_SACL_PROTECTED))
  89. #define MARTA_SD_NOT_PROTECTED(sd, si) \
  90. ((MARTA_DACL_NOT_PROTECTED((sd), (si))) || \
  91. (MARTA_SACL_NOT_PROTECTED((sd), (si))))
  92. #define MARTA_NT5_FLAGS_ON(c) \
  93. (FLAG_ON((c), (SE_SACL_AUTO_INHERITED | SE_DACL_AUTO_INHERITED | \
  94. SE_DACL_PROTECTED | SE_SACL_PROTECTED | \
  95. SE_DACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERIT_REQ)))
  96. #if 1
  97. #define MARTA_TURN_OFF_IMPERSONATION \
  98. if (OpenThreadToken( \
  99. GetCurrentThread(), \
  100. MAXIMUM_ALLOWED, \
  101. TRUE, \
  102. &ThreadHandle \
  103. )) \
  104. { \
  105. if (!RevertToSelf()) \
  106. { \
  107. dwErr = GetLastError(); \
  108. } \
  109. } \
  110. else \
  111. { \
  112. ThreadHandle = NULL; \
  113. }
  114. #define MARTA_TURN_ON_IMPERSONATION \
  115. if (ThreadHandle != NULL) \
  116. { \
  117. if (!SetThreadToken(NULL, ThreadHandle)) \
  118. { \
  119. dwErr = GetLastError(); \
  120. } \
  121. else \
  122. { \
  123. CloseHandle(ThreadHandle); \
  124. ThreadHandle = NULL; \
  125. } \
  126. }
  127. #else
  128. #define MARTA_TURN_ON_IMPERSONATION
  129. #define MARTA_TURN_OFF_IMPERSONATION
  130. #endif
  131. ////////////////////////////////////////////////////////////////////////////////
  132. // //
  133. // FUNCTION PROTOTYPES START HERE //
  134. // //
  135. ////////////////////////////////////////////////////////////////////////////////
  136. DWORD
  137. AccRewriteSetHandleRights(
  138. IN HANDLE Handle,
  139. IN SE_OBJECT_TYPE ObjectType,
  140. IN SECURITY_INFORMATION SecurityInfo,
  141. IN OUT PSECURITY_DESCRIPTOR pSecurityDescriptor
  142. );
  143. DWORD
  144. AccRewriteSetNamedRights(
  145. IN LPWSTR pObjectName,
  146. IN SE_OBJECT_TYPE ObjectType,
  147. IN SECURITY_INFORMATION SecurityInfo,
  148. IN OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
  149. IN BOOL bSkipInheritanceComputation
  150. );
  151. VOID
  152. MartaInitializeGetContext(
  153. IN SE_OBJECT_TYPE ObjectType,
  154. OUT PMARTA_GET_FUNCTION_CONTEXT pFunctionContext
  155. );
  156. VOID
  157. MartaInitializeIndexContext(
  158. IN SE_OBJECT_TYPE ObjectType,
  159. OUT PMARTA_INDEX_FUNCTION_CONTEXT pFunctionContext
  160. );
  161. BOOL
  162. MartaUpdateTree(
  163. IN SECURITY_INFORMATION SecurityInfo,
  164. IN PSECURITY_DESCRIPTOR pNewSD,
  165. IN PSECURITY_DESCRIPTOR pOldSD,
  166. IN MARTA_CONTEXT Context,
  167. IN HANDLE ProcessHandle,
  168. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  169. IN PGENERIC_MAPPING pGenMap
  170. );
  171. BOOL
  172. MartaResetTree(
  173. IN LPWSTR pObjectName,
  174. IN LPWSTR NtObjectName,
  175. IN SECURITY_INFORMATION SecurityInfo,
  176. IN SECURITY_INFORMATION TmpSeInfo,
  177. IN PSECURITY_DESCRIPTOR pNewSD,
  178. IN PSECURITY_DESCRIPTOR pEmptySD,
  179. IN MARTA_CONTEXT Context,
  180. IN HANDLE ProcessHandle,
  181. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  182. IN PGENERIC_MAPPING pGenMap,
  183. IN ACCESS_MASK MaxAccessMask,
  184. IN ACCESS_MASK AccessMask,
  185. IN ACCESS_MASK RetryAccessMask,
  186. IN OUT PPROG_INVOKE_SETTING pOperation,
  187. IN FN_PROGRESS fnProgress,
  188. IN PVOID Args,
  189. IN BOOL KeepExplicit
  190. );
  191. DWORD
  192. MartaGetNT4NodeSD(
  193. IN PSECURITY_DESCRIPTOR pOldSD,
  194. IN OUT PSECURITY_DESCRIPTOR pOldChildSD,
  195. IN HANDLE ProcessHandle,
  196. IN BOOL bIsChildContainer,
  197. IN PGENERIC_MAPPING pGenMap,
  198. IN SECURITY_INFORMATION SecurityInfo
  199. );
  200. DWORD
  201. MartaCompareAndMarkInheritedAces(
  202. IN PACL pParentAcl,
  203. IN PACL pChildAcl,
  204. IN BOOL bIsChildContainer,
  205. OUT PBOOL pCompareStatus
  206. );
  207. BOOL
  208. MartaEqualAce(
  209. IN PACE_HEADER pParentAce,
  210. IN PACE_HEADER pChildAce,
  211. IN PACE_HEADER pNextChildAce,
  212. IN BOOL bIsChildContainer,
  213. OUT PBOOL pbMarkNextAce
  214. );
  215. DWORD
  216. MartaManualPropagation(
  217. IN MARTA_CONTEXT Context,
  218. IN SECURITY_INFORMATION SecurityInfo,
  219. IN OUT PSECURITY_DESCRIPTOR pSD,
  220. IN PGENERIC_MAPPING pGenMap,
  221. IN BOOL bDoPropagate,
  222. IN BOOL bReadOldProtectedBits,
  223. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  224. IN BOOL bSkipInheritanceComputation
  225. );
  226. VOID
  227. MartaInitializeSetContext(
  228. IN SE_OBJECT_TYPE ObjectType,
  229. OUT PMARTA_SET_FUNCTION_CONTEXT pFunctionContext
  230. );
  231. DWORD
  232. AccRewriteGetHandleRights(
  233. IN HANDLE Handle,
  234. IN SE_OBJECT_TYPE ObjectType,
  235. IN SECURITY_INFORMATION SecurityInfo,
  236. OUT PSID * ppSidOwner,
  237. OUT PSID * ppSidGroup,
  238. OUT PACL * ppDacl,
  239. OUT PACL * ppSacl,
  240. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  241. );
  242. DWORD
  243. AccRewriteGetNamedRights(
  244. IN LPWSTR pObjectName,
  245. IN SE_OBJECT_TYPE ObjectType,
  246. IN SECURITY_INFORMATION SecurityInfo,
  247. OUT PSID * ppSidOwner,
  248. OUT PSID * ppSidGroup,
  249. OUT PACL * ppDacl,
  250. OUT PACL * ppSacl,
  251. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  252. );
  253. DWORD
  254. MartaGetRightsFromContext(
  255. IN MARTA_CONTEXT Context,
  256. IN PMARTA_GET_FUNCTION_CONTEXT pGetFunctionContext,
  257. IN SECURITY_INFORMATION SecurityInfo,
  258. OUT PSID * ppSidOwner,
  259. OUT PSID * ppSidGroup,
  260. OUT PACL * ppDacl,
  261. OUT PACL * ppSacl,
  262. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  263. );
  264. VOID
  265. MartaGetSidsAndAclsFromSD(
  266. IN SECURITY_INFORMATION SecurityInfo,
  267. IN PSECURITY_DESCRIPTOR pSD,
  268. OUT PSID * ppSidOwner,
  269. OUT PSID * ppSidGroup,
  270. OUT PACL * ppDacl,
  271. OUT PACL * ppSacl,
  272. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  273. );
  274. BOOL
  275. MartaIsSDNT5Style(
  276. IN PSECURITY_DESCRIPTOR SD
  277. );
  278. BOOL
  279. MartaIsAclNt5Style(
  280. PACL pAcl
  281. );
  282. ////////////////////////////////////////////////////////////////////////////////
  283. // //
  284. // FUNCTIONS START HERE //
  285. // //
  286. ////////////////////////////////////////////////////////////////////////////////
  287. ////////////////////////////////////////////////////////////////////////////////
  288. // //
  289. // Function: MartaIsSDNT5Style //
  290. // //
  291. // Description: Determine if the Security Descriptor is NT5 style. //
  292. // //
  293. // Arguments: //
  294. // //
  295. // [IN pSD] Security Descriptor //
  296. // //
  297. // Returns: TRUE if any of the following is true //
  298. // Presence of Protected/AutoInherited in the contol bits of SD //
  299. // Presence of INHERITED_ACE flag in DACL/SACL //
  300. // //
  301. ////////////////////////////////////////////////////////////////////////////////
  302. BOOL
  303. MartaIsSDNT5Style(
  304. IN PSECURITY_DESCRIPTOR pSD
  305. )
  306. {
  307. BOOL bRetval = TRUE;
  308. PACL pAcl = NULL;
  309. PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR) pSD;
  310. if (MARTA_NT5_FLAGS_ON(pISD->Control))
  311. {
  312. return TRUE;
  313. }
  314. pAcl = RtlpDaclAddrSecurityDescriptor(pISD);
  315. if (NULL != pAcl)
  316. {
  317. bRetval = FALSE;
  318. if (MartaIsAclNt5Style(pAcl))
  319. {
  320. return TRUE;
  321. }
  322. }
  323. pAcl = RtlpSaclAddrSecurityDescriptor(pISD);
  324. if (NULL != pAcl)
  325. {
  326. bRetval = FALSE;
  327. if (MartaIsAclNt5Style(pAcl))
  328. {
  329. return TRUE;
  330. }
  331. }
  332. return bRetval;
  333. }
  334. ////////////////////////////////////////////////////////////////////////////////
  335. // //
  336. // Function: MartaIsAclNT5Style //
  337. // //
  338. // Description: Determine if the Acl is NT5 style. //
  339. // //
  340. // Arguments: //
  341. // //
  342. // [IN pAcl] ACL //
  343. // //
  344. // Returns: TRUE if INHERITED_ACE flags exists in the AceFlags //
  345. // FALSE otherwise //
  346. ////////////////////////////////////////////////////////////////////////////////
  347. BOOL
  348. MartaIsAclNt5Style(
  349. PACL pAcl
  350. )
  351. {
  352. ULONG i = 0;
  353. PACE_HEADER pAce = (PACE_HEADER) FirstAce(pAcl);
  354. for (; i < pAcl->AceCount; i++, pAce = (PACE_HEADER) NextAce(pAce))
  355. {
  356. if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
  357. {
  358. return TRUE;
  359. }
  360. }
  361. return FALSE;
  362. }
  363. ////////////////////////////////////////////////////////////////////////////////
  364. // //
  365. // Function: MartaInitializeGetContext //
  366. // //
  367. // Description: Initializes the function pointers based on object-type. //
  368. // //
  369. // Arguments: //
  370. // //
  371. // [IN ObjectType] Type of the object //
  372. // [OUT pFunctionContext] Structure to hold function pointers //
  373. // //
  374. ////////////////////////////////////////////////////////////////////////////////
  375. VOID
  376. MartaInitializeGetContext(
  377. IN SE_OBJECT_TYPE ObjectType,
  378. OUT PMARTA_GET_FUNCTION_CONTEXT pFunctionContext
  379. )
  380. {
  381. pFunctionContext->fAddRefContext = MartaAddRefContext[ObjectType];
  382. pFunctionContext->fCloseContext = MartaCloseContext[ObjectType];
  383. pFunctionContext->fOpenNamedObject = MartaOpenNamedObject[ObjectType];
  384. pFunctionContext->fOpenHandleObject = MartaOpenHandleObject[ObjectType];
  385. pFunctionContext->fGetRights = MartaGetRights[ObjectType];
  386. pFunctionContext->fGetDesiredAccess = MartaGetDesiredAccess[ObjectType];
  387. pFunctionContext->fGetParentContext = MartaGetParentContext[ObjectType];
  388. pFunctionContext->fGetTypeProperties = MartaGetTypeProperties[ObjectType];
  389. pFunctionContext->fGetProperties = MartaGetProperties[ObjectType];
  390. }
  391. ////////////////////////////////////////////////////////////////////////////////
  392. // //
  393. // Function: MartaGetSidsAndAclsFromSD //
  394. // //
  395. // Description: Fill in the fields requested by GetSecurity API. //
  396. // //
  397. // Arguments: //
  398. // //
  399. // [IN SecurityInfo] Security Information requested //
  400. // [IN pSD] Security Descriptor from which the out //
  401. // fields will be returned //
  402. // //
  403. // [OUT ppSIdOwner] To return the owner //
  404. // [OUT ppSidGroup] To return the group //
  405. // [OUT ppDacl] To return the Dacl //
  406. // [OUT ppSacl] To return the Sacl //
  407. // [OUT ppSecurityDescriptor] To return the Security Descriptor //
  408. // //
  409. ////////////////////////////////////////////////////////////////////////////////
  410. VOID
  411. MartaGetSidsAndAclsFromSD(
  412. IN SECURITY_INFORMATION SecurityInfo,
  413. IN PSECURITY_DESCRIPTOR pSD,
  414. OUT PSID * ppSidOwner,
  415. OUT PSID * ppSidGroup,
  416. OUT PACL * ppDacl,
  417. OUT PACL * ppSacl,
  418. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  419. )
  420. {
  421. PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR) pSD;
  422. if (FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION) && (NULL != ppSidOwner))
  423. {
  424. *ppSidOwner = RtlpOwnerAddrSecurityDescriptor(pISD);
  425. }
  426. if (FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION) && (NULL != ppSidGroup))
  427. {
  428. *ppSidGroup = RtlpGroupAddrSecurityDescriptor(pISD);
  429. }
  430. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION) && (NULL != ppDacl))
  431. {
  432. *ppDacl = RtlpDaclAddrSecurityDescriptor(pISD);
  433. }
  434. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION) && (ppSacl != NULL))
  435. {
  436. *ppSacl = RtlpSaclAddrSecurityDescriptor(pISD);
  437. }
  438. if (NULL != ppSecurityDescriptor)
  439. {
  440. *ppSecurityDescriptor = pSD;
  441. }
  442. }
  443. ////////////////////////////////////////////////////////////////////////////////
  444. // //
  445. // Function: MartaGetRightsFromContext //
  446. // //
  447. // Description: Get the security information requested given the Context. //
  448. // //
  449. // Arguments: //
  450. // //
  451. // [IN Context] Context structure for the object //
  452. // [IN pGetFunctionContext] Structure holding the function pointers //
  453. // [IN SecurityInfo] Security Information requested //
  454. // //
  455. // [OUT ppSIdOwner] To return the owner //
  456. // [OUT ppSidGroup] To return the group //
  457. // [OUT ppDacl] To return the Dacl //
  458. // [OUT ppSacl] To return the Sacl //
  459. // [OUT ppSecurityDescriptor] To return the Security Descriptor //
  460. // //
  461. ////////////////////////////////////////////////////////////////////////////////
  462. DWORD
  463. MartaGetRightsFromContext(
  464. IN MARTA_CONTEXT Context,
  465. IN PMARTA_GET_FUNCTION_CONTEXT pGetFunctionContext,
  466. IN SECURITY_INFORMATION SecurityInfo,
  467. OUT PSID * ppSidOwner,
  468. OUT PSID * ppSidGroup,
  469. OUT PACL * ppDacl,
  470. OUT PACL * ppSacl,
  471. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  472. )
  473. {
  474. DWORD dwErr = ERROR_SUCCESS;
  475. PSECURITY_DESCRIPTOR pSD = NULL;
  476. PSECURITY_DESCRIPTOR pParentSD = NULL;
  477. HANDLE ProcessHandle = NULL;
  478. GENERIC_MAPPING ZeroGenMap = {0, 0, 0, 0};
  479. MARTA_CONTEXT ParentContext = NULL_MARTA_CONTEXT;
  480. BOOL bIsContainer = FALSE;
  481. MARTA_OBJECT_PROPERTIES ObjectProperties;
  482. MARTA_OBJECT_TYPE_PROPERTIES ObjectTypeProperties;
  483. dwErr = (*(pGetFunctionContext->fGetRights))(
  484. Context,
  485. SecurityInfo,
  486. &pSD
  487. );
  488. CONDITIONAL_RETURN(dwErr);
  489. if (NULL == pSD)
  490. {
  491. goto End;
  492. }
  493. if (!FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))
  494. {
  495. goto GetResults;
  496. }
  497. //
  498. // If the SD is NT4 && acl requested is not PROTECTED && ManualPropagation
  499. // is required then
  500. // Get the ParentSD and convert the SD into NT5 style
  501. // else
  502. // Goto GetResults
  503. //
  504. if (!MARTA_SD_NOT_PROTECTED((PISECURITY_DESCRIPTOR) pSD, SecurityInfo))
  505. {
  506. goto GetResults;
  507. }
  508. if (MartaIsSDNT5Style(pSD))
  509. {
  510. goto GetResults;
  511. }
  512. //
  513. // Get the "Type" properties for the object,
  514. //
  515. ObjectTypeProperties.cbSize = sizeof(ObjectTypeProperties);
  516. ObjectTypeProperties.dwFlags = 0;
  517. ObjectTypeProperties.GenMap = ZeroGenMap;
  518. dwErr = (*(pGetFunctionContext->fGetTypeProperties))(&ObjectTypeProperties);
  519. CONDITIONAL_EXIT(dwErr, End);
  520. if (!FLAG_ON(ObjectTypeProperties.dwFlags, MARTA_OBJECT_TYPE_MANUAL_PROPAGATION_NEEDED_FLAG))
  521. {
  522. goto GetResults;
  523. }
  524. dwErr = (*(pGetFunctionContext->fGetParentContext))(
  525. Context,
  526. (*(pGetFunctionContext->fGetDesiredAccess))(READ_ACCESS_RIGHTS, FALSE, SecurityInfo),
  527. &ParentContext
  528. );
  529. CONDITIONAL_EXIT(dwErr, End);
  530. //
  531. // The SD is NT4 style. Read the parent SD to determine whether the aces are
  532. // the "same" on both the parent and the child.
  533. //
  534. if (NULL == ParentContext)
  535. {
  536. goto GetResults;
  537. }
  538. dwErr = (*(pGetFunctionContext->fGetRights))(
  539. ParentContext,
  540. SecurityInfo,
  541. &pParentSD
  542. );
  543. (VOID) (*(pGetFunctionContext->fCloseContext))(ParentContext);
  544. CONDITIONAL_EXIT(dwErr, End);
  545. if (NULL == pParentSD)
  546. {
  547. goto GetResults;
  548. }
  549. dwErr = GetCurrentToken(&ProcessHandle);
  550. CONDITIONAL_EXIT(dwErr, End);
  551. if (!((FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION)) &&
  552. (FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION))))
  553. {
  554. AccFree(pSD);
  555. pSD = NULL;
  556. dwErr = (*(pGetFunctionContext->fGetRights))(
  557. Context,
  558. (SecurityInfo | OWNER_SECURITY_INFORMATION |
  559. GROUP_SECURITY_INFORMATION),
  560. &pSD
  561. );
  562. CONDITIONAL_EXIT(dwErr, End);
  563. }
  564. ObjectProperties.cbSize = sizeof(ObjectProperties);
  565. ObjectProperties.dwFlags = 0;
  566. dwErr = (*(pGetFunctionContext->fGetProperties))(
  567. Context,
  568. &ObjectProperties
  569. );
  570. CONDITIONAL_EXIT(dwErr, End);
  571. bIsContainer = FLAG_ON(ObjectProperties.dwFlags, MARTA_OBJECT_IS_CONTAINER);
  572. dwErr = MartaGetNT4NodeSD(
  573. pParentSD,
  574. pSD,
  575. ProcessHandle,
  576. bIsContainer,
  577. &(ObjectTypeProperties.GenMap),
  578. SecurityInfo
  579. );
  580. CONDITIONAL_EXIT(dwErr, End);
  581. GetResults:
  582. MartaGetSidsAndAclsFromSD(
  583. SecurityInfo,
  584. pSD,
  585. ppSidOwner,
  586. ppSidGroup,
  587. ppDacl,
  588. ppSacl,
  589. ppSecurityDescriptor
  590. );
  591. End:
  592. if (NULL != pParentSD)
  593. {
  594. AccFree(pParentSD);
  595. }
  596. if (NULL != ProcessHandle)
  597. {
  598. CloseHandle(ProcessHandle);
  599. }
  600. if (ERROR_SUCCESS != dwErr)
  601. {
  602. AccFree(pSD);
  603. }
  604. return dwErr;
  605. }
  606. ////////////////////////////////////////////////////////////////////////////////
  607. // //
  608. // Function: AccRewriteGetNamedRights //
  609. // //
  610. // Description: Get the security information requested given the object //
  611. // name and information. This is the routine that is called by //
  612. // advapi32. //
  613. // //
  614. // Arguments: //
  615. // //
  616. // [IN pObjectName] Name of the Object //
  617. // [IN ObjectType] Type of the object //
  618. // [IN SecurityInfo] Security Information requested //
  619. // //
  620. // [OUT ppSIdOwner] To return the owner //
  621. // [OUT ppSidGroup] To return the group //
  622. // [OUT ppDacl] To return the Dacl //
  623. // [OUT ppSacl] To return the Sacl //
  624. // [OUT ppSecurityDescriptor] To return the Security Descriptor //
  625. // //
  626. ////////////////////////////////////////////////////////////////////////////////
  627. DWORD
  628. AccRewriteGetNamedRights(
  629. IN LPWSTR pObjectName,
  630. IN SE_OBJECT_TYPE ObjectType,
  631. IN SECURITY_INFORMATION SecurityInfo,
  632. OUT PSID * ppSidOwner,
  633. OUT PSID * ppSidGroup,
  634. OUT PACL * ppDacl,
  635. OUT PACL * ppSacl,
  636. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  637. )
  638. {
  639. DWORD dwErr = ERROR_SUCCESS;
  640. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  641. MARTA_GET_FUNCTION_CONTEXT MartaGetFunctionContext;
  642. switch (ObjectType)
  643. {
  644. case SE_FILE_OBJECT:
  645. case SE_SERVICE:
  646. case SE_PRINTER:
  647. case SE_REGISTRY_KEY:
  648. case SE_REGISTRY_WOW64_32KEY:
  649. case SE_LMSHARE:
  650. case SE_KERNEL_OBJECT:
  651. case SE_WINDOW_OBJECT:
  652. case SE_WMIGUID_OBJECT:
  653. case SE_DS_OBJECT:
  654. case SE_DS_OBJECT_ALL:
  655. break;
  656. case SE_PROVIDER_DEFINED_OBJECT:
  657. case SE_UNKNOWN_OBJECT_TYPE:
  658. default:
  659. return ERROR_INVALID_PARAMETER;
  660. }
  661. MartaInitializeGetContext(ObjectType, &MartaGetFunctionContext);
  662. //
  663. // Open the object with permissions to read the object type as well. If that
  664. // fails, open the object with just read permissions. This has to be done in
  665. // order to accomodate NT4 SDs.
  666. //
  667. dwErr = (*(MartaGetFunctionContext.fOpenNamedObject))(
  668. pObjectName,
  669. (*(MartaGetFunctionContext.fGetDesiredAccess))(READ_ACCESS_RIGHTS, TRUE, SecurityInfo),
  670. &Context
  671. );
  672. if (ERROR_SUCCESS != dwErr)
  673. {
  674. dwErr = (*(MartaGetFunctionContext.fOpenNamedObject))(
  675. pObjectName,
  676. (*(MartaGetFunctionContext.fGetDesiredAccess))(READ_ACCESS_RIGHTS, FALSE, SecurityInfo),
  677. &Context
  678. );
  679. CONDITIONAL_EXIT(dwErr, End);
  680. }
  681. dwErr = MartaGetRightsFromContext(
  682. Context,
  683. &MartaGetFunctionContext,
  684. SecurityInfo,
  685. ppSidOwner,
  686. ppSidGroup,
  687. ppDacl,
  688. ppSacl,
  689. ppSecurityDescriptor
  690. );
  691. (VOID) (*(MartaGetFunctionContext.fCloseContext))(Context);
  692. End:
  693. return dwErr;
  694. }
  695. ////////////////////////////////////////////////////////////////////////////////
  696. // //
  697. // Function: AccRewriteGetHandleRights //
  698. // //
  699. // Description: Get the security information requested given the object //
  700. // handle and information. This is the routine that is called by //
  701. // advapi32. //
  702. // //
  703. // Arguments: //
  704. // //
  705. // [IN Handle] Handle to the Object //
  706. // [IN pGetFunctionContext] Structure holding the function pointers //
  707. // [IN SecurityInfo] Security Information requested //
  708. // //
  709. // [OUT ppSIdOwner] To return the owner //
  710. // [OUT ppSidGroup] To return the group //
  711. // [OUT ppDacl] To return the Dacl //
  712. // [OUT ppSacl] To return the Sacl //
  713. // [OUT ppSecurityDescriptor] To return the Security Descriptor //
  714. // //
  715. ////////////////////////////////////////////////////////////////////////////////
  716. DWORD
  717. AccRewriteGetHandleRights(
  718. IN HANDLE Handle,
  719. IN SE_OBJECT_TYPE ObjectType,
  720. IN SECURITY_INFORMATION SecurityInfo,
  721. OUT PSID * ppSidOwner,
  722. OUT PSID * ppSidGroup,
  723. OUT PACL * ppDacl,
  724. OUT PACL * ppSacl,
  725. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  726. )
  727. {
  728. DWORD dwErr = ERROR_SUCCESS;
  729. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  730. MARTA_GET_FUNCTION_CONTEXT MartaGetFunctionContext;
  731. switch (ObjectType)
  732. {
  733. case SE_FILE_OBJECT:
  734. case SE_SERVICE:
  735. case SE_PRINTER:
  736. case SE_REGISTRY_KEY:
  737. case SE_LMSHARE:
  738. case SE_KERNEL_OBJECT:
  739. case SE_WINDOW_OBJECT:
  740. case SE_WMIGUID_OBJECT:
  741. break;
  742. case SE_DS_OBJECT:
  743. case SE_DS_OBJECT_ALL:
  744. case SE_PROVIDER_DEFINED_OBJECT:
  745. case SE_UNKNOWN_OBJECT_TYPE:
  746. default:
  747. return ERROR_INVALID_PARAMETER;
  748. }
  749. MartaInitializeGetContext(ObjectType, &MartaGetFunctionContext);
  750. //
  751. // Open the object with permissions to read the object type as well. If that
  752. // fails, open the object with just read permissions. This has to be done in
  753. // order to accomodate NT4 SDs.
  754. //
  755. dwErr = (*(MartaGetFunctionContext.fOpenHandleObject))(
  756. Handle,
  757. (*(MartaGetFunctionContext.fGetDesiredAccess))(READ_ACCESS_RIGHTS, TRUE, SecurityInfo),
  758. &Context
  759. );
  760. if (ERROR_SUCCESS != dwErr)
  761. {
  762. dwErr = (*(MartaGetFunctionContext.fOpenHandleObject))(
  763. Handle,
  764. (*(MartaGetFunctionContext.fGetDesiredAccess))(READ_ACCESS_RIGHTS, FALSE, SecurityInfo),
  765. &Context
  766. );
  767. CONDITIONAL_EXIT(dwErr, End);
  768. }
  769. dwErr = MartaGetRightsFromContext(
  770. Context,
  771. &MartaGetFunctionContext,
  772. SecurityInfo,
  773. ppSidOwner,
  774. ppSidGroup,
  775. ppDacl,
  776. ppSacl,
  777. ppSecurityDescriptor
  778. );
  779. (VOID) (*(MartaGetFunctionContext.fCloseContext))(Context);
  780. End:
  781. return dwErr;
  782. }
  783. ////////////////////////////////////////////////////////////////////////////////
  784. // //
  785. // Function: MartaInitializeSetContext //
  786. // //
  787. // Description: Initializes the function pointers based on object-type. //
  788. // //
  789. // Arguments: //
  790. // //
  791. // [IN ObjectType] Type of the object //
  792. // [OUT pFunctionContext] Structure to hold function pointers //
  793. // //
  794. ////////////////////////////////////////////////////////////////////////////////
  795. VOID
  796. MartaInitializeSetContext(
  797. IN SE_OBJECT_TYPE ObjectType,
  798. OUT PMARTA_SET_FUNCTION_CONTEXT pFunctionContext
  799. )
  800. {
  801. pFunctionContext->fAddRefContext = MartaAddRefContext[ObjectType];
  802. pFunctionContext->fCloseContext = MartaCloseContext[ObjectType];
  803. pFunctionContext->fFindFirst = MartaFindFirst[ObjectType];
  804. pFunctionContext->fFindNext = MartaFindNext[ObjectType];
  805. pFunctionContext->fGetParentContext = MartaGetParentContext[ObjectType];
  806. pFunctionContext->fGetProperties = MartaGetProperties[ObjectType];
  807. pFunctionContext->fGetTypeProperties = MartaGetTypeProperties[ObjectType];
  808. pFunctionContext->fGetRights = MartaGetRights[ObjectType];
  809. pFunctionContext->fOpenNamedObject = MartaOpenNamedObject[ObjectType];
  810. pFunctionContext->fOpenHandleObject = MartaOpenHandleObject[ObjectType];
  811. pFunctionContext->fSetRights = MartaSetRights[ObjectType];
  812. pFunctionContext->fGetDesiredAccess = MartaGetDesiredAccess[ObjectType];
  813. pFunctionContext->fReopenContext = MartaReopenContext[ObjectType];
  814. pFunctionContext->fReopenOrigContext = MartaReopenOrigContext[ObjectType];
  815. pFunctionContext->fGetNameFromContext = MartaGetNameFromContext[ObjectType];
  816. }
  817. ////////////////////////////////////////////////////////////////////////////////
  818. // //
  819. // Function: MartaManualPropagation //
  820. // //
  821. // Description: Stamp the security descriptor on the object referred by the //
  822. // context and propagate the inheritable aces to its children. //
  823. // //
  824. // Arguments: //
  825. // //
  826. // [IN Context] Context structure for the object //
  827. // [IN SecurityInfo] Security Information requested //
  828. // [IN OUT pSD] Security Descriptor to be stamped on the //
  829. // object in absolute format. //
  830. // [IN pGenMap] Generic mapping of the object rights //
  831. // [IN bDoPropagate] Whether propagation _can_ be done //
  832. // [IN bReadOldProtectedBits] Whether to read existing protection info //
  833. // [IN pSetFunctionContext] Structure holding the function pointers //
  834. // [IN bSkipInheritanceComputation] Whether to compute inherited aces //
  835. // from the parent
  836. // //
  837. ////////////////////////////////////////////////////////////////////////////////
  838. DWORD
  839. MartaManualPropagation(
  840. IN MARTA_CONTEXT Context,
  841. IN SECURITY_INFORMATION SecurityInfo,
  842. IN OUT PSECURITY_DESCRIPTOR pSD,
  843. IN PGENERIC_MAPPING pGenMap,
  844. IN BOOL bDoPropagate,
  845. IN BOOL bReadOldProtectedBits,
  846. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  847. IN BOOL bSkipInheritanceComputation
  848. )
  849. {
  850. DWORD dwErr = ERROR_SUCCESS;
  851. BOOL bProtected = TRUE;
  852. BOOL bIsChildContainer = FALSE;
  853. BOOL bRetryPropagation = FALSE;
  854. PSECURITY_DESCRIPTOR pParentSD = NULL;
  855. PSECURITY_DESCRIPTOR pOldSD = NULL;
  856. PSECURITY_DESCRIPTOR pNewSD = NULL;
  857. PSID pSidOwner = NULL;
  858. HANDLE ProcessHandle = NULL;
  859. HANDLE ThreadHandle = NULL;
  860. MARTA_CONTEXT ParentContext = NULL_MARTA_CONTEXT;
  861. SECURITY_DESCRIPTOR_CONTROL LocalControl = (SECURITY_DESCRIPTOR_CONTROL) 0;
  862. MARTA_OBJECT_PROPERTIES ObjectProperties;
  863. //
  864. // Check if manual propagation should be done. Propagation is not tried if
  865. // any errors are encountered.
  866. //
  867. ObjectProperties.cbSize = sizeof(ObjectProperties);
  868. ObjectProperties.dwFlags = 0;
  869. dwErr = (*(pMartaSetFunctionContext->fGetProperties))(
  870. Context,
  871. &ObjectProperties
  872. );
  873. CONDITIONAL_EXIT(dwErr, End);
  874. bIsChildContainer = FLAG_ON(ObjectProperties.dwFlags, MARTA_OBJECT_IS_CONTAINER);
  875. dwErr = GetCurrentToken(&ProcessHandle);
  876. CONDITIONAL_EXIT(dwErr, End);
  877. //
  878. // Compute inherited aces if the caller has not already. This is the usual
  879. // case.
  880. //
  881. if (FALSE == bSkipInheritanceComputation)
  882. {
  883. //
  884. // Read the parent ACL only if xACL is to be stamped on is not protected.
  885. //
  886. if (MARTA_SD_NOT_PROTECTED((PISECURITY_DESCRIPTOR) pSD, SecurityInfo))
  887. {
  888. bProtected = FALSE;
  889. dwErr = (*(pMartaSetFunctionContext->fGetParentContext))(
  890. Context,
  891. (*(pMartaSetFunctionContext->fGetDesiredAccess))(READ_ACCESS_RIGHTS, FALSE, SecurityInfo),
  892. &ParentContext
  893. );
  894. CONDITIONAL_EXIT(dwErr, End);
  895. if (NULL != ParentContext)
  896. {
  897. dwErr = (*(pMartaSetFunctionContext->fGetRights))(
  898. ParentContext,
  899. SecurityInfo,
  900. &pParentSD
  901. );
  902. (VOID) (*(pMartaSetFunctionContext->fCloseContext))(ParentContext);
  903. CONDITIONAL_EXIT(dwErr, End);
  904. if (NULL != pParentSD)
  905. {
  906. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  907. {
  908. ((PISECURITY_DESCRIPTOR) pParentSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  909. }
  910. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  911. {
  912. ((PISECURITY_DESCRIPTOR) pParentSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  913. }
  914. }
  915. }
  916. }
  917. //
  918. // Read the old security descriptor on the child.
  919. // To take case of creator-owner/group aces, read in Owner/Group info as
  920. // well and set it in the SD passed in if it is not already present.
  921. //
  922. {
  923. SECURITY_INFORMATION LocalSeInfo = SecurityInfo;
  924. if (NULL == RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD))
  925. {
  926. LocalSeInfo |= OWNER_SECURITY_INFORMATION;
  927. }
  928. if (NULL == RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD))
  929. {
  930. LocalSeInfo |= GROUP_SECURITY_INFORMATION;
  931. }
  932. dwErr = (*(pMartaSetFunctionContext->fGetRights))(
  933. Context,
  934. LocalSeInfo,
  935. &pOldSD
  936. );
  937. CONDITIONAL_EXIT(dwErr, End);
  938. if (NULL == RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD))
  939. {
  940. if (FALSE == SetSecurityDescriptorOwner(
  941. pSD,
  942. RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldSD),
  943. FALSE))
  944. {
  945. dwErr = GetLastError();
  946. }
  947. CONDITIONAL_EXIT(dwErr, End);
  948. }
  949. if (NULL == RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD))
  950. {
  951. if (FALSE == SetSecurityDescriptorGroup(
  952. pSD,
  953. RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldSD),
  954. FALSE))
  955. {
  956. dwErr = GetLastError();
  957. }
  958. CONDITIONAL_EXIT(dwErr, End);
  959. }
  960. }
  961. //
  962. // If none of the PROTECTED flags are passed in then do the "right" thing.
  963. // Read the PROTECTED bit from the existing security descriptor and set it
  964. // in the new one.
  965. //
  966. if (bReadOldProtectedBits && (NULL != pOldSD))
  967. {
  968. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  969. {
  970. if (!FLAG_ON(SecurityInfo, (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)))
  971. {
  972. ((PISECURITY_DESCRIPTOR) pSD)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_DACL_PROTECTED;
  973. }
  974. }
  975. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  976. {
  977. if (!FLAG_ON(SecurityInfo, (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
  978. {
  979. ((PISECURITY_DESCRIPTOR) pSD)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_SACL_PROTECTED;
  980. }
  981. }
  982. }
  983. //
  984. // Merge the SD with the parent SD whether or not it is protected.
  985. // This is done to lose the inherited aces if the child is protected.
  986. //
  987. MARTA_TURN_OFF_IMPERSONATION;
  988. CONDITIONAL_EXIT(dwErr, End);
  989. if (FALSE == CreatePrivateObjectSecurityEx(
  990. pParentSD,
  991. pSD,
  992. &pNewSD,
  993. NULL,
  994. bIsChildContainer,
  995. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT | SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  996. ProcessHandle,
  997. pGenMap
  998. ))
  999. {
  1000. dwErr = GetLastError();
  1001. }
  1002. MARTA_TURN_ON_IMPERSONATION;
  1003. CONDITIONAL_EXIT(dwErr, End);
  1004. }
  1005. else
  1006. {
  1007. //
  1008. // Stamp the security descriptor as prvided by the caller. The only
  1009. // caller of this is SCE.
  1010. //
  1011. pNewSD = pSD;
  1012. //
  1013. // Read the old security descriptor on the child if xAcl it is a container.
  1014. //
  1015. if (bIsChildContainer)
  1016. {
  1017. dwErr = (*(pMartaSetFunctionContext->fGetRights))(
  1018. Context,
  1019. (SecurityInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)),
  1020. &pOldSD
  1021. );
  1022. CONDITIONAL_EXIT(dwErr, End);
  1023. }
  1024. }
  1025. //
  1026. // If the child is a container then update the subtree underneath it.
  1027. //
  1028. if (bIsChildContainer)
  1029. {
  1030. if (bDoPropagate)
  1031. {
  1032. bRetryPropagation = MartaUpdateTree(
  1033. SecurityInfo,
  1034. pNewSD,
  1035. pOldSD,
  1036. Context,
  1037. ProcessHandle,
  1038. pMartaSetFunctionContext,
  1039. pGenMap
  1040. );
  1041. }
  1042. else
  1043. {
  1044. bRetryPropagation = TRUE;
  1045. }
  1046. }
  1047. //
  1048. // Stamp NewNodeSD on the node
  1049. //
  1050. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  1051. {
  1052. ((PISECURITY_DESCRIPTOR) pNewSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  1053. }
  1054. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  1055. {
  1056. ((PISECURITY_DESCRIPTOR) pNewSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  1057. }
  1058. dwErr = (*(pMartaSetFunctionContext->fSetRights))(
  1059. Context,
  1060. SecurityInfo,
  1061. pNewSD
  1062. );
  1063. CONDITIONAL_EXIT(dwErr, End);
  1064. //
  1065. // If propagation had failed in the first attept then try again. This is to
  1066. // cover the case when the container can be enumerated after setting the new
  1067. // security.
  1068. if (bRetryPropagation && (SecurityInfo & DACL_SECURITY_INFORMATION))
  1069. {
  1070. ACCESS_MASK Access = (*(pMartaSetFunctionContext->fGetDesiredAccess))(
  1071. NO_ACCESS_RIGHTS,
  1072. TRUE,
  1073. SecurityInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)
  1074. );
  1075. DWORD lErr = (*(pMartaSetFunctionContext->fReopenOrigContext))(
  1076. Context,
  1077. Access
  1078. );
  1079. CONDITIONAL_EXIT(lErr, End);
  1080. (VOID) MartaUpdateTree(
  1081. SecurityInfo,
  1082. pNewSD,
  1083. pOldSD,
  1084. Context,
  1085. ProcessHandle,
  1086. pMartaSetFunctionContext,
  1087. pGenMap
  1088. );
  1089. }
  1090. End:
  1091. if (NULL != ProcessHandle)
  1092. {
  1093. CloseHandle(ProcessHandle);
  1094. }
  1095. if (NULL != pOldSD)
  1096. {
  1097. AccFree(pOldSD);
  1098. }
  1099. if (NULL != pParentSD)
  1100. {
  1101. AccFree(pParentSD);
  1102. }
  1103. if ((NULL != pNewSD) && (pNewSD != pSD))
  1104. {
  1105. DestroyPrivateObjectSecurity(&pNewSD);
  1106. }
  1107. return dwErr;
  1108. }
  1109. ////////////////////////////////////////////////////////////////////////////////
  1110. // //
  1111. // Function: MartaEqualAce //
  1112. // //
  1113. // Description: Compare an ace from child to an ace from parent to determine //
  1114. // if the child ace has been inherited from its parent. //
  1115. // //
  1116. // Arguments: //
  1117. // //
  1118. // [IN pParentAce] The ace for the parent object //
  1119. // [IN pChildAce] The ace for the child object //
  1120. // [IN pNextChildAce] The next ace for the child object //
  1121. // [IN bIsChildContainer] Whether the child object is a Container //
  1122. // [OUT pbMarkNextAce] Whether next ACE should be marked inherited //
  1123. // //
  1124. // Returns: TRUE if the two aces are equal //
  1125. // FALSE otherwise //
  1126. // //
  1127. // Notes: No ace should contain generic bits and the parent ace should not //
  1128. // have INHERIT_ONLY bit. //
  1129. // Inherit flags are ignored. //
  1130. // //
  1131. ////////////////////////////////////////////////////////////////////////////////
  1132. BOOL
  1133. MartaEqualAce(
  1134. IN PACE_HEADER pParentAce,
  1135. IN PACE_HEADER pChildAce,
  1136. IN PACE_HEADER pNextChildAce,
  1137. IN BOOL bIsChildContainer,
  1138. OUT PBOOL pbMarkNextAce
  1139. )
  1140. {
  1141. PSID pSid1 = NULL;
  1142. PSID pSid2 = NULL;
  1143. ACCESS_MASK Access1 = 0;
  1144. ACCESS_MASK Access2 = 0;
  1145. ULONG Length1 = 0;
  1146. ULONG Length2 = 0;
  1147. UCHAR ParentFlags = pParentAce->AceFlags & ~INHERITED_ACE;
  1148. *pbMarkNextAce = FALSE;
  1149. if ((NULL == pParentAce) || (NULL == pChildAce))
  1150. {
  1151. return FALSE;
  1152. }
  1153. //
  1154. // Compare ACE type.
  1155. //
  1156. if (pParentAce->AceType != pChildAce->AceType)
  1157. {
  1158. return FALSE;
  1159. }
  1160. if ((pParentAce->AceFlags & ~INHERITED_ACE) != (pChildAce->AceFlags))
  1161. {
  1162. //
  1163. // The flags did not match exactly. So, this is not a NT4 object created
  1164. // on Win2K+ system. But, this may be a NT4 object created on NT4 system.
  1165. // The inheritance algorithm on NT4 was not optimal and it creates two
  1166. // ACEs when one is sufficient.
  1167. // The specific case we are trying to catch is:
  1168. // Ace on the parent = combination of OI, CI
  1169. // On Child
  1170. // ACE1 = NO Flags
  1171. // ACE2 = Same flags as well as OI
  1172. //
  1173. if (bIsChildContainer &&
  1174. (ParentFlags != 0) &&
  1175. (pNextChildAce != NULL) &&
  1176. (pChildAce->AceFlags == 0) &&
  1177. ((ParentFlags & INHERIT_ONLY) == 0) &&
  1178. (ParentFlags == (pNextChildAce->AceFlags ^ INHERIT_ONLY))
  1179. )
  1180. {
  1181. switch (pParentAce->AceType) {
  1182. case ACCESS_ALLOWED_ACE_TYPE:
  1183. case ACCESS_DENIED_ACE_TYPE:
  1184. case SYSTEM_AUDIT_ACE_TYPE:
  1185. case SYSTEM_ALARM_ACE_TYPE:
  1186. if ((((PKNOWN_ACE) pParentAce)->Mask == ((PKNOWN_ACE) pNextChildAce)->Mask) &&
  1187. RtlEqualSid((PSID) &((PKNOWN_ACE) pNextChildAce)->SidStart, (PSID) &((PKNOWN_ACE) pChildAce)->SidStart)
  1188. )
  1189. {
  1190. //
  1191. // Compare the next ACE instead.
  1192. //
  1193. pChildAce = pNextChildAce;
  1194. }
  1195. else
  1196. {
  1197. return FALSE;
  1198. }
  1199. break;
  1200. default:
  1201. return FALSE;
  1202. }
  1203. }
  1204. else
  1205. {
  1206. return FALSE;
  1207. }
  1208. }
  1209. //
  1210. // Get access mask and SID pointer.
  1211. //
  1212. switch (pParentAce->AceType) {
  1213. case ACCESS_ALLOWED_ACE_TYPE:
  1214. case ACCESS_DENIED_ACE_TYPE:
  1215. case SYSTEM_AUDIT_ACE_TYPE:
  1216. case SYSTEM_ALARM_ACE_TYPE:
  1217. pSid1 = (PSID) &((PKNOWN_ACE) pParentAce)->SidStart;
  1218. pSid2 = (PSID) &((PKNOWN_ACE) pChildAce)->SidStart;
  1219. Access1 = ((PKNOWN_ACE) pParentAce)->Mask;
  1220. Access2 = ((PKNOWN_ACE) pChildAce)->Mask;
  1221. break;
  1222. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1223. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1224. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1225. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  1226. if (((PKNOWN_OBJECT_ACE) pParentAce)->Flags !=
  1227. ((PKNOWN_OBJECT_ACE) pChildAce)->Flags )
  1228. {
  1229. return FALSE;
  1230. }
  1231. if (((PKNOWN_OBJECT_ACE) pParentAce)->Flags & ACE_OBJECT_TYPE_PRESENT)
  1232. {
  1233. if (!RtlpIsEqualGuid(
  1234. RtlObjectAceObjectType(pParentAce),
  1235. RtlObjectAceObjectType(pChildAce)))
  1236. {
  1237. return FALSE;
  1238. }
  1239. }
  1240. if (((PKNOWN_OBJECT_ACE) pParentAce)->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  1241. {
  1242. if (!RtlpIsEqualGuid(
  1243. RtlObjectAceInheritedObjectType(pParentAce),
  1244. RtlObjectAceInheritedObjectType(pChildAce)))
  1245. {
  1246. return FALSE;
  1247. }
  1248. }
  1249. pSid1 = RtlObjectAceSid(pParentAce);
  1250. pSid2 = RtlObjectAceSid(pChildAce);
  1251. Access1 = ((PKNOWN_OBJECT_ACE) pParentAce)->Mask;
  1252. Access2 = ((PKNOWN_OBJECT_ACE) pChildAce)->Mask;
  1253. break;
  1254. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  1255. if (((PKNOWN_COMPOUND_ACE) pParentAce)->CompoundAceType !=
  1256. ((PKNOWN_COMPOUND_ACE) pChildAce)->CompoundAceType)
  1257. {
  1258. return FALSE;
  1259. }
  1260. pSid1 = (PSID) &((PKNOWN_COMPOUND_ACE) pParentAce)->SidStart;
  1261. pSid2 = (PSID) &((PKNOWN_COMPOUND_ACE) pParentAce)->SidStart;
  1262. if ((!RtlValidSid(pSid1)) || (!RtlValidSid(pSid2)))
  1263. {
  1264. return FALSE;
  1265. }
  1266. if (!RtlEqualSid(pSid1, pSid2))
  1267. {
  1268. return FALSE;
  1269. }
  1270. Length1 = RtlLengthSid(pSid1);
  1271. Length2 = RtlLengthSid(pSid2);
  1272. pSid1 = (PSID) (((PUCHAR) pSid1) + Length1);
  1273. pSid2 = (PSID) (((PUCHAR) pSid2) + Length2);
  1274. Access1 = ((PKNOWN_COMPOUND_ACE) pParentAce)->Mask;
  1275. Access2 = ((PKNOWN_COMPOUND_ACE) pChildAce)->Mask;
  1276. break;
  1277. default:
  1278. return FALSE;
  1279. }
  1280. //
  1281. // Compare access mask. There should be no generic mask and both the parent
  1282. // object and the child object should have the same object type.
  1283. //
  1284. if (Access1 != Access2) {
  1285. return FALSE;
  1286. }
  1287. //
  1288. // Compare the Sids.
  1289. //
  1290. if ((!RtlValidSid(pSid1)) || (!RtlValidSid(pSid2)))
  1291. {
  1292. return FALSE;
  1293. }
  1294. if (!RtlEqualSid(pSid1, pSid2))
  1295. {
  1296. return FALSE;
  1297. }
  1298. if (pChildAce == pNextChildAce)
  1299. {
  1300. *pbMarkNextAce = TRUE;
  1301. }
  1302. return TRUE;
  1303. }
  1304. ////////////////////////////////////////////////////////////////////////////////
  1305. // //
  1306. // Function: CompareAndMarkInheritedAces //
  1307. // //
  1308. // Description: Compare the parent acl with the child. If all the effective //
  1309. // aces from parent are present in the child then mark those //
  1310. // aces in the child with INHERITED_ACE bit. //
  1311. // //
  1312. // Arguments: //
  1313. // //
  1314. // [IN pParentAcl] The acl for the parent object //
  1315. // [IN OUT pChildAcl] The acl for the child object //
  1316. // [IN bIsChildContainer] Whether the child object is a Container //
  1317. // //
  1318. // [OUT pCompareStatus] To return the Security Descriptor //
  1319. // //
  1320. // Returns: TRUE if the all effective parent aces are present in the child //
  1321. // FALSE otherwise //
  1322. // //
  1323. ////////////////////////////////////////////////////////////////////////////////
  1324. DWORD
  1325. MartaCompareAndMarkInheritedAces(
  1326. IN PACL pParentAcl,
  1327. IN OUT PACL pChildAcl,
  1328. IN BOOL bIsChildContainer,
  1329. OUT PBOOL pCompareStatus
  1330. )
  1331. {
  1332. DWORD dwErr = ERROR_SUCCESS;
  1333. LONG ParentAceCnt = 0;
  1334. LONG ChildAceCnt = 0;
  1335. LONG i = 0;
  1336. LONG j = 0;
  1337. LONG LastDenyAce = -1;
  1338. LONG LastExplicitAce = -1;
  1339. LONG LastInheritedDenyAce = -1;
  1340. LONG FirstAllowAce = ChildAceCnt;
  1341. LONG FirstInheritedAce = ChildAceCnt;
  1342. LONG FirstExplicitAllowAce = ChildAceCnt;
  1343. BOOL bMarkNextAce = FALSE;
  1344. PACE_HEADER pParentAce = NULL;
  1345. PACE_HEADER pChildAce = NULL;
  1346. PACE_HEADER pNextChildAce = NULL;
  1347. PBOOL Flags = NULL;
  1348. PUCHAR Buffer = NULL;
  1349. PUCHAR CurrentBuffer = NULL;
  1350. //
  1351. // If the ChildAcl is NULL then it is a superset of the parent ACL.
  1352. //
  1353. if (NULL == pChildAcl)
  1354. {
  1355. *pCompareStatus = FALSE;
  1356. goto End;
  1357. }
  1358. //
  1359. // If the ParentAcl is NULL then it is a superset of the child ACL.
  1360. // Since Child Acl is non-null at this point return TRUE.
  1361. //
  1362. if (NULL == pParentAcl)
  1363. {
  1364. *pCompareStatus = TRUE;
  1365. goto End;
  1366. }
  1367. //
  1368. // If the parent has no aces that could have been inherited then all the
  1369. // child aces must be explicit.
  1370. //
  1371. ParentAceCnt = pParentAcl->AceCount;
  1372. if (0 == ParentAceCnt)
  1373. {
  1374. *pCompareStatus = TRUE;
  1375. goto End;
  1376. }
  1377. //
  1378. // If the parent has one/more inheritable aces but the child has none then
  1379. // the acl must be protected.
  1380. //
  1381. ChildAceCnt = pChildAcl->AceCount;
  1382. if (0 == ChildAceCnt)
  1383. {
  1384. *pCompareStatus = FALSE;
  1385. goto End;
  1386. }
  1387. Flags = (PBOOL) AccAlloc(sizeof(BOOL) * ChildAceCnt);
  1388. if (NULL == Flags)
  1389. {
  1390. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1391. goto End;
  1392. }
  1393. for (i = 0; i < ChildAceCnt; i++)
  1394. {
  1395. Flags[i] = FALSE;
  1396. }
  1397. //
  1398. // For all aces present in ParentAcl
  1399. // If the ace is not present in ChildAcl
  1400. // return FALSE
  1401. // else
  1402. // Mark the position of the this ace in Child Acl in fFlags.
  1403. // These will later be marked as INHERITED if the acl can be
  1404. // rearranged to be canonical.
  1405. //
  1406. i = 0;
  1407. pParentAce = (PACE_HEADER) FirstAce(pParentAcl);
  1408. for (; i < ParentAceCnt; i++, pParentAce = (PACE_HEADER) NextAce(pParentAce))
  1409. {
  1410. j = 0;
  1411. pChildAce = (PACE_HEADER) FirstAce(pChildAcl);
  1412. for (; j < ChildAceCnt; j++, pChildAce = (PACE_HEADER) NextAce(pChildAce))
  1413. {
  1414. if ((j + 1) == ChildAceCnt)
  1415. {
  1416. //
  1417. // There is no next ACE.
  1418. //
  1419. pNextChildAce = NULL;
  1420. }
  1421. else
  1422. {
  1423. pNextChildAce = (PACE_HEADER) NextAce(pChildAce);
  1424. }
  1425. if (TRUE == MartaEqualAce(pParentAce, pChildAce, pNextChildAce, bIsChildContainer, &bMarkNextAce))
  1426. {
  1427. Flags[j] = TRUE;
  1428. if (bMarkNextAce)
  1429. {
  1430. Flags[j + 1] = TRUE;
  1431. }
  1432. break;
  1433. }
  1434. }
  1435. if (ChildAceCnt == j)
  1436. {
  1437. *pCompareStatus = FALSE;
  1438. goto End;
  1439. }
  1440. }
  1441. //
  1442. // Mark all the aces that we had marked as INHERITED.
  1443. // This will make sure that they are not DUPLICATED.
  1444. //
  1445. LastDenyAce = -1;
  1446. LastExplicitAce = -1;
  1447. LastInheritedDenyAce = -1;
  1448. FirstAllowAce = ChildAceCnt;
  1449. FirstInheritedAce = ChildAceCnt;
  1450. FirstExplicitAllowAce = ChildAceCnt;
  1451. //
  1452. // Run thru the acl and mark the positions of aces. These will be later used
  1453. // to dtermine what should be done with the acl.
  1454. //
  1455. j = 0;
  1456. pChildAce = (PACE_HEADER) FirstAce(pChildAcl);
  1457. for (; j < ChildAceCnt; j++, pChildAce = (PACE_HEADER) NextAce(pChildAce))
  1458. {
  1459. switch (pChildAce->AceType)
  1460. {
  1461. case ACCESS_ALLOWED_ACE_TYPE:
  1462. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1463. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  1464. if (FALSE == Flags[j])
  1465. {
  1466. if (ChildAceCnt == FirstExplicitAllowAce)
  1467. {
  1468. FirstExplicitAllowAce = j;
  1469. }
  1470. }
  1471. if (ChildAceCnt == FirstAllowAce)
  1472. {
  1473. FirstAllowAce = j;
  1474. }
  1475. break;
  1476. case ACCESS_DENIED_ACE_TYPE:
  1477. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1478. if (TRUE == Flags[j])
  1479. {
  1480. LastInheritedDenyAce = j;
  1481. }
  1482. LastDenyAce = j;
  1483. break;
  1484. default:
  1485. break;
  1486. }
  1487. if (FALSE == Flags[j])
  1488. {
  1489. LastExplicitAce = j;
  1490. }
  1491. else
  1492. {
  1493. if (ChildAceCnt == FirstInheritedAce)
  1494. {
  1495. FirstInheritedAce = j;
  1496. }
  1497. }
  1498. }
  1499. //
  1500. // This a non-canonical acl. Do not try to correct it.
  1501. //
  1502. if ((ChildAceCnt != FirstAllowAce) && (LastDenyAce > FirstAllowAce))
  1503. {
  1504. *pCompareStatus = FALSE;
  1505. goto End;
  1506. }
  1507. //
  1508. // Do not try to rearrange the acl if
  1509. // 1. an inherited deny ace exists AND
  1510. // 2. an explicit allow ace exists.
  1511. //
  1512. if ((-1 != LastInheritedDenyAce) && (ChildAceCnt != FirstExplicitAllowAce))
  1513. {
  1514. *pCompareStatus = FALSE;
  1515. goto End;
  1516. }
  1517. //
  1518. // The acl need not be rearranged since all the explicit aces are ahead of
  1519. // the inherited ones.
  1520. //
  1521. if (LastExplicitAce < FirstInheritedAce)
  1522. {
  1523. j = 0;
  1524. pChildAce = (PACE_HEADER) FirstAce(pChildAcl);
  1525. for (; j < ChildAceCnt; j++, pChildAce = (PACE_HEADER) NextAce(pChildAce))
  1526. {
  1527. if (TRUE == Flags[j])
  1528. {
  1529. pChildAce->AceFlags |= INHERITED_ACE;
  1530. }
  1531. }
  1532. }
  1533. //
  1534. // At least one inherited ace exists before an explicit one.
  1535. // Rearrange the acl to get it in canonical form.
  1536. //
  1537. else
  1538. {
  1539. Buffer = (PUCHAR) AccAlloc(pChildAcl->AclSize - sizeof(ACL));
  1540. CurrentBuffer = Buffer;
  1541. if (NULL == Buffer)
  1542. {
  1543. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1544. goto End;
  1545. }
  1546. j = 0;
  1547. pChildAce = (PACE_HEADER) FirstAce(pChildAcl);
  1548. for (; j <= LastExplicitAce; j++, pChildAce = (PACE_HEADER) NextAce(pChildAce))
  1549. {
  1550. if (FALSE == Flags[j])
  1551. {
  1552. memcpy(CurrentBuffer, (PUCHAR) pChildAce, pChildAce->AceSize);
  1553. CurrentBuffer += pChildAce->AceSize;
  1554. }
  1555. }
  1556. j = 0;
  1557. pChildAce = (PACE_HEADER) FirstAce(pChildAcl);
  1558. for (; j < ChildAceCnt; j++, pChildAce = (PACE_HEADER) NextAce(pChildAce))
  1559. {
  1560. if (TRUE == Flags[j])
  1561. {
  1562. memcpy(CurrentBuffer, (PUCHAR) pChildAce, pChildAce->AceSize);
  1563. ((PACE_HEADER) CurrentBuffer)->AceFlags |= INHERITED_ACE;
  1564. CurrentBuffer += pChildAce->AceSize;
  1565. }
  1566. }
  1567. memcpy(
  1568. ((PUCHAR) pChildAcl) + sizeof(ACL),
  1569. Buffer,
  1570. pChildAcl->AclSize - sizeof(ACL)
  1571. );
  1572. }
  1573. *pCompareStatus = TRUE;
  1574. End:
  1575. if (NULL != Flags)
  1576. {
  1577. AccFree(Flags);
  1578. }
  1579. if (NULL != Buffer)
  1580. {
  1581. AccFree(Buffer);
  1582. }
  1583. return dwErr;;
  1584. }
  1585. ////////////////////////////////////////////////////////////////////////////////
  1586. // //
  1587. // Function: MartaGetNT4NodeSD //
  1588. // //
  1589. // Description: Converts the child security descriptor NT4 ACL into NT5 ACL //
  1590. // by comparing it to the parent ACL. //
  1591. // //
  1592. // Arguments: //
  1593. // //
  1594. // [IN pOldSD] Old parent security descriptor //
  1595. // [IN OUT pOldChildSD] Old child security descriptor //
  1596. // [IN Processhandle] Process Handle //
  1597. // [IN bIsChildContainer] Whether the child object is a Container //
  1598. // [IN pGenMap] Generic mapping of the object rights //
  1599. // [IN SecurityInfo] Security Information requested //
  1600. // //
  1601. // Algorithm: //
  1602. // if child acl and parent acl differ then //
  1603. // mark the child acl PROTECTED //
  1604. // //
  1605. // Returns: ERROR_SUCCESS on successful completion of the routine //
  1606. // ERROR_XXXX Otherwise //
  1607. // //
  1608. ////////////////////////////////////////////////////////////////////////////////
  1609. DWORD
  1610. MartaGetNT4NodeSD(
  1611. IN PSECURITY_DESCRIPTOR pOldSD,
  1612. IN OUT PSECURITY_DESCRIPTOR pOldChildSD,
  1613. IN HANDLE ProcessHandle,
  1614. IN BOOL bIsChildContainer,
  1615. IN PGENERIC_MAPPING pGenMap,
  1616. IN SECURITY_INFORMATION SecurityInfo
  1617. )
  1618. {
  1619. SECURITY_DESCRIPTOR NullSD;
  1620. DWORD dwErr = ERROR_SUCCESS;
  1621. BOOL CompareStatus = FALSE;
  1622. PACL pChildAcl = NULL;
  1623. PACL pParentAcl = NULL;
  1624. HANDLE ThreadHandle = NULL;
  1625. PSECURITY_DESCRIPTOR pTmpSD = NULL;
  1626. UCHAR Buffer[2 * sizeof(ACL)];
  1627. PACL pDacl = (PACL) Buffer;
  1628. PACL pSacl = (PACL) (Buffer + sizeof(ACL));
  1629. if (!FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)))
  1630. {
  1631. return ERROR_SUCCESS;
  1632. }
  1633. InitializeSecurityDescriptor(&NullSD, SECURITY_DESCRIPTOR_REVISION);
  1634. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  1635. {
  1636. if (FALSE == InitializeAcl(pDacl, sizeof(ACL), ACL_REVISION))
  1637. {
  1638. return ERROR_ACCESS_DENIED;
  1639. }
  1640. if (FALSE == SetSecurityDescriptorDacl(
  1641. &NullSD,
  1642. TRUE,
  1643. pDacl,
  1644. FALSE))
  1645. {
  1646. return GetLastError();
  1647. }
  1648. }
  1649. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  1650. {
  1651. if (FALSE == InitializeAcl(pSacl, sizeof(ACL), ACL_REVISION))
  1652. {
  1653. return ERROR_ACCESS_DENIED;
  1654. }
  1655. if (FALSE == SetSecurityDescriptorSacl(
  1656. &NullSD,
  1657. TRUE,
  1658. pSacl,
  1659. FALSE))
  1660. {
  1661. return GetLastError();
  1662. }
  1663. }
  1664. if (FALSE == SetSecurityDescriptorOwner(
  1665. &NullSD,
  1666. RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  1667. FALSE))
  1668. {
  1669. return GetLastError();
  1670. }
  1671. if (FALSE == SetSecurityDescriptorGroup(
  1672. &NullSD,
  1673. RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  1674. FALSE))
  1675. {
  1676. return GetLastError();
  1677. }
  1678. MARTA_TURN_OFF_IMPERSONATION;
  1679. CONDITIONAL_EXIT(dwErr, End);
  1680. if (FALSE == CreatePrivateObjectSecurityEx(
  1681. pOldSD,
  1682. &NullSD,
  1683. &pTmpSD,
  1684. NULL,
  1685. bIsChildContainer,
  1686. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT | SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  1687. ProcessHandle,
  1688. pGenMap
  1689. ))
  1690. {
  1691. dwErr = GetLastError();
  1692. }
  1693. MARTA_TURN_ON_IMPERSONATION;
  1694. CONDITIONAL_EXIT(dwErr, End);
  1695. //
  1696. // Mark the aces from the child DACL, which are present in the parent.
  1697. //
  1698. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  1699. {
  1700. pChildAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD);
  1701. pParentAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pTmpSD);
  1702. dwErr = MartaCompareAndMarkInheritedAces(
  1703. pParentAcl,
  1704. pChildAcl,
  1705. bIsChildContainer,
  1706. &CompareStatus
  1707. );
  1708. CONDITIONAL_EXIT(dwErr, End);
  1709. if (FALSE == CompareStatus)
  1710. {
  1711. ((PISECURITY_DESCRIPTOR) pOldChildSD)->Control |= SE_DACL_PROTECTED;
  1712. }
  1713. }
  1714. //
  1715. // Mark the aces from the child SACL, which are present in the parent.
  1716. //
  1717. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  1718. {
  1719. pChildAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD);
  1720. pParentAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pTmpSD);
  1721. dwErr = MartaCompareAndMarkInheritedAces(
  1722. pParentAcl,
  1723. pChildAcl,
  1724. bIsChildContainer,
  1725. &CompareStatus
  1726. );
  1727. CONDITIONAL_EXIT(dwErr, End);
  1728. if (FALSE == CompareStatus)
  1729. {
  1730. ((PISECURITY_DESCRIPTOR) pOldChildSD)->Control |= SE_SACL_PROTECTED;
  1731. }
  1732. CONDITIONAL_EXIT(dwErr, End);
  1733. }
  1734. End:
  1735. if (NULL != pTmpSD)
  1736. {
  1737. DestroyPrivateObjectSecurity(&pTmpSD);
  1738. }
  1739. return dwErr;
  1740. }
  1741. ////////////////////////////////////////////////////////////////////////////////
  1742. // //
  1743. // Function: MartaUpdateTree //
  1744. // //
  1745. // Description: Propagate the inheritable aces to the children. //
  1746. // //
  1747. // Arguments: //
  1748. // //
  1749. // [IN SecurityInfo] Security Information requested //
  1750. // [IN pNewSD] New parent security descriptor //
  1751. // [IN pOldSD] Old parent security descriptor //
  1752. // [IN Context] Context structure for the object //
  1753. // [IN Processhandle] Process Handle //
  1754. // [IN pSetFunctionContext] Structure holding the function pointers //
  1755. // [IN pGenMap] Generic mapping of the object rights //
  1756. // //
  1757. // Algorithm: //
  1758. // For all children that are not "Protected" //
  1759. // if OldChildSD = NT4 style //
  1760. // Convert it into NT5 style //
  1761. // NewChildSD = Merge(ParentSD, OldChildSD) //
  1762. // UpdateTree(Child) //
  1763. // Stamp NewChildSD on Child //
  1764. // //
  1765. // Note: An error in the propagation is ignored. //
  1766. // //
  1767. ////////////////////////////////////////////////////////////////////////////////
  1768. BOOL
  1769. MartaUpdateTree(
  1770. IN SECURITY_INFORMATION SecurityInfo,
  1771. IN PSECURITY_DESCRIPTOR pNewSD,
  1772. IN PSECURITY_DESCRIPTOR pOldSD,
  1773. IN MARTA_CONTEXT Context,
  1774. IN HANDLE ProcessHandle,
  1775. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  1776. IN PGENERIC_MAPPING pGenMap
  1777. )
  1778. {
  1779. MARTA_OBJECT_PROPERTIES ObjectProperties;
  1780. DWORD dwErr = ERROR_SUCCESS;
  1781. BOOL bIsChildContainer = FALSE;
  1782. BOOL bRetryPropagation = FALSE;
  1783. BOOL bDoPropagate = TRUE;
  1784. HANDLE ThreadHandle = NULL;
  1785. PSECURITY_DESCRIPTOR pOldChildSD = NULL;
  1786. PSECURITY_DESCRIPTOR pNewChildSD = NULL;
  1787. MARTA_CONTEXT ChildContext = NULL_MARTA_CONTEXT;
  1788. //
  1789. // Get the first child to update.
  1790. //
  1791. dwErr = (*(pMartaSetFunctionContext->fFindFirst))(
  1792. Context,
  1793. (*(pMartaSetFunctionContext->fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, TRUE, SecurityInfo),
  1794. &ChildContext
  1795. );
  1796. if (ERROR_SUCCESS != dwErr)
  1797. {
  1798. if (NULL == ChildContext)
  1799. {
  1800. dwErr = (*(pMartaSetFunctionContext->fFindFirst))(
  1801. Context,
  1802. (*(pMartaSetFunctionContext->fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo),
  1803. &ChildContext
  1804. );
  1805. }
  1806. else
  1807. {
  1808. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  1809. ChildContext,
  1810. (*(pMartaSetFunctionContext->fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo)
  1811. );
  1812. }
  1813. bDoPropagate = FALSE;
  1814. }
  1815. if (NULL == ChildContext)
  1816. {
  1817. return TRUE;
  1818. }
  1819. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1820. //
  1821. // Note: On any intermediate error the current child is skipped.
  1822. //
  1823. while (ChildContext)
  1824. {
  1825. ObjectProperties.cbSize = sizeof(ObjectProperties);
  1826. ObjectProperties.dwFlags = 0;
  1827. dwErr = (*(pMartaSetFunctionContext->fGetProperties))(
  1828. ChildContext,
  1829. &ObjectProperties
  1830. );
  1831. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1832. bIsChildContainer = FLAG_ON(ObjectProperties.dwFlags, MARTA_OBJECT_IS_CONTAINER);
  1833. dwErr = (*(pMartaSetFunctionContext->fGetRights))(
  1834. ChildContext,
  1835. (SecurityInfo | OWNER_SECURITY_INFORMATION |
  1836. GROUP_SECURITY_INFORMATION),
  1837. &pOldChildSD
  1838. );
  1839. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1840. //
  1841. // Skip the children that are protected.
  1842. //
  1843. if (!MARTA_SD_NOT_PROTECTED((PISECURITY_DESCRIPTOR) pOldChildSD, SecurityInfo))
  1844. {
  1845. goto EndOfWhile;
  1846. }
  1847. //
  1848. // Convert NT4 SD to NT5 style.
  1849. //
  1850. if (FALSE == MartaIsSDNT5Style(pOldChildSD))
  1851. {
  1852. //
  1853. // Note that this modifies OldChildSD in one of the two ways:
  1854. // 1. If any of the inheritable aces from the OldSD are missing
  1855. // from OldChild then
  1856. // Mark the acl PROTECTED.
  1857. // 2. else
  1858. // Mark the common aces in ChildSD as INHERITED.
  1859. //
  1860. dwErr = MartaGetNT4NodeSD(
  1861. pOldSD,
  1862. pOldChildSD,
  1863. ProcessHandle,
  1864. bIsChildContainer,
  1865. pGenMap,
  1866. SecurityInfo
  1867. );
  1868. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1869. }
  1870. MARTA_TURN_OFF_IMPERSONATION;
  1871. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1872. //
  1873. // Merge the NewParentSD and the OldChildSD to create NewChildSD.
  1874. //
  1875. if (FALSE == CreatePrivateObjectSecurityEx(
  1876. pNewSD,
  1877. pOldChildSD,
  1878. &pNewChildSD,
  1879. NULL,
  1880. bIsChildContainer,
  1881. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT |
  1882. SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  1883. ProcessHandle,
  1884. pGenMap
  1885. ))
  1886. {
  1887. dwErr = GetLastError();
  1888. }
  1889. MARTA_TURN_ON_IMPERSONATION;
  1890. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1891. //
  1892. // Update the subtree undrneath this child.
  1893. //
  1894. if (bIsChildContainer)
  1895. {
  1896. if (bDoPropagate)
  1897. {
  1898. bRetryPropagation = MartaUpdateTree(
  1899. SecurityInfo,
  1900. pNewChildSD,
  1901. pOldChildSD,
  1902. ChildContext,
  1903. ProcessHandle,
  1904. pMartaSetFunctionContext,
  1905. pGenMap
  1906. );
  1907. }
  1908. else
  1909. {
  1910. bRetryPropagation = TRUE;
  1911. }
  1912. }
  1913. //
  1914. // Stamp NewChildSD on child.
  1915. //
  1916. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  1917. {
  1918. ((PISECURITY_DESCRIPTOR) pNewChildSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  1919. }
  1920. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  1921. {
  1922. ((PISECURITY_DESCRIPTOR) pNewChildSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  1923. }
  1924. dwErr = (*(pMartaSetFunctionContext->fSetRights))(
  1925. ChildContext,
  1926. SecurityInfo,
  1927. pNewChildSD
  1928. );
  1929. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1930. //
  1931. // If propagation had failed in the first attept then try again. This is to
  1932. // cover the case when the container can be enumerated after setting the new
  1933. // security.
  1934. if (bRetryPropagation && (SecurityInfo & DACL_SECURITY_INFORMATION))
  1935. {
  1936. ACCESS_MASK Access = (*(pMartaSetFunctionContext->fGetDesiredAccess))(
  1937. NO_ACCESS_RIGHTS,
  1938. TRUE,
  1939. SecurityInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)
  1940. );
  1941. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  1942. ChildContext,
  1943. Access
  1944. );
  1945. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  1946. (VOID) MartaUpdateTree(
  1947. SecurityInfo,
  1948. pNewChildSD,
  1949. pOldChildSD,
  1950. ChildContext,
  1951. ProcessHandle,
  1952. pMartaSetFunctionContext,
  1953. pGenMap
  1954. );
  1955. }
  1956. EndOfWhile:
  1957. bRetryPropagation = FALSE;
  1958. if (NULL != pOldChildSD)
  1959. {
  1960. AccFree(pOldChildSD);
  1961. pOldChildSD = NULL;
  1962. }
  1963. if (NULL != pNewChildSD)
  1964. {
  1965. DestroyPrivateObjectSecurity(&pNewChildSD);
  1966. pNewChildSD = NULL;
  1967. }
  1968. //
  1969. // Get the next child.
  1970. //
  1971. do {
  1972. dwErr = (*(pMartaSetFunctionContext->fFindNext))(
  1973. ChildContext,
  1974. (*(pMartaSetFunctionContext->fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, TRUE, SecurityInfo),
  1975. &ChildContext
  1976. );
  1977. if ((ERROR_SUCCESS != dwErr) && (NULL != ChildContext))
  1978. {
  1979. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  1980. ChildContext,
  1981. (*(pMartaSetFunctionContext->fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo)
  1982. );
  1983. bDoPropagate = FALSE;
  1984. }
  1985. else
  1986. {
  1987. bDoPropagate = TRUE;
  1988. }
  1989. } while ((ERROR_SUCCESS != dwErr) && (NULL != ChildContext));
  1990. }
  1991. return FALSE;
  1992. }
  1993. ////////////////////////////////////////////////////////////////////////////////
  1994. // //
  1995. // Function: AccRewriteSetNamedRights //
  1996. // //
  1997. // Description: Set the security descriptor passed in on the object passed in //
  1998. // by Name. //
  1999. // This routine is exported by ntmarta and called by advapi32. //
  2000. // //
  2001. // Arguments: //
  2002. // //
  2003. // [IN pObjectName] Name of the Object //
  2004. // [IN ObjectType] Type of the object //
  2005. // [IN SecurityInfo] Security Information to be stamped //
  2006. // [IN pSecurityDescriptor] Security descriptor to be stamped //
  2007. // [IN bSkipInheritanceComputation] Whether to compute inherited aces //
  2008. // from the parent
  2009. // //
  2010. ////////////////////////////////////////////////////////////////////////////////
  2011. DWORD
  2012. AccRewriteSetNamedRights(
  2013. IN LPWSTR pObjectName,
  2014. IN SE_OBJECT_TYPE ObjectType,
  2015. IN SECURITY_INFORMATION SecurityInfo,
  2016. IN OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2017. IN BOOL bSkipInheritanceComputation
  2018. )
  2019. {
  2020. DWORD dwErr = ERROR_SUCCESS;
  2021. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  2022. BOOL bDoPropagate = FALSE;
  2023. BOOL bReadOldProtectedBits = FALSE;
  2024. MARTA_OBJECT_TYPE_PROPERTIES ObjectTypeProperties;
  2025. MARTA_SET_FUNCTION_CONTEXT MartaSetFunctionContext;
  2026. GENERIC_MAPPING ZeroGenMap = {0, 0, 0, 0};
  2027. SECURITY_INFORMATION LocalSecurityInfo = (SECURITY_INFORMATION) 0;
  2028. PSECURITY_DESCRIPTOR pOldSD = NULL;
  2029. //
  2030. // Named calls are not valid only for the following object types.
  2031. //
  2032. switch (ObjectType)
  2033. {
  2034. case SE_FILE_OBJECT:
  2035. case SE_SERVICE:
  2036. case SE_PRINTER:
  2037. case SE_REGISTRY_KEY:
  2038. case SE_REGISTRY_WOW64_32KEY:
  2039. case SE_LMSHARE:
  2040. case SE_KERNEL_OBJECT:
  2041. case SE_WINDOW_OBJECT:
  2042. case SE_WMIGUID_OBJECT:
  2043. case SE_DS_OBJECT:
  2044. case SE_DS_OBJECT_ALL:
  2045. break;
  2046. case SE_PROVIDER_DEFINED_OBJECT:
  2047. case SE_UNKNOWN_OBJECT_TYPE:
  2048. default:
  2049. return ERROR_INVALID_PARAMETER;
  2050. }
  2051. //
  2052. // Initialize the structure to hold the function pointers.
  2053. //
  2054. MartaInitializeSetContext(ObjectType, &MartaSetFunctionContext);
  2055. //
  2056. // Get the "Type" properties for the object,
  2057. //
  2058. ObjectTypeProperties.cbSize = sizeof(ObjectTypeProperties);
  2059. ObjectTypeProperties.dwFlags = 0;
  2060. ObjectTypeProperties.GenMap = ZeroGenMap;
  2061. dwErr = (*(MartaSetFunctionContext.fGetTypeProperties))(&ObjectTypeProperties);
  2062. CONDITIONAL_EXIT(dwErr, End);
  2063. //
  2064. // To make sure that NT4 applications do not wipe out PROTECTED bits, make a
  2065. // note whether the caller knows what he is doing i.e. has passed in the
  2066. // appropriate PROTECTED flags.
  2067. //
  2068. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2069. {
  2070. if (!FLAG_ON(SecurityInfo, (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)))
  2071. {
  2072. bReadOldProtectedBits = TRUE;
  2073. LocalSecurityInfo |= DACL_SECURITY_INFORMATION;
  2074. }
  2075. }
  2076. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2077. {
  2078. if (!FLAG_ON(SecurityInfo, (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
  2079. {
  2080. bReadOldProtectedBits = TRUE;
  2081. LocalSecurityInfo |= SACL_SECURITY_INFORMATION;
  2082. }
  2083. }
  2084. //
  2085. // Even for objects like Files/RegistryKeys manual propagation is required
  2086. // only if DACl/SACL is to be set.
  2087. //
  2088. if ((FLAG_ON(ObjectTypeProperties.dwFlags, MARTA_OBJECT_TYPE_MANUAL_PROPAGATION_NEEDED_FLAG)) &&
  2089. (FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))))
  2090. {
  2091. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  2092. pObjectName,
  2093. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, TRUE, SecurityInfo),
  2094. &Context
  2095. );
  2096. if (ERROR_SUCCESS != dwErr)
  2097. {
  2098. bDoPropagate = FALSE;
  2099. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  2100. pObjectName,
  2101. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2102. &Context
  2103. );
  2104. CONDITIONAL_EXIT(dwErr, End);
  2105. }
  2106. else
  2107. {
  2108. bDoPropagate = TRUE;
  2109. }
  2110. dwErr = MartaManualPropagation(
  2111. Context,
  2112. SecurityInfo,
  2113. pSecurityDescriptor,
  2114. &(ObjectTypeProperties.GenMap),
  2115. bDoPropagate,
  2116. bReadOldProtectedBits,
  2117. &MartaSetFunctionContext,
  2118. bSkipInheritanceComputation
  2119. );
  2120. CONDITIONAL_EXIT(dwErr, End);
  2121. }
  2122. //
  2123. // For object for which manual propagation is not required, stamp the SD
  2124. // on the object.
  2125. //
  2126. else
  2127. {
  2128. if ((FLAG_ON(ObjectTypeProperties.dwFlags, MARTA_OBJECT_TYPE_INHERITANCE_MODEL_PRESENT_FLAG)) &&
  2129. bReadOldProtectedBits)
  2130. {
  2131. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  2132. pObjectName,
  2133. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2134. &Context
  2135. );
  2136. CONDITIONAL_EXIT(dwErr, End);
  2137. dwErr = (*(MartaSetFunctionContext.fGetRights))(
  2138. Context,
  2139. LocalSecurityInfo,
  2140. &pOldSD
  2141. );
  2142. CONDITIONAL_EXIT(dwErr, End);
  2143. //
  2144. // If none of the PROTECTED flags are passed in then do the "right" thing.
  2145. // Read the PROTECTED bit from the existing security descriptor and set it
  2146. // in the new one.
  2147. //
  2148. if (NULL != pOldSD)
  2149. {
  2150. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2151. {
  2152. if (!FLAG_ON(SecurityInfo, (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)))
  2153. {
  2154. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_DACL_PROTECTED;
  2155. }
  2156. }
  2157. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2158. {
  2159. if (!FLAG_ON(SecurityInfo, (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
  2160. {
  2161. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_SACL_PROTECTED;
  2162. }
  2163. }
  2164. }
  2165. }
  2166. else
  2167. {
  2168. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  2169. pObjectName,
  2170. (*(MartaSetFunctionContext.fGetDesiredAccess))(WRITE_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2171. &Context
  2172. );
  2173. CONDITIONAL_EXIT(dwErr, End);
  2174. }
  2175. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2176. {
  2177. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  2178. }
  2179. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2180. {
  2181. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  2182. }
  2183. dwErr = (*(MartaSetFunctionContext.fSetRights))(
  2184. Context,
  2185. SecurityInfo,
  2186. pSecurityDescriptor
  2187. );
  2188. CONDITIONAL_EXIT(dwErr, End);
  2189. }
  2190. End:
  2191. if (NULL != Context)
  2192. {
  2193. (VOID) (*(MartaSetFunctionContext.fCloseContext))(Context);
  2194. }
  2195. if (NULL != pOldSD)
  2196. {
  2197. AccFree(pOldSD);
  2198. }
  2199. return dwErr;
  2200. }
  2201. ////////////////////////////////////////////////////////////////////////////////
  2202. // //
  2203. // Function: AccRewriteSetHandleRights //
  2204. // //
  2205. // Description: Set the security descriptor passed in on the object passed in //
  2206. // as Handle. //
  2207. // This routine is exported by ntmarta and called by advapi32. //
  2208. // //
  2209. // Arguments: //
  2210. // //
  2211. // [IN Handle] Handle to the Object //
  2212. // [IN ObjectType] Type of the object //
  2213. // [IN SecurityInfo] Security Information to be stamped //
  2214. // [IN pSecurityDescriptor] Security descriptor to be stamped //
  2215. // //
  2216. ////////////////////////////////////////////////////////////////////////////////
  2217. DWORD
  2218. AccRewriteSetHandleRights(
  2219. IN HANDLE Handle,
  2220. IN SE_OBJECT_TYPE ObjectType,
  2221. IN SECURITY_INFORMATION SecurityInfo,
  2222. IN OUT PSECURITY_DESCRIPTOR pSecurityDescriptor
  2223. )
  2224. {
  2225. DWORD dwErr = ERROR_SUCCESS;
  2226. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  2227. BOOL bDoPropagate = FALSE;
  2228. BOOL bReadOldProtectedBits = FALSE;
  2229. MARTA_OBJECT_TYPE_PROPERTIES ObjectTypeProperties;
  2230. MARTA_SET_FUNCTION_CONTEXT MartaSetFunctionContext;
  2231. GENERIC_MAPPING ZeroGenMap = {0, 0, 0, 0};
  2232. SECURITY_INFORMATION LocalSecurityInfo = (SECURITY_INFORMATION) 0;
  2233. PSECURITY_DESCRIPTOR pOldSD = NULL;
  2234. //
  2235. // Handle calls are not valid for all object types.
  2236. //
  2237. switch (ObjectType)
  2238. {
  2239. case SE_FILE_OBJECT:
  2240. case SE_SERVICE:
  2241. case SE_PRINTER:
  2242. case SE_REGISTRY_KEY:
  2243. case SE_LMSHARE:
  2244. case SE_KERNEL_OBJECT:
  2245. case SE_WINDOW_OBJECT:
  2246. case SE_WMIGUID_OBJECT:
  2247. break;
  2248. case SE_DS_OBJECT:
  2249. case SE_DS_OBJECT_ALL:
  2250. case SE_PROVIDER_DEFINED_OBJECT:
  2251. case SE_UNKNOWN_OBJECT_TYPE:
  2252. default:
  2253. return ERROR_INVALID_PARAMETER;
  2254. }
  2255. //
  2256. // Initialize the structure to hold the function pointers.
  2257. //
  2258. MartaInitializeSetContext(ObjectType, &MartaSetFunctionContext);
  2259. //
  2260. // Get the "Type" properties for the object,
  2261. //
  2262. ObjectTypeProperties.cbSize = sizeof(ObjectTypeProperties);
  2263. ObjectTypeProperties.dwFlags = 0;
  2264. ObjectTypeProperties.GenMap = ZeroGenMap;
  2265. dwErr = (*(MartaSetFunctionContext.fGetTypeProperties))(&ObjectTypeProperties);
  2266. CONDITIONAL_EXIT(dwErr, End);
  2267. //
  2268. // To make sure that NT4 applications do not wipe out PROTECTED bits, make a
  2269. // note whether the caller knows what he is doing i.e. has passed in the
  2270. // appropriate PROTECTED flags.
  2271. //
  2272. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2273. {
  2274. if (!FLAG_ON(SecurityInfo, (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)))
  2275. {
  2276. bReadOldProtectedBits = TRUE;
  2277. LocalSecurityInfo |= DACL_SECURITY_INFORMATION;
  2278. }
  2279. }
  2280. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2281. {
  2282. if (!FLAG_ON(SecurityInfo, (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
  2283. {
  2284. bReadOldProtectedBits = TRUE;
  2285. LocalSecurityInfo |= SACL_SECURITY_INFORMATION;
  2286. }
  2287. }
  2288. //
  2289. // Even for objects like Files/RegistryKeys manual propagation is required
  2290. // only if DACl/SACL is to be set.
  2291. //
  2292. if ((FLAG_ON(ObjectTypeProperties.dwFlags, MARTA_OBJECT_TYPE_MANUAL_PROPAGATION_NEEDED_FLAG)) &&
  2293. (FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))))
  2294. {
  2295. dwErr = (*(MartaSetFunctionContext.fOpenHandleObject))(
  2296. Handle,
  2297. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, TRUE, SecurityInfo),
  2298. &Context
  2299. );
  2300. if (ERROR_SUCCESS != dwErr)
  2301. {
  2302. bDoPropagate = FALSE;
  2303. dwErr = (*(MartaSetFunctionContext.fOpenHandleObject))(
  2304. Handle,
  2305. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2306. &Context
  2307. );
  2308. CONDITIONAL_EXIT(dwErr, End);
  2309. }
  2310. else
  2311. {
  2312. bDoPropagate = TRUE;
  2313. }
  2314. dwErr = MartaManualPropagation(
  2315. Context,
  2316. SecurityInfo,
  2317. pSecurityDescriptor,
  2318. &(ObjectTypeProperties.GenMap),
  2319. bDoPropagate,
  2320. bReadOldProtectedBits,
  2321. &MartaSetFunctionContext,
  2322. FALSE // Do not skip inheritance computation
  2323. );
  2324. CONDITIONAL_EXIT(dwErr, End);
  2325. }
  2326. //
  2327. // For object for which manual propagation is not required, stamp the SD
  2328. // on the object.
  2329. //
  2330. else
  2331. {
  2332. if ((FLAG_ON(ObjectTypeProperties.dwFlags, MARTA_OBJECT_TYPE_INHERITANCE_MODEL_PRESENT_FLAG)) &&
  2333. bReadOldProtectedBits)
  2334. {
  2335. dwErr = (*(MartaSetFunctionContext.fOpenHandleObject))(
  2336. Handle,
  2337. (*(MartaSetFunctionContext.fGetDesiredAccess))(MODIFY_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2338. &Context
  2339. );
  2340. CONDITIONAL_EXIT(dwErr, End);
  2341. dwErr = (*(MartaSetFunctionContext.fGetRights))(
  2342. Context,
  2343. LocalSecurityInfo,
  2344. &pOldSD
  2345. );
  2346. CONDITIONAL_EXIT(dwErr, End);
  2347. //
  2348. // If none of the PROTECTED flags are passed in then do the "right" thing.
  2349. // Read the PROTECTED bit from the existing security descriptor and set it
  2350. // in the new one.
  2351. //
  2352. if (NULL != pOldSD)
  2353. {
  2354. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2355. {
  2356. if (!FLAG_ON(SecurityInfo, (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)))
  2357. {
  2358. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_DACL_PROTECTED;
  2359. }
  2360. }
  2361. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2362. {
  2363. if (!FLAG_ON(SecurityInfo, (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)))
  2364. {
  2365. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= ((PISECURITY_DESCRIPTOR) pOldSD)->Control & SE_SACL_PROTECTED;
  2366. }
  2367. }
  2368. }
  2369. }
  2370. else
  2371. {
  2372. dwErr = (*(MartaSetFunctionContext.fOpenHandleObject))(
  2373. Handle,
  2374. (*(MartaSetFunctionContext.fGetDesiredAccess))(WRITE_ACCESS_RIGHTS, FALSE, SecurityInfo),
  2375. &Context
  2376. );
  2377. CONDITIONAL_EXIT(dwErr, End);
  2378. }
  2379. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  2380. {
  2381. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  2382. }
  2383. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  2384. {
  2385. ((PISECURITY_DESCRIPTOR) pSecurityDescriptor)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  2386. }
  2387. dwErr = (*(MartaSetFunctionContext.fSetRights))(
  2388. Context,
  2389. SecurityInfo,
  2390. pSecurityDescriptor
  2391. );
  2392. CONDITIONAL_EXIT(dwErr, End);
  2393. }
  2394. End:
  2395. if (NULL != Context)
  2396. {
  2397. (VOID) (*(MartaSetFunctionContext.fCloseContext))(Context);
  2398. }
  2399. if (NULL != pOldSD)
  2400. {
  2401. AccFree(pOldSD);
  2402. }
  2403. return dwErr;
  2404. }
  2405. typedef struct _FN_OBJECT_FUNCTIONS
  2406. {
  2407. ULONG Flags;
  2408. } FN_OBJECT_FUNCTIONS, *PFN_OBJECT_FUNCTIONS;
  2409. #define MARTA_NO_PARENT (LONG) -1
  2410. #define MARTA_EXPLICIT_ACE 0
  2411. VOID
  2412. MartaInitializeIndexContext(
  2413. IN SE_OBJECT_TYPE ObjectType,
  2414. OUT PMARTA_INDEX_FUNCTION_CONTEXT pFunctionContext
  2415. )
  2416. {
  2417. pFunctionContext->fCloseContext = MartaCloseContext[ObjectType];
  2418. pFunctionContext->fOpenNamedObject = MartaOpenNamedObject[ObjectType];
  2419. pFunctionContext->fGetRights = MartaGetRights[ObjectType];
  2420. pFunctionContext->fGetParentName = MartaGetParentName[ObjectType];
  2421. }
  2422. typedef DWORD (*PFN_FREE) (IN PVOID Mem);
  2423. DWORD
  2424. AccFreeIndexArray(
  2425. IN OUT PINHERITED_FROMW pInheritArray,
  2426. IN USHORT AceCnt,
  2427. IN PFN_FREE pfnFree
  2428. );
  2429. ////////////////////////////////////////////////////////////////////////////////
  2430. // //
  2431. // Function: AccGetInheritanceSource //
  2432. // //
  2433. // Description: Get the source of every inherited ace in the gicen acl. //
  2434. // //
  2435. // Arguments: //
  2436. // //
  2437. // [IN pObjectName] Name of the object //
  2438. // [IN ObjecType] Type of the object ex. File/Reg/DS //
  2439. // [IN SecurityInfo] Whether DACL/SACL //
  2440. // [IN Container] Whether Object or Container //
  2441. // [IN ObjecTypeGuid] Type of the object (for DS objects) //
  2442. // [IN pAcl] DACL or SACL depending on SecurityInfo //
  2443. // [IN pGenericMapping] GenericMapping for the object type //
  2444. // [IN pfnArray] Function pointers when we support non-DS/FS/Reg //
  2445. // [OUT pInheritArray] To return the results //
  2446. // //
  2447. // //
  2448. // Algorithm: //
  2449. // Initialize the output structure. //
  2450. // Read the Owner/Group info needed for CreatePrivateObjectSecurityEx. //
  2451. // while (unmarked inherited aces exist) //
  2452. // Get the parent at the next level. //
  2453. // if we are at the root, //
  2454. // break //
  2455. // Get the xAcl for the parent. //
  2456. // for ancestors other than the immediate parent //
  2457. // Mask off inheritance flags for ACES with NP or ID //
  2458. // for immediate parent //
  2459. // Mask off inheritance flags for ACES with ID //
  2460. // Call CreatePrivateObjectSecurityEx with the empty SD and ParentSD //
  2461. // to get ExpectedSD //
  2462. // From the input xAcl, //
  2463. // mark unmarked common inherited aces //
  2464. // Update count //
  2465. // If the parent xAcl was protected, //
  2466. // break //
  2467. // //
  2468. // Returns: ERROR_SUCCESS on successful completion of the routine //
  2469. // ERROR_XXXX Otherwise //
  2470. // //
  2471. ////////////////////////////////////////////////////////////////////////////////
  2472. DWORD
  2473. AccGetInheritanceSource(
  2474. IN LPWSTR pObjectName,
  2475. IN SE_OBJECT_TYPE ObjectType,
  2476. IN SECURITY_INFORMATION SecurityInfo,
  2477. IN BOOL Container,
  2478. IN GUID ** pObjectTypeGuid OPTIONAL,
  2479. IN DWORD GuidCount,
  2480. IN PACL pAcl,
  2481. IN PGENERIC_MAPPING pGenericMapping,
  2482. IN PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL,
  2483. OUT PINHERITED_FROMW pInheritArray
  2484. )
  2485. {
  2486. SECURITY_DESCRIPTOR EmptySD;
  2487. MARTA_INDEX_FUNCTION_CONTEXT MartaIndexFunctionContext;
  2488. USHORT i = 0;
  2489. USHORT j = 0;
  2490. USHORT AceCnt = 0;
  2491. USHORT ParentAceCnt = 0;
  2492. USHORT ExpectedAceCnt = 0;
  2493. USHORT InheritedAceCnt = 0;
  2494. USHORT ParentIndex = 0;
  2495. ULONG ProtectedBit = 0;
  2496. UCHAR FlagsToKeep = 0;
  2497. DWORD dwErr = ERROR_SUCCESS;
  2498. BOOL bKnownObject = FALSE;
  2499. BOOL Match = TRUE;
  2500. BOOL ProtectedParent = FALSE;
  2501. LPWSTR ParentName = NULL;
  2502. LPWSTR OldName = NULL;
  2503. PACL pParentAcl = NULL;
  2504. PACL pExpectedAcl = NULL;
  2505. PACE_HEADER pAce = NULL;
  2506. PACE_HEADER pParentAce = NULL;
  2507. PACE_HEADER pExpectedAce = NULL;
  2508. PSECURITY_DESCRIPTOR pSD = NULL;
  2509. PSECURITY_DESCRIPTOR pNewSD = NULL;
  2510. PSECURITY_DESCRIPTOR pParentSD = NULL;
  2511. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  2512. //
  2513. // Simple error checks to make sure that the input is valid.
  2514. //
  2515. if ((NULL == pAcl) || (!RtlValidAcl(pAcl)))
  2516. {
  2517. return ERROR_INVALID_PARAMETER;
  2518. }
  2519. if ((NULL == pObjectName) || (NULL == pInheritArray) || (NULL == pGenericMapping))
  2520. {
  2521. return ERROR_INVALID_PARAMETER;
  2522. }
  2523. //
  2524. // Make sure that the caller requested for either the SACL or the DACL and
  2525. // nothing else.
  2526. // Record the corresponding protected flag. This will be used later on.
  2527. //
  2528. switch (SecurityInfo)
  2529. {
  2530. case DACL_SECURITY_INFORMATION:
  2531. ProtectedBit = SE_DACL_PROTECTED;
  2532. break;
  2533. case SACL_SECURITY_INFORMATION:
  2534. ProtectedBit = SE_SACL_PROTECTED;
  2535. break;
  2536. default:
  2537. return ERROR_INVALID_PARAMETER;
  2538. }
  2539. //
  2540. // The function is supported for just files, registry, and DS objects.
  2541. //
  2542. switch (ObjectType)
  2543. {
  2544. case SE_FILE_OBJECT:
  2545. case SE_REGISTRY_KEY:
  2546. case SE_DS_OBJECT:
  2547. case SE_DS_OBJECT_ALL:
  2548. bKnownObject = TRUE;
  2549. MartaInitializeIndexContext(ObjectType, &MartaIndexFunctionContext);
  2550. break;
  2551. default:
  2552. return ERROR_INVALID_PARAMETER;
  2553. }
  2554. AceCnt = pAcl->AceCount;
  2555. //
  2556. // Return for an empty acl.
  2557. //
  2558. if (0 == AceCnt)
  2559. {
  2560. return ERROR_SUCCESS;
  2561. }
  2562. //
  2563. // We need to mask off certain aceflags for ancestors other than the parent.
  2564. //
  2565. if (Container)
  2566. {
  2567. FlagsToKeep = ~(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
  2568. }
  2569. else
  2570. {
  2571. FlagsToKeep = ~OBJECT_INHERIT_ACE;
  2572. }
  2573. //
  2574. // Run thru the acl and mark the aces as either INHERITED or EXPLICIT.
  2575. // Keep a count of inherited aces and set return values to default.
  2576. //
  2577. pAce = (PACE_HEADER) FirstAce(pAcl);
  2578. for (i = 0; i < AceCnt; pAce = (PACE_HEADER) NextAce(pAce), i++)
  2579. {
  2580. if (FLAG_ON(pAce->AceFlags, INHERITED_ACE))
  2581. {
  2582. pInheritArray[i].GenerationGap = MARTA_NO_PARENT;
  2583. InheritedAceCnt++;
  2584. }
  2585. else
  2586. {
  2587. pInheritArray[i].GenerationGap = MARTA_EXPLICIT_ACE;
  2588. }
  2589. pInheritArray[i].AncestorName = NULL;
  2590. }
  2591. //
  2592. // Return for an acl with no inherited aces.
  2593. //
  2594. if (0 == InheritedAceCnt)
  2595. {
  2596. return ERROR_SUCCESS;
  2597. }
  2598. InitializeSecurityDescriptor(&EmptySD, SECURITY_DESCRIPTOR_REVISION);
  2599. if (bKnownObject)
  2600. {
  2601. //
  2602. // Read the owner and group information on the object.
  2603. //
  2604. dwErr = (*(MartaIndexFunctionContext.fOpenNamedObject))(
  2605. pObjectName,
  2606. READ_CONTROL,
  2607. &Context
  2608. );
  2609. CONDITIONAL_EXIT(dwErr, End);
  2610. dwErr = (*(MartaIndexFunctionContext.fGetRights))(
  2611. Context,
  2612. OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
  2613. &pSD
  2614. );
  2615. // Note: This has to be freed immediately!!
  2616. (VOID) (*(MartaIndexFunctionContext.fCloseContext))(Context);
  2617. CONDITIONAL_EXIT(dwErr, End);
  2618. }
  2619. else
  2620. {
  2621. //
  2622. // Get the owner and group information.
  2623. //
  2624. }
  2625. //
  2626. // Set the owner and group information in pSD.
  2627. //
  2628. if (!SetSecurityDescriptorOwner(
  2629. &EmptySD,
  2630. RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD),
  2631. FALSE))
  2632. {
  2633. dwErr = GetLastError();
  2634. goto End;
  2635. }
  2636. if (!SetSecurityDescriptorGroup(
  2637. &EmptySD,
  2638. RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSD),
  2639. FALSE))
  2640. {
  2641. dwErr = GetLastError();
  2642. goto End;
  2643. }
  2644. if (bKnownObject)
  2645. {
  2646. dwErr = (*(MartaIndexFunctionContext.fGetParentName))(
  2647. pObjectName,
  2648. &ParentName
  2649. );
  2650. CONDITIONAL_EXIT(dwErr, End);
  2651. //
  2652. // A null parent name means we have hit the root of the hierarchy.
  2653. //
  2654. if (NULL == ParentName)
  2655. {
  2656. goto End;
  2657. }
  2658. }
  2659. else
  2660. {
  2661. }
  2662. OldName = ParentName;
  2663. //
  2664. // Run thru the list of ancestors as long as
  2665. // 1. we have inherited aces whose ancestor is yet to be found AND
  2666. // 2. we have not yet hit an ancestor that is PROTECTED.
  2667. //
  2668. for (ParentIndex = 1; InheritedAceCnt > 0 && !ProtectedParent; ParentIndex++)
  2669. {
  2670. if (bKnownObject)
  2671. {
  2672. #ifdef MARTA_DEBUG
  2673. wprintf(L"\n\nParentIndex = %d, ParentName = %s\n", ParentIndex, ParentName);
  2674. #endif
  2675. //
  2676. // Get parent security descriptor
  2677. //
  2678. dwErr = AccRewriteGetNamedRights(
  2679. ParentName,
  2680. ObjectType,
  2681. SecurityInfo,
  2682. NULL,
  2683. NULL,
  2684. NULL,
  2685. NULL,
  2686. &pParentSD
  2687. );
  2688. CONDITIONAL_EXIT(dwErr, End);
  2689. }
  2690. else
  2691. {
  2692. // Get the ParentName and ParentSD
  2693. }
  2694. //
  2695. // This might happen if we were to extend the API to support new object
  2696. // types.
  2697. //
  2698. if (NULL == pParentSD)
  2699. {
  2700. dwErr = ERROR_ACCESS_DENIED;
  2701. goto End;
  2702. }
  2703. //
  2704. // Get the Acl
  2705. //
  2706. if (DACL_SECURITY_INFORMATION == SecurityInfo)
  2707. {
  2708. pParentAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pParentSD);
  2709. }
  2710. else
  2711. {
  2712. pParentAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pParentSD);
  2713. }
  2714. //
  2715. // Null acls are really protected.
  2716. //
  2717. if (NULL == pParentAcl)
  2718. {
  2719. break;
  2720. }
  2721. ParentAceCnt = pParentAcl->AceCount;
  2722. if (ParentIndex > 1)
  2723. {
  2724. //
  2725. // This is an ancestor other then the immediate parent. Mask off its
  2726. // inheritable inherited aces as well as those with NP flag in them.
  2727. // Now we will not see them in the inherited part of the acl after
  2728. // calling CreatePrivateObjectSecurityEx.
  2729. // We save on multiple calls to CreatePrivateObjectSecurityEx by
  2730. // masking off the NP aces.
  2731. //
  2732. pParentAce = (PACE_HEADER) FirstAce(pParentAcl);
  2733. for (i = 0; i < ParentAceCnt; pParentAce = (PACE_HEADER) NextAce(pParentAce), i++)
  2734. {
  2735. if (FLAG_ON(pParentAce->AceFlags, INHERITED_ACE) ||
  2736. FLAG_ON(pParentAce->AceFlags, NO_PROPAGATE_INHERIT_ACE))
  2737. {
  2738. pParentAce->AceFlags &= FlagsToKeep;
  2739. }
  2740. }
  2741. }
  2742. else
  2743. {
  2744. //
  2745. // This is the immediate parent. Mask off its inheritable inherited
  2746. // aces so that we will not see them in the inherited part of the
  2747. // acl after calling CreatePrivateObjectSecurityEx.
  2748. //
  2749. pParentAce = (PACE_HEADER) FirstAce(pParentAcl);
  2750. for (i = 0; i < ParentAceCnt; pParentAce = (PACE_HEADER) NextAce(pParentAce), i++)
  2751. {
  2752. if (FLAG_ON(pParentAce->AceFlags, INHERITED_ACE))
  2753. {
  2754. pParentAce->AceFlags &= FlagsToKeep;
  2755. }
  2756. }
  2757. }
  2758. //
  2759. // Merge the Empty SD with the modified parent SD.
  2760. //
  2761. if (!CreatePrivateObjectSecurityWithMultipleInheritance(
  2762. pParentSD,
  2763. &EmptySD,
  2764. &pNewSD,
  2765. pObjectTypeGuid,
  2766. GuidCount,
  2767. Container,
  2768. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT | SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  2769. NULL,
  2770. pGenericMapping
  2771. ))
  2772. {
  2773. dwErr = GetLastError();
  2774. goto End;
  2775. }
  2776. //
  2777. // Get the ChildAcl
  2778. //
  2779. if (DACL_SECURITY_INFORMATION == SecurityInfo)
  2780. {
  2781. pExpectedAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pNewSD);
  2782. }
  2783. else
  2784. {
  2785. pExpectedAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pNewSD);
  2786. }
  2787. if (NULL == pExpectedAcl)
  2788. {
  2789. #ifdef MARTA_DEBUG
  2790. wprintf(L"ExpectedAcl is NULL!!!\n\n");
  2791. #endif
  2792. pExpectedAce = NULL;
  2793. ExpectedAceCnt = 0;
  2794. }
  2795. else
  2796. {
  2797. pExpectedAce = (PACE_HEADER) FirstAce(pExpectedAcl);
  2798. ExpectedAceCnt = pExpectedAcl->AceCount;
  2799. }
  2800. Match = FALSE;
  2801. #ifdef MARTA_DEBUG
  2802. wprintf(L"ExpectedAceCnt = %d, AceCnt = %d\n", ExpectedAceCnt, AceCnt);
  2803. #endif
  2804. //
  2805. // for all expected inherited aces
  2806. // if there's a match with an "avaliable" ace in the supplied ACL
  2807. // Record the name and the level of the ancestor in the output array
  2808. //
  2809. for (i = 0; i < ExpectedAceCnt; pExpectedAce = (PACE_HEADER) NextAce(pExpectedAce), i++)
  2810. {
  2811. pAce = (PACE_HEADER) FirstAce(pAcl);
  2812. for (j = 0; j < AceCnt; pAce = (PACE_HEADER) NextAce(pAce), j++)
  2813. {
  2814. //
  2815. // Skip aces whose ancestor has already been determined.
  2816. //
  2817. if (MARTA_NO_PARENT != pInheritArray[j].GenerationGap)
  2818. {
  2819. #ifdef MARTA_DEBUG
  2820. wprintf(L"Ace %d taken by level %d, name = %s\n", j,
  2821. pInheritArray[j].GenerationGap, pInheritArray[j].AncestorName);
  2822. #endif
  2823. continue;
  2824. }
  2825. #ifdef MARTA_DEBUG
  2826. wprintf(L"Ace matching i = %d, j = %d, Parent = %s\n", i, j, ParentName);
  2827. #endif
  2828. //
  2829. // Check if the aces match.
  2830. //
  2831. if ((pAce->AceSize == pExpectedAce->AceSize) &&
  2832. !memcmp(pAce, pExpectedAce, pAce->AceSize))
  2833. {
  2834. #ifdef MARTA_DEBUG
  2835. wprintf(L"Ace match found i = %d, j = %d, left = %d, Parent = %s\n",
  2836. i, j, InheritedAceCnt, ParentName);
  2837. #endif
  2838. //
  2839. // Record the name and level of the parent.
  2840. //
  2841. pInheritArray[j].GenerationGap = ParentIndex;
  2842. pInheritArray[j].AncestorName = ParentName;
  2843. //
  2844. // A match has been found.
  2845. //
  2846. Match = TRUE;
  2847. //
  2848. // Decrement the "available" ace count.
  2849. //
  2850. InheritedAceCnt--;
  2851. break;
  2852. }
  2853. }
  2854. }
  2855. //
  2856. // Check if the ancestor is protected. The loop stops after we have
  2857. // processed a protected ancestor.
  2858. //
  2859. ProtectedParent = FLAG_ON(((PISECURITY_DESCRIPTOR) pParentSD)->Control, ProtectedBit);
  2860. if (NULL != pParentSD)
  2861. {
  2862. if (bKnownObject)
  2863. {
  2864. LocalFree(pParentSD);
  2865. }
  2866. else
  2867. {
  2868. }
  2869. pParentSD = NULL;
  2870. }
  2871. ParentName = NULL;
  2872. //
  2873. // Get the name of the next ancestor only if we still need to continue.
  2874. //
  2875. if (InheritedAceCnt > 0 && !ProtectedParent)
  2876. {
  2877. dwErr = (*(MartaIndexFunctionContext.fGetParentName))(
  2878. OldName,
  2879. &ParentName
  2880. );
  2881. }
  2882. //
  2883. // Free the ancestor name if no aces were inherited from it.
  2884. //
  2885. if (!Match)
  2886. {
  2887. if (bKnownObject)
  2888. {
  2889. LocalFree(OldName);
  2890. }
  2891. else
  2892. {
  2893. }
  2894. }
  2895. OldName = NULL;
  2896. CONDITIONAL_EXIT(dwErr, End);
  2897. //
  2898. // A null parent name means we have hit the root of the hierarchy.
  2899. //
  2900. if (NULL == ParentName)
  2901. {
  2902. break;
  2903. }
  2904. OldName = ParentName;
  2905. }
  2906. End:
  2907. if (bKnownObject)
  2908. {
  2909. if (ERROR_SUCCESS != dwErr)
  2910. {
  2911. AccFreeIndexArray(pInheritArray, AceCnt, NULL);
  2912. }
  2913. if (NULL != pSD)
  2914. {
  2915. LocalFree(pSD);
  2916. }
  2917. if (NULL != OldName)
  2918. {
  2919. LocalFree(OldName);
  2920. }
  2921. if (NULL != pParentSD)
  2922. {
  2923. LocalFree(pParentSD);
  2924. }
  2925. }
  2926. else
  2927. {
  2928. }
  2929. return dwErr;
  2930. }
  2931. #ifdef MAX_INDEX_LEVEL
  2932. #undef MAX_INDEX_LEVEL
  2933. #endif
  2934. #define MAX_INDEX_LEVEL 10
  2935. ////////////////////////////////////////////////////////////////////////////////
  2936. // //
  2937. // Function: AccFreeIndexArray //
  2938. // //
  2939. // Description: Free the strings allocated and stored in the array. //
  2940. // //
  2941. // Arguments: //
  2942. // //
  2943. // [IN OUT pInheritArray] Array to free results from //
  2944. // [IN AceCnt] Number of elements in the array //
  2945. // [IN pfnFree] Function to use for freeing //
  2946. // //
  2947. // Algorithm: //
  2948. // Note that there is a single allocated string for all nodes at the same //
  2949. // level. //
  2950. // In (1, p1), (2, p2), (3, p3), (1, p1) (1, p1) (2, p2) //
  2951. // we free just three strings p1, p2 and p3. //
  2952. // Initialize the boolean 'freed' array to TRUE //
  2953. // For all elements of the array, //
  2954. // if (InheritedAce AND Ancestor name non-NULL AND Not already freed) //
  2955. // Mark as Freed and free the string. //
  2956. // //
  2957. // Returns: ERROR_SUCCESS on successful completion of the routine //
  2958. // ERROR_XXXX Otherwise //
  2959. // //
  2960. ////////////////////////////////////////////////////////////////////////////////
  2961. DWORD
  2962. AccFreeIndexArray(
  2963. IN OUT PINHERITED_FROMW pInheritArray,
  2964. IN USHORT AceCnt,
  2965. IN PFN_FREE pfnFree
  2966. )
  2967. {
  2968. USHORT i = 0;
  2969. LONG MaxLevel = 0;
  2970. BOOL LevelBuffer[MAX_INDEX_LEVEL + 1];
  2971. PBOOL pLevelStatus = (PBOOL) LevelBuffer;
  2972. for (i = 0; i < AceCnt; i++)
  2973. {
  2974. if (pInheritArray[i].GenerationGap > MaxLevel)
  2975. {
  2976. MaxLevel = pInheritArray[i].GenerationGap;
  2977. }
  2978. }
  2979. if (MaxLevel <= 0)
  2980. {
  2981. return ERROR_SUCCESS;
  2982. }
  2983. if (MaxLevel > MAX_INDEX_LEVEL)
  2984. {
  2985. pLevelStatus = (PBOOL) AccAlloc(sizeof(BOOL) * (MaxLevel + 1));
  2986. if (NULL == pLevelStatus)
  2987. {
  2988. return ERROR_NOT_ENOUGH_MEMORY;
  2989. }
  2990. }
  2991. for (i = 0; i <= MaxLevel; i++)
  2992. {
  2993. pLevelStatus[i] = TRUE;
  2994. }
  2995. for (i = 0; i < AceCnt; i++)
  2996. {
  2997. if ((pInheritArray[i].GenerationGap > 0) &&
  2998. (NULL != pInheritArray[i].AncestorName) &&
  2999. (pLevelStatus[pInheritArray[i].GenerationGap]))
  3000. {
  3001. pLevelStatus[pInheritArray[i].GenerationGap] = FALSE;
  3002. if (NULL == pfnFree)
  3003. {
  3004. AccFree(pInheritArray[i].AncestorName);
  3005. }
  3006. else
  3007. {
  3008. pfnFree(pInheritArray[i].AncestorName);
  3009. }
  3010. }
  3011. }
  3012. if (pLevelStatus != (PBOOL) LevelBuffer)
  3013. {
  3014. AccFree(pLevelStatus);
  3015. }
  3016. return ERROR_SUCCESS;
  3017. }
  3018. ////////////////////////////////////////////////////////////////////////////////
  3019. // //
  3020. // Function: AccTreeResetNamedSecurityInfo //
  3021. // //
  3022. // Description: Reset permissions on the subtree starting at pObjectName. //
  3023. // //
  3024. // Arguments: //
  3025. // //
  3026. // [IN pObjectName] Name of the Object //
  3027. // [IN ObjectType] Type of the object //
  3028. // [IN SecurityInfo] Security info to reset //
  3029. // [IN pOwner] Owner sid to reset //
  3030. // [IN pGroup] Group sid to reset //
  3031. // [IN pDacl] Dacl to reset //
  3032. // [IN pSacl] Sacl to reset //
  3033. // [IN KeepExplicit] if TRUE, retain explicit aces on the subtree, not //
  3034. // including the object. //
  3035. // [IN fnProgress] Caller supplied callback function //
  3036. // [IN ProgressInvokeSetting] To determine if callback should be invoked.//
  3037. // callback function. //
  3038. // [IN Args] Arguments supplied by the caller //
  3039. // //
  3040. // Returns: TRUE if reset succeeded. //
  3041. // FALSE o/w //
  3042. // //
  3043. ////////////////////////////////////////////////////////////////////////////////
  3044. DWORD
  3045. AccTreeResetNamedSecurityInfo(
  3046. IN LPWSTR pObjectName,
  3047. IN SE_OBJECT_TYPE ObjectType,
  3048. IN SECURITY_INFORMATION SecurityInfo,
  3049. IN PSID pOwner OPTIONAL,
  3050. IN PSID pGroup OPTIONAL,
  3051. IN PACL pDacl OPTIONAL,
  3052. IN PACL pSacl OPTIONAL,
  3053. IN BOOL KeepExplicit,
  3054. IN FN_PROGRESS fnProgress OPTIONAL,
  3055. IN PROG_INVOKE_SETTING ProgressInvokeSetting,
  3056. IN PVOID Args OPTIONAL
  3057. )
  3058. {
  3059. MARTA_OBJECT_TYPE_PROPERTIES ObjectTypeProperties;
  3060. MARTA_SET_FUNCTION_CONTEXT MartaSetFunctionContext;
  3061. MARTA_OBJECT_PROPERTIES ObjectProperties;
  3062. SECURITY_DESCRIPTOR TmpSD;
  3063. UCHAR Buffer[2 * sizeof(ACL)];
  3064. ACL EmptyDacl;
  3065. ACL EmptySacl;
  3066. SECURITY_INFORMATION LocalSeInfo = 0;
  3067. PSID LocalGroup = pGroup;
  3068. PSID LocalOwner = pOwner;
  3069. ACCESS_MASK LocalAccessMask = 0;
  3070. MARTA_CONTEXT Context = NULL_MARTA_CONTEXT;
  3071. MARTA_CONTEXT ParentContext = NULL_MARTA_CONTEXT;
  3072. GENERIC_MAPPING ZeroGenMap = {0, 0, 0, 0};
  3073. PSECURITY_DESCRIPTOR pOldSD = NULL;
  3074. PSECURITY_DESCRIPTOR pParentSD = NULL;
  3075. PSECURITY_DESCRIPTOR pNewSD = NULL;
  3076. DWORD dwErr = ERROR_SUCCESS;
  3077. BOOL bIsContainer = FALSE;
  3078. HANDLE ProcessHandle = NULL;
  3079. HANDLE ThreadHandle = NULL;
  3080. ACCESS_MASK AccessMask = 0;
  3081. ACCESS_MASK RetryAccessMask = 0;
  3082. ACCESS_MASK MaxAccessMask = 0;
  3083. BOOL bRetry = FALSE;
  3084. BOOL bSetWorked = FALSE;
  3085. PROG_INVOKE_SETTING Operation = ProgressInvokeSetting;
  3086. SECURITY_INFORMATION TmpSeInfo = (OWNER_SECURITY_INFORMATION |
  3087. GROUP_SECURITY_INFORMATION );
  3088. LPWSTR NtObjectName = NULL;
  3089. //
  3090. // TmpSeInfo records whether Owner + Group sids have been supplied by the
  3091. // caller.
  3092. //
  3093. TmpSeInfo = (SecurityInfo & TmpSeInfo) ^ TmpSeInfo;
  3094. //
  3095. // Initialize the dummy security descriptor. This may be changed by the
  3096. // recursive calls.
  3097. //
  3098. InitializeSecurityDescriptor(&TmpSD, SECURITY_DESCRIPTOR_REVISION);
  3099. //
  3100. // Initialize the function pointers based on the object type.
  3101. //
  3102. MartaInitializeSetContext(ObjectType, &MartaSetFunctionContext);
  3103. //
  3104. // Basic error checks for owner and group.
  3105. //
  3106. if (FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION))
  3107. {
  3108. if ((NULL == pOwner) || !RtlValidSid(pOwner))
  3109. {
  3110. return ERROR_INVALID_SID;
  3111. }
  3112. }
  3113. if (FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION))
  3114. {
  3115. if ((NULL == pGroup) || !RtlValidSid(pGroup))
  3116. {
  3117. return ERROR_INVALID_SID;
  3118. }
  3119. }
  3120. //
  3121. // For both DACL and SACL:
  3122. // If the caller requested for inheritance blocking
  3123. // set the appropriate bit in TmpSD
  3124. // else
  3125. // note that the parent Acl should be read for computing inherited aces
  3126. // Do basic error checks on the Acl.
  3127. //
  3128. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  3129. {
  3130. if (FLAG_ON(SecurityInfo, PROTECTED_DACL_SECURITY_INFORMATION))
  3131. {
  3132. TmpSD.Control |= SE_DACL_PROTECTED;
  3133. }
  3134. else
  3135. {
  3136. LocalSeInfo |= DACL_SECURITY_INFORMATION;
  3137. }
  3138. if ((NULL == pDacl) || !RtlValidAcl(pDacl))
  3139. {
  3140. return ERROR_INVALID_ACL;
  3141. }
  3142. if (FALSE == SetSecurityDescriptorDacl(&TmpSD, TRUE, pDacl, FALSE))
  3143. {
  3144. return GetLastError();
  3145. }
  3146. }
  3147. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  3148. {
  3149. if (FLAG_ON(SecurityInfo, PROTECTED_SACL_SECURITY_INFORMATION))
  3150. {
  3151. TmpSD.Control |= SE_SACL_PROTECTED;
  3152. }
  3153. else
  3154. {
  3155. LocalSeInfo |= SACL_SECURITY_INFORMATION;
  3156. }
  3157. if ((NULL == pSacl) || !RtlValidAcl(pSacl))
  3158. {
  3159. return ERROR_INVALID_ACL;
  3160. }
  3161. if (FALSE == SetSecurityDescriptorSacl(&TmpSD, TRUE, pSacl, FALSE))
  3162. {
  3163. return GetLastError();
  3164. }
  3165. }
  3166. if (FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)))
  3167. {
  3168. //
  3169. // We need read as well as write access to take care of CO/CG.
  3170. //
  3171. MaxAccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3172. MODIFY_ACCESS_RIGHTS,
  3173. TRUE,
  3174. SecurityInfo
  3175. );
  3176. AccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3177. MODIFY_ACCESS_RIGHTS,
  3178. FALSE,
  3179. SecurityInfo
  3180. );
  3181. }
  3182. else
  3183. {
  3184. //
  3185. // We only need WRITE access if we are not setting any ACL.
  3186. //
  3187. MaxAccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3188. WRITE_ACCESS_RIGHTS,
  3189. TRUE,
  3190. SecurityInfo
  3191. );
  3192. AccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3193. WRITE_ACCESS_RIGHTS,
  3194. FALSE,
  3195. SecurityInfo
  3196. );
  3197. }
  3198. RetryAccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3199. NO_ACCESS_RIGHTS,
  3200. TRUE,
  3201. SecurityInfo
  3202. );
  3203. //
  3204. // Open the object for maximum access that may be needed for computing
  3205. // new SD, setting it on the object and Listing the subtree below this node.
  3206. //
  3207. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  3208. pObjectName,
  3209. MaxAccessMask,
  3210. &Context
  3211. );
  3212. if (ERROR_SUCCESS != dwErr)
  3213. {
  3214. //
  3215. // We did not have List permission. Open the object for computing the
  3216. // new SD and setting it on the object.
  3217. //
  3218. dwErr = (*(MartaSetFunctionContext.fOpenNamedObject))(
  3219. pObjectName,
  3220. AccessMask,
  3221. &Context
  3222. );
  3223. CONDITIONAL_EXIT(dwErr, End);
  3224. //
  3225. // Note that we must retry List and propagate on the subtree.
  3226. //
  3227. bRetry = TRUE;
  3228. }
  3229. if (SE_FILE_OBJECT == ObjectType)
  3230. {
  3231. dwErr = (*(MartaSetFunctionContext.fGetNameFromContext))(
  3232. NULL, // Special case of the root of the subtree.
  3233. NULL, // Special case of the root of the subtree.
  3234. Context,
  3235. &NtObjectName
  3236. );
  3237. CONDITIONAL_EXIT(dwErr, End);
  3238. }
  3239. //
  3240. // Read the object atributes to figure out whether the object is a container.
  3241. //
  3242. ObjectProperties.cbSize = sizeof(ObjectProperties);
  3243. ObjectProperties.dwFlags = 0;
  3244. dwErr = (*(MartaSetFunctionContext.fGetProperties))(
  3245. Context,
  3246. &ObjectProperties
  3247. );
  3248. CONDITIONAL_EXIT(dwErr, End);
  3249. bIsContainer = FLAG_ON(ObjectProperties.dwFlags, MARTA_OBJECT_IS_CONTAINER);
  3250. //
  3251. // LocalSeInfo != corresponds to
  3252. // Resetting ACL(s) in LocalSeInfo and they should not be PROTECTED.
  3253. //
  3254. // Read the existing ACL(s) on the parent.
  3255. //
  3256. if (0 != LocalSeInfo)
  3257. {
  3258. LocalAccessMask = (*(MartaSetFunctionContext.fGetDesiredAccess))(
  3259. READ_ACCESS_RIGHTS,
  3260. FALSE,
  3261. LocalSeInfo
  3262. );
  3263. dwErr = (*(MartaSetFunctionContext.fGetParentContext))(
  3264. Context,
  3265. LocalAccessMask,
  3266. &ParentContext
  3267. );
  3268. CONDITIONAL_EXIT(dwErr, End);
  3269. if (NULL != ParentContext)
  3270. {
  3271. dwErr = (*(MartaSetFunctionContext.fGetRights))(
  3272. ParentContext,
  3273. SecurityInfo,
  3274. &pParentSD
  3275. );
  3276. (VOID) (*(MartaSetFunctionContext.fCloseContext))(ParentContext);
  3277. CONDITIONAL_EXIT(dwErr, End);
  3278. }
  3279. }
  3280. if (FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)))
  3281. {
  3282. //
  3283. // Read the owner and group info from the object if it has not been
  3284. // supplied by the caller.
  3285. //
  3286. if (!((FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION)) &&
  3287. (FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION))))
  3288. {
  3289. dwErr = (*(MartaSetFunctionContext.fGetRights))(
  3290. Context,
  3291. TmpSeInfo,
  3292. &pOldSD
  3293. );
  3294. CONDITIONAL_EXIT(dwErr, End);
  3295. }
  3296. //
  3297. // If Owner sid has not been provided by the caller, pick it up from the
  3298. // existing security descriptor.
  3299. //
  3300. LocalOwner = pOwner;
  3301. if (NULL == LocalOwner)
  3302. {
  3303. LocalOwner = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldSD);
  3304. }
  3305. //
  3306. // Set the owner sid in the TmpSd.
  3307. //
  3308. if (FALSE == SetSecurityDescriptorOwner(
  3309. &TmpSD,
  3310. LocalOwner,
  3311. FALSE))
  3312. {
  3313. dwErr = GetLastError();
  3314. CONDITIONAL_EXIT(dwErr, End);
  3315. }
  3316. //
  3317. // If Group sid has not been provided by the caller, pick it up from the
  3318. // existing security descriptor.
  3319. //
  3320. if (NULL == LocalGroup)
  3321. {
  3322. LocalGroup = RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldSD);
  3323. }
  3324. //
  3325. // Set the group sid in the TmpSd.
  3326. //
  3327. if (FALSE == SetSecurityDescriptorGroup(
  3328. &TmpSD,
  3329. LocalGroup,
  3330. FALSE))
  3331. {
  3332. dwErr = GetLastError();
  3333. CONDITIONAL_EXIT(dwErr, End);
  3334. }
  3335. dwErr = GetCurrentToken(&ProcessHandle);
  3336. CONDITIONAL_EXIT(dwErr, End);
  3337. ObjectTypeProperties.cbSize = sizeof(ObjectTypeProperties);
  3338. ObjectTypeProperties.dwFlags = 0;
  3339. ObjectTypeProperties.GenMap = ZeroGenMap;
  3340. //
  3341. // Get information regarding the object type.
  3342. //
  3343. dwErr = (*(MartaSetFunctionContext.fGetTypeProperties))(&ObjectTypeProperties);
  3344. CONDITIONAL_EXIT(dwErr, End);
  3345. MARTA_TURN_OFF_IMPERSONATION;
  3346. CONDITIONAL_EXIT(dwErr, End);
  3347. //
  3348. // Compute the new security descriptor.
  3349. //
  3350. if (FALSE == CreatePrivateObjectSecurityEx(
  3351. pParentSD,
  3352. &TmpSD,
  3353. &pNewSD,
  3354. NULL,
  3355. bIsContainer,
  3356. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT | SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  3357. ProcessHandle,
  3358. &ObjectTypeProperties.GenMap
  3359. ))
  3360. {
  3361. dwErr = GetLastError();
  3362. }
  3363. MARTA_TURN_ON_IMPERSONATION;
  3364. CONDITIONAL_EXIT(dwErr, End);
  3365. //
  3366. // Set the owner and the group fields in TmpSD to NULL if the caller
  3367. // did not want to set these.
  3368. //
  3369. if (NULL == pOwner)
  3370. {
  3371. if (FALSE == SetSecurityDescriptorOwner(
  3372. &TmpSD,
  3373. NULL,
  3374. FALSE))
  3375. {
  3376. dwErr = GetLastError();
  3377. }
  3378. CONDITIONAL_EXIT(dwErr, End);
  3379. }
  3380. if (NULL == pGroup)
  3381. {
  3382. if (FALSE == SetSecurityDescriptorGroup(
  3383. &TmpSD,
  3384. NULL,
  3385. FALSE))
  3386. {
  3387. dwErr = GetLastError();
  3388. }
  3389. CONDITIONAL_EXIT(dwErr, End);
  3390. }
  3391. //
  3392. // Set the DACL to Empty if the caller requested for resetting the DACL.
  3393. //
  3394. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  3395. {
  3396. if (FALSE == InitializeAcl(&EmptyDacl, sizeof(ACL), ACL_REVISION))
  3397. {
  3398. return ERROR_ACCESS_DENIED;
  3399. }
  3400. if (FALSE == SetSecurityDescriptorDacl(
  3401. &TmpSD,
  3402. TRUE,
  3403. &EmptyDacl,
  3404. FALSE))
  3405. {
  3406. return GetLastError();
  3407. }
  3408. }
  3409. //
  3410. // Set the SACL to Empty if the caller requested for resetting the SACL.
  3411. //
  3412. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  3413. {
  3414. if (FALSE == InitializeAcl(&EmptySacl, sizeof(ACL), ACL_REVISION))
  3415. {
  3416. return ERROR_ACCESS_DENIED;
  3417. }
  3418. if (FALSE == SetSecurityDescriptorSacl(
  3419. &TmpSD,
  3420. TRUE,
  3421. &EmptySacl,
  3422. FALSE))
  3423. {
  3424. return GetLastError();
  3425. }
  3426. }
  3427. //
  3428. // We now have TmpSD with
  3429. // Owner Sid if SecurityInfo contains OWNER_SECURITY_INFORMATION
  3430. // Group Sid if SecurityInfo contains GROUP_SECURITY_INFORMATION
  3431. // Empty DACL if SecurityInfo contains DACL_SECURITY_INFORMATION
  3432. // Empty SACL if SecurityInfo contains SACL_SECURITY_INFORMATION
  3433. //
  3434. }
  3435. else
  3436. {
  3437. //
  3438. // The caller requested for resetting owner and/or group.
  3439. // Set these in the TmpSD which will be passed to the recursive routine.
  3440. //
  3441. if (FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION))
  3442. {
  3443. if (FALSE == SetSecurityDescriptorOwner(
  3444. &TmpSD,
  3445. LocalOwner,
  3446. FALSE))
  3447. {
  3448. dwErr = GetLastError();
  3449. }
  3450. CONDITIONAL_EXIT(dwErr, End);
  3451. }
  3452. if (FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION))
  3453. {
  3454. if (FALSE == SetSecurityDescriptorGroup(
  3455. &TmpSD,
  3456. LocalGroup,
  3457. FALSE))
  3458. {
  3459. dwErr = GetLastError();
  3460. }
  3461. CONDITIONAL_EXIT(dwErr, End);
  3462. }
  3463. //
  3464. // This is also out New SD to set on the object.
  3465. //
  3466. pNewSD = &TmpSD;
  3467. }
  3468. //
  3469. // If the child is a container then update the subtree underneath it.
  3470. //
  3471. if (bIsContainer)
  3472. {
  3473. TmpSD.Control &= ~(SE_DACL_PROTECTED | SE_SACL_PROTECTED);
  3474. if (!bRetry)
  3475. {
  3476. bRetry = MartaResetTree(
  3477. pObjectName,
  3478. NtObjectName,
  3479. SecurityInfo,
  3480. TmpSeInfo,
  3481. pNewSD,
  3482. &TmpSD,
  3483. Context,
  3484. ProcessHandle,
  3485. &MartaSetFunctionContext,
  3486. &ObjectTypeProperties.GenMap,
  3487. MaxAccessMask,
  3488. AccessMask,
  3489. RetryAccessMask,
  3490. &Operation,
  3491. fnProgress,
  3492. Args,
  3493. KeepExplicit
  3494. );
  3495. }
  3496. }
  3497. else
  3498. {
  3499. bRetry = FALSE;
  3500. }
  3501. //
  3502. // Set the computed security descriptor on the object.
  3503. //
  3504. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  3505. {
  3506. ((PISECURITY_DESCRIPTOR) pNewSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  3507. }
  3508. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  3509. {
  3510. ((PISECURITY_DESCRIPTOR) pNewSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  3511. }
  3512. dwErr = (*(MartaSetFunctionContext.fSetRights))(
  3513. Context,
  3514. SecurityInfo,
  3515. pNewSD
  3516. );
  3517. CONDITIONAL_EXIT(dwErr, End);
  3518. //
  3519. // Note that the set operation on the object is successful.
  3520. //
  3521. bSetWorked = TRUE;
  3522. //
  3523. // Abort if the progress function requested a "Cancel" in the subtree
  3524. // below this node. The value is propagated all the way to the root as
  3525. // the stack unwinds.
  3526. //
  3527. if (ProgressCancelOperation == Operation)
  3528. {
  3529. goto End;
  3530. }
  3531. //
  3532. // If propagation had failed in the first attept then try again. This is to
  3533. // cover the case when the container can be enumerated after setting the new
  3534. // security.
  3535. //
  3536. if (bRetry && bIsContainer && (SecurityInfo & DACL_SECURITY_INFORMATION))
  3537. {
  3538. Retry:
  3539. bRetry = FALSE;
  3540. //
  3541. // Reopen the object for List and retry on the subtree. Note that for
  3542. // file objects this is just a dummy routine. The actual reopen happens
  3543. // in FindFirst.
  3544. //
  3545. dwErr = (*(MartaSetFunctionContext.fReopenOrigContext))(
  3546. Context,
  3547. RetryAccessMask
  3548. );
  3549. CONDITIONAL_EXIT(dwErr, End);
  3550. bRetry = MartaResetTree(
  3551. pObjectName,
  3552. NtObjectName,
  3553. SecurityInfo,
  3554. TmpSeInfo,
  3555. pNewSD,
  3556. &TmpSD,
  3557. Context,
  3558. ProcessHandle,
  3559. &MartaSetFunctionContext,
  3560. &ObjectTypeProperties.GenMap,
  3561. MaxAccessMask,
  3562. AccessMask,
  3563. RetryAccessMask,
  3564. &Operation,
  3565. fnProgress,
  3566. Args,
  3567. KeepExplicit
  3568. );
  3569. //
  3570. // Retry failed. We should give a callback stating enum failed.
  3571. //
  3572. if (bRetry)
  3573. {
  3574. switch (Operation)
  3575. {
  3576. case ProgressInvokeNever:
  3577. break;
  3578. case ProgressInvokeOnError:
  3579. if (ERROR_SUCCESS == dwErr)
  3580. {
  3581. break;
  3582. }
  3583. //
  3584. // Fallthrough is intended!!
  3585. //
  3586. case ProgressInvokeEveryObject:
  3587. if (NULL != fnProgress)
  3588. {
  3589. fnProgress(
  3590. pObjectName,
  3591. ERROR_ACCESS_DENIED,
  3592. &Operation,
  3593. Args,
  3594. TRUE
  3595. );
  3596. //
  3597. // This was the latest feature request by HiteshR. At this
  3598. // point, retry has failed, but the caller has made some
  3599. // changes and expects retry to work okay now.
  3600. //
  3601. if (ProgressRetryOperation == Operation)
  3602. {
  3603. Operation = ProgressInvokeEveryObject;
  3604. goto Retry;
  3605. }
  3606. }
  3607. break;
  3608. default:
  3609. break;
  3610. }
  3611. }
  3612. }
  3613. End:
  3614. if (bRetry && bIsContainer)
  3615. {
  3616. dwErr = ERROR_ACCESS_DENIED;
  3617. }
  3618. switch (Operation)
  3619. {
  3620. case ProgressInvokeNever:
  3621. break;
  3622. case ProgressInvokeOnError:
  3623. if (ERROR_SUCCESS == dwErr)
  3624. {
  3625. break;
  3626. }
  3627. //
  3628. // Fallthrough is intended!!
  3629. //
  3630. case ProgressInvokeEveryObject:
  3631. if (NULL != fnProgress)
  3632. {
  3633. fnProgress(
  3634. pObjectName,
  3635. dwErr,
  3636. &Operation,
  3637. Args,
  3638. bSetWorked
  3639. );
  3640. //
  3641. // This was the latest feature request by HiteshR. At this
  3642. // point, retry has failed, but the caller has made some
  3643. // changes and expects retry to work okay now.
  3644. //
  3645. if (ProgressRetryOperation == Operation)
  3646. {
  3647. Operation = ProgressInvokeEveryObject;
  3648. goto Retry;
  3649. }
  3650. }
  3651. break;
  3652. default:
  3653. break;
  3654. }
  3655. if (NULL != ProcessHandle)
  3656. {
  3657. CloseHandle(ProcessHandle);
  3658. }
  3659. if (NULL != pOldSD)
  3660. {
  3661. AccFree(pOldSD);
  3662. }
  3663. if (NULL != pParentSD)
  3664. {
  3665. AccFree(pParentSD);
  3666. }
  3667. if ((NULL != pNewSD) && (&TmpSD != pNewSD))
  3668. {
  3669. DestroyPrivateObjectSecurity(&pNewSD);
  3670. }
  3671. if (NULL != Context)
  3672. {
  3673. (VOID) (*(MartaSetFunctionContext.fCloseContext))(Context);
  3674. }
  3675. if (NULL != NtObjectName)
  3676. {
  3677. LocalFree(NtObjectName);
  3678. }
  3679. return dwErr;
  3680. }
  3681. ////////////////////////////////////////////////////////////////////////////////
  3682. // //
  3683. // Function: MartaResetTree //
  3684. // //
  3685. // Description: Reset permissions on the subtree below the node represented //
  3686. // by Context.
  3687. // //
  3688. // Arguments: //
  3689. // //
  3690. // [IN pObjectName] Name of the root of the subtree //
  3691. // [IN NtObjectName] Nt Name of the root of the subtree //
  3692. // Valid only for file objects //
  3693. // [IN SecurityInfo] Security info to reset //
  3694. // [IN TmpSeInfo] Info that needs to be read from the //
  3695. // object //
  3696. // [IN pNewSD] New security Descriptor on the parent //
  3697. // [IN pEmptySD] Security Descriptor with owner/group //
  3698. // [IN Context] Context for the root of the subtree //
  3699. // [IN ProcessHandle] Handle to the process token //
  3700. // [IN pMartaSetFunctionContext] Struct holding function pointers //
  3701. // [IN pGenMap] Generic mapping for the object //
  3702. // [IN MaxAccessMask] Desired access mask for R, W, List //
  3703. // [IN AccessMask] Desired access mask for W //
  3704. // [IN RetryMask] Desired access mask for List //
  3705. // [IN OUT pOperation] To determine if callback should be //
  3706. // invoked. Value may be changed by the //
  3707. // callback function. //
  3708. // [IN Args] Arguments supplied by the caller //
  3709. // [IN fnProgress] Caller supplied callback function //
  3710. // [IN KeepExplicit] if TRUE, retain explicit aces //
  3711. // //
  3712. // //
  3713. // Algorithm: //
  3714. // Open the first child for R, W, List //
  3715. // if open failed //
  3716. // Try again for just R, W and note that a retry is needed. //
  3717. // Return TRUE if no children exist. //
  3718. // Return FALSE if we can not list //
  3719. // for all children //
  3720. // If resetting xAcl (and maybe owner/group) //
  3721. // if KeepExplicit //
  3722. // read old xAcl and (owner/group if not provided by the caller) //
  3723. // else //
  3724. // read owner/group if not provided by the caller) //
  3725. // Compute NewChildSD using this computed info and new parent SD //
  3726. // else //
  3727. // NewChildSD = EmptySD //
  3728. // Invoke callback depending on the flag. //
  3729. // Retry propagation if it failed the first time. //
  3730. // If at any time, the callback function requests a cancel //
  3731. // Abort. //
  3732. //
  3733. // Returns: TRUE if propagation succeeded //
  3734. // //
  3735. ////////////////////////////////////////////////////////////////////////////////
  3736. BOOL
  3737. MartaResetTree(
  3738. IN LPWSTR pObjectName,
  3739. IN LPWSTR NtObjectName,
  3740. IN SECURITY_INFORMATION SecurityInfo,
  3741. IN SECURITY_INFORMATION TmpSeInfo,
  3742. IN PSECURITY_DESCRIPTOR pNewSD,
  3743. IN PSECURITY_DESCRIPTOR pEmptySD,
  3744. IN MARTA_CONTEXT Context,
  3745. IN HANDLE ProcessHandle,
  3746. IN PMARTA_SET_FUNCTION_CONTEXT pMartaSetFunctionContext,
  3747. IN PGENERIC_MAPPING pGenMap,
  3748. IN ACCESS_MASK MaxAccessMask,
  3749. IN ACCESS_MASK AccessMask,
  3750. IN ACCESS_MASK RetryAccessMask,
  3751. IN OUT PPROG_INVOKE_SETTING pOperation,
  3752. IN FN_PROGRESS fnProgress,
  3753. IN PVOID Args,
  3754. IN BOOL KeepExplicit
  3755. )
  3756. {
  3757. MARTA_OBJECT_PROPERTIES ObjectProperties;
  3758. MARTA_CONTEXT ChildContext = NULL_MARTA_CONTEXT;
  3759. PSECURITY_DESCRIPTOR pNewChildSD = NULL;
  3760. PSECURITY_DESCRIPTOR pOldChildSD = NULL;
  3761. DWORD dwErr = ERROR_SUCCESS;
  3762. BOOL bIsContainer = FALSE;
  3763. HANDLE ThreadHandle = NULL;
  3764. BOOL bRetry = FALSE;
  3765. BOOL bSetWorked = FALSE;
  3766. //
  3767. // Get the first child of this container. In the first attempt try to open
  3768. // the child with read/write as well as list.
  3769. //
  3770. dwErr = (*(pMartaSetFunctionContext->fFindFirst))(
  3771. Context,
  3772. MaxAccessMask,
  3773. &ChildContext
  3774. );
  3775. if (ERROR_SUCCESS != dwErr)
  3776. {
  3777. #ifdef MARTA_DEBUG
  3778. wprintf(L"FindFirst failed\n");
  3779. #endif
  3780. if (NULL == ChildContext)
  3781. {
  3782. //
  3783. // This should never happen. A NULL ChildContext represents no
  3784. // more children. We have this code path just in case some resource
  3785. // manager cannot open the object for list.
  3786. //
  3787. dwErr = (*(pMartaSetFunctionContext->fFindFirst))(
  3788. Context,
  3789. AccessMask,
  3790. &ChildContext
  3791. );
  3792. }
  3793. else
  3794. {
  3795. //
  3796. // Try opening the child again, this time with permissions sufficent
  3797. // for computing security info to set and setting it.
  3798. //
  3799. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  3800. ChildContext,
  3801. AccessMask
  3802. );
  3803. }
  3804. //
  3805. // We failed to open the object for list. Record this failure and open
  3806. // the child again if it is a container.
  3807. //
  3808. bRetry = TRUE;
  3809. }
  3810. else
  3811. {
  3812. #ifdef MARTA_DEBUG
  3813. wprintf(L"FindFirst succeeded\n");
  3814. #endif
  3815. }
  3816. if (NULL == ChildContext)
  3817. {
  3818. //
  3819. // The parent does not have any children.
  3820. //
  3821. if (ERROR_SUCCESS == dwErr)
  3822. {
  3823. #ifdef MARTA_DEBUG
  3824. wprintf(L"The container does not have any children\n");
  3825. #endif
  3826. return FALSE;
  3827. }
  3828. #ifdef MARTA_DEBUG
  3829. wprintf(L"Can not list objects in the current container. Retry needed\n");
  3830. #endif
  3831. //
  3832. // We need a propagation retry for the parent.
  3833. //
  3834. return TRUE;
  3835. }
  3836. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3837. //
  3838. // Child context becomes NULL when there are no more children.
  3839. //
  3840. while (ChildContext)
  3841. {
  3842. ObjectProperties.cbSize = sizeof(ObjectProperties);
  3843. ObjectProperties.dwFlags = 0;
  3844. //
  3845. // Get information about the current child. We need to know whether
  3846. // it is a container.
  3847. //
  3848. //
  3849. dwErr = (*(pMartaSetFunctionContext->fGetProperties))(
  3850. ChildContext,
  3851. &ObjectProperties
  3852. );
  3853. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3854. #ifdef MARTA_DEBUG
  3855. wprintf(L"GetProperties succeeded\n");
  3856. #endif
  3857. bIsContainer = FLAG_ON(ObjectProperties.dwFlags, MARTA_OBJECT_IS_CONTAINER);
  3858. //
  3859. // If we are setting any of the ACLs then the security descriptor must
  3860. // be recomputed.
  3861. //
  3862. if (FLAG_ON(SecurityInfo, (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)))
  3863. {
  3864. //
  3865. // TmpSeInfo is ZERO if the caller is resetting both OWNER and GROUP
  3866. // as well.
  3867. // We have to read the old ACLs if the caller wants to retain explicit
  3868. // aces.
  3869. //
  3870. if (KeepExplicit)
  3871. {
  3872. TmpSeInfo |= (SecurityInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION));
  3873. }
  3874. //
  3875. // Read the existing security on the child.
  3876. //
  3877. if (0 != TmpSeInfo)
  3878. {
  3879. dwErr = (*(pMartaSetFunctionContext->fGetRights))(
  3880. ChildContext,
  3881. TmpSeInfo,
  3882. &pOldChildSD
  3883. );
  3884. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3885. //
  3886. // Set the existing owner information in the empty security descriptor
  3887. // if the caller has not provided an Owner sid to set.
  3888. //
  3889. if (!FLAG_ON(SecurityInfo, OWNER_SECURITY_INFORMATION))
  3890. {
  3891. if (FALSE == SetSecurityDescriptorOwner(
  3892. pEmptySD,
  3893. RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  3894. FALSE))
  3895. {
  3896. dwErr = GetLastError();
  3897. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3898. }
  3899. }
  3900. if (KeepExplicit)
  3901. {
  3902. //
  3903. // Set the ACLs in the EmptySD to existing ones in order to
  3904. // retain explicit aces.
  3905. //
  3906. if (FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  3907. {
  3908. if (FALSE == SetSecurityDescriptorDacl(
  3909. pEmptySD,
  3910. TRUE,
  3911. RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  3912. FALSE))
  3913. {
  3914. dwErr = GetLastError();
  3915. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3916. }
  3917. }
  3918. if (FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  3919. {
  3920. if (FALSE == SetSecurityDescriptorSacl(
  3921. pEmptySD,
  3922. TRUE,
  3923. RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  3924. FALSE))
  3925. {
  3926. dwErr = GetLastError();
  3927. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3928. }
  3929. }
  3930. }
  3931. //
  3932. // Set the existing group information in the empty security descriptor
  3933. // if the caller has not provided a group sid to set.
  3934. //
  3935. if (!FLAG_ON(SecurityInfo, GROUP_SECURITY_INFORMATION))
  3936. {
  3937. if (FALSE == SetSecurityDescriptorGroup(
  3938. pEmptySD,
  3939. RtlpGroupAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pOldChildSD),
  3940. FALSE))
  3941. {
  3942. dwErr = GetLastError();
  3943. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3944. }
  3945. }
  3946. }
  3947. MARTA_TURN_OFF_IMPERSONATION;
  3948. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3949. //
  3950. // Merge the NewParentSD and the OldChildSD to create NewChildSD.
  3951. //
  3952. if (FALSE == CreatePrivateObjectSecurityEx(
  3953. pNewSD,
  3954. pEmptySD,
  3955. &pNewChildSD,
  3956. NULL,
  3957. bIsContainer,
  3958. (SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT |
  3959. SEF_AVOID_OWNER_CHECK | SEF_AVOID_PRIVILEGE_CHECK),
  3960. ProcessHandle,
  3961. pGenMap
  3962. ))
  3963. {
  3964. dwErr = GetLastError();
  3965. }
  3966. MARTA_TURN_ON_IMPERSONATION;
  3967. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  3968. }
  3969. else
  3970. {
  3971. //
  3972. // The new ChildSD does not have to computed. We only want to set
  3973. // Owner/Group information.
  3974. //
  3975. pNewChildSD = pEmptySD;
  3976. }
  3977. //
  3978. // Update the subtree undrneath this child.
  3979. //
  3980. if (bIsContainer)
  3981. {
  3982. if (!bRetry)
  3983. {
  3984. #ifdef MARTA_DEBUG
  3985. wprintf(L"Trying reset \n");
  3986. #endif
  3987. bRetry = MartaResetTree(
  3988. pObjectName,
  3989. NtObjectName,
  3990. SecurityInfo,
  3991. TmpSeInfo,
  3992. pNewChildSD,
  3993. pEmptySD,
  3994. ChildContext,
  3995. ProcessHandle,
  3996. pMartaSetFunctionContext,
  3997. pGenMap,
  3998. MaxAccessMask,
  3999. AccessMask,
  4000. RetryAccessMask,
  4001. pOperation,
  4002. fnProgress,
  4003. Args,
  4004. KeepExplicit
  4005. );
  4006. }
  4007. }
  4008. else
  4009. {
  4010. bRetry = FALSE;
  4011. }
  4012. //
  4013. // Stamp NewChildSD on child.
  4014. //
  4015. if(FLAG_ON(SecurityInfo, DACL_SECURITY_INFORMATION))
  4016. {
  4017. ((PISECURITY_DESCRIPTOR) pNewChildSD)->Control |= SE_DACL_AUTO_INHERIT_REQ;
  4018. }
  4019. if(FLAG_ON(SecurityInfo, SACL_SECURITY_INFORMATION))
  4020. {
  4021. ((PISECURITY_DESCRIPTOR) pNewChildSD)->Control |= SE_SACL_AUTO_INHERIT_REQ;
  4022. }
  4023. dwErr = (*(pMartaSetFunctionContext->fSetRights))(
  4024. ChildContext,
  4025. SecurityInfo,
  4026. pNewChildSD
  4027. );
  4028. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  4029. #ifdef MARTA_DEBUG
  4030. wprintf(L"Set right succeeded\n");
  4031. #endif
  4032. //
  4033. // Note down that we were able to set security on this object.
  4034. //
  4035. bSetWorked = TRUE;
  4036. //
  4037. // Abort if the progress function requested a "Cancel" in the subtree
  4038. // below this node. The value is propagated all the way to the root as
  4039. // the stack unwinds.
  4040. //
  4041. if (ProgressCancelOperation == *pOperation)
  4042. {
  4043. goto EndOfWhile;
  4044. }
  4045. //
  4046. // If propagation had failed in the first attept then try again. This is to
  4047. // cover the case when the container can be enumerated after setting the new
  4048. // security.
  4049. //
  4050. if (bRetry && bIsContainer && (SecurityInfo & DACL_SECURITY_INFORMATION))
  4051. {
  4052. Retry:
  4053. bRetry = FALSE;
  4054. //
  4055. // Reopen the object for List and retry on the subtree.
  4056. //
  4057. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  4058. ChildContext,
  4059. RetryAccessMask
  4060. );
  4061. CONDITIONAL_EXIT(dwErr, EndOfWhile);
  4062. bRetry = MartaResetTree(
  4063. pObjectName,
  4064. NtObjectName,
  4065. SecurityInfo,
  4066. TmpSeInfo,
  4067. pNewSD,
  4068. pEmptySD,
  4069. ChildContext,
  4070. ProcessHandle,
  4071. pMartaSetFunctionContext,
  4072. pGenMap,
  4073. MaxAccessMask,
  4074. AccessMask,
  4075. RetryAccessMask,
  4076. pOperation,
  4077. fnProgress,
  4078. Args,
  4079. KeepExplicit
  4080. );
  4081. }
  4082. EndOfWhile:
  4083. if (bRetry && bIsContainer)
  4084. {
  4085. dwErr = ERROR_ACCESS_DENIED;
  4086. }
  4087. switch (*pOperation)
  4088. {
  4089. case ProgressInvokeNever:
  4090. break;
  4091. case ProgressInvokeOnError:
  4092. if (ERROR_SUCCESS == dwErr)
  4093. {
  4094. break;
  4095. }
  4096. //
  4097. // Fallthough is intended!!
  4098. //
  4099. case ProgressInvokeEveryObject:
  4100. if (NULL != fnProgress)
  4101. {
  4102. LPWSTR Name = NULL;
  4103. //
  4104. // Get the name of the current object from the context and call
  4105. // the progress function with the arguments provided by the
  4106. // caller of ResetTree API.
  4107. //
  4108. DWORD Error = (*(pMartaSetFunctionContext->fGetNameFromContext))(
  4109. pObjectName,
  4110. NtObjectName,
  4111. ChildContext,
  4112. &Name
  4113. );
  4114. if (ERROR_SUCCESS == Error)
  4115. {
  4116. fnProgress(
  4117. Name,
  4118. dwErr,
  4119. pOperation,
  4120. Args,
  4121. bSetWorked
  4122. );
  4123. LocalFree(Name);
  4124. //
  4125. // This was the latest feature request by HiteshR. At this
  4126. // point, retry has failed, but the caller has made some
  4127. // changes and expects retry to work okay now.
  4128. //
  4129. if (ProgressRetryOperation == *pOperation)
  4130. {
  4131. *pOperation = ProgressInvokeEveryObject;
  4132. goto Retry;
  4133. }
  4134. }
  4135. }
  4136. break;
  4137. default:
  4138. break;
  4139. }
  4140. bSetWorked = bRetry = FALSE;
  4141. if ((NULL != pNewChildSD) && (pEmptySD != pNewChildSD))
  4142. {
  4143. DestroyPrivateObjectSecurity(&pNewChildSD);
  4144. pNewChildSD = NULL;
  4145. }
  4146. if (NULL != pOldChildSD)
  4147. {
  4148. LocalFree(pOldChildSD);
  4149. pOldChildSD = NULL;
  4150. }
  4151. //
  4152. // Abort if the progress function requested a "Cancel".
  4153. //
  4154. if (ProgressCancelOperation == *pOperation)
  4155. {
  4156. (*(pMartaSetFunctionContext->fCloseContext)) (ChildContext);
  4157. return TRUE;
  4158. }
  4159. //
  4160. // Get the next child.
  4161. //
  4162. do {
  4163. bRetry = FALSE;
  4164. dwErr = (*(pMartaSetFunctionContext->fFindNext))(
  4165. ChildContext,
  4166. MaxAccessMask,
  4167. &ChildContext
  4168. );
  4169. if (NULL == ChildContext)
  4170. {
  4171. break;
  4172. }
  4173. if (ERROR_SUCCESS != dwErr)
  4174. {
  4175. #ifdef MARTA_DEBUG
  4176. wprintf(L"FindNext failed\n");
  4177. #endif
  4178. dwErr = (*(pMartaSetFunctionContext->fReopenContext))(
  4179. ChildContext,
  4180. AccessMask
  4181. );
  4182. #ifdef MARTA_DEBUG
  4183. if (dwErr == ERROR_SUCCESS)
  4184. {
  4185. wprintf(L"FindNext failed\n");
  4186. }
  4187. #endif
  4188. bRetry = TRUE;
  4189. }
  4190. else
  4191. {
  4192. #ifdef MARTA_DEBUG
  4193. wprintf(L"Findnext succeeded\n");
  4194. #endif
  4195. }
  4196. switch (*pOperation)
  4197. {
  4198. case ProgressInvokeNever:
  4199. break;
  4200. case ProgressInvokeOnError:
  4201. //
  4202. // If we encountered an error in FindNext then report it to the
  4203. // caller.
  4204. //
  4205. if (ERROR_SUCCESS == dwErr)
  4206. {
  4207. break;
  4208. }
  4209. //
  4210. // Fallthough is intended!!
  4211. //
  4212. case ProgressInvokeEveryObject:
  4213. if (NULL != fnProgress)
  4214. {
  4215. LPWSTR Name = NULL;
  4216. //
  4217. // Get the name of the current object.
  4218. //
  4219. DWORD Error = (*(pMartaSetFunctionContext->fGetNameFromContext))(
  4220. pObjectName,
  4221. NtObjectName,
  4222. ChildContext,
  4223. &Name
  4224. );
  4225. if (ERROR_SUCCESS == Error)
  4226. {
  4227. fnProgress(
  4228. Name,
  4229. dwErr,
  4230. pOperation,
  4231. Args,
  4232. bSetWorked
  4233. );
  4234. LocalFree(Name);
  4235. }
  4236. }
  4237. break;
  4238. default:
  4239. break;
  4240. }
  4241. //
  4242. // Abort if the progress function requested a "Cancel".
  4243. //
  4244. if (ProgressCancelOperation == *pOperation)
  4245. {
  4246. (*(pMartaSetFunctionContext->fCloseContext)) (ChildContext);
  4247. return TRUE;
  4248. }
  4249. } while ((ERROR_SUCCESS != dwErr) && (NULL != ChildContext));
  4250. }
  4251. return FALSE;
  4252. }