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.

4959 lines
138 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. persist.cxx
  5. Abstract:
  6. Routines implementing the common logic for persisting the authz policy.
  7. This file contains routine called by the core logic to submit changes.
  8. It also contains routines that are called by the particular providers to
  9. find out information about the changed objects.
  10. Author:
  11. Cliff Van Dyke (cliffv) 9-May-2001
  12. --*/
  13. #include "pch.hxx"
  14. DWORD
  15. WINAPI
  16. AzpeCreateObject(
  17. IN AZPE_OBJECT_HANDLE AzpeParentHandle,
  18. IN ULONG ChildObjectType,
  19. IN LPCWSTR ChildObjectNameString,
  20. IN GUID *ChildObjectGuid OPTIONAL,
  21. IN ULONG lPersistFlags,
  22. OUT AZPE_OBJECT_HANDLE *AzpeChildHandle
  23. );
  24. VOID
  25. WINAPI
  26. AzpeObjectFinished(
  27. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  28. IN DWORD WinStatus
  29. );
  30. DWORD
  31. WINAPI
  32. AzpeGetProperty(
  33. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  34. IN ULONG lPersistFlags,
  35. IN ULONG PropertyId,
  36. OUT PVOID *PropertyValue
  37. );
  38. DWORD
  39. WINAPI
  40. AzpeGetDeltaArray(
  41. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  42. IN ULONG PropertyId,
  43. OUT PULONG DeltaArrayCount,
  44. OUT PAZP_DELTA_ENTRY **DeltaArray
  45. );
  46. DWORD
  47. WINAPI
  48. AzpeGetSecurityDescriptorFromCache(
  49. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  50. IN ULONG lPersistFlags,
  51. IN PAZP_POLICY_USER_RIGHTS *ppPolicyAdminRights OPTIONAL,
  52. IN PAZP_POLICY_USER_RIGHTS *ppPolicyReaderRights OPTIONAL,
  53. IN PAZP_POLICY_USER_RIGHTS *ppDelegatedPolicyUsersRights OPTIONAL,
  54. IN GUID *pDelegatedObjectGuid OPTIONAL,
  55. IN PAZP_POLICY_USER_RIGHTS pDelegatedUsersAttributeRights OPTIONAL,
  56. IN GUID *pAttributeGuid OPTIONAL,
  57. IN PAZP_POLICY_USER_RIGHTS pSaclRights OPTIONAL,
  58. IN PSECURITY_DESCRIPTOR OldSd OPTIONAL,
  59. OUT PSECURITY_DESCRIPTOR *NewSd
  60. );
  61. //
  62. // Routines to return a single field of an object
  63. //
  64. DWORD
  65. WINAPI
  66. AzpeObjectType(
  67. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  68. );
  69. DWORD
  70. WINAPI
  71. AzpeDirtyBits(
  72. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  73. );
  74. GUID *
  75. WINAPI
  76. AzpePersistenceGuid(
  77. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  78. );
  79. AZPE_OBJECT_HANDLE
  80. WINAPI
  81. AzpeParentOfChild(
  82. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  83. );
  84. BOOLEAN
  85. WINAPI
  86. AzpeIsParentWritable(
  87. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  88. );
  89. BOOLEAN
  90. WINAPI
  91. AzpeUpdateChildren(
  92. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  93. );
  94. BOOLEAN
  95. WINAPI
  96. AzpeCanCreateChildren(
  97. IN AZPE_OBJECT_HANDLE AzpeCanCreateChildren
  98. );
  99. //
  100. // Routines to change an object
  101. //
  102. DWORD
  103. WINAPI
  104. AzpeSetProperty(
  105. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  106. IN ULONG lPersistFlags,
  107. IN ULONG PropertyId,
  108. IN PVOID PropertyValue
  109. );
  110. DWORD
  111. WINAPI
  112. AzpeSetObjectOptions(
  113. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  114. IN ULONG lPersistFlags,
  115. IN ULONG ObjectOptions
  116. );
  117. DWORD
  118. WINAPI
  119. AzpeAddPropertyItemGuid(
  120. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  121. IN ULONG lPersistFlags,
  122. IN ULONG PropertyId,
  123. IN GUID *ObjectGuid
  124. );
  125. DWORD
  126. WINAPI
  127. AzpeAddPropertyItemGuidString(
  128. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  129. IN ULONG lPersistFlags,
  130. IN ULONG PropertyId,
  131. IN WCHAR *ObjectGuidString
  132. );
  133. VOID
  134. WINAPI
  135. AzpeSetProviderData(
  136. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  137. IN PVOID ProviderData
  138. );
  139. PVOID
  140. WINAPI
  141. AzpeGetProviderData(
  142. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  143. );
  144. DWORD
  145. WINAPI
  146. AzpeSetSecurityDescriptorIntoCache(
  147. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  148. IN PSECURITY_DESCRIPTOR pSD,
  149. IN ULONG lPersistFlags,
  150. IN PAZP_POLICY_USER_RIGHTS pAdminRights,
  151. IN PAZP_POLICY_USER_RIGHTS pReadersRights,
  152. IN PAZP_POLICY_USER_RIGHTS pDelegatedUserRights OPTIONAL,
  153. IN PAZP_POLICY_USER_RIGHTS pSaclRights OPTIONAL
  154. );
  155. PVOID
  156. WINAPI
  157. AzpeAllocateMemory(
  158. IN SIZE_T Size
  159. );
  160. VOID
  161. WINAPI
  162. AzpeFreeMemory (
  163. IN PVOID Buffer
  164. );
  165. BOOLEAN
  166. WINAPI
  167. AzpeIsParentWritable(
  168. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  169. );
  170. BOOLEAN
  171. WINAPI
  172. AzpeUpdateChildren(
  173. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  174. );
  175. BOOLEAN
  176. WINAPI
  177. AzpeCanCreateChildren(
  178. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  179. );
  180. BOOL
  181. WINAPI
  182. AzpeAzStoreIsBatchUpdateMode(
  183. IN AZPE_OBJECT_HANDLE hObject
  184. );
  185. AZPE_OBJECT_HANDLE
  186. WINAPI
  187. AzpeGetAuthorizationStore(
  188. IN AZPE_OBJECT_HANDLE hObject
  189. );
  190. //
  191. // Define the Azrole info structure to pass to the providers
  192. //
  193. AZPE_AZROLES_INFO AzGlAzrolesInfo = {
  194. AZPE_AZROLES_INFO_VERSION_2,
  195. //
  196. // Routines exported by azroles to the provider
  197. //
  198. AzpeCreateObject,
  199. AzpeObjectFinished,
  200. AzpeGetProperty,
  201. AzpeGetDeltaArray,
  202. AzpeGetSecurityDescriptorFromCache,
  203. AzpeObjectType,
  204. AzpeDirtyBits,
  205. AzpePersistenceGuid,
  206. AzpeParentOfChild,
  207. AzpeSetProperty,
  208. AzpeSetObjectOptions,
  209. AzpeAddPropertyItemSid,
  210. AzpeAddPropertyItemGuid,
  211. AzpeAddPropertyItemGuidString,
  212. AzpeSetProviderData,
  213. AzpeGetProviderData,
  214. AzpeSetSecurityDescriptorIntoCache,
  215. AzpeAllocateMemory,
  216. AzpeFreeMemory,
  217. //
  218. // These routines available for Version 2 and higher only
  219. //
  220. AzpeIsParentWritable,
  221. AzpeUpdateChildren,
  222. AzpeCanCreateChildren,
  223. AzpeAzStoreIsBatchUpdateMode,
  224. AzpeGetAuthorizationStore
  225. };
  226. //
  227. // The enumeration context describes the current state of an enumeration
  228. // through the list of all the objects in the authz policy database
  229. //
  230. typedef struct _AZP_PERSIST_ENUM_CONTEXT {
  231. //
  232. // Stack Index
  233. // The enumeration walks the tree of objects. While enumerating child objects,
  234. // the context of the parent object enumeration is kept on the stack of contexts.
  235. //
  236. LONG StackIndex;
  237. #define AZ_PERSIST_MAX_INDEX 4
  238. //
  239. // Object to return on the first call to AzpPersistEnumNext
  240. //
  241. PGENERIC_OBJECT GenericObject;
  242. //
  243. // Pointer to the current Generic Child Head being enumerated
  244. //
  245. PGENERIC_OBJECT_HEAD GenericChildHead[AZ_PERSIST_MAX_INDEX];
  246. ULONG EnumerationContext[AZ_PERSIST_MAX_INDEX];
  247. //
  248. // Variables for remembering the last object that was returned
  249. // These are maintained to allow us to detect if that object was deleted.
  250. //
  251. PGENERIC_OBJECT PreviousObject;
  252. PGENERIC_OBJECT_HEAD PreviousGenericChildHead;
  253. ULONG PreviousEnumContext;
  254. } AZP_PERSIST_ENUM_CONTEXT, *PAZP_PERSIST_ENUM_CONTEXT;
  255. DWORD
  256. AzpPersistEnumOpen(
  257. IN PGENERIC_OBJECT GenericObject,
  258. OUT PVOID *PersistEnumContext
  259. )
  260. /*++
  261. Routine Description:
  262. This routine begins an enumeration of the objects in the authz policy database from
  263. GenericObject
  264. On entry, AzGlResource must be locked exclusive.
  265. Arguments:
  266. GenericObject - Specifies the object that is being queried
  267. PersistEnumContext - Returns a context that can be passed to AzpPersistEnumNext.
  268. This context must be closed by calling AzPersistClose.
  269. Return Value:
  270. NO_ERROR - The operation was successful
  271. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  272. Other status codes
  273. --*/
  274. {
  275. PAZP_PERSIST_ENUM_CONTEXT Context = NULL;
  276. //
  277. // Allocate memory for the context
  278. //
  279. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  280. Context = (PAZP_PERSIST_ENUM_CONTEXT) AzpAllocateHeap( sizeof(*Context), "PEENUMCX" );
  281. if ( Context == NULL ) {
  282. return ERROR_NOT_ENOUGH_MEMORY;
  283. }
  284. RtlZeroMemory( Context, sizeof(*Context) );
  285. //
  286. // Initialize it
  287. //
  288. Context->GenericObject = GenericObject;
  289. Context->StackIndex = -1;
  290. //
  291. // Return the context to the caller
  292. //
  293. *PersistEnumContext = Context;
  294. return NO_ERROR;
  295. }
  296. DWORD
  297. AzpPersistEnumNext(
  298. IN PVOID PersistEnumContext,
  299. OUT PGENERIC_OBJECT *GenericObject
  300. )
  301. /*++
  302. Routine Description:
  303. This routine returns the next object in the list of all objects in the authz policy database.
  304. The caller may feel free to delete the returned object and its children. However,
  305. the caller should not delete any other objects.
  306. On entry, AzGlResource must be locked exclusive.
  307. Arguments:
  308. PersistEnumContext - A context describing the current state of the enumeration
  309. GenericObject - Returns a pointer to an next object.
  310. There is no reference on this object
  311. Return Value:
  312. NO_ERROR - The operation was successful (a GenericObject was returned)
  313. ERROR_NO_MORE_ITEMS - No more items were available for enumeration
  314. Other status codes
  315. --*/
  316. {
  317. DWORD WinStatus;
  318. PGENERIC_OBJECT PreviousObject = NULL;
  319. PAZP_PERSIST_ENUM_CONTEXT Context = (PAZP_PERSIST_ENUM_CONTEXT) PersistEnumContext;
  320. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  321. //
  322. // If this is the first call,
  323. // return the AzAuthorizationStore itself.
  324. //
  325. if ( Context->PreviousObject == NULL ) {
  326. *GenericObject = Context->GenericObject;
  327. Context->PreviousObject = *GenericObject;
  328. Context->PreviousGenericChildHead = NULL;
  329. Context->PreviousEnumContext = NULL;
  330. return NO_ERROR;
  331. }
  332. //
  333. // Detect if the previously returned object was deleted by the caller
  334. //
  335. if ( Context->PreviousGenericChildHead == NULL ) {
  336. PreviousObject = Context->GenericObject;
  337. } else {
  338. WinStatus = ObEnumObjects( Context->PreviousGenericChildHead,
  339. TRUE, // return deleted objects
  340. FALSE, // Don't refresh the cache
  341. &Context->PreviousEnumContext,
  342. &PreviousObject );
  343. if ( WinStatus != NO_ERROR ) {
  344. if ( WinStatus != ERROR_NO_MORE_ITEMS ) {
  345. return WinStatus;
  346. }
  347. PreviousObject = NULL;
  348. }
  349. }
  350. //
  351. // If the previously returned object wasn't deleted by the caller,
  352. // process its children.
  353. //
  354. if ( Context->PreviousObject == PreviousObject ) {
  355. //
  356. // Only push onto the stack if the current object can have children
  357. //
  358. if ( Context->PreviousObject->ChildGenericObjectHead != NULL ) {
  359. if ( Context->StackIndex+1 >= AZ_PERSIST_MAX_INDEX ) {
  360. ASSERT(FALSE);
  361. return ERROR_INTERNAL_ERROR;
  362. }
  363. Context->StackIndex++;
  364. Context->GenericChildHead[Context->StackIndex] = Context->PreviousObject->ChildGenericObjectHead;
  365. Context->EnumerationContext[Context->StackIndex] = 0;
  366. }
  367. }
  368. //
  369. // Loop until we find another object to return
  370. //
  371. for (;;) {
  372. //
  373. // Don't return pseudo objects to the caller.
  374. //
  375. if ( Context->GenericChildHead[Context->StackIndex]->ObjectType != OBJECT_TYPE_SID ) {
  376. ULONG PreviousEnumContext;
  377. //
  378. // Get the next object from the current list
  379. //
  380. PreviousEnumContext = Context->EnumerationContext[Context->StackIndex];
  381. WinStatus = ObEnumObjects( Context->GenericChildHead[Context->StackIndex],
  382. TRUE, // return deleted objects
  383. FALSE, // Don't refresh the cache
  384. &Context->EnumerationContext[Context->StackIndex],
  385. GenericObject );
  386. //
  387. // If that worked,
  388. // remember the object that was found and return it to the caller
  389. //
  390. if ( WinStatus == NO_ERROR ) {
  391. Context->PreviousObject = *GenericObject;
  392. Context->PreviousGenericChildHead = Context->GenericChildHead[Context->StackIndex];
  393. Context->PreviousEnumContext = PreviousEnumContext;
  394. return NO_ERROR;
  395. }
  396. if ( WinStatus != ERROR_NO_MORE_ITEMS ) {
  397. return WinStatus;
  398. }
  399. }
  400. //
  401. // Move on to the next set of sibling object types.
  402. //
  403. Context->EnumerationContext[Context->StackIndex] = 0;
  404. if ( Context->GenericChildHead[Context->StackIndex]->SiblingGenericObjectHead != NULL ) {
  405. Context->GenericChildHead[Context->StackIndex] = Context->GenericChildHead[Context->StackIndex]->SiblingGenericObjectHead;
  406. continue;
  407. }
  408. //
  409. // There are no more sibling object types for the same parent.
  410. // Continue the enumeration of the parent objects
  411. //
  412. if ( Context->StackIndex == 0 ) {
  413. return ERROR_NO_MORE_ITEMS;
  414. }
  415. Context->StackIndex--;
  416. }
  417. }
  418. VOID
  419. AzpPersistEnumClose(
  420. IN PVOID PersistEnumContext
  421. )
  422. /*++
  423. Routine Description:
  424. This routine returns free any resources consumed by the PersistEnumContext.
  425. On entry, AzGlResource must be locked exclusive.
  426. Arguments:
  427. PersistEnumContext - A context describing the current state of the enumeration
  428. Return Value:
  429. NO_ERROR - The operation was successful
  430. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  431. Other status codes
  432. --*/
  433. {
  434. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  435. AzpFreeHeap( PersistEnumContext );
  436. }
  437. //
  438. // Operation being reconciled
  439. //
  440. typedef enum _RECONCILE_TYPE {
  441. IsOpen, // AzPersistOpen
  442. PreUpdateCache, // AzPersistUpdateCache (prior to calling provider), AzPersistUpdateChildrenCache
  443. IsUpdateCache, // AzPersistUpdateCache
  444. IsUpdateChildCache, // AzPersisUpdateChildrenCache
  445. IsRefresh // AzPersistRefresh
  446. } RECONCILE_TYPE, *PRECONCILE_TYPE;
  447. DWORD
  448. AzpPersistReconcileDeltaArray(
  449. IN PGENERIC_OBJECT GenericObject,
  450. IN PGENERIC_OBJECT_LIST GenericObjectList,
  451. IN RECONCILE_TYPE ReconType
  452. )
  453. /*++
  454. Routine Description:
  455. Implements AzpPersistReconcile for a single generic object list
  456. On entry, AzGlResource must be locked exclusive.
  457. PersistCritSect must be locked. (unless this is a refresh)
  458. Arguments:
  459. GenericObject - Specifies the object in the cache that is to be reconciled
  460. GenericObjectList - Specifies the delta array to reconcile.
  461. ReconType - Specifies the routine that called the persistence provider
  462. Return Value:
  463. NO_ERROR - The operation was successful
  464. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  465. Other status codes
  466. --*/
  467. {
  468. DWORD SavedWinStatus = NO_ERROR;
  469. DWORD WinStatus;
  470. ULONG Index;
  471. ULONG DeltaIndex;
  472. PAZP_DELTA_ENTRY DeltaEntry;
  473. //
  474. // Skip back links
  475. //
  476. if ( GenericObjectList->IsBackLink ) {
  477. goto Cleanup;
  478. }
  479. //
  480. // Ensure each entry in the delta array has an entry in the object list
  481. //
  482. for ( DeltaIndex=0; DeltaIndex<GenericObjectList->DeltaArray.UsedCount; DeltaIndex++ ) {
  483. //
  484. // If the entry corresponds to an "add",
  485. // do an "add" to the object list.
  486. //
  487. DeltaEntry = (PAZP_DELTA_ENTRY)GenericObjectList->DeltaArray.Array[DeltaIndex];
  488. if ( DeltaEntry->DeltaFlags & AZP_DELTA_ADD ) {
  489. PAZP_STRING StringToAdd;
  490. AZP_STRING SidString;
  491. ULONG Flags = AZP_FLAGS_RECONCILE;
  492. //
  493. // Compute the parameters to ObAddPropertyItem
  494. //
  495. if ( DeltaEntry->DeltaFlags & AZP_DELTA_SID ) {
  496. AzpInitSid( &SidString, DeltaEntry->Sid );
  497. StringToAdd = &SidString;
  498. } else {
  499. AzPrint(( AZD_REF, "AzpPersistReconcileOne (by guid): " ));
  500. AzpDumpGuid( AZD_REF, &DeltaEntry->Guid );
  501. AzPrint(( AZD_REF, "\n" ));
  502. Flags |= AZP_FLAGS_BY_GUID;
  503. StringToAdd = (PAZP_STRING) &DeltaEntry->Guid;
  504. }
  505. //
  506. // Add the property item
  507. //
  508. WinStatus = ObAddPropertyItem(
  509. GenericObject,
  510. GenericObjectList,
  511. Flags,
  512. StringToAdd );
  513. //
  514. // We ignore links that have already been updated.
  515. // During the update child cache routine, we want to ignore objects that exist in the store
  516. // but not yet in the cache since the user has not called an update on the entire policy cache
  517. //
  518. if ( (WinStatus != NO_ERROR && WinStatus != ERROR_ALREADY_EXISTS) &&
  519. ((ReconType != IsUpdateChildCache) ||
  520. (ReconType == IsUpdateChildCache && WinStatus != ERROR_NOT_FOUND)) ) {
  521. AzPrint(( AZD_REF,
  522. "AzpPersistReconcileOne: ObAddPropertyItem failed %ld\n",
  523. WinStatus
  524. ));
  525. SavedWinStatus = WinStatus;
  526. }
  527. }
  528. }
  529. //
  530. // Remove entries from the object list that should no longer exist
  531. //
  532. for ( Index=0; Index<GenericObjectList->GenericObjects.UsedCount; ) {
  533. PGENERIC_OBJECT LinkedToGenericObject;
  534. DWORD DeltaFlags;
  535. GUID *Guid;
  536. //
  537. // Determine if the object is in the DeltaArray
  538. //
  539. LinkedToGenericObject = (PGENERIC_OBJECT)(GenericObjectList->GenericObjects.Array[Index]);
  540. if ( LinkedToGenericObject->ObjectType == OBJECT_TYPE_SID ) {
  541. DeltaFlags = AZP_DELTA_SID;
  542. Guid = (GUID *)&LinkedToGenericObject->ObjectName->ObjectName;
  543. } else {
  544. DeltaFlags = 0;
  545. Guid = &LinkedToGenericObject->PersistenceGuid;
  546. }
  547. if ( ObLookupDelta( DeltaFlags,
  548. Guid,
  549. &GenericObjectList->DeltaArray,
  550. &DeltaIndex ) ) {
  551. //
  552. // Found it.
  553. //
  554. // If the entry is an "add" entry,
  555. // this is one we added above,
  556. // just move to the next entry.
  557. //
  558. DeltaEntry = (PAZP_DELTA_ENTRY)GenericObjectList->DeltaArray.Array[DeltaIndex];
  559. if ( DeltaEntry->DeltaFlags & AZP_DELTA_ADD ) {
  560. Index++;
  561. continue;
  562. }
  563. }
  564. //
  565. // Link should be removed
  566. //
  567. // Either there was no entry in the DeltaArray (or the entry is a "remove" entry
  568. //
  569. // Remove the links in both directions
  570. //
  571. ObRemoveObjectListLink( GenericObject,
  572. GenericObjectList,
  573. Index );
  574. }
  575. Cleanup:
  576. //
  577. // Clear the bit that got us here
  578. //
  579. GenericObject->PersistDirtyBits &= ~GenericObjectList->DirtyBit;
  580. //
  581. // Free entries from the delta arrays that were added by the persist provider.
  582. //
  583. ObFreeDeltaArray( &GenericObjectList->DeltaArray, FALSE );
  584. return SavedWinStatus;
  585. }
  586. DWORD
  587. AzpPersistReconcileOne(
  588. IN PGENERIC_OBJECT GenericObject,
  589. IN RECONCILE_TYPE ReconType,
  590. IN BOOLEAN OpenFailed
  591. )
  592. /*++
  593. Routine Description:
  594. Implements AzpPersistReconcile for a single object.
  595. On entry, AzGlResource must be locked exclusive.
  596. PersistCritSect must be locked. (unless this is a refresh)
  597. Arguments:
  598. GenericObject - Specifies the object in the cache that is to be reconciled
  599. ReconType - Specifies the routine that called the persistence provider
  600. OpenFailed - TRUE if the open call to the persistence provider failed.
  601. Return Value:
  602. NO_ERROR - The operation was successful
  603. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  604. Other status codes
  605. --*/
  606. {
  607. DWORD WinStatus;
  608. DWORD SavedWinStatus = NO_ERROR;
  609. ULONG DirtyBits;
  610. PGENERIC_OBJECT_LIST GenericObjectList;
  611. //
  612. // Initialization
  613. //
  614. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  615. ASSERT( ReconType == IsRefresh || ReconType == PreUpdateCache || AzpIsCritsectLocked( &GenericObject->AzStoreObject->PersistCritSect ) );
  616. AzPrint(( AZD_PERSIST,
  617. "AzpPersistReconcileOne: %ws %ld 0x%lx 0x%lx\n",
  618. GenericObject->ObjectName == NULL ? NULL : GenericObject->ObjectName->ObjectName.String,
  619. GenericObject->ObjectType,
  620. GenericObject->PersistDirtyBits,
  621. GenericObject->DirtyBits ));
  622. if ( ReconType == IsOpen ) {
  623. ASSERT( GenericObject->DirtyBits == 0 || GenericObject->ObjectType == OBJECT_TYPE_AZAUTHSTORE);
  624. }
  625. //
  626. // If the provider didn't create this object, then the object doesn't exist in the store.
  627. //
  628. if ( (GenericObject->PersistDirtyBits & AZ_DIRTY_CREATE) == 0 ) {
  629. //
  630. // Never delete cached objects if the persistence provider failed.
  631. // The provider may have bailed before processing the object.
  632. // If an object is abosultely clean, then we should just let it stay there.
  633. //
  634. if ( OpenFailed ) {
  635. goto Cleanup;
  636. }
  637. if ( ReconType == IsOpen ) {
  638. ASSERT( GenericObject->PersistDirtyBits & AZ_DIRTY_CREATE );
  639. }
  640. //
  641. // If the app didn't create this object either,
  642. // then the object should be deleted from the cache,
  643. // Unless it already has been marked for deletion.
  644. // This is also not marked for deletion if the children of AzApplication/AzScope
  645. // are being loaded into cache
  646. //
  647. // NOTE: other attributes might be dirty. This simply reflects the fact
  648. // that during reconciliation a delete overides a modification.
  649. //
  650. if ( (GenericObject->DirtyBits & AZ_DIRTY_CREATE) == 0 ) {
  651. //
  652. // Mark the entry (and its child objects) as deleted
  653. // We do this since other threads may have references to the objects.
  654. // We want to ensure those threads know the objects are deleted.
  655. //
  656. ObMarkObjectDeleted( GenericObject );
  657. GenericObject = NULL; // Don't reference this again
  658. goto Cleanup;
  659. }
  660. //
  661. // If the provider created this object,
  662. // and successfully set all of the attributes it knows about,
  663. // clean up the attributes.
  664. //
  665. } else if ((GenericObject->Flags & GENOBJ_FLAGS_PERSIST_OK) != 0 ) {
  666. //
  667. // Never bother updating objects if the persistence provider failed and this
  668. // is AzInitialize. We'll delete the attributes soon anyway.
  669. //
  670. if ( OpenFailed ) {
  671. goto Cleanup;
  672. }
  673. //
  674. // Compute the properties that were neither written by
  675. // the provider nor by the application.
  676. DirtyBits = 0xFFFFFFFF & (~GenericObject->DirtyBits) & (~GenericObject->PersistDirtyBits);
  677. //
  678. // All such properties should be set to their default value
  679. //
  680. WinStatus = ObSetPropertyToDefault( GenericObject, DirtyBits );
  681. if ( WinStatus != NO_ERROR ) {
  682. SavedWinStatus = WinStatus;
  683. AzPrint(( AZD_CRITICAL, "AzpPersistReconcile: Cannot refresh object: %ws %ld\n", GenericObject->ObjectName->ObjectName.String, WinStatus ));
  684. // Continue processing
  685. }
  686. //
  687. // Fix up all of the links from this object
  688. //
  689. // Walk all of the GenericObjectLists rooted on by this object
  690. //
  691. for ( GenericObjectList = GenericObject->GenericObjectLists;
  692. GenericObjectList != NULL;
  693. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  694. //
  695. // Reconcile this individual object list entry.
  696. //
  697. WinStatus = AzpPersistReconcileDeltaArray( GenericObject, GenericObjectList, ReconType );
  698. if ( WinStatus != NO_ERROR ) {
  699. SavedWinStatus = WinStatus;
  700. // ASSERT(FALSE);
  701. }
  702. }
  703. }
  704. Cleanup:
  705. //
  706. // If the object wasn't deleted,
  707. // clean it up.
  708. //
  709. if ( GenericObject != NULL ) {
  710. //
  711. // Clear any bits the provider left lying around
  712. //
  713. GenericObject->PersistDirtyBits = 0;
  714. GenericObject->Flags &= !GENOBJ_FLAGS_PERSIST_OK;
  715. //
  716. // Indicate whether the cache entry needs to be refreshed.
  717. //
  718. // If the provider didn't successfully update the cache,
  719. // leave the refresh bit alone.
  720. //
  721. // If the caller IsOpen,
  722. // we don't care since we'll be deleting the cache shortly.
  723. // If the caller IsUpdateCache,
  724. // we haven't changed the state one way or another.
  725. // The cache is guaranteed to not be worse than it was before. But that's
  726. // all we can say.
  727. // If the caller IsRefresh,
  728. // that bit was set when we were called so we leave it set.
  729. //
  730. if ( OpenFailed ) {
  731. /* Drop through */
  732. //
  733. // If we detected an error,
  734. // mark the item as needing refreshed since the current state of the cache is bogus.
  735. //
  736. } else if ( SavedWinStatus != NO_ERROR ) {
  737. GenericObject->Flags |= GENOBJ_FLAGS_REFRESH_ME;
  738. //
  739. // Otherwise, the cache entry is known to match the underlying store
  740. //
  741. } else {
  742. GenericObject->Flags &= ~GENOBJ_FLAGS_REFRESH_ME;
  743. }
  744. //
  745. // Free entries from the delta arrays that were added by the persist provider.
  746. //
  747. for ( GenericObjectList = GenericObject->GenericObjectLists;
  748. GenericObjectList != NULL;
  749. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  750. ObFreeDeltaArray( &GenericObjectList->DeltaArray, FALSE );
  751. }
  752. }
  753. return SavedWinStatus;
  754. }
  755. DWORD
  756. AzpPersistReconcile(
  757. IN PGENERIC_OBJECT GenericObject,
  758. IN RECONCILE_TYPE ReconType,
  759. IN BOOLEAN OpenFailed
  760. )
  761. /*++
  762. Routine Description:
  763. This routine reconciles any inconsistencies in the cache that were left around
  764. by the persistence provider during the initial population of the cache or
  765. during a periodic cache update.
  766. Examples, are given in the code below. However, the philosophy is the persistence
  767. providers shouldn't have to worry about ordering issues and naming issues. For instance,
  768. they should be able to link to objects that are not yet in the cache. They should
  769. be able to create an object with the same name as a deleted object.
  770. On entry, AzGlResource must be locked exclusive.
  771. Arguments:
  772. GenericObject - Specifies the object that is being queried
  773. ReconType - Specifies the routine that called the persistence provider
  774. OpenFailed - TRUE if the open call to the persistence provider failed.
  775. Return Value:
  776. NO_ERROR - The operation was successful
  777. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  778. Other status codes
  779. --*/
  780. {
  781. DWORD WinStatus;
  782. DWORD SavedWinStatus = NO_ERROR;
  783. PVOID EnumContext = NULL;
  784. PGENERIC_OBJECT NextGenericObject;
  785. BOOL FixMoreNames = TRUE;
  786. PNEW_OBJECT_NAME NewObjectName;
  787. PLIST_ENTRY ListEntry;
  788. PAZP_AZSTORE AzAuthorizationStore = GenericObject->AzStoreObject;
  789. //
  790. // Prepare to enumerate all of the objects in the cache
  791. //
  792. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  793. WinStatus = AzpPersistEnumOpen( GenericObject, &EnumContext );
  794. if ( WinStatus != NO_ERROR ) {
  795. SavedWinStatus = WinStatus;
  796. goto Cleanup;
  797. }
  798. //
  799. // If this call is from UpdateChildrenCache, we donot want to call AzpPersistReconcileOne
  800. // on the parent object, but only on its children
  801. //
  802. if ( ReconType == IsUpdateChildCache ) {
  803. WinStatus = AzpPersistEnumNext( EnumContext, &NextGenericObject );
  804. if ( WinStatus != NO_ERROR) {
  805. if ( WinStatus != ERROR_NO_MORE_ITEMS ) {
  806. SavedWinStatus = WinStatus;
  807. }
  808. goto Cleanup;
  809. }
  810. ASSERT( NextGenericObject == GenericObject );
  811. }
  812. //
  813. // Loop through each object
  814. //
  815. for (;;) {
  816. //
  817. // Get the next object
  818. //
  819. WinStatus = AzpPersistEnumNext( EnumContext, &NextGenericObject );
  820. if ( WinStatus != NO_ERROR) {
  821. if ( WinStatus != ERROR_NO_MORE_ITEMS ) {
  822. SavedWinStatus = WinStatus;
  823. }
  824. break;
  825. }
  826. //
  827. // Reconcile that one object
  828. //
  829. WinStatus = AzpPersistReconcileOne( NextGenericObject, ReconType, OpenFailed );
  830. if ( WinStatus != NO_ERROR ) {
  831. SavedWinStatus = WinStatus;
  832. AzPrint(( AZD_CRITICAL,
  833. "AzpPersistReconcile: Cannot reconcile object: %ws %ld %ld\n",
  834. NextGenericObject->ObjectName == NULL ? NULL : NextGenericObject->ObjectName->ObjectName.String,
  835. NextGenericObject->ObjectType,
  836. WinStatus ));
  837. // Continue processing
  838. }
  839. }
  840. //
  841. // Loop attempting to fix up any name conflicts.
  842. // Keep looping as long as a pass fixed at least one name
  843. //
  844. // Don't fix name comflicts if we're just cleaning up.
  845. //
  846. while ( ReconType != PreUpdateCache && FixMoreNames ) {
  847. FixMoreNames = FALSE;
  848. //
  849. // Loop handling each conflicting name
  850. //
  851. for ( ListEntry = AzAuthorizationStore->NewNames.Flink;
  852. ListEntry != &AzAuthorizationStore->NewNames;
  853. ) {
  854. NewObjectName = CONTAINING_RECORD( ListEntry,
  855. NEW_OBJECT_NAME,
  856. Next );
  857. // Entry might be deleted below
  858. ListEntry = ListEntry->Flink;
  859. //
  860. // Try to set the name
  861. //
  862. WinStatus = ObSetProperty(
  863. NewObjectName->GenericObject,
  864. AZP_FLAGS_RECONCILE,
  865. AZ_PROP_NAME,
  866. &NewObjectName->ObjectName );
  867. if ( WinStatus == NO_ERROR ) {
  868. ObFreeNewName( NewObjectName );
  869. FixMoreNames = TRUE;
  870. }
  871. }
  872. }
  873. //
  874. // If we couldn't fix all of the collided names,
  875. // return the problem to the caller.
  876. //
  877. if ( SavedWinStatus == NO_ERROR &&
  878. !IsListEmpty( &AzAuthorizationStore->NewNames ) ) {
  879. SavedWinStatus = ERROR_ALREADY_EXISTS;
  880. }
  881. Cleanup:
  882. if ( EnumContext != NULL ) {
  883. AzpPersistEnumClose( EnumContext );
  884. }
  885. //
  886. // Free the list of conflicting names
  887. //
  888. while ( !IsListEmpty( &AzAuthorizationStore->NewNames ) ) {
  889. ListEntry = RemoveHeadList( &AzAuthorizationStore->NewNames );
  890. NewObjectName = CONTAINING_RECORD( ListEntry,
  891. NEW_OBJECT_NAME,
  892. Next );
  893. ObFreeNewName( NewObjectName );
  894. }
  895. return SavedWinStatus;
  896. }
  897. //
  898. // List of providers that are built into azroles.dll
  899. //
  900. struct {
  901. LPWSTR PolicyUrlPrefix;
  902. AZ_PERSIST_PROVIDER_INITIALIZE ProviderInitRoutine;
  903. } AzGlInternalProviders[] = {
  904. #ifdef USE_INTERNAL_MSXML
  905. { AZ_XML_PROVIDER_NAME, XmlProviderInitialize },
  906. #endif // USE_INTERNAL_MSXML
  907. { AZ_AD_PROVIDER_NAME, AdProviderInitialize },
  908. };
  909. #define INTERNAL_PROVIDER_COUNT (sizeof(AzGlInternalProviders)/sizeof(AzGlInternalProviders[0]))
  910. DWORD
  911. AzpPersistDetermineProvider(
  912. IN PAZP_AZSTORE AzAuthorizationStore
  913. )
  914. /*++
  915. Routine Description:
  916. This routine determines which provider to use for a particular Policy URL.
  917. Arguments:
  918. AzAuthorizationStore - A pointer to the authorization store object the provider is needed for
  919. The PolicyUrl should already have been set.
  920. On successfull return, the ProviderInfo and ProviderDll will be properly set.
  921. Return Value:
  922. NO_ERROR - The operation was successful
  923. ERROR_INVALID_PARAMETER - The policy URL cannot identify the provider
  924. Other status codes
  925. --*/
  926. {
  927. DWORD WinStatus;
  928. ULONG Index;
  929. ULONG UrlPrefixLength;
  930. AZ_PERSIST_PROVIDER_INITIALIZE ProviderInitRoutine = NULL;
  931. PAZPE_PROVIDER_INFO ProviderInfo;
  932. LPWSTR PolicyUrl = AzAuthorizationStore->PolicyUrl.String;
  933. LPWSTR KeyName = NULL;
  934. HKEY KeyHandle = NULL;
  935. HMODULE DllHandle = NULL;
  936. //
  937. // Initialization
  938. //
  939. ASSERT( AzAuthorizationStore->PolicyUrl.String != NULL );
  940. ASSERT( AzAuthorizationStore->ProviderInfo == NULL );
  941. ASSERT( AzAuthorizationStore->ProviderDll == NULL );
  942. //
  943. // Loop through the internal providers finding the one specified
  944. //
  945. for ( Index=0; Index<INTERNAL_PROVIDER_COUNT; Index++ ) {
  946. UrlPrefixLength = (ULONG) wcslen(AzGlInternalProviders[Index].PolicyUrlPrefix);
  947. //
  948. // Check if the prefix of the provider matches the passed in URL
  949. //
  950. if (_wcsnicmp( AzGlInternalProviders[Index].PolicyUrlPrefix, PolicyUrl, UrlPrefixLength) == 0) {
  951. //
  952. // Ensure the next character is a :
  953. //
  954. if ( UrlPrefixLength == 0 || PolicyUrl[UrlPrefixLength] == L':' ) {
  955. ProviderInitRoutine = AzGlInternalProviders[Index].ProviderInitRoutine;
  956. break;
  957. }
  958. }
  959. }
  960. //
  961. // If we didn't find an internal provider,
  962. // load one
  963. //
  964. if ( ProviderInitRoutine == NULL ) {
  965. LPWSTR ColonPtr;
  966. ULONG KeyNameLen;
  967. DWORD ValueType;
  968. WCHAR ProviderDll[MAX_PATH+1];
  969. DWORD ProviderDllSize;
  970. //
  971. // Determin the length of the name of the registry key
  972. //
  973. ColonPtr = wcschr( PolicyUrl, L':' );
  974. if ( ColonPtr == NULL ) {
  975. WinStatus = ERROR_BAD_PROVIDER;
  976. goto Cleanup;
  977. }
  978. UrlPrefixLength = (ULONG)(ColonPtr - PolicyUrl);
  979. KeyNameLen = AZ_REGISTRY_PROVIDER_KEY_NAME_LEN +
  980. 1 +
  981. UrlPrefixLength +
  982. 1;
  983. //
  984. // Build the name of the registry key
  985. //
  986. SafeAllocaAllocate( KeyName, KeyNameLen * sizeof(WCHAR) );
  987. if ( KeyName == NULL ) {
  988. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  989. goto Cleanup;
  990. }
  991. RtlCopyMemory( KeyName, AZ_REGISTRY_PROVIDER_KEY_NAME, AZ_REGISTRY_PROVIDER_KEY_NAME_LEN * sizeof(WCHAR) );
  992. KeyName[AZ_REGISTRY_PROVIDER_KEY_NAME_LEN] = '\\';
  993. RtlCopyMemory( &KeyName[AZ_REGISTRY_PROVIDER_KEY_NAME_LEN+1],
  994. PolicyUrl,
  995. UrlPrefixLength*sizeof(WCHAR) );
  996. KeyName[AZ_REGISTRY_PROVIDER_KEY_NAME_LEN+1+UrlPrefixLength] = '\0';
  997. AzPrint(( AZD_PERSIST, "AzpPersistDetermineProvider: Open Provider reg key at 'HKLM\\%ws'\n", KeyName ));
  998. //
  999. // Open the registry key
  1000. //
  1001. WinStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1002. KeyName,
  1003. 0,
  1004. KEY_READ,
  1005. &KeyHandle );
  1006. if ( WinStatus != NO_ERROR ) {
  1007. AzPrint(( AZD_CRITICAL, "AzpPersistDetermineProvider: Cannot open Provider reg key at 'HKLM\\%ws' %ld\n", KeyName, WinStatus ));
  1008. if ( WinStatus == ERROR_FILE_NOT_FOUND ) {
  1009. WinStatus = ERROR_BAD_PROVIDER;
  1010. }
  1011. goto Cleanup;
  1012. }
  1013. //
  1014. // Read the name of the provider dll
  1015. //
  1016. ProviderDllSize = sizeof(ProviderDll);
  1017. WinStatus = RegQueryValueEx( KeyHandle,
  1018. AZ_REGISTRY_PROVIDER_DLL_VALUE_NAME,
  1019. NULL,
  1020. &ValueType,
  1021. (LPBYTE)ProviderDll,
  1022. &ProviderDllSize );
  1023. if ( WinStatus != NO_ERROR ) {
  1024. AzPrint(( AZD_CRITICAL,
  1025. "AzpPersistDetermineProvider: Cannot open Provider reg value at 'HKLM\\%ws\\%ws' %ld\n",
  1026. KeyName,
  1027. AZ_REGISTRY_PROVIDER_DLL_VALUE_NAME,
  1028. WinStatus ));
  1029. if ( WinStatus == ERROR_FILE_NOT_FOUND ) {
  1030. WinStatus = ERROR_BAD_PROVIDER;
  1031. }
  1032. goto Cleanup;
  1033. }
  1034. //
  1035. // Load the library
  1036. //
  1037. DllHandle = LoadLibrary( ProviderDll );
  1038. if ( DllHandle == NULL ) {
  1039. WinStatus = GetLastError();
  1040. AzPrint(( AZD_CRITICAL,
  1041. "AzpPersistDetermineProvider: Cannot load libary '%ws' %ld\n",
  1042. ProviderDll,
  1043. WinStatus ));
  1044. goto Cleanup;
  1045. }
  1046. //
  1047. // Get the address of the provider init routine
  1048. //
  1049. ProviderInitRoutine = (AZ_PERSIST_PROVIDER_INITIALIZE)
  1050. GetProcAddress( DllHandle, AZ_PERSIST_PROVIDER_INITIALIZE_NAME );
  1051. if ( ProviderInitRoutine == NULL ) {
  1052. WinStatus = GetLastError();
  1053. AzPrint(( AZD_CRITICAL,
  1054. "AzpPersistDetermineProvider: libary '%ws' does not export '%s': %ld\n",
  1055. ProviderDll,
  1056. AZ_PERSIST_PROVIDER_INITIALIZE_NAME,
  1057. WinStatus ));
  1058. goto Cleanup;
  1059. }
  1060. }
  1061. //
  1062. // A provider has been found
  1063. // Ask the provider for the provider info
  1064. //
  1065. WinStatus = ProviderInitRoutine( &AzGlAzrolesInfo, &ProviderInfo );
  1066. if ( WinStatus != NO_ERROR ) {
  1067. goto Cleanup;
  1068. }
  1069. //
  1070. // Ensure the provider info is a version we understand
  1071. //
  1072. if ( ProviderInfo->ProviderInfoVersion < AZPE_PROVIDER_INFO_VERSION_1 ) {
  1073. WinStatus = ERROR_UNKNOWN_REVISION;
  1074. goto Cleanup;
  1075. }
  1076. //
  1077. // Return the information to the caller
  1078. //
  1079. AzAuthorizationStore->ProviderInfo = ProviderInfo;
  1080. AzAuthorizationStore->ProviderDll = DllHandle;
  1081. DllHandle = NULL;
  1082. WinStatus = NO_ERROR;
  1083. //
  1084. // Free locally used resources
  1085. //
  1086. Cleanup:
  1087. SafeAllocaFree( KeyName );
  1088. if ( KeyHandle != NULL ) {
  1089. RegCloseKey( KeyHandle );
  1090. }
  1091. if ( DllHandle != NULL ) {
  1092. FreeLibrary( DllHandle );
  1093. }
  1094. return WinStatus;
  1095. }
  1096. DWORD
  1097. AzPersistOpen(
  1098. IN PAZP_AZSTORE AzAuthorizationStore,
  1099. IN BOOL CreatePolicy
  1100. )
  1101. /*++
  1102. Routine Description:
  1103. This routine open the authz policy database.
  1104. This routine also reads the policy database into cache.
  1105. On Success, the caller should call AzPersistClose to free any resources
  1106. consumed by the open.
  1107. This routine routes the request to the correct provider.
  1108. On entry, AzGlResource must be locked exclusive.
  1109. This routine temporarily drops the AzGlResource while waiting for updates to complete.
  1110. Arguments:
  1111. AzAuthorizationStore - Specifies the policy database that is to be read.
  1112. CreatePolicy - TRUE if the policy database is to be created.
  1113. FALSE if the policy database already exists
  1114. Return Value:
  1115. NO_ERROR - The operation was successful
  1116. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1117. ERROR_ALREADY_EXISTS - CreatePolicy is TRUE and the policy already exists
  1118. ERROR_FILE_NOT_FOUND - CreatePolicy is FALSE and the policy does not already exist
  1119. Other status codes
  1120. --*/
  1121. {
  1122. DWORD WinStatus;
  1123. DWORD TempWinStatus;
  1124. DWORD lPersistFlags;
  1125. BOOLEAN CritSectLocked = FALSE;
  1126. BOOLEAN ResourceLocked = TRUE;
  1127. LPWSTR pwszTargetMachine=NULL;
  1128. //
  1129. // Compute the flags
  1130. //
  1131. lPersistFlags = AZPE_FLAGS_PERSIST_OPEN;
  1132. //
  1133. // Drop the global crit sect across the call to the provider to ensure on
  1134. // UpdateCache that it doesn't lock out AccessCheck calls while it hits the wire
  1135. //
  1136. // Grab the Persistence crit sect maintaining locking order
  1137. //
  1138. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1139. AzpUnlockResource( &AzGlResource );
  1140. ResourceLocked = FALSE;
  1141. SafeEnterCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1142. CritSectLocked = TRUE;
  1143. //
  1144. // Determine which provider to use
  1145. //
  1146. WinStatus = AzpPersistDetermineProvider( AzAuthorizationStore );
  1147. if ( WinStatus != NO_ERROR ) {
  1148. goto Cleanup;
  1149. }
  1150. //
  1151. // Call the appropriate provider
  1152. //
  1153. WinStatus = AzAuthorizationStore->ProviderInfo->AzPersistOpen(
  1154. AzAuthorizationStore->PolicyUrl.String,
  1155. (AZPE_OBJECT_HANDLE)AzAuthorizationStore,
  1156. lPersistFlags,
  1157. CreatePolicy,
  1158. &AzAuthorizationStore->PersistContext,
  1159. &pwszTargetMachine );
  1160. if ( WinStatus == NO_ERROR &&
  1161. pwszTargetMachine ) {
  1162. //
  1163. // target machine name is returned
  1164. // add it to the authorization store object, which will be freed when
  1165. // authorization store object is freed
  1166. //
  1167. AzpInitString(&AzAuthorizationStore->TargetMachine, pwszTargetMachine);
  1168. }
  1169. //
  1170. // Restore the lock now that we're out of the provider
  1171. //
  1172. AzpLockResourceExclusive( &AzGlResource );
  1173. ResourceLocked = TRUE;
  1174. //
  1175. // Ensure the provider set the version
  1176. //
  1177. if ( WinStatus == NO_ERROR ) {
  1178. ASSERT( (((PGENERIC_OBJECT)AzAuthorizationStore)->PersistDirtyBits & (AZ_DIRTY_AZSTORE_MAJOR_VERSION | AZ_DIRTY_AZSTORE_MINOR_VERSION)) == (AZ_DIRTY_AZSTORE_MAJOR_VERSION | AZ_DIRTY_AZSTORE_MINOR_VERSION) );
  1179. }
  1180. //
  1181. // If we didn't create the underlying store,
  1182. // Turn off the dirty bits.
  1183. // (AZ_DIRTY_CREATE was set when the object was created. But the object really isn't dirty.)
  1184. //
  1185. if ( !CreatePolicy ) {
  1186. AzAuthorizationStore->GenericObject.DirtyBits = 0;
  1187. }
  1188. else
  1189. {
  1190. //
  1191. // Major and minor versions are not to be set externally. But they always need
  1192. // to be persisted in the authorization store object. We thus set these bits dirty.
  1193. // This will make sure that these two properties are persisted upon submit.
  1194. //
  1195. ((PGENERIC_OBJECT)AzAuthorizationStore)->DirtyBits |=
  1196. (AZ_DIRTY_AZSTORE_MAJOR_VERSION | AZ_DIRTY_AZSTORE_MINOR_VERSION);
  1197. }
  1198. //
  1199. // Now that the entire cache has been updated from the store
  1200. // fix up any issues in the cache.
  1201. //
  1202. TempWinStatus = AzpPersistReconcile( (PGENERIC_OBJECT)AzAuthorizationStore, IsOpen, WinStatus != NO_ERROR );
  1203. if ( WinStatus == NO_ERROR ) {
  1204. WinStatus = TempWinStatus;
  1205. }
  1206. //
  1207. // If we created the store,
  1208. // set the default AZ_PROP_APPLY_STORE_SACL based on whether the caller has the privilege
  1209. //
  1210. if ( CreatePolicy ) {
  1211. AzAuthorizationStore->GenericObject.ApplySacl = AzAuthorizationStore->HasSecurityPrivilege;
  1212. }
  1213. Cleanup:
  1214. if ( !ResourceLocked ) {
  1215. AzpLockResourceExclusive( &AzGlResource );
  1216. }
  1217. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1218. if ( CritSectLocked ) {
  1219. SafeLeaveCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1220. }
  1221. return WinStatus;
  1222. }
  1223. DWORD
  1224. AzPersistUpdateCache(
  1225. IN PAZP_AZSTORE AzAuthorizationStore
  1226. )
  1227. /*++
  1228. Routine Description:
  1229. This routine updates the cache to reflect the current authz policy database.
  1230. This routine routes the request to the correct provider.
  1231. On entry, AzGlResource must be locked exclusive.
  1232. This routine temporarily drops the AzGlResource while waiting for other updates to complete.
  1233. Arguments:
  1234. AzAuthorizationStore - Specifies the policy database that is to be read.
  1235. Return Value:
  1236. NO_ERROR - The operation was successful
  1237. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1238. ERROR_ALREADY_EXISTS - CreatePolicy is TRUE and the policy already exists
  1239. ERROR_FILE_NOT_FOUND - CreatePolicy is FALSE and the policy does not already exist
  1240. Other status codes
  1241. --*/
  1242. {
  1243. DWORD WinStatus;
  1244. DWORD TempWinStatus = NO_ERROR;
  1245. BOOLEAN CritSectLocked = FALSE;
  1246. //
  1247. // Provider decides what to update. It passes back that information
  1248. // via the flag.
  1249. //
  1250. ULONG ulEffectiveUpdateFlag = 0;
  1251. //
  1252. // Walk the cache cleaning up from any previous failed attempt.
  1253. //
  1254. WinStatus = AzpPersistReconcile( (PGENERIC_OBJECT)AzAuthorizationStore, PreUpdateCache, TRUE );
  1255. if ( WinStatus != NO_ERROR ) {
  1256. goto Cleanup;
  1257. }
  1258. //
  1259. // Drop the global crit sect across the call to the provider to ensure on
  1260. // UpdateCache that it doesn't lock out AccessCheck calls while it hits the wire
  1261. //
  1262. // Grab the Persistence crit sect maintaining locking order
  1263. //
  1264. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1265. AzpUnlockResource( &AzGlResource );
  1266. SafeEnterCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1267. CritSectLocked = TRUE;
  1268. //
  1269. // Call the appropriate provider
  1270. // The peristence provider will drop
  1271. //
  1272. WinStatus = AzAuthorizationStore->ProviderInfo->AzPersistUpdateCache(
  1273. AzAuthorizationStore->PersistContext,
  1274. AZPE_FLAGS_PERSIST_UPDATE_CACHE,
  1275. &ulEffectiveUpdateFlag);
  1276. //
  1277. // Restore the lock now that we're out of the provider
  1278. //
  1279. AzpLockResourceExclusive( &AzGlResource );
  1280. //
  1281. // Now that the entire cache has been updated from the store
  1282. // If the store has been deleted, ERROR_FILE_NOT_FOUND is returned. In this case,
  1283. // the cache needs to cleaned up completely.
  1284. // fix up any issues in the cache.
  1285. //
  1286. if ( (AZPE_FLAG_CACHE_UPDATE_STORE_LEVEL & ulEffectiveUpdateFlag) || (WinStatus != NO_ERROR) )
  1287. {
  1288. TempWinStatus = AzpPersistReconcile( (PGENERIC_OBJECT)AzAuthorizationStore, IsUpdateCache,
  1289. (WinStatus != NO_ERROR &&
  1290. WinStatus != ERROR_FILE_NOT_FOUND) );
  1291. }
  1292. if ( WinStatus == NO_ERROR ) {
  1293. WinStatus = TempWinStatus;
  1294. }
  1295. Cleanup:
  1296. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1297. if ( CritSectLocked ) {
  1298. SafeLeaveCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1299. }
  1300. return WinStatus;
  1301. }
  1302. DWORD
  1303. AzPersistUpdateChildrenCache(
  1304. IN OUT PGENERIC_OBJECT GenericObject
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine updates the child objects (upto one level) under the object specified.
  1309. The request is routed to the relevant provider.
  1310. On entry, the global resource must be locked exclusive
  1311. Arguments:
  1312. GenericObject - Object whose children need to be updated (one-level only)
  1313. Return Value:
  1314. NO_ERROR - The operation was successful
  1315. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1316. Other status codes
  1317. --*/
  1318. {
  1319. DWORD WinStatus = 0;
  1320. DWORD TempWinStatus = 0;
  1321. BOOLEAN bCritSectLocked = FALSE;
  1322. PAZP_AZSTORE AzAuthorizationStore = (PAZP_AZSTORE) GenericObject->AzStoreObject;
  1323. //
  1324. // Validate that the provider supports lazy load
  1325. //
  1326. ASSERT( AzAuthorizationStore->ProviderInfo->ProviderInfoVersion >= AZPE_PROVIDER_INFO_VERSION_2 );
  1327. //
  1328. // If the parent object has not been submitted as yet, then no children exist for it.
  1329. // Simply return NO_ERROR
  1330. //
  1331. if ( (GenericObject->DirtyBits & AZ_DIRTY_CREATE) != 0 ) {
  1332. return NO_ERROR;
  1333. }
  1334. WinStatus = AzpPersistReconcile( GenericObject, PreUpdateCache, TRUE );
  1335. if ( WinStatus != NO_ERROR ) {
  1336. goto Cleanup;
  1337. }
  1338. AzpUnlockResource( &AzGlResource );
  1339. //
  1340. // Grab the Persistence crit sect maintaining locking order
  1341. //
  1342. SafeEnterCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1343. bCritSectLocked = TRUE;
  1344. //
  1345. // If the children have already been loaded by another thread, then
  1346. // skip this
  1347. //
  1348. if ( GenericObject->AreChildrenLoaded ) {
  1349. //
  1350. // Grab the lock back
  1351. //
  1352. AzpLockResourceExclusive( &AzGlResource );
  1353. goto Cleanup;
  1354. }
  1355. //
  1356. // Call the appropriate provider
  1357. //
  1358. WinStatus = AzAuthorizationStore->ProviderInfo->AzPersistUpdateChildrenCache(
  1359. AzAuthorizationStore->PersistContext,
  1360. (AZPE_OBJECT_HANDLE) GenericObject,
  1361. AZPE_FLAGS_PERSIST_UPDATE_CHILDREN_CACHE );
  1362. //
  1363. // Restore the lock, now that we are out of the provider
  1364. //
  1365. AzpLockResourceExclusive( &AzGlResource );
  1366. if ( WinStatus == NO_ERROR ) {
  1367. //
  1368. // Set the flag on the generic object that its children have been loaded
  1369. // and this object is no longer closed
  1370. //
  1371. GenericObject->AreChildrenLoaded = TRUE;
  1372. GenericObject->ObjectClosed = FALSE;
  1373. }
  1374. //
  1375. // Now that the cache has been updated from the store
  1376. // fix up any issues in the cache.
  1377. //
  1378. TempWinStatus = AzpPersistReconcile( GenericObject, IsUpdateChildCache, WinStatus != NO_ERROR );
  1379. if ( WinStatus == NO_ERROR ) {
  1380. WinStatus = TempWinStatus;
  1381. }
  1382. Cleanup:
  1383. if ( bCritSectLocked ) {
  1384. SafeLeaveCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1385. }
  1386. return WinStatus;
  1387. }
  1388. VOID
  1389. AzPersistClose(
  1390. IN PAZP_AZSTORE AzAuthorizationStore
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This routine closes the authz policy database storage handles.
  1395. This routine routes the request to the correct provider.
  1396. On entry, AzGlResource must be locked exclusive.
  1397. Arguments:
  1398. AzAuthorizationStore - Specifies the policy database that is to be read.
  1399. Return Value:
  1400. None
  1401. --*/
  1402. {
  1403. //
  1404. // If the store wasn't successfully opened,
  1405. // we're done.
  1406. if ( AzAuthorizationStore->PersistContext == NULL ) {
  1407. return;
  1408. }
  1409. //
  1410. // Grab the persist engine crit sect maintaining locking order
  1411. //
  1412. // The provider uses PersistCritSect to serialize access to many of its structures.
  1413. //
  1414. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1415. AzpUnlockResource( &AzGlResource );
  1416. SafeEnterCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1417. AzpLockResourceExclusive( &AzGlResource );
  1418. //
  1419. // Call the appropriate provider
  1420. //
  1421. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1422. AzAuthorizationStore->ProviderInfo->AzPersistClose( AzAuthorizationStore->PersistContext );
  1423. AzAuthorizationStore->PersistContext = NULL;
  1424. SafeLeaveCriticalSection( &AzAuthorizationStore->PersistCritSect );
  1425. }
  1426. DWORD
  1427. AzPersistSubmit(
  1428. IN PGENERIC_OBJECT GenericObject,
  1429. IN BOOLEAN DeleteMe
  1430. )
  1431. /*++
  1432. Routine Description:
  1433. This routine submits changes made to the authz policy database.
  1434. This routine routes the request to the correct provider.
  1435. If the object is being created, the GenericObject->PersistenceGuid field will be
  1436. zero on input. Upon successful creation, this routine will set PersistenceGuid to
  1437. non-zero. Upon failed creation, this routine will leave PersistenceGuid as zero.
  1438. On entry, AzGlResource must be locked exclusive.
  1439. This routine temporarily drops the AzGlResource while waiting for updates to complete.
  1440. Arguments:
  1441. GenericObject - Specifies the object in the database that is to be updated
  1442. in the underlying store.
  1443. DeleteMe - TRUE if the object and all of its children are to be deleted.
  1444. FALSE if the object is to be updated.
  1445. Return Value:
  1446. NO_ERROR - The operation was successful
  1447. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1448. Other status codes
  1449. --*/
  1450. {
  1451. DWORD WinStatus = NO_ERROR;
  1452. PGENERIC_OBJECT_LIST GenericObjectList;
  1453. //
  1454. // Grab the persist engine crit sect maintaining locking order
  1455. //
  1456. // The PersistCritSect must be locked since we want to ensure that AzpPersistReconcile
  1457. // doesn't have to deal with a changing database.
  1458. //
  1459. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1460. AzpUnlockResource( &AzGlResource );
  1461. SafeEnterCriticalSection( &GenericObject->AzStoreObject->PersistCritSect );
  1462. AzpLockResourceExclusive( &AzGlResource );
  1463. //
  1464. // Only persist dirty objects
  1465. //
  1466. if ( GenericObject->DirtyBits != 0 ||
  1467. DeleteMe ) {
  1468. //
  1469. // Call the appropriate provider
  1470. //
  1471. WinStatus = GenericObject->AzStoreObject->ProviderInfo->AzPersistSubmit(
  1472. GenericObject->AzStoreObject->PersistContext,
  1473. (AZPE_OBJECT_HANDLE)GenericObject,
  1474. AZPE_FLAGS_PERSIST_SUBMIT,
  1475. DeleteMe );
  1476. if ( WinStatus != NO_ERROR ) {
  1477. //
  1478. // Submit somehow fails, we need to remember that we are not in good
  1479. // shape with the store. So any access should refresh it.
  1480. //
  1481. GenericObject->Flags |= GENOBJ_FLAGS_REFRESH_ME;
  1482. goto Cleanup;
  1483. }
  1484. //
  1485. // Ensure the provider created a GUID
  1486. //
  1487. if ( (GenericObject->DirtyBits & AZ_DIRTY_CREATE) != 0 &&
  1488. GenericObject->ObjectType != OBJECT_TYPE_AZAUTHSTORE &&
  1489. !DeleteMe ) {
  1490. ASSERT( !IsEqualGUID( GenericObject->PersistenceGuid, AzGlZeroGuid ) );
  1491. }
  1492. //
  1493. // Ensure the provider didn't change the cache.
  1494. //
  1495. ASSERT( GenericObject->PersistDirtyBits == 0 );
  1496. //
  1497. // Clean up the list of deltas
  1498. //
  1499. // Walk all of the GenericObjectLists rooted on by this object
  1500. //
  1501. for ( GenericObjectList = GenericObject->GenericObjectLists;
  1502. GenericObjectList != NULL;
  1503. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  1504. //
  1505. // If there is a list of deltas,
  1506. // delete it
  1507. //
  1508. if ( GenericObjectList->DeltaArray.UsedCount != 0 ) {
  1509. ASSERT( !GenericObjectList->IsBackLink );
  1510. ASSERT( (GenericObject->DirtyBits & GenericObjectList->DirtyBit) != 0 );
  1511. ObFreeDeltaArray( &GenericObjectList->DeltaArray, TRUE );
  1512. }
  1513. }
  1514. //
  1515. // Turn off the dirty bits
  1516. //
  1517. GenericObject->DirtyBits = 0;
  1518. }
  1519. Cleanup:
  1520. SafeLeaveCriticalSection( &GenericObject->AzStoreObject->PersistCritSect );
  1521. return WinStatus;
  1522. }
  1523. VOID
  1524. AzPersistAbort(
  1525. IN PGENERIC_OBJECT GenericObject
  1526. )
  1527. /*++
  1528. Routine Description:
  1529. This routine aborts changes made to the authz policy database.
  1530. This routine routes the request to the correct provider.
  1531. On entry, AzGlResource must be locked exclusive.
  1532. Arguments:
  1533. GenericObject - Specifies the object in the database that is to be updated
  1534. in the underlying store.
  1535. Return Value:
  1536. NO_ERROR - The operation was successful
  1537. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1538. Other status codes
  1539. --*/
  1540. {
  1541. PGENERIC_OBJECT_LIST GenericObjectList;
  1542. BOOLEAN WasCreated;
  1543. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1544. //
  1545. // Clean up the list of deltas
  1546. // ... The changes where aborted.
  1547. //
  1548. // Walk all of the GenericObjectLists rooted on by this object
  1549. //
  1550. for ( GenericObjectList = GenericObject->GenericObjectLists;
  1551. GenericObjectList != NULL;
  1552. GenericObjectList = GenericObjectList->NextGenericObjectList ) {
  1553. //
  1554. // If there is a list of deltas,
  1555. // delete it
  1556. //
  1557. if ( GenericObjectList->DeltaArray.UsedCount != 0 ) {
  1558. ASSERT( !GenericObjectList->IsBackLink );
  1559. ASSERT( (GenericObject->DirtyBits & GenericObjectList->DirtyBit) != 0 );
  1560. ObFreeDeltaArray( &GenericObjectList->DeltaArray, TRUE );
  1561. }
  1562. }
  1563. //
  1564. // Turn off the dirty bits
  1565. // ... The changes where aborted.
  1566. //
  1567. WasCreated = (( GenericObject->DirtyBits & AZ_DIRTY_CREATE ) != 0);
  1568. GenericObject->DirtyBits = 0;
  1569. //
  1570. // Update the cache to match the real object
  1571. //
  1572. // If we were trying to persist a creation of the object,
  1573. // delete the object from the cache.
  1574. //
  1575. if ( WasCreated ) {
  1576. //
  1577. // Mark the entry (and its child objects) as deleted
  1578. // We do this since other threads may have references to the objects.
  1579. // We want to ensure those threads know the objects are deleted.
  1580. //
  1581. ObMarkObjectDeleted( GenericObject );
  1582. } else {
  1583. //
  1584. // Refresh the cache
  1585. // Ignore the status code
  1586. //
  1587. (VOID) AzPersistRefresh( GenericObject );
  1588. }
  1589. }
  1590. DWORD
  1591. AzPersistRefresh(
  1592. IN PGENERIC_OBJECT GenericObject
  1593. )
  1594. /*++
  1595. Routine Description:
  1596. This routine updates the attributes of the object from the policy database.
  1597. This routine routes the request to the correct provider.
  1598. On entry, AzGlResource must be locked exclusive.
  1599. Arguments:
  1600. GenericObject - Specifies the object in the database whose cache entry is to be
  1601. updated
  1602. The GenericObject->PersistenceGuid field should be non-zero on input.
  1603. Return Value:
  1604. NO_ERROR - The operation was successful
  1605. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1606. Other status codes
  1607. --*/
  1608. {
  1609. DWORD WinStatus;
  1610. DWORD TempWinStatus;
  1611. //
  1612. // Grab the persist engine crit sect maintaining locking order
  1613. //
  1614. // The PersistCritSect must be locked since we want to ensure that AzpPersistReconcile
  1615. // doesn't have to deal with a changing database.
  1616. //
  1617. ASSERT( AzpIsLockedExclusive( &AzGlResource ) );
  1618. AzpUnlockResource( &AzGlResource );
  1619. SafeEnterCriticalSection( &GenericObject->AzStoreObject->PersistCritSect );
  1620. //
  1621. // Mark the object that it needs to be refreshed
  1622. // so that it'll be refreshed later if we're not successful this time
  1623. //
  1624. GenericObject->Flags |= GENOBJ_FLAGS_REFRESH_ME;
  1625. //
  1626. // Clear any bits the provider left lying around
  1627. //
  1628. GenericObject->PersistDirtyBits = 0;
  1629. GenericObject->Flags &= !GENOBJ_FLAGS_PERSIST_OK;
  1630. //
  1631. // Call the appropriate provider
  1632. //
  1633. WinStatus = GenericObject->AzStoreObject->ProviderInfo->AzPersistRefresh(
  1634. GenericObject->AzStoreObject->PersistContext,
  1635. (AZPE_OBJECT_HANDLE)GenericObject,
  1636. AZPE_FLAGS_PERSIST_REFRESH );
  1637. // Provider should return WinStatus
  1638. // ASSERT( SUCCEEDED(WinStatus) );
  1639. //
  1640. // Restore the lock now that we're out of the provider
  1641. //
  1642. AzpLockResourceExclusive( &AzGlResource );
  1643. //
  1644. // If the provider couldn't find the object,
  1645. // that's OK. Reconcile will delete the cache entry.
  1646. //
  1647. if ( WinStatus == ERROR_NOT_FOUND ) {
  1648. WinStatus = NO_ERROR;
  1649. }
  1650. //
  1651. // Reconcile this one object
  1652. //
  1653. TempWinStatus = AzpPersistReconcileOne(
  1654. GenericObject,
  1655. IsRefresh,
  1656. WinStatus != NO_ERROR ); // Operation status
  1657. if ( TempWinStatus != NO_ERROR ) {
  1658. if ( WinStatus == NO_ERROR ) {
  1659. WinStatus = TempWinStatus;
  1660. }
  1661. AzPrint(( AZD_CRITICAL, "AzpPersistReconcile: Cannot reconcile object: %ws %ld\n", GenericObject->ObjectName->ObjectName.String, TempWinStatus ));
  1662. // Continue processing
  1663. }
  1664. SafeLeaveCriticalSection( &GenericObject->AzStoreObject->PersistCritSect );
  1665. return WinStatus;
  1666. }
  1667. DWORD
  1668. WINAPI
  1669. AzSubmit(
  1670. IN AZ_HANDLE AzHandle,
  1671. IN DWORD Flags,
  1672. IN DWORD Reserved
  1673. )
  1674. /*++
  1675. Routine Description:
  1676. Submit the changes made to the object via the *Create, *SetProperty, or *SetPropertyItem
  1677. APIs.
  1678. On failure, any changes made to the object are undone.
  1679. Arguments:
  1680. AzHandle - Passes in the handle to be updated.
  1681. Flags - Specifies flags that control the behavior of AzInitialize
  1682. AZ_SUBMIT_FLAG_ABORT: Abort the operation instead of commiting it
  1683. Reserved - Reserved. Must by zero.
  1684. Return Value:
  1685. NO_ERROR - The operation was successful.
  1686. ERROR_INVALID_HANDLE - The passed in handle was invalid
  1687. --*/
  1688. {
  1689. DWORD WinStatus;
  1690. PGENERIC_OBJECT ReferencedGenericObject = NULL;
  1691. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT) AzHandle;
  1692. DWORD ObjectType;
  1693. //
  1694. // Grab the global lock
  1695. // Only for the authorization store case do we modify anything.
  1696. //
  1697. AzpLockResourceExclusive( &AzGlResource );
  1698. //
  1699. // Validate the input parameters
  1700. //
  1701. if ( Reserved != 0 ) {
  1702. AzPrint(( AZD_INVPARM, "AzCloseHandle: Reserved != 0\n" ));
  1703. WinStatus = ERROR_INVALID_PARAMETER;
  1704. goto Cleanup;
  1705. }
  1706. //
  1707. // Determine the type of the object
  1708. //
  1709. WinStatus = ObGetHandleType( GenericObject,
  1710. FALSE, // Don't allow deleted objects
  1711. &ObjectType );
  1712. if ( WinStatus != NO_ERROR ) {
  1713. goto Cleanup;
  1714. }
  1715. //
  1716. // Validate the passed in handle
  1717. //
  1718. WinStatus = ObReferenceObjectByHandle( GenericObject,
  1719. FALSE, // Don't allow deleted objects
  1720. TRUE, // Refresh the cache
  1721. ObjectType );
  1722. if ( WinStatus != NO_ERROR ) {
  1723. goto Cleanup;
  1724. }
  1725. ReferencedGenericObject = GenericObject;
  1726. //
  1727. // If we've been asked to abort the changes,
  1728. // do so
  1729. //
  1730. if ( Flags & AZ_SUBMIT_FLAG_ABORT ) {
  1731. //
  1732. // Call the worker routine to abort the operation
  1733. //
  1734. AzPersistAbort( GenericObject );
  1735. //
  1736. // Submit the changes
  1737. //
  1738. } else {
  1739. //
  1740. // Submit the change
  1741. // On failure, leave the object dirty
  1742. //
  1743. WinStatus = AzPersistSubmit( GenericObject, FALSE );
  1744. if ( WinStatus != NO_ERROR ) {
  1745. goto Cleanup;
  1746. }
  1747. }
  1748. WinStatus = NO_ERROR;
  1749. //
  1750. // Free locally used resources
  1751. //
  1752. Cleanup:
  1753. if ( ReferencedGenericObject != NULL ) {
  1754. ObDereferenceObject( ReferencedGenericObject );
  1755. }
  1756. //
  1757. // Drop the global lock
  1758. //
  1759. AzpUnlockResource( &AzGlResource );
  1760. return WinStatus;
  1761. }
  1762. //
  1763. // Various functions that are callable by the provider.
  1764. // These Azpe* routines are the only routines callable by the provider.
  1765. // They are typically thin wrappers around other routines in the core.
  1766. //
  1767. DWORD
  1768. AzpeCreateObject(
  1769. IN AZPE_OBJECT_HANDLE AzpeParentHandle,
  1770. IN ULONG ChildObjectType,
  1771. IN LPCWSTR ChildObjectNameString,
  1772. IN GUID *ChildObjectGuid,
  1773. IN ULONG lPersistFlags,
  1774. OUT AZPE_OBJECT_HANDLE *AzpeChildHandle
  1775. )
  1776. /*++
  1777. Routine Description:
  1778. The provider should call AzpeCreateObject to create an object in the AzRoles object cache.
  1779. It should only be called from a thread processing a call to AzPersistOpen,
  1780. AzPersistUpdateCache, AzPersistUpdateChildrenCache or AzPersistRefresh.
  1781. Arguments:
  1782. AzpeParentHandle - Specifies a handle to the object that is the parent of the object
  1783. to create.
  1784. ChildObjectType - Specifies the type of the object to create. This should be one
  1785. of the OBJECT_TYPE_* defines. See the section entitled AzpeObjectType for a
  1786. list of valid object types. OBJECT_TYPE_AZAUTHSTORE is not valid.
  1787. ChildObjectNameString - Specifies the name of the object to create.
  1788. ChildObjectGuid - Specifies the Persistence Guid of the object to create.
  1789. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  1790. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  1791. AzpeChildHandle - On success, returns a handle to the newly created object.
  1792. The provider must call AzpeObjectFinished to close this handle.
  1793. Return Value:
  1794. NO_ERROR - The operation was successful
  1795. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1796. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  1797. --*/
  1798. {
  1799. DWORD WinStatus;
  1800. PGENERIC_OBJECT ParentGenericObject = (PGENERIC_OBJECT)AzpeParentHandle;
  1801. PGENERIC_OBJECT_HEAD GenericChildHead;
  1802. AZP_STRING ChildObjectName;
  1803. //
  1804. // Ensure the provider didn't pass bogus parameters
  1805. //
  1806. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_OPEN_MASK) != 0) {
  1807. ASSERT( FALSE );
  1808. return ERROR_INVALID_FLAGS;
  1809. }
  1810. if ( ChildObjectType >= OBJECT_TYPE_COUNT ) {
  1811. ASSERT( ChildObjectType < OBJECT_TYPE_COUNT );
  1812. return ERROR_INVALID_PARAMETER;
  1813. }
  1814. //
  1815. // Initialization
  1816. //
  1817. AzpLockResourceExclusive( &AzGlResource );
  1818. AzpInitString( &ChildObjectName, ChildObjectNameString );
  1819. //
  1820. // Find child object head data structure from parent object
  1821. //
  1822. for ( GenericChildHead = ParentGenericObject->ChildGenericObjectHead;
  1823. GenericChildHead != NULL;
  1824. GenericChildHead = GenericChildHead->SiblingGenericObjectHead ) {
  1825. if ( GenericChildHead->ObjectType == ChildObjectType ) {
  1826. //
  1827. // Found object type head
  1828. //
  1829. break;
  1830. }
  1831. }
  1832. if ( GenericChildHead == NULL ) {
  1833. WinStatus = ERROR_INVALID_PARAMETER;
  1834. AzPrint(( AZD_INVPARM,
  1835. "AzpeCreateObject: Cannot find Object Head: %ld: %ld\n",
  1836. ParentGenericObject->ObjectType,
  1837. ChildObjectType ));
  1838. goto Cleanup;
  1839. }
  1840. //
  1841. // Actually create the object
  1842. //
  1843. WinStatus = ObCreateObject(
  1844. ParentGenericObject,
  1845. GenericChildHead,
  1846. ChildObjectType,
  1847. &ChildObjectName,
  1848. ChildObjectGuid,
  1849. lPersistFlags | AZP_FLAGS_BY_GUID,
  1850. (PGENERIC_OBJECT *)AzpeChildHandle );
  1851. Cleanup:
  1852. AzpUnlockResource( &AzGlResource );
  1853. return WinStatus;
  1854. }
  1855. DWORD
  1856. AzpeSetProperty(
  1857. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  1858. IN ULONG lPersistFlags,
  1859. IN ULONG PropertyId,
  1860. IN PVOID PropertyValue
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. The provider should call AzpeSetProperty to set the value of a scalar property
  1865. in the AzRoles object cache. It should only be called from a thread processing
  1866. a call to AzPersistOpen, AzPersistUpdateCache, AzPersistUpdateChildrenCache or
  1867. AzPersistRefresh.
  1868. This operation is silently ignored if the application has already modified this
  1869. property and has not yet submitted the change.
  1870. The provider should not call AzpeSetProperty for values that it hasn't actually stored.
  1871. That is, the provider should make no assumption about the default values of the properties.
  1872. AzpeSetProperty does not bounds check, length check, or value check the PropertyValue.
  1873. The provider maintains the definitive copy of the authorization policy. AzRoles
  1874. simply maintains a cache of that authorization policy.
  1875. Arguments:
  1876. AzpeObjectHandle - Specifies a handle to the object.
  1877. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  1878. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  1879. PropertyId - Specifies the property ID of the property to set. This should be one of
  1880. the AZ_PROP_* defines. See the section entitled PropertyId parameter for a list
  1881. of valid values.
  1882. PropertyValue - Specifies a pointer to the buffer containing the property.
  1883. For properties that are strings, the pointer is of type LPWSTR.
  1884. For properties that are LONGs, the pointer is of type PULONG.
  1885. For properties that are Booleans, the pointer is of type PBOOL.
  1886. Return Value:
  1887. NO_ERROR - The operation was successful
  1888. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  1889. ERROR_INVALID_PARAMETER - Property ID is invalid
  1890. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  1891. --*/
  1892. {
  1893. DWORD WinStatus;
  1894. PGENERIC_OBJECT_LIST GenericObjectList;
  1895. ULONG ObjectType;
  1896. //
  1897. // Ensure the provider didn't pass bogus flags
  1898. //
  1899. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_OPEN_MASK) != 0) {
  1900. ASSERT( FALSE );
  1901. return ERROR_INVALID_FLAGS;
  1902. }
  1903. //
  1904. // Ensure the provider is only getting a scalar property
  1905. //
  1906. WinStatus = ObMapPropIdToObjectList(
  1907. (PGENERIC_OBJECT)AzpeObjectHandle,
  1908. PropertyId,
  1909. &GenericObjectList,
  1910. &ObjectType );
  1911. if ( WinStatus == NO_ERROR ) {
  1912. AzPrint(( AZD_INVPARM, "AzpeSetProperty: Property ID for non-scalar: %ld\n", PropertyId ));
  1913. return ERROR_INVALID_PARAMETER;
  1914. }
  1915. //
  1916. // Actually set the property
  1917. //
  1918. AzpLockResourceExclusive( &AzGlResource );
  1919. WinStatus = ObSetProperty(
  1920. (PGENERIC_OBJECT)AzpeObjectHandle,
  1921. lPersistFlags,
  1922. PropertyId,
  1923. PropertyValue);
  1924. AzpUnlockResource( &AzGlResource );
  1925. return WinStatus;
  1926. }
  1927. DWORD
  1928. AzpeSetObjectOptions(
  1929. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  1930. IN ULONG lPersistFlags,
  1931. IN ULONG ObjectOptions
  1932. )
  1933. /*++
  1934. Routine Description:
  1935. The provider should call AzpeSetObjectOptions to tell AzRoles about optional
  1936. characteristics of the object. It should be called from a thread processing
  1937. a call to AzPersistOpen, AzPersistUpdateCache, or AzPersistUpdateChildrenCache,
  1938. AzPersistRefresh for each object read from the authorization database. It should
  1939. be called from a thread processing a call to AzPersistSubmit for each newly created object.
  1940. Arguments:
  1941. AzpeObjectHandle - Specifies a handle to the object.
  1942. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  1943. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  1944. ObjectOptions - Specifies a bit mask containing one or more of the following bits:
  1945. AZPE_OPTIONS_WRITABLE (0x1) - If this bit is set, then the current user can write
  1946. this object. This corresponds to the Writable method on the various objects.
  1947. AZPE_OPTIONS_SUPPORTS_DACL (0x2) - If this bit is set, then the provider supports
  1948. setting AZ_PROP_POLICY_READERS and AZ_PROP_POLICY_ADMINS on this object.
  1949. This bit should only be specified if the object type is OBJECT_TYPE_AZAUTHSTORE,
  1950. OBJECT_TYPE_APPLICATION or OBJECT_TYPE_SCOPE.
  1951. AZPE_OPTIONS_SUPPORTS_DELEGATION (0x4) If this bit is set, then the provider
  1952. supports setting AZ_PROP_DELEGATED_POLICY_USERS on this object. This bit
  1953. should only be specified if the object type is OBJECT_TYPE_AZAUTHSTORE
  1954. or OBJECT_TYPE_APPLICATION.
  1955. AZPE_OPTIONS_SUPPORTS_SACL (0x8) - If this bit is set, then the provider
  1956. supports setting AZ_PROP_APPLY_STORE_SACL on this object. This bit should
  1957. only be specified if the object type is OBJECT_TYPE_AZAUTHSTORE,
  1958. OBJECT_TYPE_APPLICATION or OBJECT_TYPE_SCOPE.
  1959. AZPE_OPTIONS_HAS_SECURITY_PRIVILEGE (0x10) - If this bit is set, then the current
  1960. user has SE_SECURITY_PRIVILEGE on the machine containing the store.
  1961. AZPE_OPTIONS_SUUPORTS_LAZY_LOAD (0x20) - If this bit is set, then the provider supports
  1962. lazy load for children
  1963. AZPE_OPTIONS_CREATE_CHILDREN - If this bit is set, then the current user can create children
  1964. for this object. Currently, user only for AzScope objects.
  1965. Return Value:
  1966. NO_ERROR - The operation was successful
  1967. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  1968. --*/
  1969. {
  1970. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT)AzpeObjectHandle;
  1971. //
  1972. // Ensure the provider didn't pass bogus flags
  1973. //
  1974. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_MASK) != 0) {
  1975. ASSERT( FALSE );
  1976. return ERROR_INVALID_FLAGS;
  1977. }
  1978. if ( (ObjectOptions & ~AZPE_OPTIONS_VALID_MASK) != 0) {
  1979. AzPrint(( AZD_INVPARM, "AzpeSetObjectOptions: bad options mask 0x%lx\n", ObjectOptions ));
  1980. ASSERT( FALSE );
  1981. return ERROR_INVALID_PARAMETER;
  1982. }
  1983. AzpLockResourceExclusive( &AzGlResource );
  1984. //
  1985. // Mark the object as writable
  1986. //
  1987. GenericObject->IsWritable = (( ObjectOptions & AZPE_OPTIONS_WRITABLE ) != 0);
  1988. //
  1989. // Mark whether the object support a DACL
  1990. //
  1991. if ( IsContainerObject( GenericObject->ObjectType )) {
  1992. GenericObject->IsAclSupported = (( ObjectOptions & AZPE_OPTIONS_SUPPORTS_DACL ) != 0);
  1993. } else {
  1994. GenericObject->IsAclSupported = FALSE;
  1995. }
  1996. //
  1997. // Mark whether the object support a SACL
  1998. //
  1999. if ( IsContainerObject( GenericObject->ObjectType )) {
  2000. GenericObject->IsSACLSupported = (( ObjectOptions & AZPE_OPTIONS_SUPPORTS_SACL ) != 0);
  2001. } else {
  2002. GenericObject->IsSACLSupported = FALSE;
  2003. }
  2004. //
  2005. // Load delegation support flag
  2006. //
  2007. if ( IsDelegatorObject( GenericObject->ObjectType ) ) {
  2008. GenericObject->IsDelegationSupported = (( ObjectOptions & AZPE_OPTIONS_SUPPORTS_DELEGATION ) != 0);
  2009. } else {
  2010. GenericObject->IsDelegationSupported = FALSE;
  2011. }
  2012. //
  2013. // Mark whether the current user has SE_SECURITY_PRIVILEGE on the store server
  2014. //
  2015. if ( GenericObject->ObjectType == OBJECT_TYPE_AZAUTHSTORE ) {
  2016. ((PAZP_AZSTORE)GenericObject)->HasSecurityPrivilege = (( ObjectOptions & AZPE_OPTIONS_HAS_SECURITY_PRIVILEGE ) != 0);
  2017. //
  2018. // If the provider supports lazy load for children
  2019. //
  2020. ((PAZP_AZSTORE)GenericObject)->ChildLazyLoadSupported = ((ObjectOptions & AZPE_OPTIONS_SUPPORTS_LAZY_LOAD) != 0);
  2021. }
  2022. //
  2023. // Mark if the AzScope object children can be created
  2024. //
  2025. if ( IsContainerObject(GenericObject->ObjectType) ) {
  2026. GenericObject->CanCreateChildren = ((ObjectOptions & AZPE_OPTIONS_CREATE_CHILDREN) != 0);
  2027. }
  2028. AzpUnlockResource( &AzGlResource );
  2029. return NO_ERROR;
  2030. }
  2031. VOID
  2032. AzpeObjectFinished(
  2033. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2034. IN DWORD WinStatus
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. The provider should call AzpeObjectFinished to indicate that it is finished
  2039. updating the cache for a particular object. It should only be called from a
  2040. thread processing a call to AzPersistOpen, AzPersistUpdateCache, AzPersistUpdateChildrenCache,
  2041. or AzPersistRefresh.
  2042. Arguments:
  2043. AzpeObjectHandle - Specifies a handle to the object.
  2044. WinStatus - Specifies whether the provider successfully set all attributes
  2045. of the object. If all attributes were set, specify NO_ERROR. If not all attributes
  2046. were set, specify an appropriate status code.
  2047. Return Value:
  2048. None.
  2049. --*/
  2050. {
  2051. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT)AzpeObjectHandle;
  2052. //
  2053. // Initialization
  2054. //
  2055. AzpLockResourceExclusive( &AzGlResource );
  2056. // Should no longer ASSERT on this condition.
  2057. //ASSERT( WinStatus == NO_ERROR );
  2058. ASSERT( (GenericObject->Flags & GENOBJ_FLAGS_PERSIST_OK) == 0 );
  2059. //
  2060. // Indicate that the provider has blessed the object
  2061. //
  2062. if ( WinStatus == NO_ERROR ) {
  2063. GenericObject->Flags |= GENOBJ_FLAGS_PERSIST_OK;
  2064. // Providers don't call AzpeCreateObject for the authorization store object.
  2065. // So ensure the dirty bit gets set.
  2066. //ASSERT( (GenericObject->PersistDirtyBits & AZ_DIRTY_CREATE) != 0 || GenericObject->ObjectType == OBJECT_TYPE_AZAUTHSTORE );
  2067. GenericObject->PersistDirtyBits |= AZ_DIRTY_CREATE;
  2068. }
  2069. //
  2070. // If this isn't the authorization store object,
  2071. // the provider got this handle from AzpeCreateObject,
  2072. // so dereference it.
  2073. //
  2074. if ( GenericObject->ObjectType != OBJECT_TYPE_AZAUTHSTORE ) {
  2075. ObDereferenceObject( GenericObject );
  2076. }
  2077. AzpUnlockResource( &AzGlResource );
  2078. }
  2079. DWORD
  2080. AzpeGetProperty(
  2081. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2082. IN ULONG lPersistFlags,
  2083. IN ULONG PropertyId,
  2084. OUT PVOID *PropertyValue
  2085. )
  2086. /*++
  2087. Routine Description:
  2088. The provider should call AzpeGetProperty to determine the value of scalar properties
  2089. for a particular object. It should only be called from a thread processing a call to
  2090. AzPersistSubmit.
  2091. Arguments:
  2092. AzpeObjectHandle - Specifies a handle to the object.
  2093. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  2094. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  2095. PropertyId - Specifies the property ID of the property to get. This should be one
  2096. of the AZ_PROP_* defines. See the section entitled PropertyId parameter for a
  2097. list of valid values.
  2098. PropertyValue - On success, returns a pointer to the buffer containing the property.
  2099. The provider should free this buffer using AzpeFreeMemory.
  2100. For properties that are strings, the returned pointer is of type LPWSTR.
  2101. For properties that are LONGs, the returned pointer is of type PULONG.
  2102. For properties that are Booleans, the returned pointer is of type PBOOL.
  2103. Return Value:
  2104. NO_ERROR - The operation was successful
  2105. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  2106. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  2107. ERROR_INVALID_PARAMETER - PropertyId is invalid.
  2108. --*/
  2109. {
  2110. DWORD WinStatus;
  2111. PGENERIC_OBJECT_LIST GenericObjectList;
  2112. ULONG ObjectType;
  2113. //
  2114. // Ensure the provider didn't pass bogus flags
  2115. //
  2116. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_SUBMIT) != 0) {
  2117. ASSERT( FALSE );
  2118. return ERROR_INVALID_FLAGS;
  2119. }
  2120. //
  2121. // Ensure the provider is only getting a scalar property
  2122. //
  2123. WinStatus = ObMapPropIdToObjectList(
  2124. (PGENERIC_OBJECT)AzpeObjectHandle,
  2125. PropertyId,
  2126. &GenericObjectList,
  2127. &ObjectType );
  2128. if ( WinStatus == NO_ERROR ) {
  2129. AzPrint(( AZD_INVPARM, "AzpeGetProperty: Property ID for non-scalar: %ld\n", PropertyId ));
  2130. return ERROR_INVALID_PARAMETER;
  2131. }
  2132. //
  2133. // Go get the property value
  2134. //
  2135. AzpLockResourceExclusive( &AzGlResource );
  2136. WinStatus = ObGetProperty(
  2137. (PGENERIC_OBJECT)AzpeObjectHandle,
  2138. lPersistFlags |
  2139. AZP_FLAGS_BY_GUID, // use guid from persist store if apply
  2140. PropertyId,
  2141. PropertyValue);
  2142. AzpUnlockResource( &AzGlResource );
  2143. return WinStatus;
  2144. }
  2145. DWORD
  2146. AzpeGetDeltaArray(
  2147. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2148. IN ULONG PropertyId,
  2149. OUT PULONG DeltaArrayCount,
  2150. OUT PAZP_DELTA_ENTRY **DeltaArray
  2151. )
  2152. /*++
  2153. Routine Description:
  2154. The provider should call AzpeObjectFinished to determine the value of non-scalar
  2155. properties for a particular object. It should only be called from a thread
  2156. processing a call to AzPersistSubmit.
  2157. Arguments:
  2158. AzpeObjectHandle - Specifies a handle to the object.
  2159. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  2160. pass the same flags that were passed to it by AzRoles when AzRoles called the
  2161. AzPersist*.
  2162. PropertyId - Specifies the property ID of the property to get. This should be one
  2163. of the AZ_PROP_* defines. See the section entitled PropertyId parameter for
  2164. a list of valid values.
  2165. DeltaArrayCount - On success, returns the number of elements in DeltaArray.
  2166. The returned value may be zero if no changes have been made to the property.
  2167. DeltaArray - On success, returns a pointers to the delta array. This pointer need
  2168. not be freed. The pointer is only valid until the persistence provider returns
  2169. from the AzPersistSubmit call. The returned value may be NULL if no changes
  2170. have been made to the property.
  2171. Return Value:
  2172. NO_ERROR - The operation was successful
  2173. ERROR_INVALID_PARAMETER - PropertyId is invalid.
  2174. --*/
  2175. {
  2176. DWORD WinStatus;
  2177. PGENERIC_OBJECT_LIST GenericObjectList;
  2178. ULONG ObjectType;
  2179. //
  2180. // Map to the generic object list
  2181. //
  2182. WinStatus = ObMapPropIdToObjectList(
  2183. (PGENERIC_OBJECT)AzpeObjectHandle,
  2184. PropertyId,
  2185. &GenericObjectList,
  2186. &ObjectType );
  2187. if ( WinStatus != NO_ERROR ) {
  2188. AzPrint(( AZD_INVPARM, "AzpeGetDeltaArray: invalid prop id %ld\n", PropertyId ));
  2189. return WinStatus;
  2190. }
  2191. //
  2192. // Return the delta array from the object list
  2193. //
  2194. *DeltaArrayCount = GenericObjectList->DeltaArray.UsedCount;
  2195. *DeltaArray = (PAZP_DELTA_ENTRY *)GenericObjectList->DeltaArray.Array;
  2196. return NO_ERROR;
  2197. }
  2198. DWORD
  2199. AzpeObjectType(
  2200. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. The routine returns the object type for a particular object
  2205. Arguments:
  2206. AzpeObjectHandle - Specifies a handle to the objec
  2207. Return Value:
  2208. Returns the object type of the object. This will be one of the OBJECT_TYPE_* defines.
  2209. --*/
  2210. {
  2211. return ((PGENERIC_OBJECT)AzpeObjectHandle)->ObjectType;
  2212. }
  2213. DWORD
  2214. AzpeDirtyBits(
  2215. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2216. )
  2217. /*++
  2218. Routine Description:
  2219. This routine returns a bit mask of the dirty bits for a particular object.
  2220. Each bit corresponds to a property that has been modified by the application.
  2221. It should only be called from a thread processing a call to AzPersistSubmit.
  2222. The dirty bits are object type specific. The provider should determine
  2223. the object type of the object then should map each dirty bit to the corresponding
  2224. property ID. If the property ID corresponds to a scalar, the provider should call
  2225. AzpeGetProperty to get the value of the property. If the property ID corresponds
  2226. to a list, the provider should call AzpeGetDeltaArray to get a description of what
  2227. values where added to and removed from the property. See the section entitled
  2228. PropertyId Parameter for details.
  2229. Each PropertyId maps to a single AZ_DIRTY_* dirty bit as returned from AzpeDirtyBits.
  2230. The #define names exist on a one-to-one basis. That is AZ_PROP_NAME is the property
  2231. ID for AZ_DIRTY_NAME.
  2232. There is one special dirty bit, AZ_DIRTY_CREATE. That bit is set if the object
  2233. was created by the application.
  2234. If AzpeDirtyBits returns a bit the provider doesn't understand, the provider
  2235. should fail the AzPersistSubmit call.
  2236. Arguments:
  2237. AzpeObjectHandle - Specifies a handle to the object.
  2238. Return Value:
  2239. Returns a bit mask specifying which properties where changed on the object.
  2240. These bits are the AZ_DIRTY_* defines.
  2241. --*/
  2242. {
  2243. return ((PGENERIC_OBJECT)AzpeObjectHandle)->DirtyBits;
  2244. }
  2245. GUID *
  2246. AzpePersistenceGuid(
  2247. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2248. )
  2249. /*++
  2250. Routine Description:
  2251. This routine returns a pointer to the location of the persistence GUID in the
  2252. AzRoles cache. The provider may read the returned location as long as the
  2253. AzpeObjectHandle is valid. The provider may only modify the returned location
  2254. while processing an AzPersistSubmit call and then only if the AZ_DIRTY_CREATE
  2255. bit was set.
  2256. Arguments:
  2257. AzpeObjectHandle - Specifies a handle to the object.
  2258. Return Value:
  2259. Returns a pointer to the location of the persistence GUID in the AzRoles cache.
  2260. --*/
  2261. {
  2262. return &((PGENERIC_OBJECT)AzpeObjectHandle)->PersistenceGuid;
  2263. }
  2264. BOOLEAN
  2265. AzpeIsParentWritable(
  2266. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. This routine returns the IsWritable property of the object's parent
  2271. Arguments:
  2272. AzpeObjectHandle - Specifies a handle to the object
  2273. Return Value:
  2274. BOOLEAN value indicating the IsWritable property of the parent
  2275. --*/
  2276. {
  2277. return (BOOLEAN)(ParentOfChild((PGENERIC_OBJECT)AzpeObjectHandle)->IsWritable);
  2278. }
  2279. BOOLEAN
  2280. AzpeCanCreateChildren(
  2281. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2282. )
  2283. /*++
  2284. Routine Description:
  2285. This routine returns the CanCreateChildren property of the object's parent
  2286. Arguments:
  2287. AzpeObjectHandle - Specifies a handle to the object
  2288. Return Value:
  2289. BOOLEAN value indicating the IsWritable property of the parent
  2290. --*/
  2291. {
  2292. return (BOOLEAN)(ParentOfChild((PGENERIC_OBJECT)AzpeObjectHandle)->CanCreateChildren);
  2293. }
  2294. BOOLEAN
  2295. AzpeUpdateChildren(
  2296. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2297. )
  2298. /*++
  2299. Routine Description:
  2300. This routine returns TRUE if the children of the object need to be updated into cache
  2301. Arguments:
  2302. AzpeObjectHandle - Specifies a handle to the object
  2303. Return Value:
  2304. BOOLEAN value indicating if the children of the object need to be updated into the cache
  2305. --*/
  2306. {
  2307. BOOLEAN retVal = FALSE;
  2308. if ( ((PGENERIC_OBJECT)AzpeObjectHandle)->ObjectType == OBJECT_TYPE_SCOPE ||
  2309. ((PGENERIC_OBJECT)AzpeObjectHandle)->ObjectType == OBJECT_TYPE_APPLICATION ) {
  2310. retVal = ((PGENERIC_OBJECT)AzpeObjectHandle)->AreChildrenLoaded;
  2311. }
  2312. return retVal;
  2313. }
  2314. AZPE_OBJECT_HANDLE
  2315. AzpeParentOfChild(
  2316. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2317. )
  2318. /*++
  2319. Routine Description:
  2320. This routine returns a handle to the parent of a particular object.
  2321. The provider may use this parent handle as long as AzpeObjectHandle is valid.
  2322. Arguments:
  2323. AzpeObjectHandle - Specifies a handle to the object.
  2324. Return Value:
  2325. Returns a handle to the parent of a particular object.
  2326. If AzpeObjectHandle is for an authorization store object, NULL is returned.
  2327. --*/
  2328. {
  2329. return (AZPE_OBJECT_HANDLE)ParentOfChild((PGENERIC_OBJECT)AzpeObjectHandle);
  2330. }
  2331. DWORD
  2332. AzpeAddPropertyItemSid(
  2333. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2334. IN ULONG lPersistFlags,
  2335. IN ULONG PropertyId,
  2336. IN PSID Sid
  2337. )
  2338. /*++
  2339. Routine Description:
  2340. The provider should call AzpeAddPropertyItemSid to set the value of a SID list
  2341. property in the AzRoles object cache. It should be called once from each SID
  2342. in the SID list. It should only be called from a thread processing a call
  2343. to AzPersistOpen, AzPersistUpdateCache, AzPersistUpdateChildrenCache or AzPersistRefresh.
  2344. This routine may also be called from a thread processing AzPersistSubmit if the
  2345. submitted AZ_PROP_POLICY_ADMINS list is empty. In that case, the provider should default
  2346. the AZ_PROP_POLICY_ADMINS list to the owner of the submitted file and should tell AzRoles
  2347. who that own is by either calling AzpeSetSecurityDescriptorIntoCache or AzpeAddPropertyItemSid.
  2348. Arguments:
  2349. AzpeObjectHandle - Specifies a handle to the object.
  2350. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  2351. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  2352. PropertyId - Specifies the property ID of the property to set. This should be one
  2353. of the AZ_PROP_* defines. See the section entitled PropertyId parameter for a
  2354. list of valid values.
  2355. Sid - Specifies a pointer to the SID to add to the Sid list
  2356. Return Value:
  2357. NO_ERROR - The operation was successful
  2358. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  2359. ERROR_INVALID_PARAMETER - Property ID is invalid or the Sid is syntactically invalid.
  2360. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  2361. --*/
  2362. {
  2363. DWORD WinStatus;
  2364. PGENERIC_OBJECT GenericObject = (PGENERIC_OBJECT)AzpeObjectHandle;
  2365. PGENERIC_OBJECT_LIST GenericObjectList;
  2366. ULONG ObjectType;
  2367. AZP_STRING SidString;
  2368. //
  2369. // Ensure the provider didn't pass bogus flags
  2370. //
  2371. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_MASK) != 0) {
  2372. ASSERT( FALSE );
  2373. return ERROR_INVALID_FLAGS;
  2374. }
  2375. //
  2376. // Handle calls from submit.
  2377. //
  2378. if ( lPersistFlags & AZPE_FLAGS_PERSIST_SUBMIT ) {
  2379. //
  2380. // Submit is only allowed for Policy admins
  2381. // .. on the authorization store object
  2382. // .. if there is no an empty policy admins list
  2383. //
  2384. if ( PropertyId != AZ_PROP_POLICY_ADMINS ||
  2385. GenericObject->ObjectType != OBJECT_TYPE_AZAUTHSTORE &&
  2386. GenericObject->PolicyAdmins.GenericObjects.UsedCount == 0 ) {
  2387. AzPrint(( AZD_INVPARM, "AzpeAddPropertyItemSid: called from submit: %ld %ld %ld\n",
  2388. PropertyId,
  2389. GenericObject->ObjectType,
  2390. GenericObject->PolicyAdmins.GenericObjects.UsedCount ));
  2391. ASSERT( FALSE );
  2392. return ERROR_INVALID_PARAMETER;
  2393. }
  2394. //
  2395. // Treat this as though it came from reconcile.
  2396. // That ensure the cache really gets updated but the dirty bits don't
  2397. //
  2398. lPersistFlags |= AZP_FLAGS_RECONCILE;
  2399. lPersistFlags &= ~AZPE_FLAGS_PERSIST_SUBMIT;
  2400. }
  2401. //
  2402. // Initialization
  2403. //
  2404. AzpLockResourceExclusive( &AzGlResource );
  2405. //
  2406. // Validate the Property ID
  2407. //
  2408. WinStatus = ObMapPropIdToObjectList(
  2409. GenericObject,
  2410. PropertyId,
  2411. &GenericObjectList,
  2412. &ObjectType );
  2413. if ( WinStatus != NO_ERROR ) {
  2414. AzPrint(( AZD_INVPARM, "AzpeAddPropertyItemSid: invalid prop id %ld\n", PropertyId ));
  2415. goto Cleanup;
  2416. }
  2417. //
  2418. // Validate a passed in SID
  2419. //
  2420. if ( !RtlValidSid( Sid ) ) {
  2421. AzPrint(( AZD_INVPARM, "AzpeAddPropertyItemSid: SID not valid\n" ));
  2422. WinStatus = ERROR_INVALID_PARAMETER;
  2423. goto Cleanup;
  2424. }
  2425. //
  2426. // Add the property item
  2427. //
  2428. AzpInitSid( &SidString, Sid );
  2429. WinStatus = ObAddPropertyItem(
  2430. GenericObject,
  2431. GenericObjectList,
  2432. lPersistFlags,
  2433. &SidString );
  2434. Cleanup:
  2435. AzpUnlockResource( &AzGlResource );
  2436. return WinStatus;
  2437. }
  2438. DWORD
  2439. AzpeAddPropertyItemGuid(
  2440. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2441. IN ULONG lPersistFlags,
  2442. IN ULONG PropertyId,
  2443. IN GUID *ObjectGuid
  2444. )
  2445. /*++
  2446. Routine Description:
  2447. The provider should call AzpeAddPropertyItemGuid to set the value of a property
  2448. that is a list of other object in the AzRoles object cache. It should be called
  2449. once from each object in the list. It should only be called from a thread
  2450. processing a call to AzPersistOpen, AzPersistUpdateCache, AzPersistUpdateChildrenCache
  2451. or AzPersistRefresh.
  2452. Arguments:
  2453. AzpeObjectHandle - Specifies a handle to the object.
  2454. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  2455. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  2456. PropertyId - Specifies the property ID of the property to set. This should be one of
  2457. the AZ_PROP_* defines. See the section entitled PropertyId parameter for a list of
  2458. valid values.
  2459. ObjectGuid - Specifies the persistence GUID of the object in the list.
  2460. Return Value:
  2461. NO_ERROR - The operation was successful
  2462. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  2463. ERROR_INVALID_PARAMETER - Property ID is invalid
  2464. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  2465. --*/
  2466. {
  2467. DWORD WinStatus;
  2468. PGENERIC_OBJECT_LIST GenericObjectList;
  2469. ULONG ObjectType;
  2470. //
  2471. // Ensure the provider didn't pass bogus flags
  2472. //
  2473. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_OPEN_MASK) != 0) {
  2474. ASSERT( FALSE );
  2475. return ERROR_INVALID_FLAGS;
  2476. }
  2477. //
  2478. // Validate the Property ID
  2479. //
  2480. WinStatus = ObMapPropIdToObjectList(
  2481. (PGENERIC_OBJECT)AzpeObjectHandle,
  2482. PropertyId,
  2483. &GenericObjectList,
  2484. &ObjectType );
  2485. if ( WinStatus != NO_ERROR ) {
  2486. AzPrint(( AZD_INVPARM, "AzpeAddPropertyItemGuid: invalid prop id %ld\n", PropertyId ));
  2487. return WinStatus;
  2488. }
  2489. AzpLockResourceExclusive( &AzGlResource );
  2490. WinStatus = ObAddPropertyItem(
  2491. (PGENERIC_OBJECT)AzpeObjectHandle,
  2492. GenericObjectList,
  2493. lPersistFlags |
  2494. AZP_FLAGS_BY_GUID,
  2495. (PAZP_STRING)ObjectGuid);
  2496. AzpUnlockResource( &AzGlResource );
  2497. return WinStatus;
  2498. }
  2499. DWORD
  2500. AzpeAddPropertyItemGuidString(
  2501. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2502. IN ULONG lPersistFlags,
  2503. IN ULONG PropertyId,
  2504. IN WCHAR *ObjectGuidString
  2505. )
  2506. /*++
  2507. Routine Description:
  2508. AzpeAddPropertyItemGuidString is identical to AzpeAddPropertyItemGuid except it
  2509. takes the GUID as an LPWSTR. The provider may call whichever function is more convenient.
  2510. Arguments:
  2511. AzpeObjectHandle - Specifies a handle to the object.
  2512. lPersistFlags - Specifies a bit mask describing the operation. The provider should
  2513. pass the same flags that were passed to it by AzRoles when AzRoles called the AzPersist*.
  2514. PropertyId - Specifies the property ID of the property to set. This should be one
  2515. of the AZ_PROP_* defines. See the section entitled PropertyId parameter for a list
  2516. of valid values.
  2517. ObjectGuidString - Specifies the persistence GUID of the object in the list.
  2518. Return Value:
  2519. NO_ERROR - The operation was successful
  2520. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  2521. ERROR_INVALID_PARAMETER - Property ID is invalid
  2522. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  2523. --*/
  2524. {
  2525. DWORD dwErr;
  2526. GUID ObjectGuid;
  2527. //
  2528. // Convert the string to a GUID
  2529. //
  2530. ASSERT(NULL != ObjectGuidString);
  2531. dwErr = UuidFromString(ObjectGuidString, &ObjectGuid);
  2532. if (S_OK != dwErr)
  2533. {
  2534. goto Cleanup;
  2535. }
  2536. //
  2537. // Use the routine that takes a binary GUID
  2538. //
  2539. dwErr = AzpeAddPropertyItemGuid( AzpeObjectHandle,
  2540. lPersistFlags,
  2541. PropertyId,
  2542. &ObjectGuid );
  2543. Cleanup:
  2544. return dwErr;
  2545. }
  2546. PVOID
  2547. AzpeGetProviderData(
  2548. IN AZPE_OBJECT_HANDLE AzpeObjectHandle
  2549. )
  2550. /*++
  2551. Routine Description:
  2552. AzpeGetProviderData returns a pointer to buffer previously stored by AzpeSetProviderData.
  2553. The provider is responsible for providing any synchronization for the data.
  2554. The provider should only access the data from a thread processing a call to one of
  2555. the AzPersist* routines.
  2556. Arguments:
  2557. AzpeObjectHandle - Specifies a handle to the object.
  2558. Return Value:
  2559. A pointer to the data the provider previously passed into AzpeSetProviderData
  2560. --*/
  2561. {
  2562. return ((PGENERIC_OBJECT)AzpeObjectHandle)->ProviderData;
  2563. }
  2564. VOID
  2565. AzpeSetProviderData(
  2566. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  2567. IN PVOID ProviderData
  2568. )
  2569. /*++
  2570. Routine Description:
  2571. It may be convenient for the provider to store some provider specific data on
  2572. each object. AzpeSetProviderData stores a pointer to that data in the AzRoles cache.
  2573. Azoles will automatically delete the pointed to data when it deletes the cache entry.
  2574. The provider may clear a previously stored pointer by specifying NULL as
  2575. ProviderData.
  2576. The provider is responsible for providing any synchronization for the data.
  2577. The provider should only access the data from a thread processing a call to one
  2578. of the AzPersist* routines.
  2579. Arguments:
  2580. AzpeObjectHandle - Specifies a handle to the object.
  2581. ProviderData - Specifies a pointer to data to be stored by the provider.
  2582. The buffer should have been allocated using AzpeAllocateMemory. AzRoles
  2583. will delete this data when the cache entry is deleted by using AzpeFreeMemory.
  2584. Return Value:
  2585. None
  2586. --*/
  2587. {
  2588. ((PGENERIC_OBJECT)AzpeObjectHandle)->ProviderData = ProviderData;
  2589. }
  2590. VOID
  2591. AzpeFreeMemory(
  2592. IN PVOID Buffer
  2593. )
  2594. /*++
  2595. Routine Description
  2596. The provider must use AzpeFreeMemory to free memory allocated by AzpeAllocateMemory,
  2597. AzpeGetProperty, and AzpeGetSecurityDescriptorFromCache.
  2598. Arguments
  2599. Buffer - Specifies a pointer to the buffer to be free.
  2600. If NULL, the call is silently ignored.
  2601. Return Value
  2602. None
  2603. --*/
  2604. {
  2605. if ( Buffer != NULL ) {
  2606. AzpFreeHeap( Buffer );
  2607. }
  2608. }
  2609. PVOID
  2610. AzpeAllocateMemory(
  2611. IN SIZE_T Size
  2612. )
  2613. /*++
  2614. Routine Description:
  2615. The provider may call AzpeAllocateMemory to allocate memory. The provider
  2616. must use AzpeAllocateMemory to allocate memory passed to AzpeSetProviderData
  2617. and returned in the pwszTargetMachine parameter to AzPersistOpen. The provider
  2618. may use AzpeAllocateMemory for other memory allocation. The provider must
  2619. not have any memory allocated after it returns from AzPersistClose.
  2620. Arguments:
  2621. Size - Size in bytes of the memory to allocate.
  2622. Return Values:
  2623. Returns a pointer to the allocated memory.
  2624. NULL - Not enough memory
  2625. --*/
  2626. {
  2627. return AzpAllocateHeap( Size, "AZPEALOC" );
  2628. }
  2629. DWORD
  2630. AzpSdToPolicy(
  2631. IN PSECURITY_DESCRIPTOR pSD,
  2632. IN PAZP_POLICY_USER_RIGHTS pAdminRights OPTIONAL,
  2633. IN PAZP_POLICY_USER_RIGHTS pReaderRights OPTIONAL,
  2634. IN PAZP_POLICY_USER_RIGHTS pDelegatedUserRights OPTIONAL,
  2635. IN PAZP_POLICY_USER_RIGHTS pSaclRights OPTIONAL,
  2636. IN DWORD (*CallbackRoutine) (
  2637. IN PVOID Context,
  2638. IN ULONG lPersistFlags,
  2639. IN ULONG PropertyId,
  2640. IN PSID Sid ),
  2641. IN PVOID Context,
  2642. IN ULONG lPersistFlags
  2643. )
  2644. /*++
  2645. Routine Description:
  2646. AzpSdToPolicy parses a security descriptor and determines which ACEs correspond
  2647. to AZ_PROP_POLICY_ADMINS, AZ_PROP_POLICY_READERS, and AZ_PROP_DELEGATED_POLICY_USERS properties.
  2648. For each such Sid, the routine calls a callback routine to tell the caller about the sid.
  2649. It also determines whether AZ_PORP_APPLY_STORE_SACL is TRUE or FALSE by inspecting the SACL.
  2650. After determining the value, the routine calls a callback routine to tell the caller the value.
  2651. Arguments:
  2652. pSD - The current security descriptor for the object on the object in the store
  2653. pAdminRights - Rights for admins (Mask and Flags)
  2654. pReaderRights - Rights for readers (Mask and Flags). Specify NULL if the readers list
  2655. need not be added. (For instance, for AzPersistSubmit as described above.)
  2656. pDelegatedUserRights - An optional parameter specifying the delegated user's rights (Mask and Flags)
  2657. pSaclRights - Specifies the rights to put on the SACL
  2658. CallbackRoutine - Address of the routine to call for each policy sid.
  2659. Context - Context to pass to the callback routine.
  2660. lPersistFlags - Internal flags
  2661. These flags are passed to the callback routine but are otherwise unused.
  2662. Return Values:
  2663. NO_ERROR - The operation was successful
  2664. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  2665. Other values returned from CallbackRoutine
  2666. --*/
  2667. {
  2668. DWORD WinStatus = 0;
  2669. PACL pDacl;
  2670. BOOL bDaclPresent;
  2671. BOOL bDaclDefaulted;
  2672. PACL pSacl;
  2673. BOOL bSaclPresent;
  2674. BOOL bSaclDefaulted;
  2675. ACL_SIZE_INFORMATION AclInfo;
  2676. PACE_HEADER pAceHeader;
  2677. PACCESS_ALLOWED_ACE pAce;
  2678. PSID pSid;
  2679. ULONG lUserType;
  2680. ULONG i;
  2681. BOOL bPolicyAdmin;
  2682. BOOL bPolicyReader;
  2683. BOOL bDelegatedPolicyUser;
  2684. BOOL ApplySacl;
  2685. //
  2686. // Validation
  2687. //
  2688. ASSERT( pSD != NULL );
  2689. //
  2690. // If the caller is interested, do the DACL
  2691. //
  2692. if ( pAdminRights || pReaderRights || pDelegatedUserRights) {
  2693. //
  2694. // Retrive the DACL information. From this, the SIDs will
  2695. // extracted for each ACE, and loaded into the policy readers/
  2696. // admins and delegators list property accordingly.
  2697. // All inherited ACEs will be discarded
  2698. //
  2699. if ( !GetSecurityDescriptorDacl(pSD,
  2700. &bDaclPresent,
  2701. &pDacl,
  2702. &bDaclDefaulted
  2703. ) ) {
  2704. WinStatus = GetLastError();
  2705. goto Cleanup;
  2706. }
  2707. if( !bDaclPresent ||
  2708. (pDacl == NULL)
  2709. ) {
  2710. WinStatus = ERROR_INVALID_DATA;
  2711. goto Cleanup;
  2712. }
  2713. //
  2714. // We now need the ACL information from the DACL
  2715. //
  2716. if ( !GetAclInformation(
  2717. pDacl,
  2718. &AclInfo,
  2719. sizeof( ACL_SIZE_INFORMATION ),
  2720. AclSizeInformation
  2721. ) ) {
  2722. WinStatus = GetLastError();
  2723. goto Cleanup;
  2724. }
  2725. //
  2726. // Loop through all the SIDs in the ACEs adding each one to the appropriate
  2727. // user type. Ignore all inherited ACEs
  2728. //
  2729. for ( i = 0; i < AclInfo.AceCount; i++ ) {
  2730. if ( GetAce( pDacl, i, (PVOID *)&pAce ) ) {
  2731. ASSERT( pAce != NULL );
  2732. pAceHeader = (PACE_HEADER) pAce;
  2733. //
  2734. // Allowed ACEs should only be added
  2735. //
  2736. if ( pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE ||
  2737. pAceHeader->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE ) {
  2738. //
  2739. // Pick up the AzRoles policy aces. Ignore inherited ACEs
  2740. //
  2741. if ( !(pAceHeader->AceFlags & INHERITED_ACE) ) {
  2742. bDelegatedPolicyUser = pDelegatedUserRights != NULL &&
  2743. !(pAce->Mask ^ pDelegatedUserRights->lUserRightsMask) &&
  2744. (pAceHeader->AceFlags == pDelegatedUserRights->lUserRightsFlags);
  2745. bPolicyAdmin = pAdminRights != NULL &&
  2746. !(pAce->Mask ^ pAdminRights->lUserRightsMask) &&
  2747. (pAceHeader->AceFlags & INHERIT_ONLY_ACE) == 0;
  2748. bPolicyReader = pReaderRights != NULL &&
  2749. !(pAce->Mask ^ pReaderRights->lUserRightsMask) &&
  2750. (pAceHeader->AceFlags & pReaderRights->lUserRightsFlags) == pReaderRights->
  2751. lUserRightsFlags &&
  2752. (pAceHeader->AceFlags & INHERIT_ONLY_ACE) == 0;
  2753. if ( bPolicyAdmin ||
  2754. bPolicyReader ||
  2755. bDelegatedPolicyUser
  2756. ) {
  2757. pSid = (PSID)&pAce->SidStart;
  2758. if ( bDelegatedPolicyUser ) {
  2759. lUserType = AZ_PROP_DELEGATED_POLICY_USERS;
  2760. pSid = RtlObjectAceSid( pAce );
  2761. } else if ( bPolicyAdmin ) {
  2762. lUserType = AZ_PROP_POLICY_ADMINS;
  2763. } else {
  2764. lUserType = AZ_PROP_POLICY_READERS;
  2765. }
  2766. if ( IsValidSid( pSid ) ) {
  2767. WinStatus = (*CallbackRoutine)(
  2768. Context,
  2769. lPersistFlags,
  2770. lUserType,
  2771. pSid );
  2772. if ( WinStatus != NO_ERROR ) {
  2773. goto Cleanup;
  2774. }
  2775. } // if ( IsValidSid( pSid )
  2776. } // if AzRoles policy ace
  2777. } // if not inherited
  2778. } // if ACCESS_ALLOWED_ACE_TYPE
  2779. } // if GetAce
  2780. } // for ( i=0; i<AceCount; i++ )
  2781. }
  2782. //
  2783. // If the caller is interested, do the SACL
  2784. //
  2785. if ( pSaclRights ) {
  2786. //
  2787. // Retrive the SACL information.
  2788. //
  2789. // Use it to determine AZ_PORP_APPLY_STORE_SACL
  2790. //
  2791. if ( !GetSecurityDescriptorSacl(pSD,
  2792. &bSaclPresent,
  2793. &pSacl,
  2794. &bSaclDefaulted
  2795. ) ) {
  2796. WinStatus = GetLastError();
  2797. goto Cleanup;
  2798. }
  2799. //
  2800. // If there is a SACL,
  2801. // determine if we have put explicit ACEs in the SACL.
  2802. // If so, set ApplySacl TRUE
  2803. //
  2804. ApplySacl = FALSE;
  2805. if( bSaclPresent && pSacl != NULL ) {
  2806. //
  2807. // We now need the ACL information from the SACL
  2808. //
  2809. if ( !GetAclInformation(
  2810. pSacl,
  2811. &AclInfo,
  2812. sizeof( ACL_SIZE_INFORMATION ),
  2813. AclSizeInformation
  2814. ) ) {
  2815. WinStatus = GetLastError();
  2816. goto Cleanup;
  2817. }
  2818. //
  2819. // Loop through all ACEs
  2820. //
  2821. for ( i = 0; i < AclInfo.AceCount; i++ ) {
  2822. pAce = NULL;
  2823. if ( GetAce( pSacl, i, (PVOID *)&pAce ) ) {
  2824. ASSERT( pAce != NULL );
  2825. pAceHeader = (PACE_HEADER) pAce;
  2826. //
  2827. // Ignore non-audit ACEs and
  2828. // Ignore inherited ACEs
  2829. //
  2830. if ( pAceHeader->AceType != SYSTEM_AUDIT_ACE_TYPE ||
  2831. (pAceHeader->AceFlags & INHERITED_ACE) != 0 ) {
  2832. continue;
  2833. }
  2834. //
  2835. // If this is the explicit ACE we inserted,
  2836. // the consider that the ApplySacl property is true for this object.
  2837. //
  2838. pSid = (PSID)&pAce->SidStart;
  2839. if ( RtlEqualSid( pSid, AzGlWorldSid ) &&
  2840. pAce->Mask == pSaclRights->lUserRightsMask ) {
  2841. ApplySacl = TRUE;
  2842. break;
  2843. }
  2844. }
  2845. }
  2846. }
  2847. //
  2848. // Tell the caller the whether an explicit SACL was applied
  2849. //
  2850. WinStatus = (*CallbackRoutine)(
  2851. Context,
  2852. lPersistFlags,
  2853. AZ_PROP_APPLY_STORE_SACL,
  2854. (PSID)&ApplySacl );
  2855. if ( WinStatus != NO_ERROR ) {
  2856. goto Cleanup;
  2857. }
  2858. }
  2859. WinStatus = NO_ERROR;
  2860. //
  2861. // Free local resources
  2862. //
  2863. Cleanup:
  2864. return WinStatus;
  2865. }
  2866. //
  2867. // Context for AzpeGetSecurityDescriptorFromCache
  2868. //
  2869. typedef struct _AZP_GET_ACL_CONTEXT_ENTRY {
  2870. ULONG PropertyId; // Property Id for this policy
  2871. //
  2872. // Policy Rights as specified by the caller.
  2873. // NULL implies the caller isn't interested
  2874. PAZP_POLICY_USER_RIGHTS *ppPolicyRights;
  2875. //
  2876. // Delta array containing the merged data from the existing Security Descriptor
  2877. // plus the deltas added by the application
  2878. //
  2879. AZP_PTR_ARRAY ResultDeltaArray;
  2880. } AZP_GET_ACL_CONTEXT_ENTRY, *PAZP_GET_ACL_CONTEXT_ENTRY;
  2881. typedef struct _AZP_GET_ACL_CONTEXT {
  2882. //
  2883. // One entry for admins, readers, and delegators
  2884. //
  2885. #define AZP_GET_ACL_CONTEXT_ADMINS 0
  2886. #define AZP_GET_ACL_CONTEXT_READERS 1
  2887. #define AZP_GET_ACL_CONTEXT_DELEGATORS 2
  2888. #define AZP_GET_ACL_CONTEXT_COUNT 3
  2889. AZP_GET_ACL_CONTEXT_ENTRY ContextEntry[AZP_GET_ACL_CONTEXT_COUNT];
  2890. } AZP_GET_ACL_CONTEXT, *PAZP_GET_ACL_CONTEXT;
  2891. DWORD
  2892. AzpAddSidsToAcl(
  2893. IN PAZP_PTR_ARRAY DeltaArray,
  2894. IN DWORD AceFlags,
  2895. IN ACCESS_MASK Mask,
  2896. IN OUT PACL pDacl,
  2897. IN GUID *pDelegatedObjectGuid
  2898. )
  2899. /*++
  2900. Routine Description:
  2901. This routine adds the SIDs in the passed SID array into the ACL
  2902. with the given mask.
  2903. Arguments:
  2904. pSids - The array of SIDs that need to be added to the ACL
  2905. Mask - The mask used in each ace
  2906. pDacl - Pointer to the ACL
  2907. pDelegatedObjectGuid - GUID of the object this ACL will be placed on
  2908. Return Values:
  2909. NO_ERROR - The SIDs were added successfully
  2910. Other Status codes
  2911. --*/
  2912. {
  2913. DWORD WinStatus = 0;
  2914. ULONG i = 0;
  2915. BOOL bResult = FALSE;
  2916. //
  2917. // Validation
  2918. //
  2919. AZASSERT( DeltaArray != NULL );
  2920. AZASSERT( pDacl != NULL );
  2921. for ( i = 0; i < DeltaArray->UsedCount; i++ ) {
  2922. PAZP_DELTA_ENTRY DeltaEntry = (PAZP_DELTA_ENTRY)DeltaArray->Array[i];
  2923. ASSERT( DeltaEntry->DeltaFlags & AZP_DELTA_SID );
  2924. ASSERT( DeltaEntry->DeltaFlags & AZP_DELTA_ADD );
  2925. if ( pDelegatedObjectGuid == NULL ) {
  2926. bResult = AddAccessAllowedAceEx(
  2927. pDacl,
  2928. ACL_REVISION,
  2929. AceFlags,
  2930. Mask,
  2931. DeltaEntry->Sid
  2932. );
  2933. } else {
  2934. bResult = AddAccessAllowedObjectAce(
  2935. pDacl,
  2936. ACL_REVISION_DS,
  2937. AceFlags,
  2938. Mask,
  2939. pDelegatedObjectGuid,
  2940. NULL,
  2941. DeltaEntry->Sid
  2942. );
  2943. }
  2944. if ( !bResult ) {
  2945. WinStatus = GetLastError();
  2946. goto Cleanup;
  2947. }
  2948. }
  2949. WinStatus = NO_ERROR;
  2950. Cleanup:
  2951. return WinStatus;
  2952. }
  2953. DWORD
  2954. AzpGetSdWorker(
  2955. IN PVOID Context,
  2956. IN ULONG lPersistFlags,
  2957. IN ULONG PropertyId,
  2958. IN PSID Sid
  2959. )
  2960. /*++
  2961. Routine Description:
  2962. Worker routine for AzpeGetSecurityDescriptorFromCache. This is a callback routine for AzpSdToPolicy.
  2963. It is called for each policy SID and simply remembers the list of sids
  2964. Arguments:
  2965. Context - Context from AzpeSetSecurityDescriptorIntoCache. In this case, the context
  2966. is a pointer to a AZP_GET_ACL_CONTEXT structure.
  2967. lPersistFlags - Internal flags
  2968. PropertyId - AZ_PROP_* identifying the right granted to the Sid.
  2969. Sid - Specifies the Sid the right is granted to.
  2970. Return Values:
  2971. NO_ERROR - The operation was successful
  2972. Other errors from AzpeAddPropertyItemSid.
  2973. --*/
  2974. {
  2975. ULONG PolicyIndex;
  2976. PAZP_GET_ACL_CONTEXT RealContext = (PAZP_GET_ACL_CONTEXT)Context;
  2977. PAZP_GET_ACL_CONTEXT_ENTRY ContextEntry = NULL;
  2978. AZP_STRING SidString;
  2979. //
  2980. // AZ_PROP_APPLY_STORE_SACL is a boolean.
  2981. // There is nothing to merge.
  2982. //
  2983. ASSERT( PropertyId != AZ_PROP_APPLY_STORE_SACL );
  2984. //
  2985. // Find the context entry for this policy
  2986. //
  2987. for ( PolicyIndex=0; PolicyIndex<AZP_GET_ACL_CONTEXT_COUNT; PolicyIndex++ ) {
  2988. //
  2989. // If the property ID matches,
  2990. // use it.
  2991. //
  2992. ContextEntry = &RealContext->ContextEntry[PolicyIndex];
  2993. if ( ContextEntry->PropertyId == PropertyId ) {
  2994. break;
  2995. }
  2996. }
  2997. if ( PolicyIndex == AZP_GET_ACL_CONTEXT_COUNT ) {
  2998. ASSERT( PolicyIndex != AZP_GET_ACL_CONTEXT_COUNT );
  2999. return NO_ERROR;
  3000. }
  3001. //
  3002. // If the caller isn't interested in this right,
  3003. // we're done.
  3004. //
  3005. if ( ContextEntry->ppPolicyRights == NULL ) {
  3006. return NO_ERROR;
  3007. }
  3008. //
  3009. // Add this sid to the list of Sids for this policy
  3010. //
  3011. AzpInitSid( &SidString, Sid );
  3012. return ObAddDeltaToArray(
  3013. AZP_DELTA_SID | AZP_DELTA_ADD,
  3014. (GUID *)&SidString,
  3015. &ContextEntry->ResultDeltaArray,
  3016. TRUE ); // Discard entries that are deletions
  3017. UNREFERENCED_PARAMETER( lPersistFlags );
  3018. }
  3019. DWORD
  3020. AzpeGetSecurityDescriptorFromCache(
  3021. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  3022. IN ULONG lPersistFlags,
  3023. IN PAZP_POLICY_USER_RIGHTS *ppPolicyAdminRights OPTIONAL,
  3024. IN PAZP_POLICY_USER_RIGHTS *ppPolicyReaderRights OPTIONAL,
  3025. IN PAZP_POLICY_USER_RIGHTS *ppDelegatedPolicyUsersRights OPTIONAL,
  3026. IN GUID *pDelegatedObjectGuid OPTIONAL,
  3027. IN PAZP_POLICY_USER_RIGHTS pDelegatedUsersAttributeRights OPTIONAL,
  3028. IN GUID *pAttributeGuid OPTIONAL,
  3029. IN PAZP_POLICY_USER_RIGHTS pSaclRights OPTIONAL,
  3030. IN PSECURITY_DESCRIPTOR OldSd OPTIONAL,
  3031. OUT PSECURITY_DESCRIPTOR *NewSd
  3032. )
  3033. /*++
  3034. Routine Description:
  3035. AzpeGetSecurityDescriptorFromCache is a support routine for the AZ_PROP_POLICY_ADMINS,
  3036. AZ_PROP_POLICY_READERS, AZ_PROP_DELEGATED_POLICY_USERS, and AZ_PROP_APPLY_STORE_SACL properties.
  3037. The routine reads the deltas to those properties from the object cache and
  3038. builds a DACL and SACL corresponding to that policy.
  3039. The provider may choose to call AzpeGetDeltaArray for each of those properties
  3040. if the provider's security model does not match that provided by this routine.
  3041. This routine should only be called from a thread processing a call to AzPersistSubmit.
  3042. The caller should only call this routine if the security descriptor should be written.
  3043. Specifically, if the object was just created (the AZ_DIRTY_CREATE dirty bits is set
  3044. for the object) or if the dirty bit for the properties mentioned above are set.
  3045. AzpeGetSecurityDescriptorFromCache process the DACL and SACL separately.
  3046. The caller should also. The caller should only specify the DACL specific parameters
  3047. to this routine if the DACL is to be written. The caller should only specify the SACL
  3048. specific parameter to this routine if the SACL is to be written.
  3049. If the AZ_DIRTY_CREATE bit is not set, then the previous security descriptor from
  3050. the object needs to be passed to AzpeGetSecurityDescriptorFromCache. Again, the
  3051. DACL should only be read if the DACL changed (as indicated by the dirty bits).
  3052. The SACL should only be read if the SACL changed (as indicated by the dirty bits).
  3053. Otherwise, the security descriptor read may fail because the caller has no access.
  3054. The returned security descriptor has the SE_DACL_PROTECTED if an only if the DACL
  3055. is to be marked as protected.
  3056. The caller should not pass the generic access bit GENERIC_READ, GENERIC_WRITE,
  3057. or GENERIC_EXECUTE to this routine. This routine needs to do bit mask comparisons
  3058. with the access mask on the ACLs on the security descriptor. It cannot interpret
  3059. the generic bits. Instead, pass the object specific mask such as FILE_GENERIC_READ.
  3060. Arguments:
  3061. AzpeObjectHandle - Handle to object whose ACLs will be read
  3062. lPersistFlags - Internal flags
  3063. ppPolicyAdminRights - Rights for policy admins.
  3064. Specifies a NULL terminated array of pointers to AZP_POLICY_USER_RIGHTS structures.
  3065. Each structure specifies an ACE to add to the DACL for each policy admin.
  3066. The first element of the array must be the one passed to AzpeSetSecurityDescriptorIntoCache.
  3067. ppPolicyReaderRights - Rights for policy readers
  3068. Specifies a NULL terminated array of pointers to AZP_POLICY_USER_RIGHTS structures.
  3069. Each structure specifies an ACE to add to the DACL for each policy reader.
  3070. The first element of the array must be the one passed to AzpeSetSecurityDescriptorIntoCache.
  3071. ppDelegatedPolicyUsersRights - Rights for delegated users
  3072. Specifies a NULL terminated array of pointers to AZP_POLICY_USER_RIGHTS structures.
  3073. Each structure specifies an ACE to add to the DACL for each delegated policy user.
  3074. The first element of the array must be the one passed to AzpeSetSecurityDescriptorIntoCache.
  3075. pDelegatedObjectGuid - GUID for an object on which the delegated users
  3076. will have read access on
  3077. pDelegatedUsersAttributeRights - the rights that needs to be granted to the delegated users
  3078. for the attribute whoese guid is given by the next parameter.
  3079. pAttributeGuid - the attribute that will grant special access to the delegated attribute users,
  3080. pSaclRights - Specifies the rights to put on the SACL
  3081. OldSd - Specifies the existing security descriptor for the object
  3082. Specify NULL for a newly created object.
  3083. NewSd - Returns the new self relative security descriptor for the object.
  3084. The returned buffer should be freed using AzpeFreeHeap.
  3085. Return Values:
  3086. NO_ERROR - The ACLs were got successfully
  3087. ERROR_EMPTY - The PolicyAdmins list was empty. AzpeGetSecurityDescriptorFromCache added the
  3088. CreatorOwner Sid to the DACL a admin. The provider should apply that
  3089. DACL then re-read the DACL to determine the actual PolicyAdmin. The
  3090. provider should tell AzRole about the actual AZ_PROP_POLICY_ADMINS by
  3091. calling AzpeSetSecurityDescriptorIntoCache or by calling AzpeAddPropertyItemSid for the actual
  3092. creator/owner returned in the read DACL
  3093. Other status codes
  3094. --*/
  3095. {
  3096. DWORD WinStatus;
  3097. ULONG PolicyIndex;
  3098. ULONG DeltaIndex;
  3099. ULONG RightsCountIndex;
  3100. AZP_GET_ACL_CONTEXT Context;
  3101. PAZP_GET_ACL_CONTEXT_ENTRY ContextEntry;
  3102. AZP_STRING SidString;
  3103. ULONG SidSize;
  3104. BOOLEAN UpdateDacl = (ppPolicyAdminRights != NULL || ppPolicyReaderRights != NULL || ppDelegatedPolicyUsersRights != NULL);
  3105. DWORD DaclSize;
  3106. PACL TempDacl = NULL;
  3107. DWORD SaclSize;
  3108. PACL TempSacl = NULL;
  3109. SECURITY_DESCRIPTOR TempSd;
  3110. ULONG ObjectType = AzpeObjectType(AzpeObjectHandle);
  3111. BOOL SetCreatorOwner = FALSE;
  3112. //
  3113. // Initialization
  3114. //
  3115. // Build a table since each of the three policies are handled the same way
  3116. //
  3117. ASSERT( AzpeObjectHandle != NULL );
  3118. RtlZeroMemory( &Context, sizeof(Context) );
  3119. Context.ContextEntry[AZP_GET_ACL_CONTEXT_ADMINS].PropertyId = AZ_PROP_POLICY_ADMINS;
  3120. Context.ContextEntry[AZP_GET_ACL_CONTEXT_ADMINS].ppPolicyRights = ppPolicyAdminRights;
  3121. Context.ContextEntry[AZP_GET_ACL_CONTEXT_READERS].PropertyId = AZ_PROP_POLICY_READERS;
  3122. Context.ContextEntry[AZP_GET_ACL_CONTEXT_READERS].ppPolicyRights = ppPolicyReaderRights;
  3123. Context.ContextEntry[AZP_GET_ACL_CONTEXT_DELEGATORS].PropertyId = AZ_PROP_DELEGATED_POLICY_USERS;
  3124. Context.ContextEntry[AZP_GET_ACL_CONTEXT_DELEGATORS].ppPolicyRights = ppDelegatedPolicyUsersRights;
  3125. //
  3126. // Ensure the provider didn't pass bogus parameters
  3127. //
  3128. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_SUBMIT) != 0) {
  3129. ASSERT( FALSE );
  3130. WinStatus = ERROR_INVALID_FLAGS;
  3131. goto Cleanup;
  3132. }
  3133. //
  3134. // Initialize the local security descriptor
  3135. //
  3136. if ( !InitializeSecurityDescriptor( &TempSd, SECURITY_DESCRIPTOR_REVISION) ) {
  3137. WinStatus = GetLastError();
  3138. goto Cleanup;
  3139. }
  3140. //
  3141. // Get the Sids from the existing security descriptor on the object
  3142. //
  3143. // Call AzpGetSdWorker for each sid in the Security Descriptor
  3144. //
  3145. if ( OldSd != NULL ) {
  3146. WinStatus = AzpSdToPolicy(
  3147. OldSd,
  3148. ppPolicyAdminRights ? ppPolicyAdminRights[0] : NULL,
  3149. ppPolicyReaderRights ? ppPolicyReaderRights[0] : NULL,
  3150. ppDelegatedPolicyUsersRights ? ppDelegatedPolicyUsersRights[0] : NULL,
  3151. NULL, // No need to determine previous state of boolean
  3152. AzpGetSdWorker,
  3153. &Context, // Context
  3154. lPersistFlags );
  3155. if ( WinStatus != NO_ERROR ) {
  3156. goto Cleanup;
  3157. }
  3158. }
  3159. //
  3160. // If the caller asked for one,
  3161. // Build the DACL
  3162. //
  3163. if ( UpdateDacl ) {
  3164. //
  3165. // Get the Sids that the application submitted
  3166. //
  3167. // Do it for each policy
  3168. //
  3169. for ( PolicyIndex=0; PolicyIndex<AZP_GET_ACL_CONTEXT_COUNT; PolicyIndex++ ) {
  3170. ULONG SubmittedDeltaArrayCount;
  3171. PAZP_DELTA_ENTRY *SubmittedDeltaArray;
  3172. //
  3173. // If the caller isn't asking for this policy,
  3174. // move to the next one
  3175. ContextEntry = &Context.ContextEntry[PolicyIndex];
  3176. if ( ContextEntry->ppPolicyRights == NULL ) {
  3177. continue;
  3178. }
  3179. //
  3180. // Get the submitted delta array from the object
  3181. //
  3182. WinStatus = AzpeGetDeltaArray(
  3183. AzpeObjectHandle,
  3184. ContextEntry->PropertyId,
  3185. &SubmittedDeltaArrayCount,
  3186. &SubmittedDeltaArray );
  3187. if ( WinStatus != NO_ERROR ) {
  3188. ASSERT( FALSE );
  3189. goto Cleanup;
  3190. }
  3191. //
  3192. // Add each Submitted delta entry to passed in delta array
  3193. //
  3194. for ( DeltaIndex=0; DeltaIndex<SubmittedDeltaArrayCount; DeltaIndex++ ) {
  3195. ASSERT( SubmittedDeltaArray[DeltaIndex]->DeltaFlags & AZP_DELTA_SID );
  3196. ASSERT( (SubmittedDeltaArray[DeltaIndex]->DeltaFlags & AZP_DELTA_PERSIST_PROVIDER) == 0 );
  3197. AzpInitSid( &SidString, SubmittedDeltaArray[DeltaIndex]->Sid );
  3198. WinStatus = ObAddDeltaToArray(
  3199. SubmittedDeltaArray[DeltaIndex]->DeltaFlags,
  3200. (GUID *)&SidString,
  3201. &ContextEntry->ResultDeltaArray,
  3202. TRUE ); // Discard entries that are deletions
  3203. if ( WinStatus != NO_ERROR ) {
  3204. goto Cleanup;
  3205. }
  3206. }
  3207. }
  3208. //
  3209. // If the caller wants the list of admins,
  3210. // and the AdminSids list is empty,
  3211. // and this is the authorization store object (and thus doesn't inherit PolicyAdmins),
  3212. // create one with just the creator/owner in it
  3213. //
  3214. if ( ppPolicyAdminRights != NULL &&
  3215. Context.ContextEntry[AZP_GET_ACL_CONTEXT_ADMINS].ResultDeltaArray.UsedCount == 0 &&
  3216. ObjectType == OBJECT_TYPE_AZAUTHSTORE ) {
  3217. AzpInitSid( &SidString, AzGlCreatorOwnerSid );
  3218. WinStatus = ObAddDeltaToArray(
  3219. AZP_DELTA_SID | AZP_DELTA_ADD,
  3220. (GUID *)&SidString,
  3221. &Context.ContextEntry[AZP_GET_ACL_CONTEXT_ADMINS].ResultDeltaArray,
  3222. TRUE ); // Discard entries that are deletions
  3223. if ( WinStatus != NO_ERROR ) {
  3224. goto Cleanup;
  3225. }
  3226. SetCreatorOwner = TRUE;
  3227. }
  3228. //
  3229. // Compute the size of the DACL
  3230. //
  3231. // Do it for each policy
  3232. //
  3233. DaclSize = sizeof( ACL );
  3234. for ( PolicyIndex=0; PolicyIndex<AZP_GET_ACL_CONTEXT_COUNT; PolicyIndex++ ) {
  3235. ULONG i;
  3236. //
  3237. // If the caller isn't asking for this policy,
  3238. // move to the next one
  3239. ContextEntry = &Context.ContextEntry[PolicyIndex];
  3240. if ( ContextEntry->ppPolicyRights == NULL ) {
  3241. continue;
  3242. }
  3243. //
  3244. // Determine the size of the ACLS after adding these ACEs
  3245. //
  3246. for ( i = 0; i < ContextEntry->ResultDeltaArray.UsedCount; i++ ) {
  3247. PAZP_DELTA_ENTRY DeltaEntry = (PAZP_DELTA_ENTRY)ContextEntry->ResultDeltaArray.Array[i];
  3248. ASSERT( DeltaEntry->DeltaFlags & AZP_DELTA_SID );
  3249. ASSERT( DeltaEntry->DeltaFlags & AZP_DELTA_ADD );
  3250. SidSize = GetLengthSid( DeltaEntry->Sid );
  3251. //
  3252. // We have one right count for delegate user's attribute specific ACE
  3253. //
  3254. if ( PolicyIndex == AZP_GET_ACL_CONTEXT_DELEGATORS &&
  3255. pDelegatedUsersAttributeRights != NULL && pAttributeGuid != NULL ) {
  3256. DaclSize += sizeof( ACE_HEADER ) + sizeof ( ACCESS_MASK ) + SidSize +
  3257. + sizeof (ULONG) // For object ACE flags
  3258. + sizeof( GUID ); // For attribute GUID
  3259. }
  3260. for ( RightsCountIndex = 0;
  3261. ContextEntry->ppPolicyRights[RightsCountIndex] != NULL;
  3262. RightsCountIndex++ ) {
  3263. DaclSize += sizeof( ACE_HEADER ) + sizeof ( ACCESS_MASK ) + SidSize;
  3264. if ( ContextEntry->ppPolicyRights[RightsCountIndex]->lUserRightsFlags &
  3265. INHERIT_ONLY_ACE ) {
  3266. DaclSize += sizeof (ULONG) // For object ACE flags
  3267. + sizeof( GUID ); // For object GUID
  3268. }
  3269. }
  3270. }
  3271. }
  3272. //
  3273. // Allocate a temporary buffer for the DACL
  3274. //
  3275. SafeAllocaAllocate( TempDacl, DaclSize )
  3276. if ( TempDacl == NULL ) {
  3277. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  3278. goto Cleanup;
  3279. }
  3280. //
  3281. // Fill in the DACL
  3282. //
  3283. if ( !InitializeAcl( TempDacl, DaclSize, ACL_REVISION ) ) {
  3284. WinStatus = GetLastError();
  3285. goto Cleanup;
  3286. }
  3287. for ( PolicyIndex=0; PolicyIndex<AZP_GET_ACL_CONTEXT_COUNT; PolicyIndex++ ) {
  3288. //
  3289. // If the caller isn't asking for this policy,
  3290. // move to the next one
  3291. ContextEntry = &Context.ContextEntry[PolicyIndex];
  3292. if ( ContextEntry->ppPolicyRights == NULL ) {
  3293. continue;
  3294. }
  3295. //
  3296. // If there are no Sids to add,
  3297. // move on to the next one
  3298. //
  3299. if ( ContextEntry->ResultDeltaArray.UsedCount == 0 ) {
  3300. continue;
  3301. }
  3302. //
  3303. // Loop for each right to add
  3304. //
  3305. for ( RightsCountIndex = 0;
  3306. ContextEntry->ppPolicyRights[RightsCountIndex] != NULL;
  3307. RightsCountIndex++ ) {
  3308. PAZP_POLICY_USER_RIGHTS pPolicyRights = ContextEntry->ppPolicyRights[RightsCountIndex];
  3309. WinStatus = AzpAddSidsToAcl(
  3310. &ContextEntry->ResultDeltaArray,
  3311. pPolicyRights->lUserRightsFlags,
  3312. pPolicyRights->lUserRightsMask,
  3313. TempDacl,
  3314. (pPolicyRights->lUserRightsFlags & INHERIT_ONLY_ACE) ? pDelegatedObjectGuid:NULL );
  3315. if ( WinStatus != NO_ERROR ) {
  3316. goto Cleanup;
  3317. }
  3318. }
  3319. //
  3320. // If we are processing delegators and the caller
  3321. // asks us to put delegated users' attribute rights
  3322. //
  3323. if ( PolicyIndex == AZP_GET_ACL_CONTEXT_DELEGATORS &&
  3324. pDelegatedUsersAttributeRights != NULL && pAttributeGuid != NULL ) {
  3325. WinStatus = AzpAddSidsToAcl(
  3326. &ContextEntry->ResultDeltaArray,
  3327. pDelegatedUsersAttributeRights->lUserRightsFlags,
  3328. pDelegatedUsersAttributeRights->lUserRightsMask,
  3329. TempDacl,
  3330. pAttributeGuid
  3331. );
  3332. if ( WinStatus != NO_ERROR ) {
  3333. goto Cleanup;
  3334. }
  3335. }
  3336. }
  3337. //
  3338. // Add the DACL to the security descriptor
  3339. //
  3340. if ( !SetSecurityDescriptorDacl(
  3341. &TempSd,
  3342. TRUE,
  3343. TempDacl,
  3344. FALSE ) ) {
  3345. WinStatus = GetLastError();
  3346. goto Cleanup;
  3347. }
  3348. //
  3349. // If this is the authorization store object, and
  3350. // the caller isn't asking for the SD of the "container" object for delegators,
  3351. // mark the SD as protected so azroles has absolute control of the DACL.
  3352. //
  3353. if ( ObjectType == OBJECT_TYPE_AZAUTHSTORE &&
  3354. (ppPolicyAdminRights != NULL || ppPolicyReaderRights != NULL) ) {
  3355. TempSd.Control |= SE_DACL_PROTECTED;
  3356. }
  3357. }
  3358. //
  3359. // If the caller asked for one, Build the SACL
  3360. //
  3361. // Only container objects can have a SACL
  3362. //
  3363. if ( pSaclRights && IsContainerObject( ObjectType ) ) {
  3364. //
  3365. // Only apply a SACL if one is configured
  3366. //
  3367. if ( ((PGENERIC_OBJECT)AzpeObjectHandle)->ApplySacl ) {
  3368. //
  3369. // Determine the size of the SACL
  3370. //
  3371. SaclSize = sizeof(ACL) +
  3372. sizeof(ACE_HEADER) +
  3373. sizeof(ACCESS_MASK) +
  3374. AzGlWorldSidSize;
  3375. //
  3376. // Allocate a buffer for the SACL
  3377. //
  3378. SafeAllocaAllocate( TempSacl, SaclSize );
  3379. if ( TempSacl == NULL ) {
  3380. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  3381. goto Cleanup;
  3382. }
  3383. //
  3384. // Initialize the SACL
  3385. //
  3386. if ( !InitializeAcl( TempSacl, SaclSize, ACL_REVISION ) ) {
  3387. WinStatus = GetLastError();
  3388. goto Cleanup;
  3389. }
  3390. if ( !AddAuditAccessAceEx( TempSacl,
  3391. ACL_REVISION,
  3392. pSaclRights->lUserRightsFlags,
  3393. pSaclRights->lUserRightsMask,
  3394. AzGlWorldSid,
  3395. TRUE, // Audit Success
  3396. TRUE )) { // Audit Failure
  3397. WinStatus = GetLastError();
  3398. goto Cleanup;
  3399. }
  3400. //
  3401. // Add the SACL to the security descriptor
  3402. //
  3403. // The SACL is never protected
  3404. //
  3405. if ( !SetSecurityDescriptorSacl(
  3406. &TempSd,
  3407. TRUE,
  3408. TempSacl,
  3409. FALSE ) ) {
  3410. WinStatus = GetLastError();
  3411. goto Cleanup;
  3412. }
  3413. }
  3414. }
  3415. //
  3416. // Return a self relative SD back to the caller.
  3417. //
  3418. WinStatus = AzpConvertAbsoluteSDToSelfRelative(
  3419. &TempSd,
  3420. NewSd );
  3421. if ( WinStatus != NO_ERROR ) {
  3422. goto Cleanup;
  3423. }
  3424. //
  3425. // Tell the caller that he needs to re-read the security descriptor
  3426. //
  3427. if ( SetCreatorOwner ) {
  3428. WinStatus = ERROR_EMPTY;
  3429. }
  3430. Cleanup:
  3431. //
  3432. // Free the temporary resultant delta array
  3433. //
  3434. for ( PolicyIndex=0; PolicyIndex<AZP_GET_ACL_CONTEXT_COUNT; PolicyIndex++ ) {
  3435. //
  3436. // If the caller isn't asking for this policy,
  3437. // move to the next one
  3438. ContextEntry = &Context.ContextEntry[PolicyIndex];
  3439. ASSERT( ContextEntry->ResultDeltaArray.UsedCount == 0 ||
  3440. ContextEntry->ppPolicyRights != NULL );
  3441. ObFreeDeltaArray( &ContextEntry->ResultDeltaArray,
  3442. TRUE ); // FreeAllEntries
  3443. }
  3444. SafeAllocaFree( TempDacl )
  3445. SafeAllocaFree( TempSacl )
  3446. return WinStatus;
  3447. }
  3448. DWORD
  3449. AzpSetSdWorker(
  3450. IN PVOID Context,
  3451. IN ULONG lPersistFlags,
  3452. IN ULONG PropertyId,
  3453. IN PSID Sid
  3454. )
  3455. /*++
  3456. Routine Description:
  3457. Worker routine for AzpeSetSecurityDescriptorIntoCache. It is a callback routine for AzpSdToPolicy.
  3458. It is called for each policy SID and simply call AzpeAddPropertyItemSid for the SID.
  3459. Arguments:
  3460. Context - Context from AzpeSetSecurityDescriptorIntoCache In this case, the context is the
  3461. AzpeObjectHandle.
  3462. lPersistFlags - Internal flags
  3463. PropertyId - AZ_PROP_* identifying the right granted to the Sid.
  3464. Sid - Specifies the Sid the right is granted to.
  3465. Return Values:
  3466. NO_ERROR - The operation was successful
  3467. Other errors from AzpeAddPropertyItemSid.
  3468. --*/
  3469. {
  3470. //
  3471. // For AZ_PROP_APPLY_STORE_SACL, call AzpeSetProperty.
  3472. //
  3473. if ( PropertyId == AZ_PROP_APPLY_STORE_SACL ) {
  3474. return AzpeSetProperty(
  3475. (AZPE_OBJECT_HANDLE)Context,
  3476. lPersistFlags,
  3477. PropertyId,
  3478. Sid );
  3479. //
  3480. // For all other property IDs, simply add the sid to the cache
  3481. //
  3482. } else {
  3483. return AzpeAddPropertyItemSid(
  3484. (AZPE_OBJECT_HANDLE)Context,
  3485. lPersistFlags,
  3486. PropertyId,
  3487. Sid );
  3488. }
  3489. }
  3490. DWORD
  3491. AzpeSetSecurityDescriptorIntoCache(
  3492. IN AZPE_OBJECT_HANDLE AzpeObjectHandle,
  3493. IN PSECURITY_DESCRIPTOR pSD,
  3494. IN ULONG lPersistFlags,
  3495. IN PAZP_POLICY_USER_RIGHTS pAdminRights,
  3496. IN PAZP_POLICY_USER_RIGHTS pReaderRights OPTIONAL,
  3497. IN PAZP_POLICY_USER_RIGHTS pDelegatedUserRights OPTIONAL,
  3498. IN PAZP_POLICY_USER_RIGHTS pSaclRights OPTIONAL
  3499. )
  3500. /*++
  3501. Routine Description:
  3502. AzpeSetSecurityDescriptorIntoCache is a support routine for the AZ_PROP_POLICY_ADMINS,
  3503. AZ_PROP_POLICY_READERS, AZ_PROP_DELEGATED_POLICY_USERS, and AZ_PROP_APPLY_STORE_SACL properties.
  3504. It inspects the security descriptor for the object and set each of the above
  3505. properties based on the ACEs found.
  3506. The routine walks the DACL of the security descriptor for an object then
  3507. calls AzpeAddPropertyItemSid for each non-inherited ACE. The provider
  3508. may choose to call AzpeAddPropertyItemSid itself if the provider's security model
  3509. does not match that provided by this routine.
  3510. The routine also walks the SACL of the security descriptor and calls AzpeSetProperty
  3511. setting AZ_PROP_APPLY_STORE_SACL to TRUE or FALSE depending on whether there is a
  3512. non-inherited ACE specifying the rights passed in pSaclRights.
  3513. This routine should only be called from a thread processing a call to AzPersistOpen,
  3514. AzPersistUpdateCache, AzPersistUpdateChildrenCache or AzPersistRefresh.
  3515. This routine may also be called from a thread processing AzPersistSubmit if the
  3516. submitted AZ_PROP_POLICY_ADMINS list is empty. In that case, the provider should default
  3517. the AZ_PROP_POLICY_ADMINS list to the owner of the submitted file and should tell AzRoles
  3518. who that own is by either calling AzpeSetSecurityDescriptorIntoCache or AzpeAddPropertyItemSid.
  3519. Arguments:
  3520. AzpeObjectHandle - Pointer to object whose policy admins and readers needs to be loaded.
  3521. pSD - The current security descriptor for the object on the object in the store
  3522. lPersistFlags - Internal flags
  3523. pAdminRights - Rights for admins (Mask and Flags)
  3524. pReaderRights - Rights for readers (Mask and Flags). Specify NULL if the readers list
  3525. need not be added. (For instance, for AzPersistSubmit as described above.)
  3526. pDelegatedUserRights - An optional parameter specifying the delegated user's rights (Mask and Flags)
  3527. pSaclRights - Specifies the rights for the SACL. By convention the provider
  3528. should specify a mask consisting of all the access bits indicating modification
  3529. to the policy store. For instance, DELETE|WRITE_DAC|WRITE_OWNER|FILE_GENERIC_WRITE,
  3530. would be appropriate for a file based store.
  3531. The parameter should be NULL if AZ_PROP_APPLY_STORE_SACL isn't being set
  3532. into the cache. For instance, when caller doesn't have SE_SECURITY_PRIVILEGE
  3533. or during AzPersistSubmit if the submitted AZ_PROP_POLICY_ADMINS list is empty.
  3534. Return Values:
  3535. NO_ERROR - The operation was successful
  3536. ERROR_INVALID_FLAGS - lPersistFlags is invalid.
  3537. ERROR_INVALID_PARAMETER - Property ID is invalid
  3538. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  3539. --*/
  3540. {
  3541. //
  3542. // Validation
  3543. //
  3544. ASSERT( AzpeObjectHandle != NULL );
  3545. //
  3546. // Ensure the provider didn't pass bogus flags
  3547. //
  3548. if ( (lPersistFlags & ~AZPE_FLAGS_PERSIST_MASK) != 0) {
  3549. ASSERT( FALSE );
  3550. return ERROR_INVALID_FLAGS;
  3551. }
  3552. //
  3553. // Call AzpSetSdWorker for each sid in the Security Descriptor
  3554. //
  3555. return AzpSdToPolicy(
  3556. pSD,
  3557. pAdminRights,
  3558. pReaderRights,
  3559. pDelegatedUserRights,
  3560. pSaclRights,
  3561. AzpSetSdWorker,
  3562. AzpeObjectHandle, // Context
  3563. lPersistFlags );
  3564. }
  3565. BOOL
  3566. AzpeAzStoreIsBatchUpdateMode(
  3567. IN AZPE_OBJECT_HANDLE hObject
  3568. )
  3569. /*++
  3570. Description:
  3571. Determines if the az store is initialized with a batch update flag.
  3572. This flag is set if the store is created to update massive amount of objects.
  3573. Arguments:
  3574. hObject - the object handle
  3575. Return Values:
  3576. True if the initialization flag has that bit set.
  3577. --*/
  3578. {
  3579. PAZP_AZSTORE pAzStore = (PAZP_AZSTORE)( ((PGENERIC_OBJECT)hObject)->AzStoreObject );
  3580. return (pAzStore->InitializeFlag & AZ_AZSTORE_FLAG_BATCH_UPDATE);
  3581. }
  3582. AZPE_OBJECT_HANDLE
  3583. AzpeGetAuthorizationStore(
  3584. IN AZPE_OBJECT_HANDLE hObject
  3585. )
  3586. /*++
  3587. Description:
  3588. Get the store handle from any object
  3589. Arguments:
  3590. hObject - the object handle
  3591. Return Values:
  3592. Returns the object's store handle
  3593. --*/
  3594. {
  3595. return (AZPE_OBJECT_HANDLE)( ((PGENERIC_OBJECT)hObject)->AzStoreObject );
  3596. }