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

7843 lines
226 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. authzp.c
  5. Abstract:
  6. This module implements the internal worker routines for access check and
  7. audit APIs.
  8. Author:
  9. Kedar Dubhashi - March 2000
  10. Environment:
  11. User mode only.
  12. Revision History:
  13. Created - March 2000
  14. --*/
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <authzp.h>
  18. DWORD AuthzpPrincipalSelfSidBuffer[] = {0x101, 0x5000000, 0xA};
  19. PSID pAuthzPrincipalSelfSid = (PSID) AuthzpPrincipalSelfSidBuffer;
  20. USHORT AuthzpPrincipalSelfSidLen = sizeof(AuthzpPrincipalSelfSidBuffer);
  21. DWORD AuthzpCreatorOwnerSidBuffer[] = {0x101, 0x3000000, 0x0};
  22. PSID pAuthzCreatorOwnerSid = (PSID) AuthzpCreatorOwnerSidBuffer;
  23. //
  24. // This is used to get the index of the first '1' bit in a given byte.
  25. // a[0] = 9 // This is a dummy.
  26. // a[1] = 0
  27. // a[2] = 1
  28. // a[3] = 0
  29. // ...
  30. // a[i] = first '1' bit from LSB
  31. //
  32. UCHAR AuthzpByteToIndexLookupTable[] = {
  33. 9,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  34. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  35. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  36. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  37. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  38. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  39. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  40. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  41. 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  42. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  43. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  44. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  45. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  46. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  47. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  48. 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
  49. };
  50. #ifndef AUTHZ_DEBUG_MEMLEAK
  51. #define AuthzpAlloc(s) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (s))
  52. #define AuthzpFree(p) LocalFree((p))
  53. #else
  54. //
  55. // This is to be used for debugging memory leaks. Primitive method but works in
  56. // a small project like this.
  57. //
  58. PVOID
  59. AuthzpAlloc(IN DWORD Size)
  60. {
  61. PVOID l = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Size);
  62. wprintf(L"Allocated %d at %x\n", Size, l);
  63. return l;
  64. }
  65. VOID
  66. AuthzpFree(PVOID l)
  67. {
  68. LocalFree(l);
  69. wprintf(L"Freeing %x\n", l);
  70. }
  71. #endif
  72. BOOL
  73. DllMain(
  74. HINSTANCE hInstance,
  75. DWORD dwReason,
  76. LPVOID lpReserved
  77. )
  78. /*++
  79. Routine Description
  80. This initializes global events and variables for the DLL.
  81. Arguments
  82. Predefined DllMain arguments.
  83. Return Value
  84. Boolean: TRUE on success, FALSE on fail.
  85. --*/
  86. {
  87. UNREFERENCED_PARAMETER(hInstance);
  88. UNREFERENCED_PARAMETER(lpReserved);
  89. UNREFERENCED_PARAMETER(dwReason);
  90. return TRUE;
  91. }
  92. BOOL
  93. AuthzpVerifyAccessCheckArguments(
  94. IN PAUTHZI_CLIENT_CONTEXT pCC,
  95. IN PAUTHZ_ACCESS_REQUEST pRequest,
  96. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  97. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  98. IN DWORD OptionalSecurityDescriptorCount,
  99. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  100. IN OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults OPTIONAL
  101. )
  102. /*++
  103. Routine description:
  104. This routine validates inputs for the access check call. It also initializes
  105. input parameters to default.
  106. Arguments:
  107. pCC - Pointer to the client context.
  108. pRequest - Access request specifies the desired access mask, principal self
  109. sid, the object type list strucutre (if any).
  110. pSecurityDescriptor - Primary security descriptor to be used for access
  111. checks. The owner sid for the object is picked from this one. A NULL
  112. DACL in this security descriptor represents a NULL DACL for the entire
  113. object. A NULL SACL in this security descriptor is treated the same way
  114. as an EMPTY SACL.
  115. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  116. of security descriptors. NULL ACLs in these security descriptors are
  117. treated as EMPTY ACLS and the ACL for the entire object is the logical
  118. concatenation of all the ACLs.
  119. OptionalSecurityDescriptorCount - Number of optional security descriptors
  120. This does not include the Primary security descriptor.
  121. pReply - Supplies a pointer to a reply structure used to return the results.
  122. phAccessCheckResults - Supplies a pointer to return a handle to the cached results
  123. of access check.
  124. Return Value:
  125. A value of TRUE is returned if the routine is successful. Otherwise,
  126. a value of FALSE is returned. In the failure case, error value may be
  127. retrieved using GetLastError().
  128. --*/
  129. {
  130. if (ARGUMENT_PRESENT(phAccessCheckResults))
  131. {
  132. *phAccessCheckResults = NULL;
  133. }
  134. if (!ARGUMENT_PRESENT(pCC))
  135. {
  136. SetLastError(ERROR_INVALID_PARAMETER);
  137. return FALSE;
  138. }
  139. if (!ARGUMENT_PRESENT(pSecurityDescriptor))
  140. {
  141. SetLastError(ERROR_INVALID_PARAMETER);
  142. return FALSE;
  143. }
  144. #ifdef DBG
  145. if (!RtlValidSecurityDescriptor(pSecurityDescriptor))
  146. {
  147. SetLastError(ERROR_INVALID_PARAMETER);
  148. return FALSE;
  149. }
  150. #endif
  151. if (!ARGUMENT_PRESENT(RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor)))
  152. {
  153. SetLastError(ERROR_INVALID_PARAMETER);
  154. return FALSE;
  155. }
  156. if ((0 != OptionalSecurityDescriptorCount) && (!ARGUMENT_PRESENT(OptionalSecurityDescriptorArray)))
  157. {
  158. SetLastError(ERROR_INVALID_PARAMETER);
  159. return FALSE;
  160. }
  161. //
  162. // The caller can specify one of the two values for Reply->ResultListLength
  163. // a. 1 - representing the whole object.
  164. // b. pRequest->ObjectTypeListLength - for every node in the type list.
  165. //
  166. if ((1 != pReply->ResultListLength) &&
  167. (pReply->ResultListLength != pRequest->ObjectTypeListLength))
  168. {
  169. SetLastError(ERROR_INVALID_PARAMETER);
  170. return FALSE;
  171. }
  172. return TRUE;
  173. }
  174. BOOL
  175. AuthzpVerifyOpenObjectArguments(
  176. IN PAUTHZI_CLIENT_CONTEXT pCC,
  177. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  178. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  179. IN DWORD OptionalSecurityDescriptorCount,
  180. IN PAUTHZI_AUDIT_EVENT pAuditEvent
  181. )
  182. /*++
  183. Routine description:
  184. This routine validates inputs for AuthzOpenObjectAuditAlarm.
  185. Arguments:
  186. pCC - Pointer to the client context.
  187. pRequest - Access request specifies the desired access mask, principal self
  188. sid, the object type list strucutre (if any).
  189. pSecurityDescriptor - Primary security descriptor to be used for access
  190. checks. The owner sid for the object is picked from this one. A NULL
  191. DACL in this security descriptor represents a NULL DACL for the entire
  192. object. A NULL SACL in this security descriptor is treated the same way
  193. as an EMPTY SACL.
  194. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  195. of security descriptors. NULL ACLs in these security descriptors are
  196. treated as EMPTY ACLS and the ACL for the entire object is the logical
  197. concatenation of all the ACLs.
  198. OptionalSecurityDescriptorCount - Number of optional security descriptors
  199. This does not include the Primary security descriptor.
  200. pReply - Supplies a pointer to a reply structure containing the results of
  201. an AuthzAccessCheck.
  202. pAuditEvent - pointer to AUTHZ_AUDIT_EVENT.
  203. Return Value:
  204. A value of TRUE is returned if the routine is successful. Otherwise,
  205. a value of FALSE is returned. In the failure case, error value may be
  206. retrieved using GetLastError().
  207. --*/
  208. {
  209. if (!ARGUMENT_PRESENT(pCC))
  210. {
  211. SetLastError(ERROR_INVALID_PARAMETER);
  212. return FALSE;
  213. }
  214. if (!ARGUMENT_PRESENT(pAuditEvent))
  215. {
  216. SetLastError(ERROR_INVALID_PARAMETER);
  217. return FALSE;
  218. }
  219. if (!ARGUMENT_PRESENT(pSecurityDescriptor))
  220. {
  221. SetLastError(ERROR_INVALID_PARAMETER);
  222. return FALSE;
  223. }
  224. #if DBG
  225. if (!RtlValidSecurityDescriptor(pSecurityDescriptor))
  226. {
  227. SetLastError(ERROR_INVALID_PARAMETER);
  228. return FALSE;
  229. }
  230. #endif
  231. if (!ARGUMENT_PRESENT(RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor)))
  232. {
  233. SetLastError(ERROR_INVALID_PARAMETER);
  234. return FALSE;
  235. }
  236. if ((0 != OptionalSecurityDescriptorCount) && (!ARGUMENT_PRESENT(OptionalSecurityDescriptorArray)))
  237. {
  238. SetLastError(ERROR_INVALID_PARAMETER);
  239. return FALSE;
  240. }
  241. return TRUE;
  242. }
  243. BOOL
  244. AuthzpCaptureObjectTypeList(
  245. IN POBJECT_TYPE_LIST ObjectTypeList,
  246. IN DWORD ObjectTypeListLength,
  247. OUT PIOBJECT_TYPE_LIST *CapturedObjectTypeList,
  248. OUT PIOBJECT_TYPE_LIST *CapturedCachingObjectTypeList OPTIONAL
  249. )
  250. /*++
  251. Routine description:
  252. This routine captures an object type list into internal structres.
  253. Arguments:
  254. ObjectTypeList - Object type list to capture.
  255. ObjectTypeListLength - Length of the object type list.
  256. CapturedObjectTypeList - To return the internal representation of the
  257. input list. This routine allocates memory for this structure.
  258. CapturedCachingObjectTypeList - To return internal representation of the
  259. input list This list will be used to hold static always-granted access bits.
  260. This routine allocates memory for this structure.
  261. Return Value:
  262. A value of TRUE is returned if the routine is successful. Otherwise,
  263. a value of FALSE is returned. In the failure case, error value may be
  264. retrieved using GetLastError().
  265. --*/
  266. {
  267. DWORD i = 0;
  268. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  269. PIOBJECT_TYPE_LIST LocalCachingTypeList = NULL;
  270. DWORD Size = 0;
  271. BOOL b = TRUE;
  272. DWORD Levels[ACCESS_MAX_LEVEL + 1];
  273. if (ARGUMENT_PRESENT(CapturedCachingObjectTypeList))
  274. {
  275. *CapturedCachingObjectTypeList = NULL;
  276. }
  277. *CapturedObjectTypeList = NULL;
  278. if ((0 == ObjectTypeListLength) || (!ARGUMENT_PRESENT(ObjectTypeList)))
  279. {
  280. SetLastError(ERROR_INVALID_PARAMETER);
  281. return FALSE;
  282. }
  283. Size = sizeof(IOBJECT_TYPE_LIST) * ObjectTypeListLength;
  284. LocalTypeList = (PIOBJECT_TYPE_LIST) AuthzpAlloc(Size);
  285. if (AUTHZ_ALLOCATION_FAILED(LocalTypeList))
  286. {
  287. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  288. return FALSE;
  289. }
  290. for (i = 0; i < ObjectTypeListLength; i++)
  291. {
  292. USHORT CurrentLevel;
  293. CurrentLevel = ObjectTypeList[i].Level;
  294. if (CurrentLevel > ACCESS_MAX_LEVEL)
  295. {
  296. SetLastError(ERROR_INVALID_PARAMETER);
  297. b = FALSE;
  298. goto Cleanup;
  299. }
  300. //
  301. // Copy data the caller passed in.
  302. //
  303. LocalTypeList[i].Level = CurrentLevel;
  304. LocalTypeList[i].Flags = 0;
  305. LocalTypeList[i].ObjectType = *ObjectTypeList[i].ObjectType;
  306. LocalTypeList[i].Remaining = 0;
  307. LocalTypeList[i].CurrentGranted = 0;
  308. LocalTypeList[i].CurrentDenied = 0;
  309. //
  310. // Ensure that the level number is consistent with the
  311. // level number of the previous entry.
  312. //
  313. if (0 == i)
  314. {
  315. if (0 != CurrentLevel)
  316. {
  317. SetLastError(ERROR_INVALID_PARAMETER);
  318. b = FALSE;
  319. goto Cleanup;
  320. }
  321. }
  322. else
  323. {
  324. //
  325. // The previous entry is either:
  326. // my immediate parent,
  327. // my sibling, or
  328. // the child (or grandchild, etc.) of my sibling.
  329. //
  330. if ( CurrentLevel > LocalTypeList[i-1].Level + 1 )
  331. {
  332. SetLastError(ERROR_INVALID_PARAMETER);
  333. b = FALSE;
  334. goto Cleanup;
  335. }
  336. //
  337. // Don't support two roots.
  338. //
  339. if (0 == CurrentLevel)
  340. {
  341. SetLastError(ERROR_INVALID_PARAMETER);
  342. b = FALSE;
  343. goto Cleanup;
  344. }
  345. }
  346. //
  347. // If the above rules are maintained,
  348. // then my parent object is the last object seen that
  349. // has a level one less than mine.
  350. //
  351. if (0 == CurrentLevel)
  352. {
  353. LocalTypeList[i].ParentIndex = -1;
  354. }
  355. else
  356. {
  357. LocalTypeList[i].ParentIndex = Levels[CurrentLevel-1];
  358. }
  359. //
  360. // Save this obect as the last object seen at this level.
  361. //
  362. Levels[CurrentLevel] = i;
  363. }
  364. //
  365. // If the caller has requested caching then create a copy of the object type
  366. // list that we just captured.
  367. //
  368. if (ARGUMENT_PRESENT(CapturedCachingObjectTypeList))
  369. {
  370. LocalCachingTypeList = (PIOBJECT_TYPE_LIST) AuthzpAlloc(Size);
  371. if (AUTHZ_ALLOCATION_FAILED(LocalCachingTypeList))
  372. {
  373. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  374. b = FALSE;
  375. goto Cleanup;
  376. }
  377. memcpy(
  378. LocalCachingTypeList,
  379. LocalTypeList,
  380. Size
  381. );
  382. *CapturedCachingObjectTypeList = LocalCachingTypeList;
  383. }
  384. *CapturedObjectTypeList = LocalTypeList;
  385. return TRUE;
  386. Cleanup:
  387. AuthzpFreeNonNull(LocalTypeList);
  388. return FALSE;
  389. }
  390. VOID
  391. AuthzpFillReplyStructure(
  392. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  393. IN DWORD Error,
  394. IN ACCESS_MASK GrantedAccess
  395. )
  396. /*++
  397. Routine description:
  398. This routine fills the reply structure with supplied parameters.
  399. Arguments:
  400. pReply - The reply structure to fill.
  401. Error - The same error value is filled in all the elements of the array.
  402. GrantedAccess - Access granted to the entire object.
  403. Return Value:
  404. None.
  405. --*/
  406. {
  407. DWORD i = 0;
  408. for (i = 0; i < pReply->ResultListLength; i++)
  409. {
  410. pReply->GrantedAccessMask[i] = GrantedAccess;
  411. pReply->Error[i] = Error;
  412. }
  413. }
  414. BOOL
  415. AuthzpMaximumAllowedAccessCheck(
  416. IN PAUTHZI_CLIENT_CONTEXT pCC,
  417. IN PAUTHZ_ACCESS_REQUEST pRequest,
  418. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  419. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  420. IN DWORD OptionalSecurityDescriptorCount,
  421. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  422. IN OUT PIOBJECT_TYPE_LIST LocalCachingTypeList OPTIONAL,
  423. IN DWORD LocalTypeListLength,
  424. IN BOOL ObjectTypeListPresent,
  425. OUT PDWORD pCachingFlags
  426. )
  427. /*++
  428. Routine description:
  429. This routine does a maximum allowed access check on multiple security
  430. descriptors. In case of restricted tokens, access granted is a bitwise
  431. AND of granted access by the normal as well as the restricted parts of
  432. the client context.
  433. Arguments:
  434. pCC - Pointer to the client context.
  435. pRequest - Access request specifies the desired access mask, principal self
  436. sid, the object type list strucutre (if any).
  437. pSecurityDescriptor - Primary security descriptor to be used for access
  438. checks. The owner sid for the object is picked from this one. A NULL
  439. DACL in this security descriptor represents a NULL DACL for the entire
  440. object. A NULL SACL in this security descriptor is treated the same way
  441. as an EMPTY SACL.
  442. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  443. of security descriptors. NULL ACLs in these security descriptors are
  444. treated as EMPTY ACLS and the ACL for the entire object is the logical
  445. concatenation of all the ACLs.
  446. OptionalSecurityDescriptorCount - Number of optional security descriptors
  447. This does not include the Primary security descriptor.
  448. LocalTypeList - Internal object type list structure used to hold
  449. intermediate results.
  450. LocalCachingTypeList - Internal object type list structure used to hold
  451. intermediate results for static granted bits.
  452. LocalTypeListLength - Length of the array represnting the object.
  453. ObjectTypeListPresent - Whether the called supplied an object type list.
  454. pCachingFlags - To return the flags that will be stored in the caching
  455. handle if the caller requested caching.
  456. Return Value:
  457. A value of TRUE is returned if the routine is successful. Otherwise,
  458. a value of FALSE is returned. In the failure case, error value may be
  459. retrieved using GetLastError().
  460. --*/
  461. {
  462. BOOL b = TRUE;
  463. //
  464. // Do the access check with the non-restricted part of the client context.
  465. //
  466. b = AuthzpMaximumAllowedMultipleSDAccessCheck(
  467. pCC,
  468. pRequest,
  469. pSecurityDescriptor,
  470. OptionalSecurityDescriptorArray,
  471. OptionalSecurityDescriptorCount,
  472. LocalTypeList,
  473. LocalCachingTypeList,
  474. LocalTypeListLength,
  475. ObjectTypeListPresent,
  476. FALSE, // Non-restricted access check
  477. pCachingFlags
  478. );
  479. #ifdef AUTHZ_DEBUG
  480. wprintf(L"AuthzpMaximumAllowedAccessCheck: GrantedAccess = %x\n",
  481. LocalTypeList->CurrentGranted);
  482. #endif
  483. if (!b)
  484. {
  485. return FALSE;
  486. }
  487. //
  488. // Do the access check with the restricted part of the client context if
  489. // it exists.
  490. //
  491. if (AUTHZ_TOKEN_RESTRICTED(pCC))
  492. {
  493. b = AuthzpMaximumAllowedMultipleSDAccessCheck(
  494. pCC,
  495. pRequest,
  496. pSecurityDescriptor,
  497. OptionalSecurityDescriptorArray,
  498. OptionalSecurityDescriptorCount,
  499. LocalTypeList,
  500. LocalCachingTypeList,
  501. LocalTypeListLength,
  502. ObjectTypeListPresent,
  503. TRUE, // Restricted access check
  504. pCachingFlags
  505. );
  506. #ifdef AUTHZ_DEBUG
  507. wprintf(L"AuthzpMaximumAllowedAccessCheck: RestrictedGrantedAccess = %x\n",
  508. LocalTypeList->CurrentGranted);
  509. #endif
  510. }
  511. return b;
  512. }
  513. BOOL
  514. AuthzpMaximumAllowedMultipleSDAccessCheck(
  515. IN PAUTHZI_CLIENT_CONTEXT pCC,
  516. IN PAUTHZ_ACCESS_REQUEST pRequest,
  517. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  518. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  519. IN DWORD OptionalSecurityDescriptorCount,
  520. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  521. IN OUT PIOBJECT_TYPE_LIST LocalCachingTypeList OPTIONAL,
  522. IN DWORD LocalTypeListLength,
  523. IN BOOL ObjectTypeListPresent,
  524. IN BOOL Restricted,
  525. OUT PDWORD pCachingFlags
  526. )
  527. /*++
  528. Routine description:
  529. This routine performs access check for all security descriptors provided.
  530. Arguments:
  531. pCC - Pointer to the client context.
  532. pRequest - Access request specifies the desired access mask, principal self
  533. sid, the object type list strucutre (if any).
  534. pSecurityDescriptor - Primary security descriptor to be used for access
  535. checks. The owner sid for the object is picked from this one. A NULL
  536. DACL in this security descriptor represents a NULL DACL for the entire
  537. object. A NULL SACL in this security descriptor is treated the same way
  538. as an EMPTY SACL.
  539. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  540. of security descriptors. NULL ACLs in these security descriptors are
  541. treated as EMPTY ACLS and the ACL for the entire object is the logical
  542. concatenation of all the ACLs.
  543. OptionalSecurityDescriptorCount - Number of optional security descriptors
  544. This does not include the Primary security descriptor.
  545. LocalTypeList - Internal object type list structure used to hold
  546. intermediate results.
  547. LocalCachingTypeList - Internal object type list structure used to hold
  548. intermediate results for static granted bits.
  549. LocalTypeListLength - Length of the array represnting the object.
  550. ObjectTypeListPresent - Whether the called supplied an object type list.
  551. Restricted - Whether the restricted part of the client context should be
  552. used for access check.
  553. pCachingFlags - To return the flags that will be stored in the caching
  554. handle if the caller requested caching.
  555. Return Value:
  556. A value of TRUE is returned if the routine is successful. Otherwise,
  557. a value of FALSE is returned. In the failure case, error value may be
  558. retrieved using GetLastError().
  559. --*/
  560. {
  561. DWORD i = 0;
  562. DWORD j = 0;
  563. DWORD SidCount = 0;
  564. BOOL b = TRUE;
  565. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  566. PACL pAcl = NULL;
  567. PSID pOwnerSid = NULL;
  568. PAUTHZI_SID_HASH_ENTRY pSidHash = NULL;
  569. pOwnerSid = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  570. if (Restricted)
  571. {
  572. //
  573. // For restricted client context, granted access is a bitwise AND of
  574. // granted access from both parts of the context.
  575. //
  576. if (ARGUMENT_PRESENT(LocalCachingTypeList))
  577. {
  578. for (j = 0; j < LocalTypeListLength; j++)
  579. {
  580. LocalTypeList[j].Remaining = LocalTypeList[j].CurrentGranted;
  581. LocalTypeList[j].CurrentGranted = 0;
  582. LocalCachingTypeList[j].Remaining = LocalCachingTypeList[j].CurrentGranted;
  583. LocalCachingTypeList[j].CurrentGranted = 0;
  584. }
  585. }
  586. else
  587. {
  588. for (j = 0; j < LocalTypeListLength; j++)
  589. {
  590. LocalTypeList[j].Remaining = LocalTypeList[j].CurrentGranted;
  591. LocalTypeList[j].CurrentGranted = 0;
  592. }
  593. }
  594. pSidAttr = pCC->RestrictedSids;
  595. SidCount = pCC->RestrictedSidCount;
  596. pSidHash = pCC->RestrictedSidHash;
  597. }
  598. else
  599. {
  600. pSidAttr = pCC->Sids;
  601. SidCount = pCC->SidCount;
  602. pSidHash = pCC->SidHash;
  603. }
  604. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  605. b = AuthzpMaximumAllowedSingleAclAccessCheck(
  606. pCC,
  607. pSidAttr,
  608. SidCount,
  609. pSidHash,
  610. pRequest,
  611. pAcl,
  612. pOwnerSid,
  613. LocalTypeList,
  614. LocalCachingTypeList,
  615. LocalTypeListLength,
  616. ObjectTypeListPresent,
  617. pCachingFlags
  618. );
  619. if (!b)
  620. {
  621. return FALSE;
  622. }
  623. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  624. {
  625. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  626. if (!AUTHZ_NON_NULL_PTR(pAcl))
  627. {
  628. continue;
  629. }
  630. b = AuthzpMaximumAllowedSingleAclAccessCheck(
  631. pCC,
  632. pSidAttr,
  633. SidCount,
  634. pSidHash,
  635. pRequest,
  636. pAcl,
  637. pOwnerSid,
  638. LocalTypeList,
  639. LocalCachingTypeList,
  640. LocalTypeListLength,
  641. ObjectTypeListPresent,
  642. pCachingFlags
  643. );
  644. if (!b)
  645. {
  646. break;
  647. }
  648. }
  649. return b;
  650. }
  651. BOOL
  652. AuthzpMaximumAllowedSingleAclAccessCheck(
  653. IN PAUTHZI_CLIENT_CONTEXT pCC,
  654. IN PSID_AND_ATTRIBUTES pSidAttr,
  655. IN DWORD SidCount,
  656. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  657. IN PAUTHZ_ACCESS_REQUEST pRequest,
  658. IN PACL pAcl,
  659. IN PSID pOwnerSid,
  660. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  661. IN OUT PIOBJECT_TYPE_LIST LocalCachingTypeList OPTIONAL,
  662. IN DWORD LocalTypeListLength,
  663. IN BOOL ObjectTypeListPresent,
  664. OUT PDWORD pCachingFlags
  665. )
  666. /*++
  667. Routine description:
  668. This routine
  669. Arguments:
  670. pCC - Pointer to the client context.
  671. pSidAttr - Sids and attributes to be used for matching the one in the aces.
  672. SidCount - Number of sids in the pSidAttr array
  673. pRequest - Access request specifies the desired access mask, principal self
  674. sid, the object type list strucutre (if any).
  675. pAcl - Discretionary acl against which access check will be performed.
  676. It is assumed that the acl is non-null.
  677. pOwnerSid - To support the future DS requirement of not mapping Creator
  678. Owner at the time of object creation.
  679. LocalTypeList - Internal object type list structure used to hold
  680. intermediate results.
  681. LocalCachingTypeList - Internal object type list structure used to hold
  682. intermediate results for static granted bits.
  683. LocalTypeListLength - Length of the array represnting the object.
  684. ObjectTypeListPresent - Whether the called supplied an object type list.
  685. Restricted - Whether the restricted part of the client context should be
  686. used for access check.
  687. pCachingFlags - To return the flags that will be stored in the caching
  688. handle if the caller requested caching.
  689. Algorithm:
  690. BEGIN_MAX_ALGO
  691. for all aces
  692. skip INHERIT_ONLY aces
  693. ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  694. If (the sid is applicable) AND (Server Sid is also applicable)
  695. Update the entire tree starting at the root.
  696. Grant those bits that have not already been denied.
  697. Note: No one uses these!!
  698. ACCESS_ALLOWED_ACE_TYPE
  699. If the sid is applicable
  700. Update the entire tree starting at the root.
  701. Grant those bits that have not already been denied.
  702. ACCESS_ALLOWED_CALLBACK_ACE_TYPE
  703. If (the sid is applicable) AND (callback call evaluates ace applicable)
  704. Update the entire tree starting at the root.
  705. Grant those bits that have not already been denied.
  706. ACCESS_ALLOWED_OBJECT_ACE_TYPE
  707. If the sid is applicable
  708. get the ObjectType guid from the ace
  709. if the guid is NULL
  710. Update the entire tree starting at the root.
  711. Grant those bits that have not already been denied.
  712. else
  713. If (object type list exists) AND (contains a matching guid)
  714. Update the tree starting at the MATCH.
  715. Grant those bits that have not already been denied.
  716. ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
  717. If (the sid is applicable) AND (callback call evaluates ace applicable)
  718. get the ObjectType guid from the ace
  719. if the guid is NULL
  720. Update the entire tree starting at the root.
  721. Grant those bits that have not already been denied.
  722. else
  723. If (object type list exists) AND (contains a matching guid)
  724. Update the tree starting at the MATCH.
  725. Grant those bits that have not already been denied.
  726. ACCESS_DENIED_ACE_TYPE
  727. If the sid is applicable
  728. Update the entire tree starting at the root.
  729. Deny those bits that have not already been granted.
  730. Propagate the deny all the way up to the root.
  731. ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
  732. If (the sid is applicable) AND (callback call evaluates ace applicable)
  733. Update the entire tree starting at the root.
  734. Deny those bits that have not already been granted.
  735. Propagate the deny all the way up to the root.
  736. ACCESS_DENIED_OBJECT_ACE_TYPE
  737. If the sid is applicable
  738. get the ObjectType guid from the ace
  739. if the guid is NULL
  740. Update the entire tree starting at the root.
  741. Deny those bits that have not already been granted.
  742. Propagate the deny all the way up to the root.
  743. else
  744. If (object type list exists) AND (contains a matching guid)
  745. Update the tree starting at the MATCH.
  746. Deny those bits that have not already been granted.
  747. Propagate the deny all the way up to the root.
  748. ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
  749. If (the sid is applicable) AND (callback call evaluates ace applicable)
  750. get the ObjectType guid from the ace
  751. if the guid is NULL
  752. Update the entire tree starting at the root.
  753. Deny those bits that have not already been granted.
  754. Propagate the deny all the way up to the root.
  755. else
  756. If (object type list exists) AND (contains a matching guid)
  757. Update the tree starting at the MATCH.
  758. Deny those bits that have not already been granted.
  759. Propagate the deny all the way up to the root.
  760. Note:
  761. LocalCachingFlags is used to return whether the ace is contains principal
  762. self sid.
  763. We take a pessimistic view for dynamic aces. There are two types of
  764. dynamic aces:
  765. 1. Call back aces
  766. 2. Normal aces with principal self sid in it.
  767. For any dynamic ace,
  768. Grant aces are never applicable to the caching list.
  769. Deny aces are always applicable to the caching list.
  770. Return Value:
  771. A value of TRUE is returned if the routine is successful. Otherwise,
  772. a value of FALSE is returned. In the failure case, error value may be
  773. retrieved using GetLastError().
  774. --*/
  775. {
  776. DWORD AceCount = 0;
  777. DWORD i = 0;
  778. DWORD Index = 0;
  779. PVOID Ace = NULL;
  780. GUID * ObjectTypeInAce = NULL;
  781. BOOL bAceApplicable = FALSE;
  782. DWORD LocalCachingFlags = 0;
  783. AceCount = pAcl->AceCount;
  784. for (i = 0, Ace = FirstAce(pAcl); i < AceCount; i++, Ace = NextAce(Ace))
  785. {
  786. //
  787. // Skip INHERIT_ONLY aces.
  788. //
  789. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE))
  790. {
  791. continue;
  792. }
  793. LocalCachingFlags = 0;
  794. switch (((PACE_HEADER) Ace)->AceType)
  795. {
  796. case ACCESS_ALLOWED_ACE_TYPE:
  797. //
  798. // Check if the effective ace sid is present in the client context
  799. // and is enabled. S-1-5-A is replaced by the principal sid
  800. // supplied by the caller. In future, Creator Owner will be replaced
  801. // by the owner sid in the primary security descriptor.
  802. //
  803. bAceApplicable = AuthzpSidApplicable(
  804. SidCount,
  805. pSidAttr,
  806. pSidHash,
  807. AuthzAceSid(Ace),
  808. pRequest->PrincipalSelfSid,
  809. pOwnerSid,
  810. FALSE,
  811. &LocalCachingFlags
  812. );
  813. //
  814. // Record the caching flags for this ace into the global flags.
  815. //
  816. *pCachingFlags |= LocalCachingFlags;
  817. if (!bAceApplicable)
  818. {
  819. break;
  820. }
  821. //
  822. // Optimize the common case instead of calling a subroutine.
  823. //
  824. if (1 == LocalTypeListLength)
  825. {
  826. //
  827. // Grant access bits that have not already been denied.
  828. //
  829. LocalTypeList->CurrentGranted |= (((PKNOWN_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  830. //
  831. // A grant ace is considered static only if PrincipalSelf sid
  832. // is not found in the ace.
  833. //
  834. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  835. {
  836. LocalCachingTypeList->CurrentGranted |= (((PKNOWN_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentDenied);
  837. }
  838. }
  839. else
  840. {
  841. //
  842. // Propagate grant bits down the tree starting at the root.
  843. //
  844. AuthzpAddAccessTypeList(
  845. LocalTypeList,
  846. LocalTypeListLength,
  847. 0,
  848. ((PKNOWN_ACE) Ace)->Mask,
  849. AuthzUpdateCurrentGranted
  850. );
  851. //
  852. // A grant ace is considered static only if PrincipalSelf sid
  853. // is not found in the ace.
  854. //
  855. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  856. {
  857. AuthzpAddAccessTypeList(
  858. LocalCachingTypeList,
  859. LocalTypeListLength,
  860. 0,
  861. ((PKNOWN_ACE) Ace)->Mask,
  862. AuthzUpdateCurrentGranted
  863. );
  864. }
  865. }
  866. break;
  867. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  868. //
  869. // Check if the effective ace sid is present in the client context
  870. // and is enabled. S-1-5-A is replaced by the principal sid
  871. // supplied by the caller. In future, Creator Owner will be replaced
  872. // by the owner sid in the primary security descriptor.
  873. //
  874. bAceApplicable = AuthzpSidApplicable(
  875. SidCount,
  876. pSidAttr,
  877. pSidHash,
  878. AuthzCallbackAceSid(Ace),
  879. pRequest->PrincipalSelfSid,
  880. pOwnerSid,
  881. FALSE,
  882. &LocalCachingFlags
  883. );
  884. //
  885. // Record the presence of a dynamic grant ace as well as the caching
  886. // flags for this ace into the global flags.
  887. //
  888. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DYNAMIC_ALLOW_ACE_PRESENT);
  889. if (!bAceApplicable)
  890. {
  891. break;
  892. }
  893. bAceApplicable = FALSE;
  894. //
  895. // Make a call to the resource manager to get his opinion. His
  896. // evaluation is returned in bAceApplicalble.
  897. //
  898. // Note: The return value of the callback is used to decide whether
  899. // the API failed/succeeded. On a failure, we exit out of access
  900. // check. On success, we check the boolean returned by
  901. // bAceApplicable to decide whether to use the current ace.
  902. //
  903. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  904. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  905. Ace,
  906. pRequest->OptionalArguments,
  907. &bAceApplicable
  908. )))
  909. {
  910. return FALSE;
  911. }
  912. if (!bAceApplicable)
  913. {
  914. break;
  915. }
  916. //
  917. // Optimize the common case instead of calling a subroutine.
  918. //
  919. if (1 == LocalTypeListLength)
  920. {
  921. //
  922. // Grant access bits that have not already been denied.
  923. //
  924. LocalTypeList->CurrentGranted |= (((PKNOWN_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  925. }
  926. else
  927. {
  928. //
  929. // Propagate grant bits down the tree starting at the root.
  930. //
  931. AuthzpAddAccessTypeList(
  932. LocalTypeList,
  933. LocalTypeListLength,
  934. 0,
  935. ((PKNOWN_ACE) Ace)->Mask,
  936. AuthzUpdateCurrentGranted
  937. );
  938. }
  939. break;
  940. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  941. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  942. if ( ObjectTypeInAce && ( pRequest->ObjectTypeListLength == 0 ))
  943. {
  944. break;
  945. }
  946. //
  947. // Check if the effective ace sid is present in the client context
  948. // and is enabled. S-1-5-A is replaced by the principal sid
  949. // supplied by the caller. In future, Creator Owner will be replaced
  950. // by the owner sid in the primary security descriptor.
  951. //
  952. bAceApplicable = AuthzpSidApplicable(
  953. SidCount,
  954. pSidAttr,
  955. pSidHash,
  956. AuthzObjectAceSid(Ace),
  957. pRequest->PrincipalSelfSid,
  958. pOwnerSid,
  959. FALSE,
  960. &LocalCachingFlags
  961. );
  962. //
  963. // Record the the caching flags for this ace into the global flags.
  964. //
  965. *pCachingFlags |= LocalCachingFlags;
  966. if (!bAceApplicable)
  967. {
  968. break;
  969. }
  970. //
  971. // An object type ace with a NULL Object Type guid is the same as a
  972. // normal ace.
  973. //
  974. if (NULL == ObjectTypeInAce)
  975. {
  976. //
  977. // Optimize the common case instead of calling a subroutine.
  978. //
  979. if (1 == LocalTypeListLength)
  980. {
  981. //
  982. // Grant access bits that have not already been denied.
  983. //
  984. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  985. //
  986. // A grant ace is considered static only if PrincipalSelf sid
  987. // is not found in the ace.
  988. //
  989. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  990. {
  991. LocalCachingTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentDenied);
  992. }
  993. }
  994. else
  995. {
  996. //
  997. // Propagate grant bits down the tree starting at the root.
  998. //
  999. AuthzpAddAccessTypeList(
  1000. LocalTypeList,
  1001. LocalTypeListLength,
  1002. 0,
  1003. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1004. AuthzUpdateCurrentGranted
  1005. );
  1006. //
  1007. // A grant ace is considered static only if PrincipalSelf sid
  1008. // is not found in the ace.
  1009. //
  1010. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  1011. {
  1012. AuthzpAddAccessTypeList(
  1013. LocalCachingTypeList,
  1014. LocalTypeListLength,
  1015. 0,
  1016. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1017. AuthzUpdateCurrentGranted
  1018. );
  1019. }
  1020. }
  1021. }
  1022. //
  1023. // So, it is a true object type ace. Proceed only if we are doing
  1024. // access check on a object type list.
  1025. //
  1026. else if (ObjectTypeListPresent)
  1027. {
  1028. //
  1029. // Look for a matching object type guid that matches the one in
  1030. // the ace.
  1031. //
  1032. if (AuthzpObjectInTypeList(
  1033. ObjectTypeInAce,
  1034. LocalTypeList,
  1035. LocalTypeListLength,
  1036. &Index
  1037. )
  1038. )
  1039. {
  1040. //
  1041. // Propagate grant bits down the tree starting at the
  1042. // index at which the guids matched.
  1043. // In the case when this is the last of the siblings to be
  1044. // granted access, the parent also is granted access.
  1045. //
  1046. AuthzpAddAccessTypeList(
  1047. LocalTypeList,
  1048. LocalTypeListLength,
  1049. Index,
  1050. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1051. AuthzUpdateCurrentGranted
  1052. );
  1053. //
  1054. // A grant ace is considered static only if PrincipalSelf sid
  1055. // is not found in the ace.
  1056. //
  1057. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  1058. {
  1059. AuthzpAddAccessTypeList(
  1060. LocalCachingTypeList,
  1061. LocalTypeListLength,
  1062. Index,
  1063. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1064. AuthzUpdateCurrentGranted
  1065. );
  1066. }
  1067. }
  1068. }
  1069. break;
  1070. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  1071. //
  1072. // Check if the effective ace sid is present in the client context
  1073. // and is enabled. S-1-5-A is replaced by the principal sid
  1074. // supplied by the caller. In future, Creator Owner will be replaced
  1075. // by the owner sid in the primary security descriptor.
  1076. //
  1077. bAceApplicable = AuthzpSidApplicable(
  1078. SidCount,
  1079. pSidAttr,
  1080. pSidHash,
  1081. AuthzCallbackObjectAceSid(Ace),
  1082. pRequest->PrincipalSelfSid,
  1083. pOwnerSid,
  1084. FALSE,
  1085. &LocalCachingFlags
  1086. );
  1087. //
  1088. // Record the presence of a dynamic grant ace as well as the caching
  1089. // flags for this ace into the global flags.
  1090. //
  1091. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DYNAMIC_ALLOW_ACE_PRESENT);
  1092. if (!bAceApplicable)
  1093. {
  1094. break;
  1095. }
  1096. bAceApplicable = FALSE;
  1097. //
  1098. // Make a call to the resource manager to get his opinion. His
  1099. // evaluation is returned in bAceApplicalble.
  1100. //
  1101. // Note: The return value of the callback is used to decide whether
  1102. // the API failed/succeeded. On a failure, we exit out of access
  1103. // check. On success, we check the boolean returned by
  1104. // bAceApplicable to decide whether to use the current ace.
  1105. //
  1106. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  1107. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  1108. Ace,
  1109. pRequest->OptionalArguments,
  1110. &bAceApplicable
  1111. )))
  1112. {
  1113. return FALSE;
  1114. }
  1115. if (!bAceApplicable)
  1116. {
  1117. break;
  1118. }
  1119. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1120. //
  1121. // An object type ace with a NULL Object Type guid is the same as a
  1122. // normal ace.
  1123. //
  1124. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  1125. {
  1126. //
  1127. // Optimize the common case instead of calling a subroutine.
  1128. //
  1129. if (1 == LocalTypeListLength)
  1130. {
  1131. //
  1132. // Grant access bits that have not already been denied.
  1133. //
  1134. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  1135. }
  1136. else
  1137. {
  1138. //
  1139. // Propagate grant bits down the tree starting at the root.
  1140. //
  1141. AuthzpAddAccessTypeList(
  1142. LocalTypeList,
  1143. LocalTypeListLength,
  1144. 0,
  1145. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1146. AuthzUpdateCurrentGranted
  1147. );
  1148. }
  1149. }
  1150. //
  1151. // So, it is a true object type ace. Proceed only if we are doing
  1152. // access check on a object type list.
  1153. //
  1154. else if (ObjectTypeListPresent)
  1155. {
  1156. //
  1157. // Look for a matching object type guid that matches the one in
  1158. // the ace.
  1159. //
  1160. if (AuthzpObjectInTypeList(
  1161. ObjectTypeInAce,
  1162. LocalTypeList,
  1163. LocalTypeListLength,
  1164. &Index
  1165. )
  1166. )
  1167. {
  1168. //
  1169. // Propagate grant bits down the tree starting at the
  1170. // index at which the guids matched.
  1171. // In the case when this is the last of the siblings to be
  1172. // granted access, the parent also is granted access.
  1173. //
  1174. AuthzpAddAccessTypeList(
  1175. LocalTypeList,
  1176. LocalTypeListLength,
  1177. Index,
  1178. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1179. AuthzUpdateCurrentGranted
  1180. );
  1181. }
  1182. }
  1183. break;
  1184. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  1185. if (!AUTHZ_NON_NULL_PTR(pCC->Server))
  1186. {
  1187. break;
  1188. }
  1189. LocalCachingFlags = 0;
  1190. //
  1191. // Check if the effective ace sid is present in the client context
  1192. // and is enabled. S-1-5-A is replaced by the principal sid
  1193. // supplied by the caller. In future, Creator Owner will be replaced
  1194. // by the owner sid in the primary security descriptor.
  1195. //
  1196. bAceApplicable = AuthzpSidApplicable(
  1197. SidCount,
  1198. pSidAttr,
  1199. pSidHash,
  1200. RtlCompoundAceClientSid(Ace),
  1201. pRequest->PrincipalSelfSid,
  1202. pOwnerSid,
  1203. FALSE,
  1204. &LocalCachingFlags
  1205. );
  1206. //
  1207. // Record the caching flags for this ace into the global flags.
  1208. //
  1209. *pCachingFlags |= LocalCachingFlags;
  1210. if (!bAceApplicable)
  1211. {
  1212. break;
  1213. }
  1214. bAceApplicable = AuthzpSidApplicable(
  1215. pCC->Server->SidCount,
  1216. pCC->Server->Sids,
  1217. pCC->Server->SidHash,
  1218. RtlCompoundAceServerSid(Ace),
  1219. NULL,
  1220. NULL,
  1221. FALSE,
  1222. NULL
  1223. );
  1224. if (!bAceApplicable)
  1225. {
  1226. break;
  1227. }
  1228. //
  1229. // Optimize the common case instead of calling a subroutine.
  1230. //
  1231. if (1 == LocalTypeListLength)
  1232. {
  1233. //
  1234. // Grant access bits that have not already been denied.
  1235. //
  1236. LocalTypeList->CurrentGranted |= (((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  1237. //
  1238. // A grant ace is considered static only if PrincipalSelf sid
  1239. // is not found in the ace.
  1240. //
  1241. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  1242. {
  1243. LocalCachingTypeList->CurrentGranted |= (((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentDenied);
  1244. }
  1245. }
  1246. else
  1247. {
  1248. //
  1249. // Propagate grant bits down the tree starting at the root.
  1250. //
  1251. AuthzpAddAccessTypeList(
  1252. LocalTypeList,
  1253. LocalTypeListLength,
  1254. 0,
  1255. ((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask,
  1256. AuthzUpdateCurrentGranted
  1257. );
  1258. //
  1259. // A grant ace is considered static only if PrincipalSelf sid
  1260. // is not found in the ace.
  1261. //
  1262. if (ARGUMENT_PRESENT(LocalCachingTypeList) && (0 == LocalCachingFlags))
  1263. {
  1264. AuthzpAddAccessTypeList(
  1265. LocalCachingTypeList,
  1266. LocalTypeListLength,
  1267. 0,
  1268. ((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask,
  1269. AuthzUpdateCurrentGranted
  1270. );
  1271. }
  1272. }
  1273. break;
  1274. case ACCESS_DENIED_ACE_TYPE:
  1275. //
  1276. // Check if the effective ace sid is present in the client context
  1277. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  1278. // the principal sid supplied by the caller. In future, Creator
  1279. // Owner will be replaced by the owner sid in the primary security
  1280. // descriptor.
  1281. //
  1282. bAceApplicable = AuthzpSidApplicable(
  1283. SidCount,
  1284. pSidAttr,
  1285. pSidHash,
  1286. AuthzAceSid(Ace),
  1287. pRequest->PrincipalSelfSid,
  1288. pOwnerSid,
  1289. TRUE,
  1290. &LocalCachingFlags
  1291. );
  1292. //
  1293. // Record the presence of a Deny ace as well as the caching
  1294. // flags for this ace into the global flags.
  1295. //
  1296. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DENY_ACE_PRESENT);
  1297. //
  1298. // If the ace is applicable or principal self sid is present then
  1299. // deny the access bits to the cached access check results. We
  1300. // take a pessimistic view and assume that the principal self sid
  1301. // will be applicable in the next access check.
  1302. //
  1303. if ((bAceApplicable || (0 != LocalCachingFlags)) &&
  1304. (ARGUMENT_PRESENT(LocalCachingTypeList)))
  1305. {
  1306. //
  1307. // Optimize the common case instead of calling a subroutine.
  1308. //
  1309. if (1 == LocalTypeListLength)
  1310. {
  1311. //
  1312. // Deny access bits that have not already been granted.
  1313. //
  1314. LocalCachingTypeList->CurrentDenied |= (((PKNOWN_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentGranted);
  1315. }
  1316. else
  1317. {
  1318. //
  1319. // Propagate deny bits down the tree starting at the root.
  1320. //
  1321. AuthzpAddAccessTypeList(
  1322. LocalCachingTypeList,
  1323. LocalTypeListLength,
  1324. 0,
  1325. ((PKNOWN_ACE) Ace)->Mask,
  1326. AuthzUpdateCurrentDenied
  1327. );
  1328. }
  1329. }
  1330. if (!bAceApplicable)
  1331. {
  1332. break;
  1333. }
  1334. //
  1335. // Optimize the common case instead of calling a subroutine.
  1336. //
  1337. if (1 == LocalTypeListLength)
  1338. {
  1339. //
  1340. // Deny access bits that have not already been granted.
  1341. //
  1342. LocalTypeList->CurrentDenied |= (((PKNOWN_ACE) Ace)->Mask & ~LocalTypeList->CurrentGranted);
  1343. }
  1344. else
  1345. {
  1346. //
  1347. // Propagate deny bits down the tree starting at the root.
  1348. //
  1349. AuthzpAddAccessTypeList(
  1350. LocalTypeList,
  1351. LocalTypeListLength,
  1352. 0,
  1353. ((PKNOWN_ACE) Ace)->Mask,
  1354. AuthzUpdateCurrentDenied
  1355. );
  1356. }
  1357. break;
  1358. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  1359. //
  1360. // Check if the effective ace sid is present in the client context
  1361. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  1362. // the principal sid supplied by the caller. In future, Creator
  1363. // Owner will be replaced by the owner sid in the primary security
  1364. // descriptor.
  1365. //
  1366. bAceApplicable = AuthzpSidApplicable(
  1367. SidCount,
  1368. pSidAttr,
  1369. pSidHash,
  1370. AuthzCallbackAceSid(Ace),
  1371. pRequest->PrincipalSelfSid,
  1372. pOwnerSid,
  1373. TRUE,
  1374. &LocalCachingFlags
  1375. );
  1376. //
  1377. // Record the presence of a dynamic Deny ace as well as the caching
  1378. // flags for this ace into the global flags.
  1379. //
  1380. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DYNAMIC_DENY_ACE_PRESENT);
  1381. //
  1382. // If the ace is applicable or principal self sid is present then
  1383. // deny the access bits to the cached access check results. We
  1384. // take a pessimistic view and assume that the principal self sid
  1385. // will be applicable in the next access check.
  1386. //
  1387. if ((bAceApplicable || (0 != LocalCachingFlags)) &&
  1388. (ARGUMENT_PRESENT(LocalCachingTypeList)))
  1389. {
  1390. //
  1391. // Optimize the common case instead of calling a subroutine.
  1392. //
  1393. if (1 == LocalTypeListLength)
  1394. {
  1395. //
  1396. // Deny access bits that have not already been granted.
  1397. //
  1398. LocalCachingTypeList->CurrentDenied |= (((PKNOWN_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentGranted);
  1399. }
  1400. else
  1401. {
  1402. //
  1403. // Propagate deny bits down the tree starting at the root.
  1404. //
  1405. AuthzpAddAccessTypeList(
  1406. LocalCachingTypeList,
  1407. LocalTypeListLength,
  1408. 0,
  1409. ((PKNOWN_ACE) Ace)->Mask,
  1410. AuthzUpdateCurrentDenied
  1411. );
  1412. }
  1413. }
  1414. if (!bAceApplicable)
  1415. {
  1416. break;
  1417. }
  1418. bAceApplicable = FALSE;
  1419. //
  1420. // Make a call to the resource manager to get his opinion. His
  1421. // evaluation is returned in bAceApplicalble.
  1422. //
  1423. // Note: The return value of the callback is used to decide whether
  1424. // the API failed/succeeded. On a failure, we exit out of access
  1425. // check. On success, we check the boolean returned by
  1426. // bAceApplicable to decide whether to use the current ace.
  1427. //
  1428. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  1429. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  1430. Ace,
  1431. pRequest->OptionalArguments,
  1432. &bAceApplicable
  1433. )))
  1434. {
  1435. return FALSE;
  1436. }
  1437. if (!bAceApplicable)
  1438. {
  1439. break;
  1440. }
  1441. //
  1442. // Optimize the common case instead of calling a subroutine.
  1443. //
  1444. if (1 == LocalTypeListLength)
  1445. {
  1446. //
  1447. // Deny access bits that have not already been granted.
  1448. //
  1449. LocalTypeList->CurrentDenied |= (((PKNOWN_ACE) Ace)->Mask & ~LocalTypeList->CurrentGranted);
  1450. }
  1451. else
  1452. {
  1453. //
  1454. // Propagate deny bits down the tree starting at the root.
  1455. //
  1456. AuthzpAddAccessTypeList(
  1457. LocalTypeList,
  1458. LocalTypeListLength,
  1459. 0,
  1460. ((PKNOWN_ACE) Ace)->Mask,
  1461. AuthzUpdateCurrentDenied
  1462. );
  1463. }
  1464. break;
  1465. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1466. //
  1467. // Check if the effective ace sid is present in the client context
  1468. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  1469. // the principal sid supplied by the caller. In future, Creator
  1470. // Owner will be replaced by the owner sid in the primary security
  1471. // descriptor.
  1472. //
  1473. bAceApplicable = AuthzpSidApplicable(
  1474. SidCount,
  1475. pSidAttr,
  1476. pSidHash,
  1477. AuthzObjectAceSid(Ace),
  1478. pRequest->PrincipalSelfSid,
  1479. pOwnerSid,
  1480. TRUE,
  1481. &LocalCachingFlags
  1482. );
  1483. //
  1484. // Record the presence of a Deny ace as well as the caching
  1485. // flags for this ace into the global flags.
  1486. //
  1487. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DENY_ACE_PRESENT);
  1488. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1489. //
  1490. // If the ace is applicable or principal self sid is present then
  1491. // deny the access bits to the cached access check results. We
  1492. // take a pessimistic view and assume that the principal self sid
  1493. // will be applicable in the next access check.
  1494. //
  1495. if ((bAceApplicable || (0 != LocalCachingFlags)) &&
  1496. (ARGUMENT_PRESENT(LocalCachingTypeList)))
  1497. {
  1498. //
  1499. // An object type ace with a NULL Object Type guid is the same
  1500. // as a normal ace.
  1501. //
  1502. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  1503. {
  1504. //
  1505. // Optimize the common case instead of calling a subroutine.
  1506. //
  1507. if (1 == LocalTypeListLength)
  1508. {
  1509. //
  1510. // Deny access bits that have not already been granted.
  1511. //
  1512. LocalCachingTypeList->CurrentDenied |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentGranted);
  1513. }
  1514. else
  1515. {
  1516. //
  1517. // Propagate deny bits down the tree starting at the root.
  1518. //
  1519. AuthzpAddAccessTypeList(
  1520. LocalCachingTypeList,
  1521. LocalTypeListLength,
  1522. 0,
  1523. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1524. AuthzUpdateCurrentDenied
  1525. );
  1526. }
  1527. }
  1528. //
  1529. // So, it is a true object type ace. Proceed only if we are doing
  1530. // access check on a object type list.
  1531. //
  1532. else if (ObjectTypeListPresent)
  1533. {
  1534. //
  1535. // Look for a matching object type guid that matches the one in
  1536. // the ace.
  1537. //
  1538. if (AuthzpObjectInTypeList(
  1539. ObjectTypeInAce,
  1540. LocalTypeList,
  1541. LocalTypeListLength,
  1542. &Index
  1543. )
  1544. )
  1545. {
  1546. //
  1547. // Propagate deny bits down the tree starting at the
  1548. // index at which the guids matched. Deny bits are
  1549. // propagated to all the ancestors as well.
  1550. //
  1551. AuthzpAddAccessTypeList(
  1552. LocalCachingTypeList,
  1553. LocalTypeListLength,
  1554. Index,
  1555. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1556. AuthzUpdateCurrentDenied
  1557. );
  1558. }
  1559. }
  1560. }
  1561. if (!bAceApplicable)
  1562. {
  1563. break;
  1564. }
  1565. //
  1566. // An object type ace with a NULL Object Type guid is the same as a
  1567. // normal ace.
  1568. //
  1569. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  1570. {
  1571. //
  1572. // Optimize the common case instead of calling a subroutine.
  1573. //
  1574. if (1 == LocalTypeListLength)
  1575. {
  1576. //
  1577. // Deny access bits that have not already been granted.
  1578. //
  1579. LocalTypeList->CurrentDenied |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentGranted);
  1580. }
  1581. else
  1582. {
  1583. //
  1584. // Propagate deny bits down the tree starting at the root.
  1585. //
  1586. AuthzpAddAccessTypeList(
  1587. LocalTypeList,
  1588. LocalTypeListLength,
  1589. 0,
  1590. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1591. AuthzUpdateCurrentDenied
  1592. );
  1593. }
  1594. }
  1595. //
  1596. // So, it is a true object type ace. Proceed only if we are doing
  1597. // access check on a object type list.
  1598. //
  1599. else if (ObjectTypeListPresent)
  1600. {
  1601. //
  1602. // Look for a matching object type guid that matches the one in
  1603. // the ace.
  1604. //
  1605. if (AuthzpObjectInTypeList(
  1606. ObjectTypeInAce,
  1607. LocalTypeList,
  1608. LocalTypeListLength,
  1609. &Index
  1610. )
  1611. )
  1612. {
  1613. //
  1614. // Propagate deny bits down the tree starting at the
  1615. // index at which the guids matched. Deny bits are
  1616. // propagated to all the ancestors as well.
  1617. //
  1618. AuthzpAddAccessTypeList(
  1619. LocalTypeList,
  1620. LocalTypeListLength,
  1621. Index,
  1622. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1623. AuthzUpdateCurrentDenied
  1624. );
  1625. }
  1626. }
  1627. break;
  1628. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  1629. //
  1630. // Check if the effective ace sid is present in the client context
  1631. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  1632. // the principal sid supplied by the caller. In future, Creator
  1633. // Owner will be replaced by the owner sid in the primary security
  1634. // descriptor.
  1635. //
  1636. bAceApplicable = AuthzpSidApplicable(
  1637. SidCount,
  1638. pSidAttr,
  1639. pSidHash,
  1640. AuthzObjectAceSid(Ace),
  1641. pRequest->PrincipalSelfSid,
  1642. pOwnerSid,
  1643. TRUE,
  1644. &LocalCachingFlags
  1645. );
  1646. //
  1647. // Record the presence of a dynamic Deny ace as well as the caching
  1648. // flags for this ace into the global flags.
  1649. //
  1650. *pCachingFlags |= (LocalCachingFlags | AUTHZ_DYNAMIC_DENY_ACE_PRESENT);
  1651. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1652. //
  1653. // If the ace is applicable or principal self sid is present then
  1654. // deny the access bits to the cached access check results. We
  1655. // take a pessimistic view and assume that the principal self sid
  1656. // will be applicable in the next access check.
  1657. //
  1658. if ((bAceApplicable || (0 != LocalCachingFlags)) &&
  1659. (ARGUMENT_PRESENT(LocalCachingTypeList)))
  1660. {
  1661. //
  1662. // An object type ace with a NULL Object Type guid is the same
  1663. // as a normal ace.
  1664. //
  1665. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  1666. {
  1667. //
  1668. // Optimize the common case instead of calling a subroutine.
  1669. //
  1670. if (1 == LocalTypeListLength)
  1671. {
  1672. //
  1673. // Deny access bits that have not already been granted.
  1674. //
  1675. LocalCachingTypeList->CurrentDenied |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalCachingTypeList->CurrentGranted);
  1676. }
  1677. else
  1678. {
  1679. //
  1680. // Propagate deny bits down the tree starting at the root.
  1681. //
  1682. AuthzpAddAccessTypeList(
  1683. LocalCachingTypeList,
  1684. LocalTypeListLength,
  1685. 0,
  1686. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1687. AuthzUpdateCurrentDenied
  1688. );
  1689. }
  1690. }
  1691. //
  1692. // So, it is a true object type ace. Proceed only if we are doing
  1693. // access check on a object type list.
  1694. //
  1695. else if (ObjectTypeListPresent)
  1696. {
  1697. //
  1698. // Look for a matching object type guid that matches the one in
  1699. // the ace.
  1700. //
  1701. if (AuthzpObjectInTypeList(
  1702. ObjectTypeInAce,
  1703. LocalTypeList,
  1704. LocalTypeListLength,
  1705. &Index
  1706. )
  1707. )
  1708. {
  1709. //
  1710. // Propagate deny bits down the tree starting at the
  1711. // index at which the guids matched. Deny bits are
  1712. // propagated to all the ancestors as well.
  1713. //
  1714. AuthzpAddAccessTypeList(
  1715. LocalCachingTypeList,
  1716. LocalTypeListLength,
  1717. Index,
  1718. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1719. AuthzUpdateCurrentDenied
  1720. );
  1721. }
  1722. }
  1723. }
  1724. if (!bAceApplicable)
  1725. {
  1726. break;
  1727. }
  1728. bAceApplicable = FALSE;
  1729. //
  1730. // Make a call to the resource manager to get his opinion. His
  1731. // evaluation is returned in bAceApplicalble.
  1732. //
  1733. // Note: The return value of the callback is used to decide whether
  1734. // the API failed/succeeded. On a failure, we exit out of access
  1735. // check. On success, we check the boolean returned by
  1736. // bAceApplicable to decide whether to use the current ace.
  1737. //
  1738. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  1739. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  1740. Ace,
  1741. pRequest->OptionalArguments,
  1742. &bAceApplicable
  1743. )))
  1744. {
  1745. return FALSE;
  1746. }
  1747. //
  1748. // An object type ace with a NULL Object Type guid is the same as a
  1749. // normal ace.
  1750. //
  1751. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  1752. {
  1753. //
  1754. // Optimize the common case instead of calling a subroutine.
  1755. //
  1756. if (1 == LocalTypeListLength)
  1757. {
  1758. //
  1759. // Deny access bits that have not already been granted.
  1760. //
  1761. LocalTypeList->CurrentDenied |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentGranted);
  1762. }
  1763. else
  1764. {
  1765. //
  1766. // Propagate deny bits down the tree starting at the root.
  1767. //
  1768. AuthzpAddAccessTypeList(
  1769. LocalTypeList,
  1770. LocalTypeListLength,
  1771. 0,
  1772. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1773. AuthzUpdateCurrentDenied
  1774. );
  1775. }
  1776. }
  1777. //
  1778. // So, it is a true object type ace. Proceed only if we are doing
  1779. // access check on a object type list.
  1780. //
  1781. else if (ObjectTypeListPresent)
  1782. {
  1783. //
  1784. // Look for a matching object type guid that matches the one in
  1785. // the ace.
  1786. //
  1787. if (AuthzpObjectInTypeList(
  1788. ObjectTypeInAce,
  1789. LocalTypeList,
  1790. LocalTypeListLength,
  1791. &Index
  1792. )
  1793. )
  1794. {
  1795. //
  1796. // Propagate deny bits down the tree starting at the
  1797. // index at which the guids matched. Deny bits are
  1798. // propagated to all the ancestors as well.
  1799. //
  1800. AuthzpAddAccessTypeList(
  1801. LocalTypeList,
  1802. LocalTypeListLength,
  1803. Index,
  1804. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  1805. AuthzUpdateCurrentDenied
  1806. );
  1807. }
  1808. }
  1809. break;
  1810. default:
  1811. break;
  1812. }
  1813. }
  1814. return TRUE;
  1815. }
  1816. #if 0
  1817. BOOL
  1818. AuthzpSidApplicableOrig(
  1819. IN DWORD SidCount,
  1820. IN PSID_AND_ATTRIBUTES pSidAttr,
  1821. IN PSID pAceSid,
  1822. IN PSID PrincipalSelfSid,
  1823. IN PSID CreatorOwnerSid,
  1824. IN BOOL DenyAce,
  1825. OUT PDWORD pCachingFlags
  1826. )
  1827. /*++
  1828. Routine description:
  1829. This routine decides whether the ace is applicable to the client context.
  1830. Arguments:
  1831. SidCount - Number of sids in the pSidAttrArray
  1832. pSidAttr - Sid and attributes against which the ace sid should be compared.
  1833. pAceSid - Sid in the ace.
  1834. PrincipalSelfSid - To replace the ace sid if the ace sid is
  1835. Principal Self Sid (S-1-5-A).
  1836. CreatorOwnerSid - To replace the ace sid if the ace sid is Creator Owner
  1837. sid (S-1-3-0). This will not be used in the current implementation but
  1838. will come in effect once we do single instancing.
  1839. DenyAce - Boolean specifying whether the ace is a deny ace.
  1840. pCachingFlags - To return caching information in the form of:
  1841. AUTHZ_PRINCIPAL_SELF_ACE_PRESENT
  1842. AUTHZ_DYNAMIC_ALLOW_ACE_PRESENT
  1843. AUTHZ_DYNAMIC_DENY_ACE_PRESENT
  1844. Return Value:
  1845. A value of TRUE is returned if the effective sid is found in the client
  1846. context and (is enabled OR enabled for deny only for deny aces).
  1847. FALSE otherwise.
  1848. --*/
  1849. {
  1850. DWORD i = 0;
  1851. PISID MatchSid = NULL;
  1852. PSID pSid = pAceSid;
  1853. DWORD SidLen = RtlLengthSid(pAceSid);
  1854. UNREFERENCED_PARAMETER(CreatorOwnerSid);
  1855. //
  1856. // If the principal ace sid is principal self sid and Principal self sid
  1857. // has been provided then use it.
  1858. //
  1859. if (AUTHZ_EQUAL_SID(pSid, pAuthzPrincipalSelfSid, SidLen))
  1860. {
  1861. //
  1862. // Record the presence of a principal self sid in this ace.
  1863. //
  1864. *pCachingFlags |= AUTHZ_PRINCIPAL_SELF_ACE_PRESENT;
  1865. if (ARGUMENT_PRESENT(PrincipalSelfSid))
  1866. {
  1867. pSid = PrincipalSelfSid;
  1868. SidLen = RtlLengthSid(pSid);
  1869. }
  1870. else
  1871. {
  1872. return FALSE;
  1873. }
  1874. }
  1875. #ifdef AUTHZ_SINGLE_INSTANCE
  1876. //
  1877. // Single instance security descriptor code
  1878. //
  1879. else if (ARGUMENT_PRESENT(CreatorOwnerSid) && AUTHZ_EQUAL_SID(pSid, pAuthzCreatorOwnerSid, SidLen))
  1880. {
  1881. pSid = CreatorOwnerSid;
  1882. SidLen = RtlLengthSid(pSid);
  1883. }
  1884. #endif
  1885. //
  1886. // Loop thru the sids to find a match.
  1887. //
  1888. for (i = 0; i < SidCount; i++, pSidAttr++)
  1889. {
  1890. MatchSid = (PISID) pSidAttr->Sid;
  1891. if (AUTHZ_EQUAL_SID(pSid, MatchSid, SidLen))
  1892. {
  1893. //
  1894. // Return TRUE if
  1895. // a. the sid is enabled OR
  1896. // b the sid is enabled for deny only and the ace is a Deny ace.
  1897. // Else
  1898. // return FALSE.
  1899. //
  1900. if (FLAG_ON(pSidAttr->Attributes, SE_GROUP_ENABLED) ||
  1901. (DenyAce && FLAG_ON(pSidAttr->Attributes, SE_GROUP_USE_FOR_DENY_ONLY))
  1902. )
  1903. {
  1904. #ifdef AUTHZ_DEBUG
  1905. wprintf(L"Applicable sid = %x, %x, %x, %x, %x, %x, %x\n",
  1906. ((DWORD *) MatchSid)[0], ((DWORD *) MatchSid)[1],
  1907. ((DWORD *) MatchSid)[2], ((DWORD *) MatchSid)[3],
  1908. ((DWORD *) MatchSid)[4], ((DWORD *) MatchSid)[5],
  1909. ((DWORD *) MatchSid)[1]);
  1910. #endif
  1911. return TRUE;
  1912. }
  1913. return FALSE;
  1914. }
  1915. }
  1916. return FALSE;
  1917. }
  1918. #endif
  1919. #define AUTHZ_SID_HASH_BYTE(s) ((UCHAR)(((PISID)s)->SubAuthority[((PISID)s)->SubAuthorityCount - 1]))
  1920. VOID
  1921. AuthzpInitSidHash(
  1922. IN PSID_AND_ATTRIBUTES pSidAttr,
  1923. IN ULONG SidCount,
  1924. OUT PAUTHZI_SID_HASH_ENTRY pHash
  1925. )
  1926. /*++
  1927. Routine Description
  1928. Initializes the SID hash table.
  1929. Arguments
  1930. pSidAttr - array of sids to store in hash.
  1931. SidCount - number of sids in array.
  1932. pHash - pointer to the sid hash table.
  1933. Return Value
  1934. None.
  1935. --*/
  1936. {
  1937. ULONG i = 0;
  1938. ULONG PositionBit = 0;
  1939. BYTE HashByte = 0;
  1940. //
  1941. // Zero the table.
  1942. //
  1943. RtlZeroMemory(
  1944. pHash,
  1945. sizeof(AUTHZI_SID_HASH_ENTRY) * AUTHZI_SID_HASH_SIZE
  1946. );
  1947. if (pSidAttr == NULL)
  1948. {
  1949. return;
  1950. }
  1951. //
  1952. // Can only hash the number of sids that each table entry can hold
  1953. //
  1954. if (SidCount > AUTHZI_SID_HASH_ENTRY_NUM_BITS)
  1955. {
  1956. SidCount = AUTHZI_SID_HASH_ENTRY_NUM_BITS;
  1957. }
  1958. for (i = 0; i < SidCount; i++)
  1959. {
  1960. //
  1961. // HashByte is last byte in SID.
  1962. //
  1963. HashByte = AUTHZ_SID_HASH_BYTE(pSidAttr[i].Sid);
  1964. //
  1965. // Position indicates the location of this SID in pSidAttr.
  1966. //
  1967. PositionBit = 1 << i;
  1968. //
  1969. // Store the position bit in the low hash indexed by the low order bits of the HashByte
  1970. //
  1971. pHash[(HashByte & AUTHZ_SID_HASH_LOW_MASK)] |= PositionBit;
  1972. //
  1973. // Store the position bit in the high hash indexed by the high order bits of the HashByte
  1974. //
  1975. pHash[AUTHZ_SID_HASH_HIGH + ((HashByte & AUTHZ_SID_HASH_HIGH_MASK) >> 4)] |= PositionBit;
  1976. }
  1977. }
  1978. BOOL
  1979. AuthzpSidApplicable(
  1980. IN DWORD SidCount,
  1981. IN PSID_AND_ATTRIBUTES pSidAttr,
  1982. IN PAUTHZI_SID_HASH_ENTRY pHash,
  1983. IN PSID pAceSid,
  1984. IN PSID PrincipalSelfSid,
  1985. IN PSID CreatorOwnerSid,
  1986. IN BOOL DenyAce,
  1987. OUT PDWORD pCachingFlags
  1988. )
  1989. /*++
  1990. Routine description:
  1991. This routine decides whether the ace is applicable to the client context.
  1992. Arguments:
  1993. SidCount - Number of sids in the pSidAttrArray
  1994. pSidAttr - Sid and attributes against which the ace sid should be compared.
  1995. pHash - Hash table of the pSidAttr array.
  1996. pAceSid - Sid in the ace.
  1997. PrincipalSelfSid - To replace the ace sid if the ace sid is
  1998. Principal Self Sid (S-1-5-A).
  1999. CreatorOwnerSid - To replace the ace sid if the ace sid is Creator Owner
  2000. sid (S-1-3-0). This will not be used in the current implementation but
  2001. will come in effect once we do single instancing.
  2002. DenyAce - Boolean specifying whether the ace is a deny ace.
  2003. pCachingFlags - To return caching information in the form of:
  2004. AUTHZ_PRINCIPAL_SELF_ACE_PRESENT
  2005. AUTHZ_DYNAMIC_ALLOW_ACE_PRESENT
  2006. AUTHZ_DYNAMIC_DENY_ACE_PRESENT
  2007. Return Value:
  2008. A value of TRUE is returned if the effective sid is found in the client
  2009. context and (is enabled OR enabled for deny only for deny aces).
  2010. FALSE otherwise.
  2011. --*/
  2012. {
  2013. DWORD SidLen;
  2014. DWORD BitIndex;
  2015. UCHAR HashByte;
  2016. DWORD i;
  2017. UCHAR ByteToExamine;
  2018. UCHAR ByteOffset;
  2019. AUTHZI_SID_HASH_ENTRY SidPositionBitMap;
  2020. PSID_AND_ATTRIBUTES pSA;
  2021. UNREFERENCED_PARAMETER(CreatorOwnerSid);
  2022. //
  2023. // If the principal ace sid is principal self sid and Principal self sid
  2024. // has been provided then use it.
  2025. //
  2026. if (ARGUMENT_PRESENT(PrincipalSelfSid))
  2027. {
  2028. SidLen = RtlLengthSid(pAceSid);
  2029. if ((SidLen == AuthzpPrincipalSelfSidLen) &&
  2030. (AUTHZ_EQUAL_SID(pAceSid, pAuthzPrincipalSelfSid, SidLen)))
  2031. {
  2032. //
  2033. // Record the presence of a principal self sid in this ace.
  2034. //
  2035. *pCachingFlags |= AUTHZ_PRINCIPAL_SELF_ACE_PRESENT;
  2036. pAceSid = PrincipalSelfSid;
  2037. SidLen = RtlLengthSid(pAceSid);
  2038. }
  2039. }
  2040. //
  2041. // Index into pHash by the last byte of the SID. The resulting value (SidPositionBitMap)
  2042. // indicates the locations of SIDs in a corresponding SID_AND_ATTRIBUTES array that match
  2043. // that last byte.
  2044. //
  2045. HashByte = AUTHZ_SID_HASH_BYTE(pAceSid);
  2046. SidPositionBitMap = AUTHZ_SID_HASH_LOOKUP(pHash, HashByte);
  2047. SidLen = RtlLengthSid(pAceSid);
  2048. ByteOffset = 0;
  2049. while (0 != SidPositionBitMap)
  2050. {
  2051. ByteToExamine = (UCHAR)SidPositionBitMap;
  2052. while (ByteToExamine)
  2053. {
  2054. //
  2055. // Get the first nonzero bit in ByteToExamine
  2056. //
  2057. BitIndex = AuthzpByteToIndexLookupTable[ByteToExamine];
  2058. //
  2059. // Find the PSID_AND_ATTRIBUTES to which the bit refers.
  2060. //
  2061. pSA = &pSidAttr[ByteOffset + BitIndex];
  2062. if (AUTHZ_EQUAL_SID(pAceSid, pSA->Sid, SidLen))
  2063. {
  2064. if ((FLAG_ON(pSA->Attributes, SE_GROUP_ENABLED)) ||
  2065. (DenyAce && FLAG_ON(pSA->Attributes, SE_GROUP_USE_FOR_DENY_ONLY)))
  2066. {
  2067. return TRUE;
  2068. }
  2069. return FALSE;
  2070. }
  2071. //
  2072. // Turn the current bit off and try the next SID.
  2073. //
  2074. ByteToExamine ^= (1 << BitIndex);
  2075. }
  2076. ByteOffset = ByteOffset + sizeof(UCHAR);
  2077. SidPositionBitMap = SidPositionBitMap >> sizeof(UCHAR);
  2078. }
  2079. //
  2080. // If a matching sid was not found in the pHash and there are SIDS in pSidAttr which did not
  2081. // get placed in pHash, then search those SIDS for a match.
  2082. //
  2083. for (i = AUTHZI_SID_HASH_ENTRY_NUM_BITS; i < SidCount; i++)
  2084. {
  2085. pSA = &pSidAttr[i];
  2086. if (AUTHZ_EQUAL_SID(pAceSid, pSA->Sid, SidLen))
  2087. {
  2088. if ((FLAG_ON(pSA->Attributes, SE_GROUP_ENABLED)) ||
  2089. (DenyAce && FLAG_ON(pSA->Attributes, SE_GROUP_USE_FOR_DENY_ONLY)))
  2090. {
  2091. return TRUE;
  2092. }
  2093. return FALSE;
  2094. }
  2095. }
  2096. return FALSE;
  2097. }
  2098. BOOL
  2099. AuthzpAccessCheckWithCaching(
  2100. IN DWORD Flags,
  2101. IN PAUTHZI_CLIENT_CONTEXT pCC,
  2102. IN PAUTHZ_ACCESS_REQUEST pRequest,
  2103. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2104. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  2105. IN DWORD OptionalSecurityDescriptorCount,
  2106. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  2107. OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults OPTIONAL,
  2108. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  2109. IN OUT PIOBJECT_TYPE_LIST LocalCachingTypeList OPTIONAL,
  2110. IN DWORD LocalTypeListLength
  2111. )
  2112. /*++
  2113. Routine description:
  2114. This routine does a MaximumAllowed access check. It is called if any of the
  2115. following is TRUE
  2116. 1. RM has requested for caching
  2117. 2. DesiredAccessMask has MAXIMUM_ALLOWED turned on.
  2118. 3. ObjectTypeList is present and pReply->ResultList has a length > 1
  2119. Arguments:
  2120. pCC - Pointer to the client context.
  2121. pRequest - Access request specifies the desired access mask, principal self
  2122. sid, the object type list strucutre (if any).
  2123. pSecurityDescriptor - Primary security descriptor to be used for access
  2124. checks. The owner sid for the object is picked from this one. A NULL
  2125. DACL in this security descriptor represents a NULL DACL for the entire
  2126. object. A NULL SACL in this security descriptor is treated the same way
  2127. as an EMPTY SACL.
  2128. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  2129. of security descriptors. NULL ACLs in these security descriptors are
  2130. treated as EMPTY ACLS and the ACL for the entire object is the logical
  2131. concatenation of all the ACLs.
  2132. OptionalSecurityDescriptorCount - Number of optional security descriptors
  2133. This does not include the Primary security descriptor.
  2134. pReply - To return the results of access check call.
  2135. phAccessCheckResults - To return a handle to cached results of the access check
  2136. call.
  2137. LocalTypeList - Internal object type list structure used to hold
  2138. intermediate results.
  2139. LocalCachingTypeList - Internal object type list structure used to hold
  2140. intermediate results for static granted bits.
  2141. LocalTypeListLength - Length of the array represnting the object.
  2142. Return Value:
  2143. A value of TRUE is returned if the routine is successful. Otherwise,
  2144. a value of FALSE is returned. In the failure case, error value may be
  2145. retrieved using GetLastError().
  2146. --*/
  2147. {
  2148. ACCESS_MASK PreviouslyGrantedAccess = 0;
  2149. DWORD CachingFlags = 0;
  2150. DWORD i = 0;
  2151. BOOL b = TRUE;
  2152. PACL pAcl = NULL;
  2153. //
  2154. // Owner is always granted READ_CONTROL and WRITE_DAC.
  2155. //
  2156. if (AuthzpOwnerSidInClientContext(pCC, pSecurityDescriptor))
  2157. {
  2158. PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
  2159. }
  2160. //
  2161. // Take ownership privilege grants WRITE_OWNER.
  2162. //
  2163. if (AUTHZ_PRIVILEGE_CHECK(pCC, AUTHZ_TAKE_OWNERSHIP_PRIVILEGE_ENABLED))
  2164. {
  2165. PreviouslyGrantedAccess |= WRITE_OWNER;
  2166. }
  2167. //
  2168. // SecurityPrivilege grants ACCESS_SYSTEM_SECURITY.
  2169. //
  2170. if (AUTHZ_PRIVILEGE_CHECK(pCC, AUTHZ_SECURITY_PRIVILEGE_ENABLED))
  2171. {
  2172. PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
  2173. }
  2174. else if (FLAG_ON(pRequest->DesiredAccess, ACCESS_SYSTEM_SECURITY))
  2175. {
  2176. AuthzpFillReplyStructure(
  2177. pReply,
  2178. ERROR_PRIVILEGE_NOT_HELD,
  2179. 0
  2180. );
  2181. SetLastError(ERROR_SUCCESS);
  2182. return TRUE;
  2183. }
  2184. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  2185. //
  2186. // NULL Dacl is synonymous with Full Control.
  2187. //
  2188. if (!AUTHZ_NON_NULL_PTR(pAcl))
  2189. {
  2190. PreviouslyGrantedAccess |= (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL);
  2191. for (i = 0; i < LocalTypeListLength; i++)
  2192. {
  2193. LocalTypeList[i].CurrentGranted |= PreviouslyGrantedAccess;
  2194. if (ARGUMENT_PRESENT(LocalCachingTypeList))
  2195. {
  2196. LocalCachingTypeList[i].CurrentGranted |= PreviouslyGrantedAccess;
  2197. }
  2198. }
  2199. }
  2200. else
  2201. {
  2202. for (i = 0; i < LocalTypeListLength; i++)
  2203. {
  2204. LocalTypeList[i].CurrentGranted |= PreviouslyGrantedAccess;
  2205. if (ARGUMENT_PRESENT(LocalCachingTypeList))
  2206. {
  2207. LocalCachingTypeList[i].CurrentGranted |= PreviouslyGrantedAccess;
  2208. }
  2209. }
  2210. b = AuthzpMaximumAllowedAccessCheck(
  2211. pCC,
  2212. pRequest,
  2213. pSecurityDescriptor,
  2214. OptionalSecurityDescriptorArray,
  2215. OptionalSecurityDescriptorCount,
  2216. LocalTypeList,
  2217. LocalCachingTypeList,
  2218. LocalTypeListLength,
  2219. 0 != pRequest->ObjectTypeListLength,
  2220. &CachingFlags
  2221. );
  2222. if (!b)
  2223. {
  2224. goto Cleanup;
  2225. }
  2226. }
  2227. //
  2228. // If the caller asked for caching then allocate a handle, store the results
  2229. // of the static access check in it and insert it into the list of handles.
  2230. //
  2231. if (ARGUMENT_PRESENT(phAccessCheckResults))
  2232. {
  2233. b = AuthzpCacheResults(
  2234. Flags,
  2235. pCC,
  2236. LocalCachingTypeList,
  2237. LocalTypeListLength,
  2238. pSecurityDescriptor,
  2239. OptionalSecurityDescriptorArray,
  2240. OptionalSecurityDescriptorCount,
  2241. CachingFlags,
  2242. phAccessCheckResults
  2243. );
  2244. if (!b) goto Cleanup;
  2245. }
  2246. AuthzpFillReplyFromParameters(
  2247. pRequest,
  2248. pReply,
  2249. LocalTypeList
  2250. );
  2251. Cleanup:
  2252. return b;
  2253. }
  2254. VOID
  2255. AuthzpFillReplyFromParameters(
  2256. IN PAUTHZ_ACCESS_REQUEST pRequest,
  2257. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  2258. IN PIOBJECT_TYPE_LIST LocalTypeList
  2259. )
  2260. /*++
  2261. Routine description:
  2262. This routine fills in the reply structure wih the results of access check
  2263. supplied by LocalTypeList.
  2264. Arguments:
  2265. pRequest - Access request specifies the desired access mask, principal self
  2266. sid, the object type list strucutre (if any).
  2267. pReply - The reply structure to fill.
  2268. LocalTypeList - Internal object type list structure used to hold
  2269. intermediate results. This is used to fill the reply structure.
  2270. Return Value:
  2271. None.
  2272. --*/
  2273. {
  2274. ACCESS_MASK DesiredAccess = 0;
  2275. ACCESS_MASK RelevantAccess = 0;
  2276. DWORD i = 0;
  2277. if (FLAG_ON(pRequest->DesiredAccess, ACCESS_SYSTEM_SECURITY))
  2278. {
  2279. RelevantAccess = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL | ACCESS_SYSTEM_SECURITY;
  2280. }
  2281. else
  2282. {
  2283. RelevantAccess = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
  2284. }
  2285. if (FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED))
  2286. {
  2287. DesiredAccess = pRequest->DesiredAccess & ~(MAXIMUM_ALLOWED);
  2288. for (i = 0; i < pReply->ResultListLength; i++)
  2289. {
  2290. if (FLAG_ON(DesiredAccess, ~(LocalTypeList[i].CurrentGranted)) ||
  2291. (0 == LocalTypeList[i].CurrentGranted))
  2292. {
  2293. pReply->GrantedAccessMask[i] = 0;
  2294. pReply->Error[i] = ERROR_ACCESS_DENIED;
  2295. }
  2296. else
  2297. {
  2298. pReply->GrantedAccessMask[i] = LocalTypeList[i].CurrentGranted & RelevantAccess;
  2299. pReply->Error[i] = ERROR_SUCCESS;
  2300. }
  2301. }
  2302. }
  2303. else
  2304. {
  2305. for (i = 0; i < pReply->ResultListLength; i++)
  2306. {
  2307. if (FLAG_ON(pRequest->DesiredAccess, ~(LocalTypeList[i].CurrentGranted)))
  2308. {
  2309. pReply->GrantedAccessMask[i] = 0;
  2310. pReply->Error[i] = ERROR_ACCESS_DENIED;
  2311. }
  2312. else
  2313. {
  2314. pReply->GrantedAccessMask[i] = pRequest->DesiredAccess & RelevantAccess;
  2315. pReply->Error[i] = ERROR_SUCCESS;
  2316. }
  2317. }
  2318. }
  2319. }
  2320. BOOL
  2321. AuthzpNormalAccessCheckWithoutCaching(
  2322. IN PAUTHZI_CLIENT_CONTEXT pCC,
  2323. IN PAUTHZ_ACCESS_REQUEST pRequest,
  2324. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2325. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  2326. IN DWORD OptionalSecurityDescriptorCount,
  2327. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  2328. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  2329. IN DWORD LocalTypeListLength
  2330. )
  2331. /*++
  2332. Routine description:
  2333. This routine does a normal access check. If desired access is denied at any
  2334. point then it stops acl evaluation.
  2335. Arguments:
  2336. pCC - Pointer to the client context.
  2337. pRequest - Access request specifies the desired access mask, principal self
  2338. sid, the object type list strucutre (if any).
  2339. pSecurityDescriptor - Primary security descriptor to be used for access
  2340. checks. The owner sid for the object is picked from this one. A NULL
  2341. DACL in this security descriptor represents a NULL DACL for the entire
  2342. object. A NULL SACL in this security descriptor is treated the same way
  2343. as an EMPTY SACL.
  2344. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  2345. of security descriptors. NULL ACLs in these security descriptors are
  2346. treated as EMPTY ACLS and the ACL for the entire object is the logical
  2347. concatenation of all the ACLs.
  2348. OptionalSecurityDescriptorCount - Number of optional security descriptors
  2349. This does not include the Primary security descriptor.
  2350. pReply - The reply structure to return the results.
  2351. LocalTypeList - Internal object type list structure used to hold
  2352. intermediate results.
  2353. LocalTypeListLength - Length of the array represnting the object.
  2354. Return Value:
  2355. A value of TRUE is returned if the routine is successful. Otherwise,
  2356. a value of FALSE is returned. In the failure case, error value may be
  2357. retrieved using GetLastError().
  2358. --*/
  2359. {
  2360. ACCESS_MASK Remaining = pRequest->DesiredAccess;
  2361. PACL pAcl = NULL;
  2362. BOOL b = TRUE;
  2363. //
  2364. // Check for SeSecurityPrivilege.
  2365. //
  2366. if (FLAG_ON(Remaining, ACCESS_SYSTEM_SECURITY))
  2367. {
  2368. if (AUTHZ_PRIVILEGE_CHECK(pCC, AUTHZ_SECURITY_PRIVILEGE_ENABLED))
  2369. {
  2370. Remaining &= ~(ACCESS_SYSTEM_SECURITY);
  2371. }
  2372. else
  2373. {
  2374. AuthzpFillReplyStructure(
  2375. pReply,
  2376. ERROR_PRIVILEGE_NOT_HELD,
  2377. 0
  2378. );
  2379. SetLastError(ERROR_SUCCESS);
  2380. return TRUE;
  2381. }
  2382. }
  2383. //
  2384. // Ownership of the object grants READ_CONTROL and WRITE_DAC.
  2385. //
  2386. if (FLAG_ON(Remaining, (READ_CONTROL | WRITE_DAC)) &&
  2387. AuthzpOwnerSidInClientContext(pCC, pSecurityDescriptor))
  2388. {
  2389. Remaining &= ~(WRITE_DAC | READ_CONTROL);
  2390. }
  2391. //
  2392. // SeTakeOwnership privilege grants WRITE_OWNER.
  2393. //
  2394. if (FLAG_ON(Remaining, WRITE_OWNER) &&
  2395. AUTHZ_PRIVILEGE_CHECK(pCC, AUTHZ_TAKE_OWNERSHIP_PRIVILEGE_ENABLED))
  2396. {
  2397. Remaining &= ~(WRITE_OWNER);
  2398. }
  2399. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  2400. //
  2401. // Null acl represents FULL CONTROL.
  2402. //
  2403. if (!AUTHZ_NON_NULL_PTR(pAcl))
  2404. {
  2405. Remaining = 0;
  2406. }
  2407. //
  2408. // If we have been granted access at this point then acl evaluation is not
  2409. // needed.
  2410. //
  2411. if (0 == Remaining)
  2412. {
  2413. AuthzpFillReplyStructure(
  2414. pReply,
  2415. ERROR_SUCCESS,
  2416. pRequest->DesiredAccess
  2417. );
  2418. SetLastError(ERROR_SUCCESS);
  2419. return TRUE;
  2420. }
  2421. //
  2422. // Do the access check with the non-restricted part of the client context.
  2423. //
  2424. b = AuthzpNormalMultipleSDAccessCheck(
  2425. pCC,
  2426. pCC->Sids,
  2427. pCC->SidCount,
  2428. pCC->SidHash,
  2429. Remaining,
  2430. pRequest,
  2431. pSecurityDescriptor,
  2432. OptionalSecurityDescriptorArray,
  2433. OptionalSecurityDescriptorCount,
  2434. LocalTypeList,
  2435. LocalTypeListLength
  2436. );
  2437. if (!b)
  2438. {
  2439. return FALSE;
  2440. }
  2441. #ifdef AUTHZ_DEBUG
  2442. wprintf(L"Remaining = %x, LocalTypeList = %x\n", Remaining, LocalTypeList->Remaining);
  2443. #endif
  2444. if (0 != LocalTypeList->Remaining)
  2445. {
  2446. AuthzpFillReplyStructure(
  2447. pReply,
  2448. ERROR_ACCESS_DENIED,
  2449. 0
  2450. );
  2451. SetLastError(ERROR_SUCCESS);
  2452. return TRUE;
  2453. }
  2454. //
  2455. // If the client context is resticted then even the resticted part has to
  2456. // grant all the access bits that were asked.
  2457. //
  2458. if (AUTHZ_TOKEN_RESTRICTED(pCC))
  2459. {
  2460. b = AuthzpNormalMultipleSDAccessCheck(
  2461. pCC,
  2462. pCC->RestrictedSids,
  2463. pCC->RestrictedSidCount,
  2464. pCC->RestrictedSidHash,
  2465. Remaining,
  2466. pRequest,
  2467. pSecurityDescriptor,
  2468. OptionalSecurityDescriptorArray,
  2469. OptionalSecurityDescriptorCount,
  2470. LocalTypeList,
  2471. LocalTypeListLength
  2472. );
  2473. if (!b)
  2474. {
  2475. return FALSE;
  2476. }
  2477. if (0 != LocalTypeList->Remaining)
  2478. {
  2479. AuthzpFillReplyStructure(
  2480. pReply,
  2481. ERROR_ACCESS_DENIED,
  2482. 0
  2483. );
  2484. SetLastError(ERROR_SUCCESS);
  2485. return TRUE;
  2486. }
  2487. }
  2488. //
  2489. // If we made it till here then all access bits have been granted.
  2490. //
  2491. AuthzpFillReplyStructure(
  2492. pReply,
  2493. ERROR_SUCCESS,
  2494. pRequest->DesiredAccess
  2495. );
  2496. SetLastError(ERROR_SUCCESS);
  2497. return TRUE;
  2498. }
  2499. BOOL
  2500. AuthzpNormalMultipleSDAccessCheck(
  2501. IN PAUTHZI_CLIENT_CONTEXT pCC,
  2502. IN PSID_AND_ATTRIBUTES pSidAttr,
  2503. IN DWORD SidCount,
  2504. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  2505. IN ACCESS_MASK Remaining,
  2506. IN PAUTHZ_ACCESS_REQUEST pRequest,
  2507. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2508. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  2509. IN DWORD OptionalSecurityDescriptorCount,
  2510. IN OUT PIOBJECT_TYPE_LIST LocalTypeList OPTIONAL,
  2511. IN DWORD LocalTypeListLength
  2512. )
  2513. /*++
  2514. Routine description:
  2515. This routine loops thru all the security descriptors and calls
  2516. AuthzpNormalAccessCheck.
  2517. Arguments:
  2518. pCC - Pointer to the client context.
  2519. pSidAttr - Sids and attributes array to compare ace sids.
  2520. SidCount - Number of elements in the array.
  2521. Remaining - Access bits that are yet to be granted.
  2522. pRequest - Access request specifies the desired access mask, principal self
  2523. sid, the object type list strucutre (if any).
  2524. pSecurityDescriptor - Primary security descriptor to be used for access
  2525. checks. The owner sid for the object is picked from this one. A NULL
  2526. DACL in this security descriptor represents a NULL DACL for the entire
  2527. object. A NULL SACL in this security descriptor is treated the same way
  2528. as an EMPTY SACL.
  2529. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  2530. of security descriptors. NULL ACLs in these security descriptors are
  2531. treated as EMPTY ACLS and the ACL for the entire object is the logical
  2532. concatenation of all the ACLs.
  2533. OptionalSecurityDescriptorCount - Number of optional security descriptors
  2534. This does not include the Primary security descriptor.
  2535. LocalTypeList - Internal object type list structure used to hold
  2536. intermediate results.
  2537. LocalTypeListLength - Length of the array represnting the object.
  2538. Return Value:
  2539. A value of TRUE is returned if the routine is successful. Otherwise,
  2540. a value of FALSE is returned. In the failure case, error value may be
  2541. retrieved using GetLastError().
  2542. --*/
  2543. {
  2544. PSID pOwnerSid = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  2545. PACL pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  2546. BOOL b = TRUE;
  2547. DWORD i = 0;
  2548. ASSERT(AUTHZ_NON_NULL_PTR(pAcl));
  2549. b = AuthzpNormalAccessCheck(
  2550. pCC,
  2551. pSidAttr,
  2552. SidCount,
  2553. pSidHash,
  2554. Remaining,
  2555. pRequest,
  2556. pAcl,
  2557. pOwnerSid,
  2558. LocalTypeList,
  2559. LocalTypeListLength
  2560. );
  2561. if (!b)
  2562. {
  2563. return FALSE;
  2564. }
  2565. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  2566. {
  2567. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  2568. if (!AUTHZ_NON_NULL_PTR(pAcl))
  2569. {
  2570. continue;
  2571. }
  2572. b = AuthzpNormalAccessCheck(
  2573. pCC,
  2574. pSidAttr,
  2575. SidCount,
  2576. pSidHash,
  2577. Remaining,
  2578. pRequest,
  2579. pAcl,
  2580. pOwnerSid,
  2581. LocalTypeList,
  2582. LocalTypeListLength
  2583. );
  2584. if (!b)
  2585. {
  2586. break;
  2587. }
  2588. }
  2589. return b;
  2590. }
  2591. BOOL
  2592. AuthzpOwnerSidInClientContext(
  2593. IN PAUTHZI_CLIENT_CONTEXT pCC,
  2594. IN PISECURITY_DESCRIPTOR pSecurityDescriptor
  2595. )
  2596. /*++
  2597. Routine description:
  2598. This routine determines if client context is the owner of the given object.
  2599. Arguments:
  2600. pCC - Pointer to the client context.
  2601. pSecurityDescriptor - To supply the owner sid for the object.
  2602. Return Value:
  2603. A value of TRUE is returned if the owner sid in the security descriptor is
  2604. present in the normal part (as well as the restricted part, if it exists).
  2605. --*/
  2606. {
  2607. PSID pOwnerSid = RtlpOwnerAddrSecurityDescriptor(pSecurityDescriptor);
  2608. BOOL b = TRUE;
  2609. //
  2610. // Check if the sid exists in the normal part of the token.
  2611. //
  2612. b = AuthzpSidApplicable(
  2613. pCC->SidCount,
  2614. pCC->Sids,
  2615. pCC->SidHash,
  2616. pOwnerSid,
  2617. NULL,
  2618. NULL,
  2619. FALSE,
  2620. NULL
  2621. );
  2622. if (!b)
  2623. {
  2624. return FALSE;
  2625. }
  2626. //
  2627. // If the token is restricted then the sid must exist in the restricted part
  2628. // of the token.
  2629. //
  2630. if (AUTHZ_TOKEN_RESTRICTED(pCC))
  2631. {
  2632. b = AuthzpSidApplicable(
  2633. pCC->RestrictedSidCount,
  2634. pCC->RestrictedSids,
  2635. pCC->RestrictedSidHash,
  2636. pOwnerSid,
  2637. NULL,
  2638. NULL,
  2639. FALSE,
  2640. NULL
  2641. );
  2642. return b;
  2643. }
  2644. return TRUE;
  2645. }
  2646. BOOL
  2647. AuthzpNormalAccessCheck(
  2648. IN PAUTHZI_CLIENT_CONTEXT pCC,
  2649. IN PSID_AND_ATTRIBUTES pSidAttr,
  2650. IN DWORD SidCount,
  2651. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  2652. IN ACCESS_MASK Remaining,
  2653. IN PAUTHZ_ACCESS_REQUEST pRequest,
  2654. IN PACL pAcl,
  2655. IN PSID pOwnerSid,
  2656. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  2657. IN DWORD LocalTypeListLength
  2658. )
  2659. /*++
  2660. Routine description:
  2661. This routine loops thru the acl till we are denied some access bit that the
  2662. caller asked for or the acl is exhausted.
  2663. Arguments:
  2664. pCC - Pointer to the client context.
  2665. pSidAttr - Sids and attributes array to compare ace sids.
  2666. SidCount - Number of elements in the array.
  2667. Remaining - Access bits that are yet to be granted.
  2668. pRequest - Access request specifies the desired access mask, principal self
  2669. sid, the object type list strucutre (if any).
  2670. pAcl - Dacl against which the access check will be performed.
  2671. LocalTypeList - Internal object type list structure used to hold
  2672. intermediate results.
  2673. LocalCachingTypeList - Internal object type list structure used to hold
  2674. intermediate results for static granted bits.
  2675. LocalTypeListLength - Length of the array represnting the object.
  2676. Return Value:
  2677. A value of TRUE is returned if the routine is successful. Otherwise,
  2678. a value of FALSE is returned. In the failure case, error value may be
  2679. retrieved using GetLastError().
  2680. --*/
  2681. {
  2682. DWORD i = 0;
  2683. DWORD AceCount = 0;
  2684. DWORD Index = 0;
  2685. DWORD Ignore = 0;
  2686. PVOID Ace = NULL;
  2687. GUID * ObjectTypeInAce = NULL;
  2688. BOOL ObjectTypeListPresent = (0 != pRequest->ObjectTypeListLength);
  2689. BOOL bAceApplicable = FALSE;
  2690. for (i = 0; i < LocalTypeListLength; i++)
  2691. {
  2692. LocalTypeList[i].Remaining = Remaining;
  2693. }
  2694. AceCount = pAcl->AceCount;
  2695. for (i = 0, Ace = FirstAce(pAcl);
  2696. (i < AceCount) && (LocalTypeList[0].Remaining != 0);
  2697. i++, Ace = NextAce(Ace))
  2698. {
  2699. //
  2700. // Skip INHERIT_ONLY aces.
  2701. //
  2702. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE))
  2703. {
  2704. continue;
  2705. }
  2706. switch (((PACE_HEADER) Ace)->AceType)
  2707. {
  2708. case ACCESS_ALLOWED_ACE_TYPE:
  2709. //
  2710. // Check if the effective ace sid is present in the client context
  2711. // and is enabled. S-1-5-A is replaced by the principal sid
  2712. // supplied by the caller. In future, Creator Owner will be replaced
  2713. // by the owner sid in the primary security descriptor.
  2714. //
  2715. if (!AuthzpSidApplicable(
  2716. SidCount,
  2717. pSidAttr,
  2718. pSidHash,
  2719. AuthzAceSid(Ace),
  2720. pRequest->PrincipalSelfSid,
  2721. pOwnerSid,
  2722. FALSE,
  2723. &Ignore
  2724. ))
  2725. {
  2726. break;
  2727. }
  2728. #ifdef AUTHZ_DEBUG
  2729. wprintf(L"Allowed access Mask = %x\n", ((PKNOWN_ACE) Ace)->Mask);
  2730. #endif
  2731. //
  2732. // Optimize the common case instead of calling a subroutine.
  2733. //
  2734. if (1 == LocalTypeListLength)
  2735. {
  2736. //
  2737. // Clear the granted bits from the remaining.
  2738. //
  2739. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  2740. }
  2741. else
  2742. {
  2743. //
  2744. // Clear off the granted bits from the remaining for the entire
  2745. // tree.
  2746. //
  2747. AuthzpAddAccessTypeList(
  2748. LocalTypeList,
  2749. LocalTypeListLength,
  2750. 0,
  2751. ((PKNOWN_ACE) Ace)->Mask,
  2752. AuthzUpdateRemaining
  2753. );
  2754. }
  2755. break;
  2756. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  2757. //
  2758. // Check if the effective ace sid is present in the client context
  2759. // and is enabled. S-1-5-A is replaced by the principal sid
  2760. // supplied by the caller. In future, Creator Owner will be replaced
  2761. // by the owner sid in the primary security descriptor.
  2762. //
  2763. if (!AuthzpSidApplicable(
  2764. SidCount,
  2765. pSidAttr,
  2766. pSidHash,
  2767. AuthzAceSid(Ace),
  2768. pRequest->PrincipalSelfSid,
  2769. pOwnerSid,
  2770. FALSE,
  2771. &Ignore
  2772. ))
  2773. {
  2774. break;
  2775. }
  2776. bAceApplicable = FALSE;
  2777. //
  2778. // Make a call to the resource manager to get his opinion. His
  2779. // evaluation is returned in bAceApplicalble.
  2780. //
  2781. // Note: The return value of the callback is used to decide whether
  2782. // the API failed/succeeded. On a failure, we exit out of access
  2783. // check. On success, we check the boolean returned by
  2784. // bAceApplicable to decide whether to use the current ace.
  2785. //
  2786. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  2787. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  2788. Ace,
  2789. pRequest->OptionalArguments,
  2790. &bAceApplicable
  2791. )))
  2792. {
  2793. return FALSE;
  2794. }
  2795. if (!bAceApplicable)
  2796. {
  2797. break;
  2798. }
  2799. //
  2800. // Optimize the common case instead of calling a subroutine.
  2801. //
  2802. if (1 == LocalTypeListLength)
  2803. {
  2804. //
  2805. // Clear the granted bits from the remaining.
  2806. //
  2807. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  2808. }
  2809. else
  2810. {
  2811. //
  2812. // Clear off the granted bits from the remaining for the entire
  2813. // tree.
  2814. //
  2815. AuthzpAddAccessTypeList(
  2816. LocalTypeList,
  2817. LocalTypeListLength,
  2818. 0,
  2819. ((PKNOWN_ACE) Ace)->Mask,
  2820. AuthzUpdateRemaining
  2821. );
  2822. }
  2823. break;
  2824. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  2825. if (!AUTHZ_NON_NULL_PTR(pCC->Server))
  2826. {
  2827. break;
  2828. }
  2829. if (!AuthzpSidApplicable(
  2830. SidCount,
  2831. pSidAttr,
  2832. pSidHash,
  2833. RtlCompoundAceClientSid(Ace),
  2834. pRequest->PrincipalSelfSid,
  2835. pOwnerSid,
  2836. FALSE,
  2837. &Ignore
  2838. ) ||
  2839. !AuthzpSidApplicable(
  2840. pCC->Server->SidCount,
  2841. pCC->Server->Sids,
  2842. pCC->Server->SidHash,
  2843. RtlCompoundAceServerSid(Ace),
  2844. NULL,
  2845. NULL,
  2846. FALSE,
  2847. &Ignore
  2848. ))
  2849. {
  2850. break;
  2851. }
  2852. //
  2853. // Optimize the common case instead of calling a subroutine.
  2854. //
  2855. if (1 == LocalTypeListLength)
  2856. {
  2857. //
  2858. // Clear the granted bits from the remaining.
  2859. //
  2860. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  2861. }
  2862. else
  2863. {
  2864. //
  2865. // Clear off the granted bits from the remaining for the entire
  2866. // tree.
  2867. //
  2868. AuthzpAddAccessTypeList(
  2869. LocalTypeList,
  2870. LocalTypeListLength,
  2871. 0,
  2872. ((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask,
  2873. AuthzUpdateRemaining
  2874. );
  2875. }
  2876. break;
  2877. case ACCESS_DENIED_ACE_TYPE:
  2878. //
  2879. // Check if the effective ace sid is present in the client context
  2880. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  2881. // the principal sid supplied by the caller. In future, Creator
  2882. // Owner will be replaced by the owner sid in the primary security
  2883. // descriptor.
  2884. //
  2885. if (!AuthzpSidApplicable(
  2886. SidCount,
  2887. pSidAttr,
  2888. pSidHash,
  2889. AuthzAceSid(Ace),
  2890. pRequest->PrincipalSelfSid,
  2891. pOwnerSid,
  2892. TRUE,
  2893. &Ignore
  2894. ))
  2895. {
  2896. break;
  2897. }
  2898. #ifdef AUTHZ_DEBUG
  2899. wprintf(L"Allowed access Mask = %x\n", ((PKNOWN_ACE) Ace)->Mask);
  2900. #endif
  2901. //
  2902. // If any of the remaining bits are denied by this ace, exit early.
  2903. //
  2904. if (LocalTypeList->Remaining & ((PKNOWN_ACE) Ace)->Mask)
  2905. {
  2906. return TRUE;
  2907. }
  2908. break;
  2909. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  2910. //
  2911. // Check if the effective ace sid is present in the client context
  2912. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  2913. // the principal sid supplied by the caller. In future, Creator
  2914. // Owner will be replaced by the owner sid in the primary security
  2915. // descriptor.
  2916. //
  2917. if (!AuthzpSidApplicable(
  2918. SidCount,
  2919. pSidAttr,
  2920. pSidHash,
  2921. AuthzCallbackAceSid(Ace),
  2922. pRequest->PrincipalSelfSid,
  2923. pOwnerSid,
  2924. TRUE,
  2925. &Ignore
  2926. ))
  2927. {
  2928. break;
  2929. }
  2930. bAceApplicable = FALSE;
  2931. //
  2932. // Make a call to the resource manager to get his opinion. His
  2933. // evaluation is returned in bAceApplicalble.
  2934. //
  2935. // Note: The return value of the callback is used to decide whether
  2936. // the API failed/succeeded. On a failure, we exit out of access
  2937. // check. On success, we check the boolean returned by
  2938. // bAceApplicable to decide whether to use the current ace.
  2939. //
  2940. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  2941. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  2942. Ace,
  2943. pRequest->OptionalArguments,
  2944. &bAceApplicable
  2945. )))
  2946. {
  2947. return FALSE;
  2948. }
  2949. if (!bAceApplicable)
  2950. {
  2951. break;
  2952. }
  2953. //
  2954. // If any of the remaining bits are denied by this ace, exit early.
  2955. //
  2956. if (LocalTypeList->Remaining & ((PKNOWN_ACE) Ace)->Mask)
  2957. {
  2958. return TRUE;
  2959. }
  2960. break;
  2961. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  2962. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  2963. if ((ObjectTypeInAce) && (0 == pRequest->ObjectTypeListLength))
  2964. {
  2965. break;
  2966. }
  2967. //
  2968. // Check if the effective ace sid is present in the client context
  2969. // and is enabled. S-1-5-A is replaced by the principal sid
  2970. // supplied by the caller. In future, Creator Owner will be replaced
  2971. // by the owner sid in the primary security descriptor.
  2972. //
  2973. if (!AuthzpSidApplicable(
  2974. SidCount,
  2975. pSidAttr,
  2976. pSidHash,
  2977. RtlObjectAceSid(Ace),
  2978. pRequest->PrincipalSelfSid,
  2979. pOwnerSid,
  2980. FALSE,
  2981. &Ignore
  2982. ))
  2983. {
  2984. break;
  2985. }
  2986. //
  2987. // An object type ace with a NULL Object Type guid is the same as a
  2988. // normal ace.
  2989. //
  2990. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  2991. {
  2992. //
  2993. // Optimize the common case instead of calling a subroutine.
  2994. //
  2995. if (1 == LocalTypeListLength)
  2996. {
  2997. //
  2998. // Clear the granted bits from the remaining.
  2999. //
  3000. LocalTypeList->Remaining &= ~((PKNOWN_OBJECT_ACE) Ace)->Mask;
  3001. }
  3002. else
  3003. {
  3004. //
  3005. // Clear off the granted bits from the remaining for the entire
  3006. // tree.
  3007. //
  3008. AuthzpAddAccessTypeList(
  3009. LocalTypeList,
  3010. LocalTypeListLength,
  3011. 0,
  3012. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3013. AuthzUpdateRemaining
  3014. );
  3015. }
  3016. }
  3017. //
  3018. // So, it is a true object type ace. Proceed only if we are doing
  3019. // access check on a object type list.
  3020. //
  3021. else if (ObjectTypeListPresent)
  3022. {
  3023. //
  3024. // Look for a matching object type guid that matches the one in
  3025. // the ace.
  3026. //
  3027. if (AuthzpObjectInTypeList(
  3028. ObjectTypeInAce,
  3029. LocalTypeList,
  3030. LocalTypeListLength,
  3031. &Index
  3032. )
  3033. )
  3034. {
  3035. //
  3036. // Clear off the granted bits from the remaining for the
  3037. // subtree starting at the matched Index.
  3038. //
  3039. AuthzpAddAccessTypeList(
  3040. LocalTypeList,
  3041. LocalTypeListLength,
  3042. Index,
  3043. ((PKNOWN_OBJECT_ACE)Ace)->Mask,
  3044. AuthzUpdateRemaining
  3045. );
  3046. }
  3047. }
  3048. break;
  3049. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  3050. //
  3051. // Check if the effective ace sid is present in the client context
  3052. // and is enabled. S-1-5-A is replaced by the principal sid
  3053. // supplied by the caller. In future, Creator Owner will be replaced
  3054. // by the owner sid in the primary security descriptor.
  3055. //
  3056. if (!AuthzpSidApplicable(
  3057. SidCount,
  3058. pSidAttr,
  3059. pSidHash,
  3060. AuthzObjectAceSid(Ace),
  3061. pRequest->PrincipalSelfSid,
  3062. pOwnerSid,
  3063. FALSE,
  3064. &Ignore
  3065. ))
  3066. {
  3067. break;
  3068. }
  3069. bAceApplicable = FALSE;
  3070. //
  3071. // Make a call to the resource manager to get his opinion. His
  3072. // evaluation is returned in bAceApplicalble.
  3073. //
  3074. // Note: The return value of the callback is used to decide whether
  3075. // the API failed/succeeded. On a failure, we exit out of access
  3076. // check. On success, we check the boolean returned by
  3077. // bAceApplicable to decide whether to use the current ace.
  3078. //
  3079. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  3080. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  3081. Ace,
  3082. pRequest->OptionalArguments,
  3083. &bAceApplicable
  3084. )))
  3085. {
  3086. return FALSE;
  3087. }
  3088. if (!bAceApplicable)
  3089. {
  3090. break;
  3091. }
  3092. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  3093. //
  3094. // An object type ace with a NULL Object Type guid is the same as a
  3095. // normal ace.
  3096. //
  3097. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  3098. {
  3099. //
  3100. // Optimize the common case instead of calling a subroutine.
  3101. //
  3102. if (1 == LocalTypeListLength)
  3103. {
  3104. //
  3105. // Clear the granted bits from the remaining.
  3106. //
  3107. LocalTypeList->Remaining &= ~((PKNOWN_OBJECT_ACE) Ace)->Mask;
  3108. }
  3109. else
  3110. {
  3111. //
  3112. // Clear off the granted bits from the remaining for the entire
  3113. // tree.
  3114. //
  3115. AuthzpAddAccessTypeList(
  3116. LocalTypeList,
  3117. LocalTypeListLength,
  3118. 0,
  3119. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3120. AuthzUpdateRemaining
  3121. );
  3122. }
  3123. }
  3124. //
  3125. // So, it is a true object type ace. Proceed only if we are doing
  3126. // access check on a object type list.
  3127. //
  3128. else if (ObjectTypeListPresent)
  3129. {
  3130. //
  3131. // Look for a matching object type guid that matches the one in
  3132. // the ace.
  3133. //
  3134. if (AuthzpObjectInTypeList(
  3135. ObjectTypeInAce,
  3136. LocalTypeList,
  3137. LocalTypeListLength,
  3138. &Index
  3139. )
  3140. )
  3141. {
  3142. //
  3143. // Clear off the granted bits from the remaining for the
  3144. // subtree starting at the matched Index.
  3145. //
  3146. AuthzpAddAccessTypeList(
  3147. LocalTypeList,
  3148. LocalTypeListLength,
  3149. Index,
  3150. ((PKNOWN_OBJECT_ACE)Ace)->Mask,
  3151. AuthzUpdateRemaining
  3152. );
  3153. }
  3154. }
  3155. break;
  3156. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  3157. //
  3158. // Check if the effective ace sid is present in the client context
  3159. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  3160. // the principal sid supplied by the caller. In future, Creator
  3161. // Owner will be replaced by the owner sid in the primary security
  3162. // descriptor.
  3163. //
  3164. if (!AuthzpSidApplicable(
  3165. SidCount,
  3166. pSidAttr,
  3167. pSidHash,
  3168. AuthzObjectAceSid(Ace),
  3169. pRequest->PrincipalSelfSid,
  3170. pOwnerSid,
  3171. TRUE,
  3172. &Ignore
  3173. ))
  3174. {
  3175. break;
  3176. }
  3177. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  3178. //
  3179. // An object type ace with a NULL Object Type guid is the same as a
  3180. // normal ace.
  3181. //
  3182. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  3183. {
  3184. //
  3185. // If any of the remaining bits are denied by this ace, exit
  3186. // early.
  3187. //
  3188. if (LocalTypeList->Remaining & ((PKNOWN_OBJECT_ACE) Ace)->Mask)
  3189. {
  3190. return TRUE;
  3191. }
  3192. }
  3193. //
  3194. // Look for a matching object type guid that matches the one in
  3195. // the ace.
  3196. //
  3197. if (AuthzpObjectInTypeList(
  3198. ObjectTypeInAce,
  3199. LocalTypeList,
  3200. LocalTypeListLength,
  3201. &Index
  3202. ))
  3203. {
  3204. //
  3205. // If any of the remaining bits are denied by this ace, exit
  3206. // early.
  3207. //
  3208. if (LocalTypeList[Index].Remaining & ((PKNOWN_OBJECT_ACE) Ace)->Mask)
  3209. {
  3210. return TRUE;
  3211. }
  3212. }
  3213. break;
  3214. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  3215. //
  3216. // Check if the effective ace sid is present in the client context
  3217. // and is enabled or enabled for deny only. S-1-5-A is replaced by
  3218. // the principal sid supplied by the caller. In future, Creator
  3219. // Owner will be replaced by the owner sid in the primary security
  3220. // descriptor.
  3221. //
  3222. if (!AuthzpSidApplicable(
  3223. SidCount,
  3224. pSidAttr,
  3225. pSidHash,
  3226. AuthzObjectAceSid(Ace),
  3227. pRequest->PrincipalSelfSid,
  3228. pOwnerSid,
  3229. TRUE,
  3230. &Ignore
  3231. ))
  3232. {
  3233. break;
  3234. }
  3235. bAceApplicable = FALSE;
  3236. //
  3237. // Make a call to the resource manager to get his opinion. His
  3238. // evaluation is returned in bAceApplicalble.
  3239. //
  3240. // Note: The return value of the callback is used to decide whether
  3241. // the API failed/succeeded. On a failure, we exit out of access
  3242. // check. On success, we check the boolean returned by
  3243. // bAceApplicable to decide whether to use the current ace.
  3244. //
  3245. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  3246. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  3247. Ace,
  3248. pRequest->OptionalArguments,
  3249. &bAceApplicable
  3250. )))
  3251. {
  3252. return FALSE;
  3253. }
  3254. if (!bAceApplicable)
  3255. {
  3256. break;
  3257. }
  3258. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  3259. //
  3260. // An object type ace with a NULL Object Type guid is the same as a
  3261. // normal ace.
  3262. //
  3263. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  3264. {
  3265. //
  3266. // If any of the remaining bits are denied by this ace, exit
  3267. // early.
  3268. //
  3269. if (LocalTypeList->Remaining & ((PKNOWN_OBJECT_ACE) Ace)->Mask)
  3270. {
  3271. return TRUE;
  3272. }
  3273. }
  3274. //
  3275. // Look for a matching object type guid that matches the one in
  3276. // the ace.
  3277. //
  3278. if (AuthzpObjectInTypeList(
  3279. ObjectTypeInAce,
  3280. LocalTypeList,
  3281. LocalTypeListLength,
  3282. &Index
  3283. ))
  3284. {
  3285. //
  3286. // If any of the remaining bits are denied by this ace, exit
  3287. // early.
  3288. //
  3289. if (LocalTypeList[Index].Remaining & ((PKNOWN_OBJECT_ACE) Ace)->Mask)
  3290. {
  3291. return TRUE;
  3292. }
  3293. }
  3294. break;
  3295. default:
  3296. break;
  3297. }
  3298. }
  3299. return TRUE;
  3300. }
  3301. BOOL
  3302. AuthzpQuickNormalAccessCheck(
  3303. IN PAUTHZI_CLIENT_CONTEXT pCC,
  3304. IN PAUTHZI_HANDLE pAH,
  3305. IN PAUTHZ_ACCESS_REQUEST pRequest,
  3306. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  3307. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  3308. IN DWORD LocalTypeListLength
  3309. )
  3310. /*++
  3311. Routine description:
  3312. This routine calls AuthzpQuickNormalAccessCheck on regular part as well as
  3313. restricted part (if it exists).
  3314. Access granted = AccessGranted(Sids) [&& AccessGranted(RestrictedSids)
  3315. for restricted tokens]
  3316. Arguments:
  3317. pCC - Pointer to the client context.
  3318. pAH - Pointer to the authz handle structure.
  3319. pRequest - Access request specifies the desired access mask, principal self
  3320. sid, the object type list strucutre (if any).
  3321. pReply - The reply structure to return the results.
  3322. LocalTypeList - Internal object type list structure used to hold
  3323. intermediate results.
  3324. LocalTypeListLength - Length of the array represnting the object.
  3325. Return Value:
  3326. A value of TRUE is returned if the routine is successful. Otherwise,
  3327. a value of FALSE is returned. In the failure case, error value may be
  3328. retrieved using GetLastError().
  3329. --*/
  3330. {
  3331. BOOL b = TRUE;
  3332. ACCESS_MASK Remaining = pRequest->DesiredAccess & ~pAH->GrantedAccessMask[0];
  3333. //
  3334. // Do the access check with the non-restricted part of the client context.
  3335. //
  3336. b = AuthzpAllowOnlyNormalMultipleSDAccessCheck(
  3337. pCC,
  3338. pCC->Sids,
  3339. pCC->SidCount,
  3340. pCC->SidHash,
  3341. Remaining,
  3342. pRequest,
  3343. pAH->pSecurityDescriptor,
  3344. pAH->OptionalSecurityDescriptorArray,
  3345. pAH->OptionalSecurityDescriptorCount,
  3346. LocalTypeList,
  3347. LocalTypeListLength
  3348. );
  3349. if (!b)
  3350. {
  3351. return FALSE;
  3352. }
  3353. //
  3354. // If some access bits were not granted then no access bits will be granted.
  3355. //
  3356. if (0 != LocalTypeList->Remaining)
  3357. {
  3358. AuthzpFillReplyStructure(
  3359. pReply,
  3360. ERROR_ACCESS_DENIED,
  3361. 0
  3362. );
  3363. SetLastError(ERROR_SUCCESS);
  3364. return TRUE;
  3365. }
  3366. //
  3367. // Do the access check with the restricted part of the client context if
  3368. // it exists.
  3369. //
  3370. if (AUTHZ_TOKEN_RESTRICTED(pCC))
  3371. {
  3372. b = AuthzpAllowOnlyNormalMultipleSDAccessCheck(
  3373. pCC,
  3374. pCC->RestrictedSids,
  3375. pCC->RestrictedSidCount,
  3376. pCC->RestrictedSidHash,
  3377. Remaining,
  3378. pRequest,
  3379. pAH->pSecurityDescriptor,
  3380. pAH->OptionalSecurityDescriptorArray,
  3381. pAH->OptionalSecurityDescriptorCount,
  3382. LocalTypeList,
  3383. LocalTypeListLength
  3384. );
  3385. if (!b)
  3386. {
  3387. return FALSE;
  3388. }
  3389. //
  3390. // Make sure that all the bits are granted by the restricted part too.
  3391. //
  3392. if (0 != LocalTypeList->Remaining)
  3393. {
  3394. AuthzpFillReplyStructure(
  3395. pReply,
  3396. ERROR_ACCESS_DENIED,
  3397. 0
  3398. );
  3399. SetLastError(ERROR_SUCCESS);
  3400. return TRUE;
  3401. }
  3402. }
  3403. AuthzpFillReplyStructure(
  3404. pReply,
  3405. ERROR_SUCCESS,
  3406. pRequest->DesiredAccess
  3407. );
  3408. return TRUE;
  3409. }
  3410. BOOL
  3411. AuthzpAllowOnlyNormalMultipleSDAccessCheck(
  3412. IN PAUTHZI_CLIENT_CONTEXT pCC,
  3413. IN PSID_AND_ATTRIBUTES pSidAttr,
  3414. IN DWORD SidCount,
  3415. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  3416. IN ACCESS_MASK Remaining,
  3417. IN PAUTHZ_ACCESS_REQUEST pRequest,
  3418. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  3419. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  3420. IN DWORD OptionalSecurityDescriptorCount,
  3421. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  3422. IN DWORD LocalTypeListLength
  3423. )
  3424. /*++
  3425. Routine description:
  3426. This routine loops thru all the security descriptors and calls
  3427. AuthzpAllowOnlyNormalSingleAclAccessCheck.
  3428. Arguments:
  3429. pCC - Pointer to the client context.
  3430. pSidAttr - Sids and attributes array to compare ace sids.
  3431. SidCount - Number of elements in the array.
  3432. Remaining - Access bits that are yet to be granted.
  3433. pRequest - Access request specifies the desired access mask, principal self
  3434. sid, the object type list strucutre (if any).
  3435. pSecurityDescriptor - Primary security descriptor to be used for access
  3436. checks. The owner sid for the object is picked from this one. A NULL
  3437. DACL in this security descriptor represents a NULL DACL for the entire
  3438. object. A NULL SACL in this security descriptor is treated the same way
  3439. as an EMPTY SACL.
  3440. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  3441. of security descriptors. NULL ACLs in these security descriptors are
  3442. treated as EMPTY ACLS and the ACL for the entire object is the logical
  3443. concatenation of all the ACLs.
  3444. OptionalSecurityDescriptorCount - Number of optional security descriptors
  3445. This does not include the Primary security descriptor.
  3446. LocalTypeList - Internal object type list structure used to hold
  3447. intermediate results.
  3448. LocalTypeListLength - Length of the array represnting the object.
  3449. Return Value:
  3450. A value of TRUE is returned if the routine is successful. Otherwise,
  3451. a value of FALSE is returned. In the failure case, error value may be
  3452. retrieved using GetLastError().
  3453. --*/
  3454. {
  3455. PACL pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  3456. BOOL b = TRUE;
  3457. DWORD i = 0;
  3458. ASSERT(AUTHZ_NON_NULL_PTR(pAcl));
  3459. b = AuthzpAllowOnlyNormalSingleAclAccessCheck(
  3460. pCC,
  3461. pSidAttr,
  3462. SidCount,
  3463. pSidHash,
  3464. Remaining,
  3465. pRequest,
  3466. pAcl,
  3467. LocalTypeList,
  3468. LocalTypeListLength
  3469. );
  3470. if (!b)
  3471. {
  3472. return FALSE;
  3473. }
  3474. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  3475. {
  3476. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  3477. if (!AUTHZ_NON_NULL_PTR(pAcl))
  3478. {
  3479. return TRUE;
  3480. }
  3481. b = AuthzpAllowOnlyNormalSingleAclAccessCheck(
  3482. pCC,
  3483. pSidAttr,
  3484. SidCount,
  3485. pSidHash,
  3486. Remaining,
  3487. pRequest,
  3488. pAcl,
  3489. LocalTypeList,
  3490. LocalTypeListLength
  3491. );
  3492. if (!b)
  3493. {
  3494. break;
  3495. }
  3496. }
  3497. return b;
  3498. }
  3499. BOOL
  3500. AuthzpAllowOnlyNormalSingleAclAccessCheck(
  3501. IN PAUTHZI_CLIENT_CONTEXT pCC,
  3502. IN PSID_AND_ATTRIBUTES pSidAttr,
  3503. IN DWORD SidCount,
  3504. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  3505. IN ACCESS_MASK Remaining,
  3506. IN PAUTHZ_ACCESS_REQUEST pRequest,
  3507. IN PACL pAcl,
  3508. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  3509. IN DWORD LocalTypeListLength
  3510. )
  3511. /*++
  3512. Routine description:
  3513. This routine evaluates only those Grant aces that have principal self sid or
  3514. are callback aces. Deny aces can not exist in the acl unless the resource
  3515. manager messed up with the assumption and changed the security descriptors.
  3516. Arguments:
  3517. pCC - Pointer to the client context.
  3518. pSidAttr - Sids and attributes array to compare ace sids.
  3519. SidCount - Number of elements in the array.
  3520. Remaining - Access bits that are yet to be granted.
  3521. pRequest - Access request specifies the desired access mask, principal self
  3522. sid, the object type list strucutre (if any).
  3523. pAcl - Dacl against which the accesscheck will be preformed.
  3524. LocalTypeList - Internal object type list structure used to hold
  3525. intermediate results.
  3526. LocalTypeListLength - Length of the array represnting the object.
  3527. Return Value:
  3528. A value of TRUE is returned if the routine is successful. Otherwise,
  3529. a value of FALSE is returned. In the failure case, error value may be
  3530. retrieved using GetLastError().
  3531. --*/
  3532. {
  3533. BOOL ObjectTypeListPresent = (0 != pRequest->ObjectTypeListLength);
  3534. DWORD i = 0;
  3535. DWORD Index = 0;
  3536. DWORD AceCount = 0;
  3537. GUID * ObjectTypeInAce = NULL;
  3538. PVOID Ace = NULL;
  3539. PSID pSid = NULL;
  3540. BOOL bAceApplicable = FALSE;
  3541. for (i = 0; i < LocalTypeListLength; i++)
  3542. {
  3543. LocalTypeList[i].Remaining = Remaining;
  3544. }
  3545. AceCount = pAcl->AceCount;
  3546. for (i = 0, Ace = FirstAce(pAcl); i < AceCount; i++, Ace = NextAce(Ace))
  3547. {
  3548. //
  3549. // Skip INHERIT_ONLY aces.
  3550. //
  3551. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE))
  3552. {
  3553. continue;
  3554. }
  3555. switch (((PACE_HEADER) Ace)->AceType)
  3556. {
  3557. case ACCESS_ALLOWED_ACE_TYPE:
  3558. //
  3559. // We have determined that only dynamic aces should be evaluated.
  3560. // For non-callback aces, the dynamic factor arises from Principal
  3561. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  3562. //
  3563. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(&((PKNOWN_ACE) Ace)->SidStart))
  3564. {
  3565. break;
  3566. }
  3567. //
  3568. // Check if the caller supplied Principal self sid is present in the
  3569. // client context and is enabled.
  3570. //
  3571. if (!AuthzpAllowOnlySidApplicable(
  3572. SidCount,
  3573. pSidAttr,
  3574. pSidHash,
  3575. pRequest->PrincipalSelfSid
  3576. ))
  3577. {
  3578. break;
  3579. }
  3580. //
  3581. // Optimize the common case instead of calling a subroutine.
  3582. //
  3583. if (1 == LocalTypeListLength)
  3584. {
  3585. //
  3586. // Clear the granted bits from the remaining.
  3587. //
  3588. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  3589. }
  3590. else
  3591. {
  3592. //
  3593. // Clear off the granted bits from the remaining for the entire
  3594. // tree.
  3595. //
  3596. AuthzpAddAccessTypeList(
  3597. LocalTypeList,
  3598. LocalTypeListLength,
  3599. 0,
  3600. ((PKNOWN_ACE) Ace)->Mask,
  3601. AuthzUpdateRemaining
  3602. );
  3603. }
  3604. break;
  3605. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  3606. if (!AUTHZ_NON_NULL_PTR(pCC->Server))
  3607. {
  3608. break;
  3609. }
  3610. //
  3611. // We have determined that only dynamic aces should be evaluated.
  3612. // For non-callback aces, the dynamic factor arises from Principal
  3613. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  3614. //
  3615. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlCompoundAceClientSid(Ace)))
  3616. {
  3617. break;
  3618. }
  3619. if (!AuthzpAllowOnlySidApplicable(
  3620. SidCount,
  3621. pSidAttr,
  3622. pSidHash,
  3623. pRequest->PrincipalSelfSid
  3624. ) ||
  3625. !AuthzpAllowOnlySidApplicable(
  3626. pCC->Server->SidCount,
  3627. pCC->Server->Sids,
  3628. pCC->Server->SidHash,
  3629. RtlCompoundAceServerSid(Ace)
  3630. ))
  3631. {
  3632. break;
  3633. }
  3634. //
  3635. // Optimize the common case instead of calling a subroutine.
  3636. //
  3637. if (1 == LocalTypeListLength)
  3638. {
  3639. //
  3640. // Clear the granted bits from the remaining.
  3641. //
  3642. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  3643. }
  3644. else
  3645. {
  3646. //
  3647. // Clear off the granted bits from the remaining for the entire
  3648. // tree.
  3649. //
  3650. AuthzpAddAccessTypeList(
  3651. LocalTypeList,
  3652. LocalTypeListLength,
  3653. 0,
  3654. ((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask,
  3655. AuthzUpdateRemaining
  3656. );
  3657. }
  3658. break;
  3659. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  3660. //
  3661. // We have determined that only dynamic aces should be evaluated.
  3662. // For non-callback aces, the dynamic factor arises from Principal
  3663. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  3664. //
  3665. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlObjectAceSid(Ace)))
  3666. {
  3667. break;
  3668. }
  3669. //
  3670. // Check if the caller supplied Principal self sid is present in the
  3671. // client context and is enabled.
  3672. //
  3673. if (!AuthzpAllowOnlySidApplicable(
  3674. SidCount,
  3675. pSidAttr,
  3676. pSidHash,
  3677. pRequest->PrincipalSelfSid
  3678. ))
  3679. {
  3680. break;
  3681. }
  3682. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  3683. //
  3684. // An object type ace with a NULL Object Type guid is the same as a
  3685. // normal ace.
  3686. //
  3687. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  3688. {
  3689. //
  3690. // Optimize the common case instead of calling a subroutine.
  3691. //
  3692. if (1 == LocalTypeListLength)
  3693. {
  3694. //
  3695. // Grant access bits that have not already been denied.
  3696. //
  3697. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  3698. }
  3699. else
  3700. {
  3701. //
  3702. // Propagate grant bits down the tree starting at the root.
  3703. //
  3704. AuthzpAddAccessTypeList(
  3705. LocalTypeList,
  3706. LocalTypeListLength,
  3707. 0,
  3708. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3709. AuthzUpdateCurrentGranted
  3710. );
  3711. }
  3712. }
  3713. //
  3714. // So, it is a true object type ace. Proceed only if we are doing
  3715. // access check on a object type list.
  3716. //
  3717. else if (ObjectTypeListPresent)
  3718. {
  3719. //
  3720. // Look for a matching object type guid that matches the one in
  3721. // the ace.
  3722. //
  3723. if (AuthzpObjectInTypeList(
  3724. ObjectTypeInAce,
  3725. LocalTypeList,
  3726. LocalTypeListLength,
  3727. &Index
  3728. )
  3729. )
  3730. {
  3731. //
  3732. // Clear off the granted bits from the remaining for the
  3733. // subtree starting at the matched Index.
  3734. //
  3735. AuthzpAddAccessTypeList(
  3736. LocalTypeList,
  3737. LocalTypeListLength,
  3738. Index,
  3739. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3740. AuthzUpdateCurrentGranted
  3741. );
  3742. }
  3743. }
  3744. break;
  3745. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  3746. //
  3747. // If the ace sid is Principal Self, replace it with the caller
  3748. // supplied Principal sid.
  3749. //
  3750. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(&(((PKNOWN_ACE) Ace)->SidStart)))
  3751. {
  3752. pSid = (PSID) &(((PKNOWN_ACE) Ace)->SidStart);
  3753. }
  3754. else
  3755. {
  3756. pSid = pRequest->PrincipalSelfSid;
  3757. }
  3758. //
  3759. // Check if the effective ace sid is present in the client context
  3760. // and is enabled.
  3761. //
  3762. if (!AuthzpAllowOnlySidApplicable(
  3763. SidCount,
  3764. pSidAttr,
  3765. pSidHash,
  3766. pSid
  3767. ))
  3768. {
  3769. break;
  3770. }
  3771. bAceApplicable = FALSE;
  3772. //
  3773. // Make a call to the resource manager to get his opinion. His
  3774. // evaluation is returned in bAceApplicalble.
  3775. //
  3776. // Note: The return value of the callback is used to decide whether
  3777. // the API failed/succeeded. On a failure, we exit out of access
  3778. // check. On success, we check the boolean returned by
  3779. // bAceApplicable to decide whether to use the current ace.
  3780. //
  3781. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  3782. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  3783. Ace,
  3784. pRequest->OptionalArguments,
  3785. &bAceApplicable
  3786. )))
  3787. {
  3788. return FALSE;
  3789. }
  3790. if (!bAceApplicable)
  3791. {
  3792. break;
  3793. }
  3794. //
  3795. // Optimize the common case instead of calling a subroutine.
  3796. //
  3797. if (1 == LocalTypeListLength)
  3798. {
  3799. //
  3800. // Clear the granted bits from the remaining.
  3801. //
  3802. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  3803. }
  3804. else
  3805. {
  3806. //
  3807. // Clear off the granted bits from the remaining for the entire
  3808. // tree.
  3809. //
  3810. AuthzpAddAccessTypeList(
  3811. LocalTypeList,
  3812. LocalTypeListLength,
  3813. 0,
  3814. ((PKNOWN_ACE) Ace)->Mask,
  3815. AuthzUpdateRemaining
  3816. );
  3817. }
  3818. break;
  3819. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  3820. //
  3821. // If the ace sid is Principal Self, replace it with the caller
  3822. // supplied Principal sid.
  3823. //
  3824. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlObjectAceSid(Ace)))
  3825. {
  3826. pSid = RtlObjectAceSid(Ace);
  3827. }
  3828. else
  3829. {
  3830. pSid = pRequest->PrincipalSelfSid;
  3831. }
  3832. //
  3833. // Check if the effective ace sid is present in the client context
  3834. // and is enabled.
  3835. //
  3836. if (!AuthzpAllowOnlySidApplicable(
  3837. SidCount,
  3838. pSidAttr,
  3839. pSidHash,
  3840. pSid
  3841. ))
  3842. {
  3843. break;
  3844. }
  3845. //
  3846. // Make a call to the resource manager to get his opinion. His
  3847. // evaluation is returned in bAceApplicalble.
  3848. //
  3849. // Note: The return value of the callback is used to decide whether
  3850. // the API failed/succeeded. On a failure, we exit out of access
  3851. // check. On success, we check the boolean returned by
  3852. // bAceApplicable to decide whether to use the current ace.
  3853. //
  3854. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  3855. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  3856. Ace,
  3857. pRequest->OptionalArguments,
  3858. &bAceApplicable
  3859. )))
  3860. {
  3861. return FALSE;
  3862. }
  3863. if (!bAceApplicable)
  3864. {
  3865. break;
  3866. }
  3867. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  3868. //
  3869. // An object type ace with a NULL Object Type guid is the same as a
  3870. // normal ace.
  3871. //
  3872. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  3873. {
  3874. //
  3875. // Optimize the common case instead of calling a subroutine.
  3876. //
  3877. if (1 == LocalTypeListLength)
  3878. {
  3879. //
  3880. // Grant access bits that have not already been denied.
  3881. //
  3882. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  3883. }
  3884. else
  3885. {
  3886. //
  3887. // Propagate grant bits down the tree starting at the root.
  3888. //
  3889. AuthzpAddAccessTypeList(
  3890. LocalTypeList,
  3891. LocalTypeListLength,
  3892. 0,
  3893. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3894. AuthzUpdateCurrentGranted
  3895. );
  3896. }
  3897. }
  3898. //
  3899. // So, it is a true object type ace. Proceed only if we are doing
  3900. // access check on a object type list.
  3901. //
  3902. else if (ObjectTypeListPresent)
  3903. {
  3904. //
  3905. // Look for a matching object type guid that matches the one in
  3906. // the ace.
  3907. //
  3908. if (AuthzpObjectInTypeList(
  3909. ObjectTypeInAce,
  3910. LocalTypeList,
  3911. LocalTypeListLength,
  3912. &Index
  3913. )
  3914. )
  3915. {
  3916. //
  3917. // Propagate grant bits down the tree starting at the
  3918. // index at which the guids matched.
  3919. // In the case when this is the last of the siblings to be
  3920. // granted access, the parent also is granted access.
  3921. //
  3922. AuthzpAddAccessTypeList(
  3923. LocalTypeList,
  3924. LocalTypeListLength,
  3925. Index,
  3926. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  3927. AuthzUpdateCurrentGranted
  3928. );
  3929. }
  3930. }
  3931. break;
  3932. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  3933. case ACCESS_DENIED_ACE_TYPE:
  3934. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  3935. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  3936. ASSERT(FALSE);
  3937. break;
  3938. default:
  3939. break;
  3940. }
  3941. }
  3942. return TRUE;
  3943. }
  3944. BOOL
  3945. AuthzpAllowOnlySidApplicable(
  3946. IN DWORD SidCount,
  3947. IN PSID_AND_ATTRIBUTES pSidAttr,
  3948. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  3949. IN PSID pSid
  3950. )
  3951. /*++
  3952. Routine description:
  3953. This routine determine whether the given ace sid is present in the client
  3954. context and is enabled.
  3955. Arguments:
  3956. SidCount - Number of sids in the pSidAttrArray
  3957. pSidAttr - Sid and attributes against which the ace sid should be compared.
  3958. pAceSid - Sid in the ace.
  3959. Return Value:
  3960. A value of TRUE is returned if the effective sid is found in the client
  3961. context and is enabled.
  3962. FALSE otherwise.
  3963. --*/
  3964. {
  3965. DWORD i = 0;
  3966. DWORD SidLen = 0;
  3967. PISID MatchSid = NULL;
  3968. UNREFERENCED_PARAMETER(pSidHash);
  3969. if (!ARGUMENT_PRESENT(pSid))
  3970. {
  3971. return FALSE;
  3972. }
  3973. SidLen = RtlLengthSid(pSid);
  3974. //
  3975. // Loop thru the sids and return TRUE is a match is found and the sid
  3976. // is enabled.
  3977. //
  3978. for (i = 0; i < SidCount; i++, pSidAttr++)
  3979. {
  3980. MatchSid = (PISID) pSidAttr->Sid;
  3981. if (AUTHZ_EQUAL_SID(pSid, MatchSid, SidLen))
  3982. {
  3983. if (FLAG_ON(pSidAttr->Attributes, SE_GROUP_ENABLED))
  3984. {
  3985. return TRUE;
  3986. }
  3987. return FALSE;
  3988. }
  3989. }
  3990. return FALSE;
  3991. }
  3992. BOOL
  3993. AuthzpQuickMaximumAllowedAccessCheck(
  3994. IN PAUTHZI_CLIENT_CONTEXT pCC,
  3995. IN PAUTHZI_HANDLE pAH,
  3996. IN PAUTHZ_ACCESS_REQUEST pRequest,
  3997. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  3998. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  3999. IN DWORD LocalTypeListLength
  4000. )
  4001. /*++
  4002. Routine description:
  4003. This routine calls AuthzpQuickMaximumAllowedAccessCheck on normal part (as
  4004. well as restricted part if it exists).
  4005. Arguments:
  4006. pCC - Pointer to the client context.
  4007. pAH - Pointer to the authz handle structure.
  4008. pRequest - Access request specifies the desired access mask, principal self
  4009. sid, the object type list strucutre (if any).
  4010. pReply - The reply structure to return the results.
  4011. LocalTypeList - Internal object type list structure used to hold
  4012. intermediate results.
  4013. LocalTypeListLength - Length of the array represnting the object.
  4014. Return Value:
  4015. A value of TRUE is returned if the routine is successful. Otherwise,
  4016. a value of FALSE is returned. In the failure case, error value may be
  4017. retrieved using GetLastError().
  4018. --*/
  4019. {
  4020. BOOL b = FALSE;
  4021. BOOL ObjectTypeListPresent = (0 != pRequest->ObjectTypeListLength);
  4022. UNREFERENCED_PARAMETER(pReply);
  4023. //
  4024. // Do the access check with the non-restricted part of the client context.
  4025. //
  4026. b = AuthzpAllowOnlyMaximumAllowedMultipleSDAccessCheck(
  4027. pCC,
  4028. pRequest,
  4029. pAH->pSecurityDescriptor,
  4030. pAH->OptionalSecurityDescriptorArray,
  4031. pAH->OptionalSecurityDescriptorCount,
  4032. LocalTypeList,
  4033. LocalTypeListLength,
  4034. ObjectTypeListPresent,
  4035. FALSE
  4036. );
  4037. if (!b)
  4038. {
  4039. return FALSE;
  4040. }
  4041. //
  4042. // Do the access check with the restricted part of the client context if
  4043. // it exists.
  4044. //
  4045. if (AUTHZ_TOKEN_RESTRICTED(pCC))
  4046. {
  4047. b = AuthzpAllowOnlyMaximumAllowedMultipleSDAccessCheck(
  4048. pCC,
  4049. pRequest,
  4050. pAH->pSecurityDescriptor,
  4051. pAH->OptionalSecurityDescriptorArray,
  4052. pAH->OptionalSecurityDescriptorCount,
  4053. LocalTypeList,
  4054. LocalTypeListLength,
  4055. ObjectTypeListPresent,
  4056. TRUE
  4057. );
  4058. }
  4059. return b;
  4060. }
  4061. BOOL
  4062. AuthzpAllowOnlyMaximumAllowedMultipleSDAccessCheck(
  4063. IN PAUTHZI_CLIENT_CONTEXT pCC,
  4064. IN PAUTHZ_ACCESS_REQUEST pRequest,
  4065. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  4066. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  4067. IN DWORD OptionalSecurityDescriptorCount OPTIONAL,
  4068. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  4069. IN DWORD LocalTypeListLength,
  4070. IN BOOL ObjectTypeListPresent,
  4071. IN BOOL Restricted
  4072. )
  4073. /*++
  4074. Routine description:
  4075. This routine call AuthzpAllowOnlyMaximumAllowedSingleAclAccessCheck for all
  4076. given security descriptors.
  4077. Arguments:
  4078. pCC - Pointer to the client context.
  4079. pRequest - Access request specifies the desired access mask, principal self
  4080. sid, the object type list strucutre (if any).
  4081. pSecurityDescriptor - Primary security descriptor to be used for access
  4082. checks. The owner sid for the object is picked from this one. A NULL
  4083. DACL in this security descriptor represents a NULL DACL for the entire
  4084. object. A NULL SACL in this security descriptor is treated the same way
  4085. as an EMPTY SACL.
  4086. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  4087. of security descriptors. NULL ACLs in these security descriptors are
  4088. treated as EMPTY ACLS and the ACL for the entire object is the logical
  4089. concatenation of all the ACLs.
  4090. OptionalSecurityDescriptorCount - Number of optional security descriptors
  4091. This does not include the Primary security descriptor.
  4092. LocalTypeList - Internal object type list structure used to hold
  4093. intermediate results.
  4094. LocalTypeListLength - Length of the array represnting the object.
  4095. ObjectTypeListPresent - Whether the called supplied an object type list.
  4096. Restricted - Whether this is an access check on the restricted part of the
  4097. client context.
  4098. Return Value:
  4099. A value of TRUE is returned if the routine is successful. Otherwise,
  4100. a value of FALSE is returned. In the failure case, error value may be
  4101. retrieved using GetLastError().
  4102. --*/
  4103. {
  4104. DWORD i = 0;
  4105. DWORD j = 0;
  4106. DWORD SidCount = 0;
  4107. BOOL b = TRUE;
  4108. PSID_AND_ATTRIBUTES pSidAttr = NULL;
  4109. PACL pAcl = NULL;
  4110. PSID pOwnerSid = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  4111. PAUTHZI_SID_HASH_ENTRY pSidHash = NULL;
  4112. if (Restricted)
  4113. {
  4114. //
  4115. // Access granted is a bitwise AND of both (normal & restricted) part
  4116. // of the client context.
  4117. //
  4118. for (j = 0; j < LocalTypeListLength; j++)
  4119. {
  4120. LocalTypeList[j].Remaining = LocalTypeList[j].CurrentGranted;
  4121. LocalTypeList[j].CurrentGranted = 0;
  4122. }
  4123. pSidAttr = pCC->RestrictedSids;
  4124. SidCount = pCC->RestrictedSidCount;
  4125. pSidHash = pCC->RestrictedSidHash;
  4126. }
  4127. else
  4128. {
  4129. pSidAttr = pCC->Sids;
  4130. SidCount = pCC->SidCount;
  4131. pSidHash = pCC->SidHash;
  4132. }
  4133. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  4134. b = AuthzpAllowOnlyMaximumAllowedSingleAclAccessCheck(
  4135. pCC,
  4136. pSidAttr,
  4137. SidCount,
  4138. pSidHash,
  4139. pRequest,
  4140. pAcl,
  4141. pOwnerSid,
  4142. LocalTypeList,
  4143. LocalTypeListLength,
  4144. ObjectTypeListPresent
  4145. );
  4146. if (!b)
  4147. {
  4148. return FALSE;
  4149. }
  4150. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  4151. {
  4152. pAcl = RtlpDaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  4153. if (!AUTHZ_NON_NULL_PTR(pAcl))
  4154. {
  4155. continue;
  4156. }
  4157. b = AuthzpAllowOnlyMaximumAllowedSingleAclAccessCheck(
  4158. pCC,
  4159. pSidAttr,
  4160. SidCount,
  4161. pSidHash,
  4162. pRequest,
  4163. pAcl,
  4164. pOwnerSid,
  4165. LocalTypeList,
  4166. LocalTypeListLength,
  4167. ObjectTypeListPresent
  4168. );
  4169. if (!b)
  4170. {
  4171. break;
  4172. }
  4173. }
  4174. return b;
  4175. }
  4176. BOOL
  4177. AuthzpAllowOnlyMaximumAllowedSingleAclAccessCheck(
  4178. IN PAUTHZI_CLIENT_CONTEXT pCC,
  4179. IN PSID_AND_ATTRIBUTES pSidAttr,
  4180. IN DWORD SidCount,
  4181. IN PAUTHZI_SID_HASH_ENTRY pSidHash,
  4182. IN PAUTHZ_ACCESS_REQUEST pRequest,
  4183. IN PACL pAcl,
  4184. IN PSID pOwnerSid,
  4185. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  4186. IN DWORD LocalTypeListLength,
  4187. IN BOOL ObjectTypeListPresent
  4188. )
  4189. /*++
  4190. Routine description:
  4191. This routine loops thru the entire acl and evaluates only those Grant aces
  4192. that have principal self sid in them or are callback aces.
  4193. Arguments:
  4194. pCC - Pointer to the client context.
  4195. pSidAttr - Sids and attributes array to compare ace sids.
  4196. SidCount - Number of elements in the array.
  4197. pRequest - Access request specifies the desired access mask, principal self
  4198. sid, the object type list strucutre (if any).
  4199. pAcl - Sacl to be used to make the decision about audit generation.
  4200. pOwnerSid - The owner sid in the primary security descriptor. This will be
  4201. needed after we implement single instancing.
  4202. LocalTypeList - Internal object type list structure used to hold
  4203. intermediate results.
  4204. LocalTypeListLength - Length of the array represnting the object.
  4205. ObjectTypeListPresent - Whether the called supplied an object type list.
  4206. Return Value:
  4207. A value of TRUE is returned if the routine is successful. Otherwise,
  4208. a value of FALSE is returned. In the failure case, error value may be
  4209. retrieved using GetLastError().
  4210. --*/
  4211. {
  4212. DWORD AceCount = 0;
  4213. DWORD i = 0;
  4214. DWORD Index = 0;
  4215. PVOID Ace = NULL;
  4216. GUID * ObjectTypeInAce = NULL;
  4217. BOOL bAceApplicable = FALSE;
  4218. PSID pSid = NULL;
  4219. UNREFERENCED_PARAMETER(pOwnerSid);
  4220. AceCount = pAcl->AceCount;
  4221. for (i = 0, Ace = FirstAce(pAcl); i < AceCount; i++, Ace = NextAce(Ace))
  4222. {
  4223. //
  4224. // Skip INHERIT_ONLY aces.
  4225. //
  4226. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE))
  4227. {
  4228. continue;
  4229. }
  4230. switch (((PACE_HEADER) Ace)->AceType)
  4231. {
  4232. case ACCESS_ALLOWED_ACE_TYPE:
  4233. //
  4234. // We have determined that only dynamic aces should be evaluated.
  4235. // For non-callback aces, the dynamic factor arises from Principal
  4236. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  4237. //
  4238. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(&((PKNOWN_ACE) Ace)->SidStart))
  4239. {
  4240. break;
  4241. }
  4242. //
  4243. // Check if the caller supplied Principal self sid is present in the
  4244. // client context and is enabled.
  4245. //
  4246. if (!AuthzpAllowOnlySidApplicable(
  4247. SidCount,
  4248. pSidAttr,
  4249. pSidHash,
  4250. pRequest->PrincipalSelfSid
  4251. ))
  4252. {
  4253. break;
  4254. }
  4255. //
  4256. // Optimize the common case instead of calling a subroutine.
  4257. //
  4258. if (1 == LocalTypeListLength)
  4259. {
  4260. //
  4261. // Grant access bits that have not already been denied.
  4262. //
  4263. LocalTypeList->CurrentGranted |= (((PKNOWN_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  4264. }
  4265. else
  4266. {
  4267. //
  4268. // Propagate grant bits down the tree starting at the root.
  4269. //
  4270. AuthzpAddAccessTypeList(
  4271. LocalTypeList,
  4272. LocalTypeListLength,
  4273. 0,
  4274. ((PKNOWN_ACE) Ace)->Mask,
  4275. AuthzUpdateCurrentGranted
  4276. );
  4277. }
  4278. break;
  4279. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  4280. if (!AUTHZ_NON_NULL_PTR(pCC->Server))
  4281. {
  4282. break;
  4283. }
  4284. //
  4285. // We have determined that only dynamic aces should be evaluated.
  4286. // For non-callback aces, the dynamic factor arises from Principal
  4287. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  4288. //
  4289. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlCompoundAceClientSid(Ace)))
  4290. {
  4291. break;
  4292. }
  4293. if (!AuthzpAllowOnlySidApplicable(
  4294. SidCount,
  4295. pSidAttr,
  4296. pSidHash,
  4297. pRequest->PrincipalSelfSid
  4298. ) ||
  4299. !AuthzpAllowOnlySidApplicable(
  4300. pCC->Server->SidCount,
  4301. pCC->Server->Sids,
  4302. pCC->Server->SidHash,
  4303. RtlCompoundAceServerSid(Ace)
  4304. ))
  4305. {
  4306. break;
  4307. }
  4308. //
  4309. // Optimize the common case instead of calling a subroutine.
  4310. //
  4311. if (1 == LocalTypeListLength)
  4312. {
  4313. //
  4314. // Grant access bits that have not already been denied.
  4315. //
  4316. LocalTypeList->CurrentGranted |= (((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  4317. }
  4318. else
  4319. {
  4320. //
  4321. // Propagate grant bits down the tree starting at the root.
  4322. //
  4323. AuthzpAddAccessTypeList(
  4324. LocalTypeList,
  4325. LocalTypeListLength,
  4326. 0,
  4327. ((PCOMPOUND_ACCESS_ALLOWED_ACE) Ace)->Mask,
  4328. AuthzUpdateCurrentGranted
  4329. );
  4330. }
  4331. break;
  4332. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  4333. //
  4334. // We have determined that only dynamic aces should be evaluated.
  4335. // For non-callback aces, the dynamic factor arises from Principal
  4336. // self sid. Skip the ace if the ace sid is not Principal Self sid.
  4337. //
  4338. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlObjectAceSid(Ace)))
  4339. {
  4340. break;
  4341. }
  4342. //
  4343. // Check if the caller supplied Principal self sid is present in the
  4344. // client context and is enabled.
  4345. //
  4346. if (!AuthzpAllowOnlySidApplicable(
  4347. SidCount,
  4348. pSidAttr,
  4349. pSidHash,
  4350. pRequest->PrincipalSelfSid
  4351. ))
  4352. {
  4353. break;
  4354. }
  4355. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  4356. //
  4357. // An object type ace with a NULL Object Type guid is the same as a
  4358. // normal ace.
  4359. //
  4360. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  4361. {
  4362. //
  4363. // Optimize the common case instead of calling a subroutine.
  4364. //
  4365. if (1 == LocalTypeListLength)
  4366. {
  4367. //
  4368. // Grant access bits that have not already been denied.
  4369. //
  4370. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  4371. }
  4372. else
  4373. {
  4374. //
  4375. // Propagate grant bits down the tree starting at the root.
  4376. //
  4377. AuthzpAddAccessTypeList(
  4378. LocalTypeList,
  4379. LocalTypeListLength,
  4380. 0,
  4381. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  4382. AuthzUpdateCurrentGranted
  4383. );
  4384. }
  4385. }
  4386. //
  4387. // So, it is a true object type ace. Proceed only if we are doing
  4388. // access check on a object type list.
  4389. //
  4390. else if (ObjectTypeListPresent)
  4391. {
  4392. //
  4393. // Look for a matching object type guid that matches the one in
  4394. // the ace.
  4395. //
  4396. if (AuthzpObjectInTypeList(
  4397. ObjectTypeInAce,
  4398. LocalTypeList,
  4399. LocalTypeListLength,
  4400. &Index
  4401. )
  4402. )
  4403. {
  4404. //
  4405. // Propagate grant bits down the tree starting at the
  4406. // index at which the guids matched.
  4407. // In the case when this is the last of the siblings to be
  4408. // granted access, the parent also is granted access.
  4409. //
  4410. AuthzpAddAccessTypeList(
  4411. LocalTypeList,
  4412. LocalTypeListLength,
  4413. Index,
  4414. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  4415. AuthzUpdateCurrentGranted
  4416. );
  4417. }
  4418. }
  4419. break;
  4420. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  4421. //
  4422. // If the ace sid is Principal Self, replace it with the caller
  4423. // supplied Principal sid.
  4424. //
  4425. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(&((PKNOWN_ACE) Ace)->SidStart))
  4426. {
  4427. pSid = (PSID) &(((PKNOWN_ACE) Ace)->SidStart);
  4428. }
  4429. else
  4430. {
  4431. pSid = pRequest->PrincipalSelfSid;
  4432. }
  4433. //
  4434. // Check if the effective ace sid is present in the client context
  4435. // and is enabled.
  4436. //
  4437. if (!AuthzpAllowOnlySidApplicable(
  4438. SidCount,
  4439. pSidAttr,
  4440. pSidHash,
  4441. pSid
  4442. ))
  4443. {
  4444. break;
  4445. }
  4446. bAceApplicable = FALSE;
  4447. //
  4448. // Make a call to the resource manager to get his opinion. His
  4449. // evaluation is returned in bAceApplicalble.
  4450. //
  4451. // Note: The return value of the callback is used to decide whether
  4452. // the API failed/succeeded. On a failure, we exit out of access
  4453. // check. On success, we check the boolean returned by
  4454. // bAceApplicable to decide whether to use the current ace.
  4455. //
  4456. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  4457. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  4458. Ace,
  4459. pRequest->OptionalArguments,
  4460. &bAceApplicable
  4461. )))
  4462. {
  4463. return FALSE;
  4464. }
  4465. if (!bAceApplicable)
  4466. {
  4467. break;
  4468. }
  4469. //
  4470. // Optimize the common case instead of calling a subroutine.
  4471. //
  4472. if (1 == LocalTypeListLength)
  4473. {
  4474. //
  4475. // Clear the granted bits from the remaining.
  4476. //
  4477. LocalTypeList->Remaining &= ~((PKNOWN_ACE) Ace)->Mask;
  4478. }
  4479. else
  4480. {
  4481. //
  4482. // Propagate grant bits down the tree starting at the root.
  4483. //
  4484. AuthzpAddAccessTypeList(
  4485. LocalTypeList,
  4486. LocalTypeListLength,
  4487. 0,
  4488. ((PKNOWN_ACE) Ace)->Mask,
  4489. AuthzUpdateCurrentGranted
  4490. );
  4491. }
  4492. break;
  4493. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  4494. //
  4495. // If the ace sid is Principal Self, replace it with the caller
  4496. // supplied Principal sid.
  4497. //
  4498. if (!AUTHZ_IS_PRINCIPAL_SELF_SID(RtlObjectAceSid(Ace)))
  4499. {
  4500. pSid = RtlObjectAceSid(Ace);
  4501. }
  4502. else
  4503. {
  4504. pSid = pRequest->PrincipalSelfSid;
  4505. }
  4506. //
  4507. // Check if the effective ace sid is present in the client context
  4508. // and is enabled.
  4509. //
  4510. if (!AuthzpAllowOnlySidApplicable(
  4511. SidCount,
  4512. pSidAttr,
  4513. pSidHash,
  4514. pSid
  4515. ))
  4516. {
  4517. break;
  4518. }
  4519. bAceApplicable = FALSE;
  4520. //
  4521. // Make a call to the resource manager to get his opinion. His
  4522. // evaluation is returned in bAceApplicalble.
  4523. //
  4524. // Note: The return value of the callback is used to decide whether
  4525. // the API failed/succeeded. On a failure, we exit out of access
  4526. // check. On success, we check the boolean returned by
  4527. // bAceApplicable to decide whether to use the current ace.
  4528. //
  4529. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  4530. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  4531. Ace,
  4532. pRequest->OptionalArguments,
  4533. &bAceApplicable
  4534. )))
  4535. {
  4536. return FALSE;
  4537. }
  4538. if (!bAceApplicable)
  4539. {
  4540. break;
  4541. }
  4542. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  4543. //
  4544. // An object type ace with a NULL Object Type guid is the same as a
  4545. // normal ace.
  4546. //
  4547. if (!AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  4548. {
  4549. //
  4550. // Optimize the common case instead of calling a subroutine.
  4551. //
  4552. if (1 == LocalTypeListLength)
  4553. {
  4554. //
  4555. // Grant access bits that have not already been denied.
  4556. //
  4557. LocalTypeList->CurrentGranted |= (((PKNOWN_OBJECT_ACE) Ace)->Mask & ~LocalTypeList->CurrentDenied);
  4558. }
  4559. else
  4560. {
  4561. //
  4562. // Propagate grant bits down the tree starting at the root.
  4563. //
  4564. AuthzpAddAccessTypeList(
  4565. LocalTypeList,
  4566. LocalTypeListLength,
  4567. 0,
  4568. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  4569. AuthzUpdateCurrentGranted
  4570. );
  4571. }
  4572. }
  4573. //
  4574. // So, it is a true object type ace. Proceed only if we are doing
  4575. // access check on a object type list.
  4576. //
  4577. else if (ObjectTypeListPresent)
  4578. {
  4579. //
  4580. // Look for a matching object type guid that matches the one in
  4581. // the ace.
  4582. //
  4583. if (AuthzpObjectInTypeList(
  4584. ObjectTypeInAce,
  4585. LocalTypeList,
  4586. LocalTypeListLength,
  4587. &Index
  4588. )
  4589. )
  4590. {
  4591. //
  4592. // Propagate grant bits down the tree starting at the
  4593. // index at which the guids matched.
  4594. // In the case when this is the last of the siblings to be
  4595. // granted access, the parent also is granted access.
  4596. //
  4597. AuthzpAddAccessTypeList(
  4598. LocalTypeList,
  4599. LocalTypeListLength,
  4600. Index,
  4601. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  4602. AuthzUpdateCurrentGranted
  4603. );
  4604. }
  4605. }
  4606. break;
  4607. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  4608. case ACCESS_DENIED_ACE_TYPE:
  4609. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  4610. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  4611. ASSERT(FALSE);
  4612. break;
  4613. default:
  4614. break;
  4615. }
  4616. }
  4617. return TRUE;
  4618. }
  4619. BOOL
  4620. AuthzpObjectInTypeList (
  4621. IN GUID *ObjectType,
  4622. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  4623. IN DWORD ObjectTypeListLength,
  4624. OUT PDWORD ReturnedIndex
  4625. )
  4626. /*++
  4627. Routine description:
  4628. This routine searches an ObjectTypeList to determine if the specified object
  4629. type is in the list. It returns the index of the node if a match is found.
  4630. Arguments:
  4631. ObjectType - Object Type guid to search for.
  4632. ObjectTypeList - The object type list to search in.
  4633. ObjectTypeListLength - Number of elements in ObjectTypeList.
  4634. ReturnedIndex - Index to the element ObjectType was found in.
  4635. Return Value:
  4636. A value of TRUE is returned if the routine is successful. Otherwise,
  4637. a value of FALSE is returned. In the failure case, error value may be
  4638. retrieved using GetLastError().
  4639. --*/
  4640. {
  4641. DWORD Index = 0;
  4642. GUID * LocalObjectType = NULL;
  4643. for (Index = 0; Index < ObjectTypeListLength; Index++)
  4644. {
  4645. LocalObjectType = &ObjectTypeList[Index].ObjectType;
  4646. if (RtlpIsEqualGuid(ObjectType, LocalObjectType))
  4647. {
  4648. *ReturnedIndex = Index;
  4649. return TRUE;
  4650. }
  4651. }
  4652. return FALSE;
  4653. }
  4654. VOID
  4655. AuthzpUpdateParentTypeList(
  4656. IN OUT PIOBJECT_TYPE_LIST ObjectTypeList,
  4657. IN DWORD ObjectTypeListLength,
  4658. IN DWORD StartIndex
  4659. )
  4660. /*++
  4661. This routine updates the Access fields of the parent object of the specified
  4662. object.
  4663. The "remaining" field of a parent object is the logical OR of
  4664. the remaining field of all of its children.
  4665. The CurrentGranted field of the parent is the collection of bits
  4666. granted to every one of its children..
  4667. The CurrentDenied fields of the parent is the logical OR of
  4668. the bits denied to any of its children.
  4669. This routine takes an index to one of the children and updates the
  4670. remaining field of the parent (and grandparents recursively).
  4671. Arguments:
  4672. ObjectTypeList - The object type list to update.
  4673. ObjectTypeListLength - Number of elements in ObjectTypeList
  4674. StartIndex - Index to the "child" element whose parents are to be updated.
  4675. Return Value:
  4676. None.
  4677. --*/
  4678. {
  4679. DWORD Index = 0;
  4680. DWORD ParentIndex = 0;
  4681. DWORD Level = 0;
  4682. ACCESS_MASK NewRemaining = 0;
  4683. ACCESS_MASK NewCurrentDenied = 0;
  4684. ACCESS_MASK NewCurrentGranted = 0xFFFFFFFF;
  4685. //
  4686. // If the target node is at the root,
  4687. // we're all done.
  4688. //
  4689. if (-1 == ObjectTypeList[StartIndex].ParentIndex)
  4690. {
  4691. return;
  4692. }
  4693. //
  4694. // Get the index to the parent that needs updating and the level of
  4695. // the siblings.
  4696. //
  4697. ParentIndex = ObjectTypeList[StartIndex].ParentIndex;
  4698. Level = ObjectTypeList[StartIndex].Level;
  4699. //
  4700. // Loop through all the children.
  4701. //
  4702. for (Index = ParentIndex + 1; Index < ObjectTypeListLength; Index++)
  4703. {
  4704. //
  4705. // By definition, the children of an object are all those entries
  4706. // immediately following the target. The list of children (or
  4707. // grandchildren) stops as soon as we reach an entry the has the
  4708. // same level as the target (a sibling) or lower than the target
  4709. // (an uncle).
  4710. //
  4711. if (ObjectTypeList[Index].Level <= ObjectTypeList[ParentIndex].Level)
  4712. {
  4713. break;
  4714. }
  4715. //
  4716. // Only handle direct children of the parent.
  4717. //
  4718. if (ObjectTypeList[Index].Level != Level)
  4719. {
  4720. continue;
  4721. }
  4722. //
  4723. // Compute the new bits for the parent.
  4724. //
  4725. NewRemaining |= ObjectTypeList[Index].Remaining;
  4726. NewCurrentGranted &= ObjectTypeList[Index].CurrentGranted;
  4727. NewCurrentDenied |= ObjectTypeList[Index].CurrentDenied;
  4728. }
  4729. //
  4730. // If we've not changed the access to the parent,
  4731. // we're done.
  4732. //
  4733. if ((NewRemaining == ObjectTypeList[ParentIndex].Remaining) &&
  4734. (NewCurrentGranted == ObjectTypeList[ParentIndex].CurrentGranted) &&
  4735. (NewCurrentDenied == ObjectTypeList[ParentIndex].CurrentDenied))
  4736. {
  4737. return;
  4738. }
  4739. //
  4740. // Change the parent.
  4741. //
  4742. ObjectTypeList[ParentIndex].Remaining = NewRemaining;
  4743. ObjectTypeList[ParentIndex].CurrentGranted = NewCurrentGranted;
  4744. ObjectTypeList[ParentIndex].CurrentDenied = NewCurrentDenied;
  4745. //
  4746. // Go update the grand parents.
  4747. //
  4748. AuthzpUpdateParentTypeList(
  4749. ObjectTypeList,
  4750. ObjectTypeListLength,
  4751. ParentIndex
  4752. );
  4753. }
  4754. VOID
  4755. AuthzpAddAccessTypeList (
  4756. IN OUT PIOBJECT_TYPE_LIST ObjectTypeList,
  4757. IN DWORD ObjectTypeListLength,
  4758. IN DWORD StartIndex,
  4759. IN ACCESS_MASK AccessMask,
  4760. IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate
  4761. )
  4762. /*++
  4763. Routine Description:
  4764. This routine grants the specified AccessMask to all of the objects that
  4765. are descendents of the object specified by StartIndex.
  4766. The Access fields of the parent objects are also recomputed as needed.
  4767. For example, if an ACE granting access to a Property Set is found,
  4768. that access is granted to all the Properties in the Property Set.
  4769. Arguments:
  4770. ObjectTypeList - The object type list to update.
  4771. ObjectTypeListLength - Number of elements in ObjectTypeList
  4772. StartIndex - Index to the target element to update.
  4773. AccessMask - Mask of access to grant to the target element and
  4774. all of its decendents
  4775. FieldToUpdate - Indicate which fields to update in object type list
  4776. Updation cases:
  4777. A
  4778. / \
  4779. / \
  4780. B E
  4781. / \ / \
  4782. C D F G
  4783. Consider an object type list of length 7, with two property sets, each with
  4784. two properties. In array form this is represented as
  4785. {(A, 0), (B, 1), (C, 2), (D, 2), (E, 1), (F, 2), (G, 2)}
  4786. The following diagrams explain access granted/denied at each node.
  4787. Access may be granted because of one (or more) of the following reasons:
  4788. a = Access granted by an ace on the node
  4789. ca = Access granted by ORing of the children
  4790. pa = Access granted by an ancestor
  4791. Access may be denied because of one (or more) of the following reasons.
  4792. d = Access explicitly denied by an ace on the node
  4793. cd = Access explicitly denied by child, grandchild, etc
  4794. pd = Access explicitly denied by an ancestor
  4795. id = Access implicitly denied because no ace was applicable
  4796. case 1: case 2: case 3:
  4797. Deny D Deny B Grant B
  4798. Grant A Grant E Grant F
  4799. Grant D Grant G
  4800. cd cd ca
  4801. / \ / \ / \
  4802. / \ / \ / \
  4803. cd pa d a a ca
  4804. / \ / \ / \ / \ / \ / \
  4805. pa d pa pa pd pd pa pa pa pa a a
  4806. case 4: case 5: case 6:
  4807. Grant A Grant C Grant B
  4808. Deny B Grant D Grant F
  4809. Deny F Grant F
  4810. Grant G
  4811. Deny A
  4812. a ca id
  4813. / \ / \ / \
  4814. / \ / \ bf154a58 / \
  4815. pa pa ca ca a id
  4816. / \ / \ / \ / \ / \ / \
  4817. pa pa pa pa a a a a pa pa a id
  4818. Return Value:
  4819. None.
  4820. --*/
  4821. {
  4822. DWORD Index;
  4823. ACCESS_MASK OldRemaining;
  4824. ACCESS_MASK OldCurrentGranted;
  4825. ACCESS_MASK OldCurrentDenied;
  4826. BOOL AvoidParent = FALSE;
  4827. //
  4828. // Update the requested field.
  4829. //
  4830. // Always handle the target entry.
  4831. //
  4832. // If we've not actually changed the bits, early out.
  4833. //
  4834. switch (FieldToUpdate)
  4835. {
  4836. case AuthzUpdateRemaining:
  4837. OldRemaining = ObjectTypeList[StartIndex].Remaining;
  4838. ObjectTypeList[StartIndex].Remaining = OldRemaining & ~AccessMask;
  4839. if (OldRemaining == ObjectTypeList[StartIndex].Remaining)
  4840. {
  4841. return;
  4842. }
  4843. break;
  4844. case AuthzUpdateCurrentGranted:
  4845. OldCurrentGranted = ObjectTypeList[StartIndex].CurrentGranted;
  4846. ObjectTypeList[StartIndex].CurrentGranted |=
  4847. AccessMask & ~ObjectTypeList[StartIndex].CurrentDenied;
  4848. if (OldCurrentGranted == ObjectTypeList[StartIndex].CurrentGranted)
  4849. {
  4850. //
  4851. // We can't simply return here.
  4852. // We have to visit our children. Consider the case where there
  4853. // was a previous deny ACE on a child. That deny would have
  4854. // propagated up the tree to this entry. However, this allow ACE
  4855. // needs to be added all of the children that haven't been
  4856. // explictly denied.
  4857. //
  4858. AvoidParent = TRUE;
  4859. }
  4860. break;
  4861. case AuthzUpdateCurrentDenied:
  4862. OldCurrentDenied = ObjectTypeList[StartIndex].CurrentDenied;
  4863. ObjectTypeList[StartIndex].CurrentDenied |=
  4864. AccessMask & ~ObjectTypeList[StartIndex].CurrentGranted;
  4865. if (OldCurrentDenied == ObjectTypeList[StartIndex].CurrentDenied)
  4866. {
  4867. return;
  4868. }
  4869. break;
  4870. default:
  4871. return;
  4872. }
  4873. //
  4874. // Go update parent of the target.
  4875. //
  4876. if (!AvoidParent)
  4877. {
  4878. AuthzpUpdateParentTypeList(
  4879. ObjectTypeList,
  4880. ObjectTypeListLength,
  4881. StartIndex
  4882. );
  4883. }
  4884. //
  4885. // Loop handling all children of the target.
  4886. //
  4887. for (Index = StartIndex + 1; Index < ObjectTypeListLength; Index++)
  4888. {
  4889. //
  4890. // By definition, the children of an object are all those entries
  4891. // immediately following the target. The list of children (or
  4892. // grandchildren) stops as soon as we reach an entry the has the
  4893. // same level as the target (a sibling) or lower than the target
  4894. // (an uncle).
  4895. //
  4896. if (ObjectTypeList[Index].Level <= ObjectTypeList[StartIndex].Level)
  4897. {
  4898. break;
  4899. }
  4900. //
  4901. // Grant access to the children
  4902. //
  4903. switch (FieldToUpdate)
  4904. {
  4905. case AuthzUpdateRemaining:
  4906. ObjectTypeList[Index].Remaining &= ~AccessMask;
  4907. break;
  4908. case AuthzUpdateCurrentGranted:
  4909. ObjectTypeList[Index].CurrentGranted |=
  4910. AccessMask & ~ObjectTypeList[Index].CurrentDenied;
  4911. break;
  4912. case AuthzUpdateCurrentDenied:
  4913. ObjectTypeList[Index].CurrentDenied |=
  4914. AccessMask & ~ObjectTypeList[Index].CurrentGranted;
  4915. break;
  4916. default:
  4917. return;
  4918. }
  4919. }
  4920. }
  4921. BOOL
  4922. AuthzpCacheResults(
  4923. IN DWORD Flags,
  4924. IN PAUTHZI_CLIENT_CONTEXT pCC,
  4925. IN PIOBJECT_TYPE_LIST LocalCachingTypeList,
  4926. IN DWORD LocalTypeListLength,
  4927. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  4928. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  4929. IN DWORD OptionalSecurityDescriptorCount,
  4930. IN DWORD CachingFlags,
  4931. OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE phAccessCheckResults
  4932. )
  4933. /*++
  4934. Routine description:
  4935. This routine allocates a handle node, stores the results of static access
  4936. check in it and inserts it into the list of handles.
  4937. Arguments:
  4938. pCC - Pointer to the client context.
  4939. LocalCachingTypeList - Internal object type list structure used to hold
  4940. intermediate results for static granted bits.
  4941. LocalTypeListLength - Length of the array represnting the object.
  4942. pSecurityDescriptor - Primary security descriptor to be used for access
  4943. checks.
  4944. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  4945. of security descriptors. NULL ACLs in these security descriptors are
  4946. treated as EMPTY ACLS and the ACL for the entire object is the logical
  4947. concatenation of all the ACLs.
  4948. OptionalSecurityDescriptorCount - Number of optional security descriptors
  4949. This does not include the Primary security descriptor.
  4950. CachingFlags - Flags that will be stored in the caching handle.
  4951. phAccessCheckResults - To return the newly allocated handle.
  4952. Return Value:
  4953. A value of TRUE is returned if the routine is successful. Otherwise,
  4954. a value of FALSE is returned. In the failure case, error value may be
  4955. retrieved using GetLastError().
  4956. --*/
  4957. {
  4958. DWORD i = 0;
  4959. DWORD Size = 0;
  4960. DWORD SDSize = 0;
  4961. DWORD SDArraySize = 0;
  4962. ULONG LengthNeeded = 0;
  4963. PAUTHZI_HANDLE pHandle = NULL;
  4964. NTSTATUS Status = STATUS_SUCCESS;
  4965. PUCHAR pWrite = NULL;
  4966. BOOL b = TRUE;
  4967. Size = PtrAlignSize((LocalTypeListLength - 1) * sizeof(ACCESS_MASK) + sizeof(AUTHZI_HANDLE));
  4968. //
  4969. // If we are going to copy the SDs we will need some space for the pointers.
  4970. //
  4971. if (!FLAG_ON(Flags, AUTHZ_ACCESS_CHECK_NO_DEEP_COPY_SD))
  4972. {
  4973. SDSize = PtrAlignSize(RtlLengthSecurityDescriptor(pSecurityDescriptor));
  4974. SDArraySize = PtrAlignSize(sizeof(ULONG_PTR) * OptionalSecurityDescriptorCount);
  4975. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  4976. {
  4977. SDArraySize += PtrAlignSize(RtlLengthSecurityDescriptor(OptionalSecurityDescriptorArray[i]));
  4978. }
  4979. }
  4980. pHandle = (PAUTHZI_HANDLE) AuthzpAlloc(Size + SDSize + SDArraySize);
  4981. if (AUTHZ_ALLOCATION_FAILED(pHandle))
  4982. {
  4983. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  4984. return FALSE;
  4985. }
  4986. if (FLAG_ON(Flags, AUTHZ_ACCESS_CHECK_NO_DEEP_COPY_SD))
  4987. {
  4988. pHandle->pSecurityDescriptor = pSecurityDescriptor;
  4989. pHandle->OptionalSecurityDescriptorArray = OptionalSecurityDescriptorArray;
  4990. }
  4991. else
  4992. {
  4993. //
  4994. // Put the primary SD immediately after the pHandle
  4995. //
  4996. pWrite = ((PUCHAR)pHandle + Size);
  4997. pHandle->pSecurityDescriptor = (PSECURITY_DESCRIPTOR) pWrite;
  4998. LengthNeeded = SDSize;
  4999. Status = RtlMakeSelfRelativeSD(
  5000. pSecurityDescriptor,
  5001. pHandle->pSecurityDescriptor,
  5002. &LengthNeeded
  5003. );
  5004. ASSERT(NT_SUCCESS(Status));
  5005. if (!NT_SUCCESS(Status))
  5006. {
  5007. b = FALSE;
  5008. goto Cleanup;
  5009. }
  5010. pWrite += PtrAlignSize(LengthNeeded);
  5011. //
  5012. // After the primary SD we put the Optional SD array
  5013. //
  5014. if (OptionalSecurityDescriptorCount == 0)
  5015. {
  5016. pHandle->OptionalSecurityDescriptorArray = NULL;
  5017. }
  5018. else
  5019. {
  5020. pHandle->OptionalSecurityDescriptorArray = (PSECURITY_DESCRIPTOR *) pWrite;
  5021. pWrite += (sizeof(ULONG_PTR) * OptionalSecurityDescriptorCount);
  5022. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  5023. {
  5024. //
  5025. // After the array put in each optional SD, and point an array element at the SD
  5026. //
  5027. pHandle->OptionalSecurityDescriptorArray[i] = pWrite;
  5028. LengthNeeded = PtrAlignSize(RtlLengthSecurityDescriptor(OptionalSecurityDescriptorArray[i]));
  5029. Status = RtlMakeSelfRelativeSD(
  5030. OptionalSecurityDescriptorArray[i],
  5031. pHandle->OptionalSecurityDescriptorArray[i],
  5032. &LengthNeeded
  5033. );
  5034. ASSERT(NT_SUCCESS(Status));
  5035. if (!NT_SUCCESS(Status))
  5036. {
  5037. b = FALSE;
  5038. goto Cleanup;
  5039. }
  5040. pWrite += PtrAlignSize(LengthNeeded);
  5041. }
  5042. }
  5043. }
  5044. ASSERT(((PUCHAR)pHandle + Size + SDSize + SDArraySize) == pWrite);
  5045. pHandle->Flags = CachingFlags;
  5046. pHandle->pAuthzClientContext = pCC;
  5047. pHandle->ResultListLength = LocalTypeListLength;
  5048. pHandle->OptionalSecurityDescriptorCount = OptionalSecurityDescriptorCount;
  5049. //
  5050. // Store the static access check results in the handle.
  5051. //
  5052. for (i = 0; i < LocalTypeListLength; i++)
  5053. {
  5054. pHandle->GrantedAccessMask[i] = LocalCachingTypeList[i].CurrentGranted;
  5055. }
  5056. AuthzpAcquireClientCacheWriteLock(pCC);
  5057. pHandle->next = pCC->AuthzHandleHead;
  5058. pCC->AuthzHandleHead = pHandle;
  5059. AuthzpReleaseClientCacheLock(pCC);
  5060. *phAccessCheckResults = (AUTHZ_ACCESS_CHECK_RESULTS_HANDLE) pHandle;
  5061. Cleanup:
  5062. if (!b)
  5063. {
  5064. AuthzpFreeNonNull(pHandle);
  5065. SetLastError(RtlNtStatusToDosError(Status));
  5066. }
  5067. return b;
  5068. }
  5069. BOOL
  5070. AuthzpDefaultAccessCheck(
  5071. IN AUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext,
  5072. IN PACE_HEADER pAce,
  5073. IN PVOID pArgs OPTIONAL,
  5074. IN OUT PBOOL pbAceApplicable
  5075. )
  5076. /*++
  5077. Routine description:
  5078. This routine is the default function to be used for callback aces if none
  5079. has been specified by the resource manager.
  5080. Returns AceApplicable = TRUE for DENY aces.
  5081. FALSE for Grant and audit aces.
  5082. Arguments:
  5083. Ignores all arguments other than pAce->AceType.
  5084. Return Value:
  5085. A value of TRUE is returned if the routine is successful. Otherwise,
  5086. a value of FALSE is returned. In the failure case, error value may be
  5087. retrieved using GetLastError().
  5088. --*/
  5089. {
  5090. UNREFERENCED_PARAMETER(pArgs);
  5091. UNREFERENCED_PARAMETER(pAuthzClientContext);
  5092. switch (pAce->AceType)
  5093. {
  5094. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  5095. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  5096. case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
  5097. case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
  5098. *pbAceApplicable = FALSE;
  5099. break;
  5100. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  5101. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  5102. *pbAceApplicable = TRUE;
  5103. break;
  5104. default:
  5105. SetLastError(ERROR_INVALID_PARAMETER);
  5106. return FALSE;
  5107. }
  5108. return TRUE;
  5109. }
  5110. BOOL
  5111. AuthzpGenerateAudit(
  5112. IN PAUTHZI_CLIENT_CONTEXT pCC,
  5113. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5114. IN PAUTHZI_AUDIT_EVENT pAuditEvent,
  5115. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  5116. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  5117. IN DWORD OptionalSecurityDescriptorCount,
  5118. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  5119. IN OUT PIOBJECT_TYPE_LIST LocalTypeList
  5120. )
  5121. /*++
  5122. Routine description:
  5123. This routine decides whether an audit needs to be generated. It is called
  5124. at the end of the access check.
  5125. Arguments:
  5126. pCC - Pointer to the client context.
  5127. pRequest - Access request specifies the desired access mask, principal self
  5128. sid, the object type list strucutre (if any).
  5129. pAuditEvent - Audit info to be in case we decide to generate an audit.
  5130. pSecurityDescriptor - Primary security descriptor to be used for access
  5131. checks. The owner sid for the object is picked from this one. A NULL
  5132. DACL in this security descriptor represents a NULL DACL for the entire
  5133. object. A NULL SACL in this security descriptor is treated the same way
  5134. as an EMPTY SACL.
  5135. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  5136. of security descriptors. NULL ACLs in these security descriptors are
  5137. treated as EMPTY ACLS and the ACL for the entire object is the logical
  5138. concatenation of all the ACLs.
  5139. OptionalSecurityDescriptorCount - Number of optional security descriptors
  5140. This does not include the Primary security descriptor.
  5141. pReply - The reply structure holding the results of the access check.
  5142. LocalTypeList - Internal object type list structure used to hold
  5143. intermediate results.
  5144. LocalTypeListLength - Length of the array represnting the object.
  5145. Return Value:
  5146. A value of TRUE is returned if the routine is successful. Otherwise,
  5147. a value of FALSE is returned. In the failure case, error value may be
  5148. retrieved using GetLastError().
  5149. --*/
  5150. {
  5151. BOOL b = FALSE;
  5152. BOOL bGenerateAudit = FALSE;
  5153. BOOL bGenerateSuccessAudit = FALSE;
  5154. BOOL bGenerateFailureAudit = FALSE;
  5155. //
  5156. // if the caller is interested in the whole object
  5157. // generate a normal audit
  5158. // else
  5159. // generate an audit for the entire tree - DS style
  5160. //
  5161. if ((1 == pReply->ResultListLength) && (NULL == pRequest->ObjectTypeList))
  5162. {
  5163. b = AuthzpExamineSacl(
  5164. pCC,
  5165. pRequest,
  5166. pSecurityDescriptor,
  5167. OptionalSecurityDescriptorArray,
  5168. OptionalSecurityDescriptorCount,
  5169. pReply,
  5170. &bGenerateAudit
  5171. );
  5172. if (!b)
  5173. {
  5174. return FALSE;
  5175. }
  5176. if (bGenerateAudit)
  5177. {
  5178. if (ERROR_SUCCESS == pReply->Error[0])
  5179. {
  5180. LocalTypeList->Flags |= AUTHZ_OBJECT_SUCCESS_AUDIT;
  5181. b = AuthzpCreateAndLogAudit(
  5182. AUTHZ_OBJECT_SUCCESS_AUDIT,
  5183. pCC,
  5184. pAuditEvent,
  5185. (PAUTHZI_RESOURCE_MANAGER)pCC->pResourceManager,
  5186. LocalTypeList,
  5187. pRequest,
  5188. pReply
  5189. );
  5190. ASSERT(b && L"AuthzpCreateAndLogAudit did not succeed.");
  5191. }
  5192. else
  5193. {
  5194. LocalTypeList->Flags |= AUTHZ_OBJECT_FAILURE_AUDIT;
  5195. b = AuthzpCreateAndLogAudit(
  5196. AUTHZ_OBJECT_FAILURE_AUDIT,
  5197. pCC,
  5198. pAuditEvent,
  5199. (PAUTHZI_RESOURCE_MANAGER)pCC->pResourceManager,
  5200. LocalTypeList,
  5201. pRequest,
  5202. pReply
  5203. );
  5204. ASSERT(b && L"AuthzpCreateAndLogAudit did not succeed.");
  5205. }
  5206. }
  5207. }
  5208. else
  5209. {
  5210. b = AuthzpExamineSaclForObjectTypeList(
  5211. pCC,
  5212. pRequest,
  5213. pSecurityDescriptor,
  5214. OptionalSecurityDescriptorArray,
  5215. OptionalSecurityDescriptorCount,
  5216. pReply,
  5217. LocalTypeList,
  5218. &bGenerateSuccessAudit,
  5219. &bGenerateFailureAudit
  5220. );
  5221. if (!b)
  5222. {
  5223. return FALSE;
  5224. }
  5225. if (bGenerateSuccessAudit)
  5226. {
  5227. b = AuthzpCreateAndLogAudit(
  5228. AUTHZ_OBJECT_SUCCESS_AUDIT,
  5229. pCC,
  5230. pAuditEvent,
  5231. (PAUTHZI_RESOURCE_MANAGER)pCC->pResourceManager,
  5232. LocalTypeList,
  5233. pRequest,
  5234. pReply
  5235. );
  5236. ASSERT(b);
  5237. }
  5238. if (bGenerateFailureAudit)
  5239. {
  5240. b = AuthzpCreateAndLogAudit(
  5241. AUTHZ_OBJECT_FAILURE_AUDIT,
  5242. pCC,
  5243. pAuditEvent,
  5244. (PAUTHZI_RESOURCE_MANAGER)pCC->pResourceManager,
  5245. LocalTypeList,
  5246. pRequest,
  5247. pReply
  5248. );
  5249. ASSERT(b);
  5250. }
  5251. }
  5252. return b;
  5253. }
  5254. BOOL
  5255. AuthzpExamineSacl(
  5256. IN PAUTHZI_CLIENT_CONTEXT pCC,
  5257. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5258. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  5259. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  5260. IN DWORD OptionalSecurityDescriptorCount,
  5261. IN PAUTHZ_ACCESS_REPLY pReply,
  5262. OUT PBOOL pbGenerateAudit
  5263. )
  5264. /*++
  5265. Routine description:
  5266. This routine loops thru the entire list of security descriptors and call
  5267. AuthzpExamineSingleSacl for each security descriptor.
  5268. Called in one of the following cases:
  5269. - the caller has not passed in an object type list
  5270. - the caller has passed in an object type list and asked for access at
  5271. the root of the tree instead of the whole tree.
  5272. Arguments:
  5273. pCC - Pointer to the client context.
  5274. pRequest - Access request specifies the desired access mask, principal self
  5275. sid, the object type list strucutre (if any).
  5276. pSecurityDescriptor - Primary security descriptor to be used for access
  5277. checks. The owner sid for the object is picked from this one. A NULL
  5278. DACL in this security descriptor represents a NULL DACL for the entire
  5279. object. A NULL SACL in this security descriptor is treated the same way
  5280. as an EMPTY SACL.
  5281. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  5282. of security descriptors. NULL ACLs in these security descriptors are
  5283. treated as EMPTY ACLS and the ACL for the entire object is the logical
  5284. concatenation of all the ACLs.
  5285. OptionalSecurityDescriptorCount - Number of optional security descriptors
  5286. This does not include the Primary security descriptor.
  5287. pReply - The reply structure holding the results of the access check.
  5288. pbGenerateAudit - To return whether an audit needs to be generated.
  5289. Return Value:
  5290. A value of TRUE is returned if the routine is successful. Otherwise,
  5291. a value of FALSE is returned. In the failure case, error value may be
  5292. retrieved using GetLastError().
  5293. --*/
  5294. {
  5295. PACL pAcl = NULL;
  5296. PSID pOwnerSid = NULL;
  5297. BOOL b = FALSE;
  5298. BOOL bMaximumFailed = FALSE;
  5299. UCHAR AuditMaskType = SUCCESSFUL_ACCESS_ACE_FLAG;
  5300. ACCESS_MASK AccessMask = 0;
  5301. DWORD i = 0;
  5302. if (0 == pReply->GrantedAccessMask[0])
  5303. {
  5304. AuditMaskType = FAILED_ACCESS_ACE_FLAG;
  5305. if (FLAG_ON(pRequest->DesiredAccess, MAXIMUM_ALLOWED))
  5306. {
  5307. bMaximumFailed = TRUE;
  5308. }
  5309. AccessMask = pRequest->DesiredAccess;
  5310. }
  5311. else
  5312. {
  5313. AccessMask = pReply->GrantedAccessMask[0];
  5314. }
  5315. pAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  5316. pOwnerSid = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  5317. b = AuthzpExamineSingleSacl(
  5318. pCC,
  5319. pRequest,
  5320. AccessMask,
  5321. pAcl,
  5322. pOwnerSid,
  5323. AuditMaskType,
  5324. bMaximumFailed,
  5325. pReply,
  5326. pbGenerateAudit
  5327. );
  5328. if (!b)
  5329. {
  5330. return FALSE;
  5331. }
  5332. for (i = 0; (i < OptionalSecurityDescriptorCount) && (!*pbGenerateAudit); i++)
  5333. {
  5334. pAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  5335. b = AuthzpExamineSingleSacl(
  5336. pCC,
  5337. pRequest,
  5338. AccessMask,
  5339. pAcl,
  5340. pOwnerSid,
  5341. AuditMaskType,
  5342. bMaximumFailed,
  5343. pReply,
  5344. pbGenerateAudit
  5345. );
  5346. if (!b)
  5347. {
  5348. break;
  5349. }
  5350. }
  5351. return b;
  5352. }
  5353. BOOL
  5354. AuthzpExamineSingleSacl(
  5355. IN PAUTHZI_CLIENT_CONTEXT pCC,
  5356. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5357. IN ACCESS_MASK AccessMask,
  5358. IN PACL pAcl,
  5359. IN PSID pOwnerSid,
  5360. IN UCHAR AuditMaskType,
  5361. IN BOOL bMaximumFailed,
  5362. OUT PAUTHZ_ACCESS_REPLY pReply,
  5363. OUT PBOOL pbGenerateAudit
  5364. )
  5365. /*++
  5366. Routine description:
  5367. This routine walk the sacl till we hit an ace that is applicable for the
  5368. access check result.
  5369. Arguments:
  5370. pCC - Pointer to the client context.
  5371. pRequest - Access request specifies the desired access mask, principal self
  5372. sid, the object type list structure (if any).
  5373. AccessMask - Desired access mask in case of failure,
  5374. Granted access mask in case of success
  5375. pAcl - The sacl against which granted/desired access bits will be matched
  5376. pOwnerSid - Need for single instance work later on
  5377. pReply - Results of the access check.
  5378. AuditMaskType - SUCCESSFUL_ACCESS_ACE_FLAG if access check succeeded
  5379. FAILED_ACCESS_ACE_FLAG otherwise
  5380. bMaximumFailed - Whether the caller asked for MaximumAllowed and access
  5381. check failed
  5382. pbGenerateAudit - To return whether an audit should be generated
  5383. Return Value:
  5384. A value of TRUE is returned if the routine is successful. Otherwise,
  5385. a value of FALSE is returned. In the failure case, error value may be
  5386. retrieved using GetLastError().
  5387. --*/
  5388. {
  5389. DWORD AceCount = 0;
  5390. DWORD i = 0;
  5391. PVOID Ace = NULL;
  5392. BOOL bAceApplicable = FALSE;
  5393. DWORD Ignore = 0;
  5394. //
  5395. // Ignore NULL as well as Empty sacls.
  5396. //
  5397. if ((!ARGUMENT_PRESENT(pAcl)) || (0 == (AceCount = pAcl->AceCount)))
  5398. {
  5399. return TRUE;
  5400. }
  5401. for (i = 0, Ace = FirstAce(pAcl); i < AceCount; i++, Ace = NextAce(Ace))
  5402. {
  5403. //
  5404. // We are not interested in the ace if one of the following is true
  5405. // - inherit only ace
  5406. // - AuditMaskType does not match
  5407. // - AccessMask has no matching bits with the Mask in the acl and
  5408. // we are not looking for a MaximumAllowed failure audit
  5409. //
  5410. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE) ||
  5411. !FLAG_ON(((PACE_HEADER) Ace)->AceFlags, AuditMaskType) ||
  5412. (!FLAG_ON(((PKNOWN_ACE) Ace)->Mask, AccessMask) && !bMaximumFailed))
  5413. {
  5414. continue;
  5415. }
  5416. switch(((PACE_HEADER) Ace)->AceType)
  5417. {
  5418. case SYSTEM_AUDIT_ACE_TYPE:
  5419. //
  5420. // Check if the effective ace sid is present in the client context
  5421. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5422. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5423. // caller. In future, Creator Owner will be replaced by the owner
  5424. // sid in the primary security descriptor.
  5425. //
  5426. bAceApplicable = AuthzpSidApplicable(
  5427. pCC->SidCount,
  5428. pCC->Sids,
  5429. pCC->SidHash,
  5430. AuthzAceSid(Ace),
  5431. pRequest->PrincipalSelfSid,
  5432. pOwnerSid,
  5433. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5434. &Ignore
  5435. );
  5436. if (!bAceApplicable)
  5437. {
  5438. break;
  5439. }
  5440. *pbGenerateAudit = TRUE;
  5441. if (NULL != pReply->SaclEvaluationResults)
  5442. {
  5443. pReply->SaclEvaluationResults[0] |=
  5444. (pReply->Error[0] == ERROR_SUCCESS ? AUTHZ_GENERATE_SUCCESS_AUDIT : AUTHZ_GENERATE_FAILURE_AUDIT);
  5445. }
  5446. return TRUE;
  5447. case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
  5448. //
  5449. // Check if the effective ace sid is present in the client context
  5450. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5451. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5452. // caller. In future, Creator Owner will be replaced by the owner
  5453. // sid in the primary security descriptor.
  5454. //
  5455. bAceApplicable = AuthzpSidApplicable(
  5456. pCC->SidCount,
  5457. pCC->Sids,
  5458. pCC->SidHash,
  5459. AuthzCallbackAceSid(Ace),
  5460. pRequest->PrincipalSelfSid,
  5461. pOwnerSid,
  5462. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5463. &Ignore
  5464. );
  5465. if (!bAceApplicable)
  5466. {
  5467. break;
  5468. }
  5469. bAceApplicable = FALSE;
  5470. //
  5471. // Make a call to the resource manager to get his opinion. His
  5472. // evaluation is returned in bAceApplicalble.
  5473. //
  5474. // Note: The return value of the callback is used to decide whether
  5475. // the API failed/succeeded. On a failure, we exit out of access
  5476. // check. On success, we check the boolean returned by
  5477. // bAceApplicable to decide whether to use the current ace.
  5478. //
  5479. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  5480. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  5481. Ace,
  5482. pRequest->OptionalArguments,
  5483. &bAceApplicable
  5484. )))
  5485. {
  5486. return FALSE;
  5487. }
  5488. if (!bAceApplicable)
  5489. {
  5490. break;
  5491. }
  5492. *pbGenerateAudit = TRUE;
  5493. if (NULL != pReply->SaclEvaluationResults)
  5494. {
  5495. pReply->SaclEvaluationResults[0] |=
  5496. (pReply->Error[0] == ERROR_SUCCESS ? AUTHZ_GENERATE_SUCCESS_AUDIT : AUTHZ_GENERATE_FAILURE_AUDIT);
  5497. }
  5498. return TRUE;
  5499. default:
  5500. break;
  5501. }
  5502. }
  5503. return TRUE;
  5504. }
  5505. BOOL
  5506. AuthzpExamineSaclForObjectTypeList(
  5507. IN PAUTHZI_CLIENT_CONTEXT pCC,
  5508. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5509. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  5510. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  5511. IN DWORD OptionalSecurityDescriptorCount,
  5512. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  5513. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  5514. OUT PBOOL pbGenerateSuccessAudit,
  5515. OUT PBOOL pbGenerateFailureAudit
  5516. )
  5517. /*++
  5518. Routine description:
  5519. This routine walks thru the entire list of security descriptors and calls
  5520. AuthzpExamineSingleSaclForObjectTypeList for each security descriptor.
  5521. Called when an object type list is passed and the caller has asked for
  5522. the results at each node.
  5523. Arguments:
  5524. pCC - Pointer to the client context.
  5525. pRequest - Access request specifies the desired access mask, principal self
  5526. sid, the object type list strucutre (if any).
  5527. pSecurityDescriptor - Primary security descriptor to be used for access
  5528. checks. The owner sid for the object is picked from this one. A NULL
  5529. DACL in this security descriptor represents a NULL DACL for the entire
  5530. object. A NULL SACL in this security descriptor is treated the same way
  5531. as an EMPTY SACL.
  5532. OptionalSecurityDescriptorArray - The caller may optionally specify a list
  5533. of security descriptors. NULL ACLs in these security descriptors are
  5534. treated as EMPTY ACLS and the ACL for the entire object is the logical
  5535. concatenation of all the ACLs.
  5536. OptionalSecurityDescriptorCount - Number of optional security descriptors
  5537. This does not include the Primary security descriptor.
  5538. pReply - The reply structure to return the results.
  5539. LocalTypeList - Internal object type list structure used to hold
  5540. intermediate results.
  5541. LocalTypeListLength - Length of the array represnting the object.
  5542. pbGenerateSuccessAudit - Returns whether a success audit should be
  5543. generated.
  5544. pbGenerateFailureAudit - Returns whether a failure audit should be
  5545. generated.
  5546. Return Value:
  5547. A value of TRUE is returned if the routine is successful. Otherwise,
  5548. a value of FALSE is returned. In the failure case, error value may be
  5549. retrieved using GetLastError().
  5550. --*/
  5551. {
  5552. PACL pAcl = NULL;
  5553. PSID pOwnerSid = NULL;
  5554. BOOL b = FALSE;
  5555. DWORD i = 0;
  5556. pAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  5557. pOwnerSid = RtlpOwnerAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) pSecurityDescriptor);
  5558. b = AuthzpExamineSingleSaclForObjectTypeList(
  5559. pCC,
  5560. pRequest,
  5561. pAcl,
  5562. pOwnerSid,
  5563. pReply,
  5564. LocalTypeList,
  5565. pbGenerateSuccessAudit,
  5566. pbGenerateFailureAudit
  5567. );
  5568. if (!b)
  5569. {
  5570. return FALSE;
  5571. }
  5572. for (i = 0; i < OptionalSecurityDescriptorCount; i++)
  5573. {
  5574. pAcl = RtlpSaclAddrSecurityDescriptor((PISECURITY_DESCRIPTOR) OptionalSecurityDescriptorArray[i]);
  5575. b = AuthzpExamineSingleSaclForObjectTypeList(
  5576. pCC,
  5577. pRequest,
  5578. pAcl,
  5579. pOwnerSid,
  5580. pReply,
  5581. LocalTypeList,
  5582. pbGenerateSuccessAudit,
  5583. pbGenerateFailureAudit
  5584. );
  5585. if (!b)
  5586. {
  5587. break;
  5588. }
  5589. }
  5590. return b;
  5591. }
  5592. BOOL
  5593. AuthzpExamineSingleSaclForObjectTypeList(
  5594. IN PAUTHZI_CLIENT_CONTEXT pCC,
  5595. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5596. IN PACL pAcl,
  5597. IN PSID pOwnerSid,
  5598. IN PAUTHZ_ACCESS_REPLY pReply,
  5599. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  5600. OUT PBOOL pbGenerateSuccessAudit,
  5601. OUT PBOOL pbGenerateFailureAudit
  5602. )
  5603. /*++
  5604. Routine description:
  5605. This routine walk thru the entire sacl and mark those nodes in the tree that
  5606. need be dumped to the audit log. It colors the whole subtree including the
  5607. node at which the ace is applicable. A normal ace is applicable at the root
  5608. of the tree.
  5609. Arguments:
  5610. pCC - Pointer to the client context to be audited.
  5611. pRequest - Access request specifies the desired access mask, principal self
  5612. sid, the object type list strucutre (if any).
  5613. pAcl - Sacl to be used to make the decision about audit generation.
  5614. pOwnerSid - The owner sid in the primary security descriptor. This will be
  5615. needed after we implement single instancing.
  5616. pReply - Supplies a pointer to a reply structure used to return the results.
  5617. LocalTypeList - Internal object type list structure used to hold
  5618. intermediate results.
  5619. pbGenerateSuccessAudit - Returns whether a success audit should be
  5620. generated.
  5621. pbGenerateFailureAudit - Returns whether a failure audit should be
  5622. generated.
  5623. Return Value:
  5624. A value of TRUE is returned if the routine is successful. Otherwise,
  5625. a value of FALSE is returned. In the failure case, error value may be
  5626. retrieved using GetLastError().
  5627. --*/
  5628. {
  5629. DWORD AceCount = 0;
  5630. DWORD i = 0;
  5631. DWORD Ignore = 0;
  5632. DWORD Index = 0;
  5633. PVOID Ace = NULL;
  5634. GUID * ObjectTypeInAce = NULL;
  5635. BOOL bAceApplicable = FALSE;
  5636. //
  5637. // Ignore NULL as well as Empty sacls.
  5638. //
  5639. if ((!ARGUMENT_PRESENT(pAcl)) || (0 == (AceCount = pAcl->AceCount)))
  5640. {
  5641. return TRUE;
  5642. }
  5643. for (i = 0, Ace = FirstAce(pAcl); i < AceCount; i++, Ace = NextAce(Ace))
  5644. {
  5645. //
  5646. // Skip INHERIT_ONLY aces.
  5647. //
  5648. if (FLAG_ON(((PACE_HEADER) Ace)->AceFlags, INHERIT_ONLY_ACE))
  5649. {
  5650. continue;
  5651. }
  5652. switch(((PACE_HEADER) Ace)->AceType)
  5653. {
  5654. case SYSTEM_AUDIT_ACE_TYPE:
  5655. //
  5656. // Check if the effective ace sid is present in the client context
  5657. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5658. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5659. // caller. In future, Creator Owner will be replaced by the owner
  5660. // sid in the primary security descriptor.
  5661. //
  5662. bAceApplicable = AuthzpSidApplicable(
  5663. pCC->SidCount,
  5664. pCC->Sids,
  5665. pCC->SidHash,
  5666. AuthzAceSid(Ace),
  5667. pRequest->PrincipalSelfSid,
  5668. pOwnerSid,
  5669. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5670. &Ignore
  5671. );
  5672. if (!bAceApplicable)
  5673. {
  5674. break;
  5675. }
  5676. //
  5677. // We have found an ace that is applicable. Walk the tree to decide
  5678. // if an audit should be generated. Also, mark the nodes that need
  5679. // be dumped to the audit log.
  5680. //
  5681. AuthzpSetAuditInfoForObjectType(
  5682. pReply,
  5683. LocalTypeList,
  5684. 0,
  5685. ((PKNOWN_ACE) Ace)->Mask,
  5686. pRequest->DesiredAccess,
  5687. ((PACE_HEADER) Ace)->AceFlags,
  5688. pbGenerateSuccessAudit,
  5689. pbGenerateFailureAudit
  5690. );
  5691. break;
  5692. case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
  5693. //
  5694. // Check if the effective ace sid is present in the client context
  5695. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5696. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5697. // caller. In future, Creator Owner will be replaced by the owner
  5698. // sid in the primary security descriptor.
  5699. //
  5700. bAceApplicable = AuthzpSidApplicable(
  5701. pCC->SidCount,
  5702. pCC->Sids,
  5703. pCC->SidHash,
  5704. AuthzAceSid(Ace),
  5705. pRequest->PrincipalSelfSid,
  5706. pOwnerSid,
  5707. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5708. &Ignore
  5709. );
  5710. if (!bAceApplicable)
  5711. {
  5712. break;
  5713. }
  5714. bAceApplicable = FALSE;
  5715. //
  5716. // Make a call to the resource manager to get his opinion. His
  5717. // evaluation is returned in bAceApplicalble.
  5718. //
  5719. // Note: The return value of the callback is used to decide whether
  5720. // the API failed/succeeded. On a failure, we exit out of access
  5721. // check. On success, we check the boolean returned by
  5722. // bAceApplicable to decide whether to use the current ace.
  5723. //
  5724. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  5725. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  5726. Ace,
  5727. pRequest->OptionalArguments,
  5728. &bAceApplicable
  5729. )))
  5730. {
  5731. return FALSE;
  5732. }
  5733. if (!bAceApplicable)
  5734. {
  5735. break;
  5736. }
  5737. //
  5738. // We have found an ace that is applicable. Walk the tree to decide
  5739. // if an audit should be generated. Also, mark the nodes that need
  5740. // be dumped to the audit log.
  5741. //
  5742. AuthzpSetAuditInfoForObjectType(
  5743. pReply,
  5744. LocalTypeList,
  5745. 0,
  5746. ((PKNOWN_ACE) Ace)->Mask,
  5747. pRequest->DesiredAccess,
  5748. ((PACE_HEADER) Ace)->AceFlags,
  5749. pbGenerateSuccessAudit,
  5750. pbGenerateFailureAudit
  5751. );
  5752. break;
  5753. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  5754. //
  5755. // Check if the effective ace sid is present in the client context
  5756. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5757. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5758. // caller. In future, Creator Owner will be replaced by the owner
  5759. // sid in the primary security descriptor.
  5760. //
  5761. bAceApplicable = AuthzpSidApplicable(
  5762. pCC->SidCount,
  5763. pCC->Sids,
  5764. pCC->SidHash,
  5765. RtlObjectAceSid(Ace),
  5766. pRequest->PrincipalSelfSid,
  5767. pOwnerSid,
  5768. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5769. &Ignore
  5770. );
  5771. if (!bAceApplicable)
  5772. {
  5773. break;
  5774. }
  5775. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  5776. Index = 0;
  5777. if (AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  5778. {
  5779. //
  5780. // Look for a matching object type guid that matches the one in
  5781. // the ace.
  5782. //
  5783. if (!AuthzpObjectInTypeList(
  5784. ObjectTypeInAce,
  5785. LocalTypeList,
  5786. pReply->ResultListLength,
  5787. &Index
  5788. ))
  5789. {
  5790. break;
  5791. }
  5792. }
  5793. //
  5794. // We have found an ace that is applicable. Walk the tree to decide
  5795. // if an audit should be generated. Also, mark the nodes that need
  5796. // be dumped to the audit log.
  5797. //
  5798. AuthzpSetAuditInfoForObjectType(
  5799. pReply,
  5800. LocalTypeList,
  5801. Index,
  5802. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  5803. pRequest->DesiredAccess,
  5804. ((PACE_HEADER) Ace)->AceFlags,
  5805. pbGenerateSuccessAudit,
  5806. pbGenerateFailureAudit
  5807. );
  5808. break;
  5809. case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
  5810. //
  5811. // Check if the effective ace sid is present in the client context
  5812. // and is enabled or enabled for deny only if FAILED_ACCESS_ACE_FLAG
  5813. // is on. S-1-5-A is replaced by the principal sid supplied by the
  5814. // caller. In future, Creator Owner will be replaced by the owner
  5815. // sid in the primary security descriptor.
  5816. //
  5817. bAceApplicable = AuthzpSidApplicable(
  5818. pCC->SidCount,
  5819. pCC->Sids,
  5820. pCC->SidHash,
  5821. AuthzObjectAceSid(Ace),
  5822. pRequest->PrincipalSelfSid,
  5823. pOwnerSid,
  5824. FLAG_ON(((PACE_HEADER) Ace)->AceFlags, FAILED_ACCESS_ACE_FLAG),
  5825. &Ignore
  5826. );
  5827. if (!bAceApplicable)
  5828. {
  5829. break;
  5830. }
  5831. bAceApplicable = FALSE;
  5832. //
  5833. // Make a call to the resource manager to get his opinion. His
  5834. // evaluation is returned in bAceApplicalble.
  5835. //
  5836. // Note: The return value of the callback is used to decide whether
  5837. // the API failed/succeeded. On a failure, we exit out of access
  5838. // check. On success, we check the boolean returned by
  5839. // bAceApplicable to decide whether to use the current ace.
  5840. //
  5841. if (!((*(pCC->pResourceManager->pfnDynamicAccessCheck)) (
  5842. (AUTHZ_CLIENT_CONTEXT_HANDLE) pCC,
  5843. Ace,
  5844. pRequest->OptionalArguments,
  5845. &bAceApplicable
  5846. )))
  5847. {
  5848. return FALSE;
  5849. }
  5850. if (!bAceApplicable)
  5851. {
  5852. break;
  5853. }
  5854. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  5855. Index = 0;
  5856. if (AUTHZ_NON_NULL_PTR(ObjectTypeInAce))
  5857. {
  5858. //
  5859. // Look for a matching object type guid that matches the one in
  5860. // the ace.
  5861. //
  5862. if (!AuthzpObjectInTypeList(
  5863. ObjectTypeInAce,
  5864. LocalTypeList,
  5865. pReply->ResultListLength,
  5866. &Index
  5867. ))
  5868. {
  5869. break;
  5870. }
  5871. }
  5872. //
  5873. // We have found an ace that is applicable. Walk the tree to decide
  5874. // if an audit should be generated. Also, mark the nodes that need
  5875. // be dumped to the audit log.
  5876. //
  5877. AuthzpSetAuditInfoForObjectType(
  5878. pReply,
  5879. LocalTypeList,
  5880. Index,
  5881. ((PKNOWN_OBJECT_ACE) Ace)->Mask,
  5882. pRequest->DesiredAccess,
  5883. ((PACE_HEADER) Ace)->AceFlags,
  5884. pbGenerateSuccessAudit,
  5885. pbGenerateFailureAudit
  5886. );
  5887. break;
  5888. default:
  5889. break;
  5890. }
  5891. }
  5892. return TRUE;
  5893. }
  5894. VOID
  5895. AuthzpSetAuditInfoForObjectType(
  5896. IN PAUTHZ_ACCESS_REPLY pReply,
  5897. IN OUT PIOBJECT_TYPE_LIST LocalTypeList,
  5898. IN DWORD StartIndex,
  5899. IN ACCESS_MASK AceAccessMask,
  5900. IN ACCESS_MASK DesiredAccessMask,
  5901. IN UCHAR AceFlags,
  5902. OUT PBOOL pbGenerateSuccessAudit,
  5903. OUT PBOOL pbGenerateFailureAudit
  5904. )
  5905. /*++
  5906. Routine description:
  5907. This routine propagate the audit decision down the subtree starting at
  5908. StartIndex.
  5909. Arguments:
  5910. pReply - This has been filled by access check at this point. We just read
  5911. the values to make audit decision.
  5912. LocalTypeList - Decision to audit a node is stored into Flags corresponding
  5913. member of this array.
  5914. StartIndex - The index in the array at which the coloring should start.
  5915. AceAccessMask - Access mask in the audit ace.
  5916. DesiredAccessMask - Desired access mask in the access request.
  5917. AceFlags - AceFlags member of the ace header. We are interested in the
  5918. audit flags.
  5919. pbGenerateSuccessAudit - Returns whether a success audit should be
  5920. generated.
  5921. pbGenerateFailureAudit - Returns whether a failure audit should be
  5922. generated.
  5923. Return Value:
  5924. None
  5925. --*/
  5926. {
  5927. DWORD i = StartIndex;
  5928. do
  5929. {
  5930. //
  5931. // Store the decision to audit in the local type list if there is a
  5932. // match of access bits.
  5933. //
  5934. if (ERROR_SUCCESS == pReply->Error[i])
  5935. {
  5936. if (FLAG_ON(AceFlags, SUCCESSFUL_ACCESS_ACE_FLAG) &&
  5937. FLAG_ON(pReply->GrantedAccessMask[i], AceAccessMask))
  5938. {
  5939. *pbGenerateSuccessAudit = TRUE;
  5940. LocalTypeList[i].Flags |= AUTHZ_OBJECT_SUCCESS_AUDIT;
  5941. if (NULL != pReply->SaclEvaluationResults)
  5942. {
  5943. pReply->SaclEvaluationResults[i] |= AUTHZ_GENERATE_SUCCESS_AUDIT;
  5944. }
  5945. }
  5946. }
  5947. else
  5948. {
  5949. //
  5950. // Failure audit is generated even if the bits do not match if the
  5951. // caller asked for MAXIMUM_ALLOWED.
  5952. //
  5953. if (FLAG_ON(AceFlags, FAILED_ACCESS_ACE_FLAG) &&
  5954. FLAG_ON(DesiredAccessMask, (AceAccessMask | MAXIMUM_ALLOWED)))
  5955. {
  5956. *pbGenerateFailureAudit = TRUE;
  5957. LocalTypeList[i].Flags |= AUTHZ_OBJECT_FAILURE_AUDIT;
  5958. if (NULL != pReply->SaclEvaluationResults)
  5959. {
  5960. pReply->SaclEvaluationResults[i] |= AUTHZ_GENERATE_FAILURE_AUDIT;
  5961. }
  5962. }
  5963. }
  5964. i++;
  5965. //
  5966. // Stop the traversal when the list is exhausted or when we have hit a
  5967. // sibling of the starting node.
  5968. //
  5969. } while ((i < pReply->ResultListLength) &&
  5970. (LocalTypeList[i].Level > LocalTypeList[StartIndex].Level));
  5971. }
  5972. BOOL
  5973. AuthzpVerifyCachedAccessCheckArguments(
  5974. IN PAUTHZI_HANDLE pAH,
  5975. IN PAUTHZ_ACCESS_REQUEST pRequest,
  5976. IN OUT PAUTHZ_ACCESS_REPLY pReply
  5977. )
  5978. /*++
  5979. Routine description:
  5980. This routine verifies arguments for the cached access check call.
  5981. Arguments:
  5982. pAH - Pointer to the authz handle structure.
  5983. pRequest - Access request specifies the desired access mask, principal self
  5984. sid, the object type list strucutre (if any).
  5985. pReply - Supplies a pointer to a reply structure used to return the results
  5986. Return Value:
  5987. A value of TRUE is returned if the routine is successful. Otherwise,
  5988. a value of FALSE is returned. In the failure case, error value may be
  5989. retrieved using GetLastError().
  5990. --*/
  5991. {
  5992. if (!ARGUMENT_PRESENT(pAH))
  5993. {
  5994. SetLastError(ERROR_INVALID_PARAMETER);
  5995. return FALSE;
  5996. }
  5997. if (!ARGUMENT_PRESENT(pRequest))
  5998. {
  5999. SetLastError(ERROR_INVALID_PARAMETER);
  6000. return FALSE;
  6001. }
  6002. if (!ARGUMENT_PRESENT(pReply))
  6003. {
  6004. SetLastError(ERROR_INVALID_PARAMETER);
  6005. return FALSE;
  6006. }
  6007. //
  6008. // The caller can specify one of the two values for Reply->ResultListLength
  6009. // a. 1 - representing the whole object.
  6010. // b. pRequest->ObjectTypeListLength - for every node in the type list.
  6011. //
  6012. if ((1 != pReply->ResultListLength) &&
  6013. (pReply->ResultListLength != pRequest->ObjectTypeListLength))
  6014. {
  6015. SetLastError(ERROR_INVALID_PARAMETER);
  6016. return FALSE;
  6017. }
  6018. return TRUE;
  6019. }
  6020. VOID
  6021. AuthzpFillReplyStructureFromCachedGrantedAccessMask(
  6022. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  6023. IN ACCESS_MASK DesiredAccess,
  6024. IN PACCESS_MASK GrantedAccessMask
  6025. )
  6026. /*++
  6027. Routine description:
  6028. This routine fills the reply structure from the granted access mask array
  6029. in the cache.
  6030. Arguments:
  6031. pReply - The reply structure to fill.
  6032. DesiredAccess - Access mask desired.
  6033. GrantedAccessMask - Array of granted masks from the cache.
  6034. Return Value:
  6035. None.
  6036. --*/
  6037. {
  6038. DWORD i = 0;
  6039. for (i = 0; i < pReply->ResultListLength; i++)
  6040. {
  6041. if (FLAG_ON(DesiredAccess, ~(GrantedAccessMask[i])))
  6042. {
  6043. pReply->GrantedAccessMask[i] = 0;
  6044. pReply->Error[i] = ERROR_ACCESS_DENIED;
  6045. }
  6046. else
  6047. {
  6048. pReply->GrantedAccessMask[i] = DesiredAccess;
  6049. pReply->Error[i] = ERROR_SUCCESS;
  6050. }
  6051. }
  6052. }
  6053. VOID
  6054. AuthzpReferenceAuditEventType(
  6055. IN AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAET
  6056. )
  6057. /*++
  6058. Routine Description
  6059. This references an AUTHZ_AUDIT_EVENT_TYPE_HANDLE. The handle is referenced whenever
  6060. it is used in a situation where it will be 'unused.' For instance, when an audit is placed
  6061. on the audit queue, we reference hAET. When we take that audit off of the queue, we deref
  6062. hAET. This allows the user to not have to concern himself with sync issues revolving around
  6063. the implementation of the hAET.
  6064. Arguments
  6065. hAET - the AUTHZ_AUDIT_EVENT_TYPE_HANDLE to reference.
  6066. Return Value
  6067. Boolean: TRUE on success, FALSE on fail. Extended information is available with GetLastError().
  6068. --*/
  6069. {
  6070. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD)hAET;
  6071. InterlockedIncrement(&pAAETO->RefCount);
  6072. }
  6073. BOOL
  6074. AuthzpDereferenceAuditEventType(
  6075. IN OUT AUTHZ_AUDIT_EVENT_TYPE_HANDLE hAET
  6076. )
  6077. /*++
  6078. Routine Description
  6079. Dereferences and AUTHZ_AUDIT_EVENT_TYPE_HANDLE.
  6080. Arguments
  6081. hAET - handle to dereference.
  6082. Return Value
  6083. Boolean: TRUE on success, FALSE on fail. Extended information is available with GetLastError().
  6084. --*/
  6085. {
  6086. PAUTHZ_AUDIT_EVENT_TYPE_OLD pAAETO = (PAUTHZ_AUDIT_EVENT_TYPE_OLD)hAET;
  6087. LONG Refs = 0;
  6088. BOOL b = TRUE;
  6089. Refs = InterlockedDecrement(&pAAETO->RefCount);
  6090. ASSERT(Refs >= 0);
  6091. if (Refs == 0)
  6092. {
  6093. b = AuthzpUnregisterAuditEvent((PAUDIT_HANDLE)&(pAAETO->hAudit));
  6094. ASSERT(pAAETO->hAudit == (ULONG_PTR)0 && b);
  6095. AuthzpFree(hAET);
  6096. }
  6097. return b;
  6098. }
  6099. BOOL
  6100. AuthzpEveryoneIncludesAnonymous(
  6101. OUT PBOOL pbInclude
  6102. )
  6103. /*++
  6104. Routine Description:
  6105. This routine checks to see if we should include Everyone Sid in Anonymous
  6106. contexts.
  6107. The reg key under system\currentcontrolset\Control\Lsa\
  6108. AnonymousIncludesEveryone indicates whether or not to include the group.
  6109. If the value is zero (or doesn't exist), we restrict Anonymous context by
  6110. not giving it the Everyone Sid.
  6111. Arguments:
  6112. bInclude - TRUE if Everyone Sid should be in the context, false otherwise.
  6113. Return Value:
  6114. Boolean: TRUE on success, FALSE on fail. Extended information is available with GetLastError().
  6115. --*/
  6116. {
  6117. NTSTATUS NtStatus = STATUS_SUCCESS;
  6118. UNICODE_STRING KeyName = {0};
  6119. OBJECT_ATTRIBUTES ObjectAttributes = {0};
  6120. HANDLE KeyHandle = NULL;
  6121. UCHAR Buffer[100];
  6122. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION) Buffer;
  6123. ULONG KeyValueLength = 100;
  6124. ULONG ResultLength = 0;
  6125. PULONG Flag = NULL;
  6126. BOOL b = TRUE;
  6127. *pbInclude = FALSE;
  6128. //
  6129. // Open the Lsa key in the registry
  6130. //
  6131. RtlInitUnicodeString(
  6132. &KeyName,
  6133. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa"
  6134. );
  6135. InitializeObjectAttributes(
  6136. &ObjectAttributes,
  6137. &KeyName,
  6138. OBJ_CASE_INSENSITIVE,
  6139. 0,
  6140. NULL
  6141. );
  6142. NtStatus = NtOpenKey(
  6143. &KeyHandle,
  6144. KEY_READ,
  6145. &ObjectAttributes
  6146. );
  6147. if (!NT_SUCCESS(NtStatus)) {
  6148. b = FALSE;
  6149. goto Cleanup;
  6150. }
  6151. RtlInitUnicodeString(
  6152. &KeyName,
  6153. L"EveryoneIncludesAnonymous"
  6154. );
  6155. NtStatus = NtQueryValueKey(
  6156. KeyHandle,
  6157. &KeyName,
  6158. KeyValuePartialInformation,
  6159. KeyValueInformation,
  6160. KeyValueLength,
  6161. &ResultLength
  6162. );
  6163. if (NT_SUCCESS(NtStatus)) {
  6164. //
  6165. // Check that the data is the correct size and type - a ULONG.
  6166. //
  6167. if ((KeyValueInformation->DataLength >= sizeof(ULONG)) &&
  6168. (KeyValueInformation->Type == REG_DWORD)) {
  6169. Flag = (PULONG) KeyValueInformation->Data;
  6170. if (*Flag != 0 ) {
  6171. *pbInclude = TRUE;
  6172. }
  6173. }
  6174. }
  6175. NtClose(KeyHandle);
  6176. Cleanup:
  6177. return b;
  6178. }