Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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