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

4212 lines
118 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Accessck.c
  5. Abstract:
  6. This Module implements the access check procedures. Both NtAccessCheck
  7. and SeAccessCheck check to is if a user (denoted by an input token) can
  8. be granted the desired access rights to object protected by a security
  9. descriptor and an optional object owner. Both procedures use a common
  10. local procedure to do the test.
  11. Author:
  12. Robert Reichel (RobertRe) 11-30-90
  13. Environment:
  14. Kernel Mode
  15. Revision History:
  16. Richard Ward (RichardW) 14-Apr-92 Changed ACE_HEADER
  17. --*/
  18. #include "pch.h"
  19. #pragma hdrstop
  20. #include <sertlp.h>
  21. //
  22. // Define the local macros and procedure for this module
  23. //
  24. #if DBG
  25. extern BOOLEAN SepDumpSD;
  26. extern BOOLEAN SepDumpToken;
  27. BOOLEAN SepShowAccessFail;
  28. #endif // DBG
  29. VOID
  30. SepUpdateParentTypeList (
  31. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  32. IN ULONG ObjectTypeListLength,
  33. IN ULONG StartIndex
  34. );
  35. typedef enum {
  36. UpdateRemaining,
  37. UpdateCurrentGranted,
  38. UpdateCurrentDenied
  39. } ACCESS_MASK_FIELD_TO_UPDATE;
  40. VOID
  41. SepAddAccessTypeList (
  42. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  43. IN ULONG ObjectTypeListLength,
  44. IN ULONG StartIndex,
  45. IN ACCESS_MASK AccessMask,
  46. IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate
  47. );
  48. NTSTATUS
  49. SeAccessCheckByType (
  50. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  51. IN PSID PrincipalSelfSid,
  52. IN HANDLE ClientToken,
  53. IN ACCESS_MASK DesiredAccess,
  54. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  55. IN ULONG ObjectTypeListLength,
  56. IN PGENERIC_MAPPING GenericMapping,
  57. OUT PPRIVILEGE_SET PrivilegeSet,
  58. IN OUT PULONG PrivilegeSetLength,
  59. OUT PACCESS_MASK GrantedAccess,
  60. OUT PNTSTATUS AccessStatus,
  61. IN BOOLEAN ReturnResultList
  62. );
  63. VOID
  64. SepMaximumAccessCheck(
  65. IN PTOKEN EToken,
  66. IN PTOKEN PrimaryToken,
  67. IN PACL Dacl,
  68. IN PSID PrincipalSelfSid,
  69. IN ULONG LocalTypeListLength,
  70. IN PIOBJECT_TYPE_LIST LocalTypeList,
  71. IN ULONG ObjectTypeListLength,
  72. IN BOOLEAN Restricted
  73. );
  74. VOID
  75. SepNormalAccessCheck(
  76. IN ACCESS_MASK Remaining,
  77. IN PTOKEN EToken,
  78. IN PTOKEN PrimaryToken,
  79. IN PACL Dacl,
  80. IN PSID PrincipalSelfSid,
  81. IN ULONG LocalTypeListLength,
  82. IN PIOBJECT_TYPE_LIST LocalTypeList,
  83. IN ULONG ObjectTypeListLength,
  84. IN BOOLEAN Restricted
  85. );
  86. BOOLEAN
  87. SepSidInTokenEx (
  88. IN PACCESS_TOKEN AToken,
  89. IN PSID PrincipalSelfSid,
  90. IN PSID Sid,
  91. IN BOOLEAN DenyAce,
  92. IN BOOLEAN Restricted
  93. );
  94. #ifdef ALLOC_PRAGMA
  95. #pragma alloc_text(PAGE,SeCaptureObjectTypeList)
  96. #pragma alloc_text(PAGE,SeFreeCapturedObjectTypeList)
  97. #pragma alloc_text(PAGE,SepUpdateParentTypeList)
  98. #pragma alloc_text(PAGE,SepObjectInTypeList)
  99. #pragma alloc_text(PAGE,SepAddAccessTypeList)
  100. #pragma alloc_text(PAGE,SepSidInToken)
  101. #pragma alloc_text(PAGE,SepSidInTokenEx)
  102. #pragma alloc_text(PAGE,SepAccessCheck)
  103. #pragma alloc_text(PAGE,NtAccessCheck)
  104. #pragma alloc_text(PAGE,NtAccessCheckByType)
  105. #pragma alloc_text(PAGE,NtAccessCheckByTypeResultList)
  106. #pragma alloc_text(PAGE,SeAccessCheckByType)
  107. #pragma alloc_text(PAGE,SeFreePrivileges)
  108. #pragma alloc_text(PAGE,SeAccessCheck)
  109. #pragma alloc_text(PAGE,SePrivilegePolicyCheck)
  110. #pragma alloc_text(PAGE,SepTokenIsOwner)
  111. #pragma alloc_text(PAGE,SeFastTraverseCheck)
  112. #pragma alloc_text(PAGE,SepMaximumAccessCheck)
  113. #pragma alloc_text(PAGE,SepNormalAccessCheck)
  114. #pragma alloc_text(PAGE,SeMaximumAuditMask)
  115. #endif
  116. NTSTATUS
  117. SeCaptureObjectTypeList (
  118. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  119. IN ULONG ObjectTypeListLength,
  120. IN KPROCESSOR_MODE RequestorMode,
  121. OUT PIOBJECT_TYPE_LIST *CapturedObjectTypeList
  122. )
  123. /*++
  124. Routine Description:
  125. This routine probes and captures a copy of any object type list
  126. that might have been provided via the ObjectTypeList argument.
  127. The object type list is converted to the internal form that explicitly
  128. specifies the hierarchical relationship between the entries.
  129. The object typs list is validated to ensure a valid hierarchical
  130. relationship is represented.
  131. Arguments:
  132. ObjectTypeList - The object type list from which the type list
  133. information is to be retrieved.
  134. ObjectTypeListLength - Number of elements in ObjectTypeList
  135. RequestorMode - Indicates the processor mode by which the access
  136. is being requested.
  137. CapturedObjectTypeList - Receives the captured type list which
  138. must be freed using SeFreeCapturedObjectTypeList().
  139. Return Value:
  140. STATUS_SUCCESS indicates no exceptions were encountered.
  141. Any access violations encountered will be returned.
  142. --*/
  143. {
  144. NTSTATUS Status = STATUS_SUCCESS;
  145. ULONG i;
  146. PIOBJECT_TYPE_LIST LocalTypeList = NULL;
  147. ULONG Levels[ACCESS_MAX_LEVEL+1];
  148. PAGED_CODE();
  149. //
  150. // Set default return
  151. //
  152. *CapturedObjectTypeList = NULL;
  153. if (RequestorMode != UserMode) {
  154. return STATUS_NOT_IMPLEMENTED;
  155. }
  156. try {
  157. if ( ObjectTypeListLength == 0 ) {
  158. // Drop through
  159. } else if ( !ARGUMENT_PRESENT(ObjectTypeList) ) {
  160. Status = STATUS_INVALID_PARAMETER;
  161. } else {
  162. if ( !IsValidElementCount( ObjectTypeListLength, IOBJECT_TYPE_LIST ) )
  163. {
  164. Status = STATUS_INVALID_PARAMETER ;
  165. //
  166. // No more to do, get out of the try statement:
  167. //
  168. leave ;
  169. }
  170. ProbeForRead( ObjectTypeList,
  171. sizeof(OBJECT_TYPE_LIST) * ObjectTypeListLength,
  172. sizeof(ULONG)
  173. );
  174. //
  175. // Allocate a buffer to copy into.
  176. //
  177. LocalTypeList = ExAllocatePoolWithTag( PagedPool, sizeof(IOBJECT_TYPE_LIST) * ObjectTypeListLength, 'tOeS' );
  178. if ( LocalTypeList == NULL ) {
  179. Status = STATUS_INSUFFICIENT_RESOURCES;
  180. //
  181. // Copy the callers structure to the local structure.
  182. //
  183. } else {
  184. GUID * CapturedObjectType;
  185. for ( i=0; i<ObjectTypeListLength; i++ ) {
  186. USHORT CurrentLevel;
  187. //
  188. // Limit ourselves
  189. //
  190. CurrentLevel = ObjectTypeList[i].Level;
  191. if ( CurrentLevel > ACCESS_MAX_LEVEL ) {
  192. Status = STATUS_INVALID_PARAMETER;
  193. break;
  194. }
  195. //
  196. // Copy data the caller passed in
  197. //
  198. LocalTypeList[i].Level = CurrentLevel;
  199. LocalTypeList[i].Flags = 0;
  200. CapturedObjectType = ObjectTypeList[i].ObjectType;
  201. ProbeForReadSmallStructure(
  202. CapturedObjectType,
  203. sizeof(GUID),
  204. sizeof(ULONG)
  205. );
  206. LocalTypeList[i].ObjectType = *CapturedObjectType;
  207. LocalTypeList[i].Remaining = 0;
  208. LocalTypeList[i].CurrentGranted = 0;
  209. LocalTypeList[i].CurrentDenied = 0;
  210. //
  211. // Ensure that the level number is consistent with the
  212. // level number of the previous entry.
  213. //
  214. if ( i == 0 ) {
  215. if ( CurrentLevel != 0 ) {
  216. Status = STATUS_INVALID_PARAMETER;
  217. break;
  218. }
  219. } else {
  220. //
  221. // The previous entry is either:
  222. // my immediate parent,
  223. // my sibling, or
  224. // the child (or grandchild, etc.) of my sibling.
  225. //
  226. if ( CurrentLevel > LocalTypeList[i-1].Level + 1 ) {
  227. Status = STATUS_INVALID_PARAMETER;
  228. break;
  229. }
  230. //
  231. // Don't support two roots.
  232. //
  233. if ( CurrentLevel == 0 ) {
  234. Status = STATUS_INVALID_PARAMETER;
  235. break;
  236. }
  237. }
  238. //
  239. // If the above rules are maintained,
  240. // then my parent object is the last object seen that
  241. // has a level one less than mine.
  242. //
  243. if ( CurrentLevel == 0 ) {
  244. LocalTypeList[i].ParentIndex = -1;
  245. } else {
  246. LocalTypeList[i].ParentIndex = Levels[CurrentLevel-1];
  247. }
  248. //
  249. // Save this obect as the last object seen at this level.
  250. //
  251. Levels[CurrentLevel] = i;
  252. }
  253. }
  254. } // end_if
  255. } except(EXCEPTION_EXECUTE_HANDLER) {
  256. //
  257. // If we captured any proxy data, we need to free it now.
  258. //
  259. if ( LocalTypeList != NULL ) {
  260. ExFreePool( LocalTypeList );
  261. LocalTypeList = NULL;
  262. }
  263. Status = GetExceptionCode();
  264. } // end_try
  265. *CapturedObjectTypeList = LocalTypeList;
  266. return Status;
  267. }
  268. VOID
  269. SeFreeCapturedObjectTypeList(
  270. IN PVOID ObjectTypeList
  271. )
  272. /*++
  273. Routine Description:
  274. This routine frees the data associated with a captured ObjectTypeList
  275. structure.
  276. Arguments:
  277. ObjectTypeList - Points to a captured object type list structure.
  278. Return Value:
  279. None.
  280. --*/
  281. {
  282. PAGED_CODE();
  283. if ( ObjectTypeList != NULL ) {
  284. ExFreePool( ObjectTypeList );
  285. }
  286. return;
  287. }
  288. BOOLEAN
  289. SepObjectInTypeList (
  290. IN GUID *ObjectType,
  291. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  292. IN ULONG ObjectTypeListLength,
  293. OUT PULONG ReturnedIndex
  294. )
  295. /*++
  296. Routine Description:
  297. This routine searches an ObjectTypeList to determine if the specified
  298. object type is in the list.
  299. Arguments:
  300. ObjectType - Object Type to search for.
  301. ObjectTypeList - The object type list to search.
  302. ObjectTypeListLength - Number of elements in ObjectTypeList
  303. ReturnedIndex - Index to the element ObjectType was found in
  304. Return Value:
  305. TRUE: ObjectType was found in list.
  306. FALSE: ObjectType was not found in list.
  307. --*/
  308. {
  309. ULONG Index;
  310. GUID *LocalObjectType;
  311. PAGED_CODE();
  312. ASSERT( sizeof(GUID) == sizeof(ULONG) * 4 );
  313. for ( Index=0; Index<ObjectTypeListLength; Index++ ) {
  314. LocalObjectType = &ObjectTypeList[Index].ObjectType;
  315. if ( RtlpIsEqualGuid( ObjectType, LocalObjectType ) ) {
  316. *ReturnedIndex = Index;
  317. return TRUE;
  318. }
  319. }
  320. return FALSE;
  321. }
  322. VOID
  323. SepUpdateParentTypeList (
  324. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  325. IN ULONG ObjectTypeListLength,
  326. IN ULONG StartIndex
  327. )
  328. /*++
  329. Routine Description:
  330. Update the Access fields of the parent object of the specified object.
  331. The "remaining" field of a parent object is the logical OR of
  332. the remaining field of all of its children.
  333. The CurrentGranted field of the parent is the collection of bits
  334. granted to every one of its children..
  335. The CurrentDenied fields of the parent is the logical OR of
  336. the bits denied to any of its children.
  337. This routine takes an index to one of the children and updates the
  338. remaining field of the parent (and grandparents recursively).
  339. Arguments:
  340. ObjectTypeList - The object type list to update.
  341. ObjectTypeListLength - Number of elements in ObjectTypeList
  342. StartIndex - Index to the "child" element whose parents are to be updated.
  343. Return Value:
  344. None.
  345. --*/
  346. {
  347. ULONG Index;
  348. ULONG ParentIndex;
  349. ULONG Level;
  350. ACCESS_MASK NewRemaining = 0;
  351. ACCESS_MASK NewCurrentGranted = 0xFFFFFFFF;
  352. ACCESS_MASK NewCurrentDenied = 0;
  353. PAGED_CODE();
  354. //
  355. // If the target node is at the root,
  356. // we're all done.
  357. //
  358. if ( ObjectTypeList[StartIndex].ParentIndex == -1 ) {
  359. return;
  360. }
  361. //
  362. // Get the index to the parent that needs updating and the level of
  363. // the siblings.
  364. //
  365. ParentIndex = ObjectTypeList[StartIndex].ParentIndex;
  366. Level = ObjectTypeList[StartIndex].Level;
  367. //
  368. // Loop through all the children.
  369. //
  370. for ( Index=ParentIndex+1; Index<ObjectTypeListLength; Index++ ) {
  371. //
  372. // By definition, the children of an object are all those entries
  373. // immediately following the target. The list of children (or
  374. // grandchildren) stops as soon as we reach an entry the has the
  375. // same level as the target (a sibling) or lower than the target
  376. // (an uncle).
  377. //
  378. if ( ObjectTypeList[Index].Level <= ObjectTypeList[ParentIndex].Level ) {
  379. break;
  380. }
  381. //
  382. // Only handle direct children of the parent.
  383. //
  384. if ( ObjectTypeList[Index].Level != Level ) {
  385. continue;
  386. }
  387. //
  388. // Compute the new bits for the parent.
  389. //
  390. NewRemaining |= ObjectTypeList[Index].Remaining;
  391. NewCurrentGranted &= ObjectTypeList[Index].CurrentGranted;
  392. NewCurrentDenied |= ObjectTypeList[Index].CurrentDenied;
  393. }
  394. //
  395. // If we've not changed the access to the parent,
  396. // we're done.
  397. //
  398. if ( NewRemaining == ObjectTypeList[ParentIndex].Remaining &&
  399. NewCurrentGranted == ObjectTypeList[ParentIndex].CurrentGranted &&
  400. NewCurrentDenied == ObjectTypeList[ParentIndex].CurrentDenied ) {
  401. return;
  402. }
  403. //
  404. // Change the parent.
  405. //
  406. ObjectTypeList[ParentIndex].Remaining = NewRemaining;
  407. ObjectTypeList[ParentIndex].CurrentGranted = NewCurrentGranted;
  408. ObjectTypeList[ParentIndex].CurrentDenied = NewCurrentDenied;
  409. //
  410. // Go update the grand parents.
  411. //
  412. SepUpdateParentTypeList( ObjectTypeList,
  413. ObjectTypeListLength,
  414. ParentIndex );
  415. }
  416. VOID
  417. SepAddAccessTypeList (
  418. IN PIOBJECT_TYPE_LIST ObjectTypeList,
  419. IN ULONG ObjectTypeListLength,
  420. IN ULONG StartIndex,
  421. IN ACCESS_MASK AccessMask,
  422. IN ACCESS_MASK_FIELD_TO_UPDATE FieldToUpdate
  423. )
  424. /*++
  425. Routine Description:
  426. This routine grants the specified AccessMask to all of the objects that
  427. are descendents of the object specified by StartIndex.
  428. The Access fields of the parent objects are also recomputed as needed.
  429. For example, if an ACE granting access to a Property Set is found,
  430. that access is granted to all the Properties in the Property Set.
  431. Arguments:
  432. ObjectTypeList - The object type list to update.
  433. ObjectTypeListLength - Number of elements in ObjectTypeList
  434. StartIndex - Index to the target element to update.
  435. AccessMask - Mask of access to grant to the target element and
  436. all of its decendents
  437. FieldToUpdate - Indicate which fields to update in object type list
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. ULONG Index;
  443. ACCESS_MASK OldRemaining;
  444. ACCESS_MASK OldCurrentGranted;
  445. ACCESS_MASK OldCurrentDenied;
  446. BOOLEAN AvoidParent = FALSE;
  447. PAGED_CODE();
  448. //
  449. // Update the requested field.
  450. //
  451. // Always handle the target entry.
  452. //
  453. // If we've not actually changed the bits,
  454. // early out.
  455. //
  456. switch (FieldToUpdate ) {
  457. case UpdateRemaining:
  458. OldRemaining = ObjectTypeList[StartIndex].Remaining;
  459. ObjectTypeList[StartIndex].Remaining = OldRemaining & ~AccessMask;
  460. if ( OldRemaining == ObjectTypeList[StartIndex].Remaining ) {
  461. return;
  462. }
  463. break;
  464. case UpdateCurrentGranted:
  465. OldCurrentGranted = ObjectTypeList[StartIndex].CurrentGranted;
  466. ObjectTypeList[StartIndex].CurrentGranted |=
  467. AccessMask & ~ObjectTypeList[StartIndex].CurrentDenied;
  468. if ( OldCurrentGranted == ObjectTypeList[StartIndex].CurrentGranted ) {
  469. //
  470. // We can't simply return here.
  471. // We have to visit our children. Consider the case where there
  472. // was a previous deny ACE on a child. That deny would have
  473. // propagated up the tree to this entry. However, this allow ACE
  474. // needs to be added all of the children that haven't been
  475. // explictly denied.
  476. //
  477. AvoidParent = TRUE;
  478. }
  479. break;
  480. case UpdateCurrentDenied:
  481. OldCurrentDenied = ObjectTypeList[StartIndex].CurrentDenied;
  482. ObjectTypeList[StartIndex].CurrentDenied |=
  483. AccessMask & ~ObjectTypeList[StartIndex].CurrentGranted;
  484. if ( OldCurrentDenied == ObjectTypeList[StartIndex].CurrentDenied ) {
  485. return;
  486. }
  487. break;
  488. default:
  489. return;
  490. }
  491. //
  492. // Go update parent of the target.
  493. //
  494. if ( !AvoidParent ) {
  495. SepUpdateParentTypeList( ObjectTypeList,
  496. ObjectTypeListLength,
  497. StartIndex );
  498. }
  499. //
  500. // Loop handling all children of the target.
  501. //
  502. for ( Index=StartIndex+1; Index<ObjectTypeListLength; Index++ ) {
  503. //
  504. // By definition, the children of an object are all those entries
  505. // immediately following the target. The list of children (or
  506. // grandchildren) stops as soon as we reach an entry the has the
  507. // same level as the target (a sibling) or lower than the target
  508. // (an uncle).
  509. //
  510. if ( ObjectTypeList[Index].Level <= ObjectTypeList[StartIndex].Level ) {
  511. break;
  512. }
  513. //
  514. // Grant access to the children
  515. //
  516. switch (FieldToUpdate) {
  517. case UpdateRemaining:
  518. ObjectTypeList[Index].Remaining &= ~AccessMask;
  519. break;
  520. case UpdateCurrentGranted:
  521. ObjectTypeList[Index].CurrentGranted |=
  522. AccessMask & ~ObjectTypeList[Index].CurrentDenied;
  523. break;
  524. case UpdateCurrentDenied:
  525. ObjectTypeList[Index].CurrentDenied |=
  526. AccessMask & ~ObjectTypeList[Index].CurrentGranted;
  527. break;
  528. default:
  529. return;
  530. }
  531. }
  532. }
  533. BOOLEAN
  534. SepSidInToken (
  535. IN PACCESS_TOKEN AToken,
  536. IN PSID PrincipalSelfSid,
  537. IN PSID Sid,
  538. IN BOOLEAN DenyAce
  539. )
  540. /*++
  541. Routine Description:
  542. Checks to see if a given SID is in the given token.
  543. N.B. The code to compute the length of a SID and test for equality
  544. is duplicated from the security runtime since this is such a
  545. frequently used routine.
  546. Arguments:
  547. Token - Pointer to the token to be examined
  548. PrincipalSelfSid - If the object being access checked is an object which
  549. represents a principal (e.g., a user object), this parameter should
  550. be the SID of the object. Any ACE containing the constant
  551. PRINCIPAL_SELF_SID is replaced by this SID.
  552. The parameter should be NULL if the object does not represent a principal.
  553. Sid - Pointer to the SID of interest
  554. Return Value:
  555. A value of TRUE indicates that the SID is in the token, FALSE
  556. otherwise.
  557. --*/
  558. {
  559. ULONG i;
  560. PISID MatchSid;
  561. ULONG SidLength;
  562. PTOKEN Token;
  563. PSID_AND_ATTRIBUTES TokenSid;
  564. ULONG UserAndGroupCount;
  565. PAGED_CODE();
  566. #if DBG
  567. SepDumpTokenInfo(AToken);
  568. #endif
  569. //
  570. // If Sid is the constant PrincipalSelfSid,
  571. // replace it with the passed in PrincipalSelfSid.
  572. //
  573. if ( PrincipalSelfSid != NULL &&
  574. RtlEqualSid( SePrincipalSelfSid, Sid ) ) {
  575. Sid = PrincipalSelfSid;
  576. }
  577. //
  578. // Get the length of the source SID since this only needs to be computed
  579. // once.
  580. //
  581. SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount);
  582. //
  583. // Get address of user/group array and number of user/groups.
  584. //
  585. Token = (PTOKEN)AToken;
  586. TokenSid = Token->UserAndGroups;
  587. UserAndGroupCount = Token->UserAndGroupCount;
  588. //
  589. // Scan through the user/groups and attempt to find a match with the
  590. // specified SID.
  591. //
  592. for (i = 0 ; i < UserAndGroupCount ; i += 1) {
  593. MatchSid = (PISID)TokenSid->Sid;
  594. //
  595. // If the SID revision and length matches, then compare the SIDs
  596. // for equality.
  597. //
  598. if ((((PISID)Sid)->Revision == MatchSid->Revision) &&
  599. (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) {
  600. if (RtlEqualMemory(Sid, MatchSid, SidLength)) {
  601. //
  602. // If this is the first one in the list, then it is the User,
  603. // and return success immediately.
  604. //
  605. // If this is not the first one, then it represents a group,
  606. // and we must make sure the group is currently enabled before
  607. // we can say that the group is "in" the token.
  608. //
  609. if ((i == 0) || (TokenSid->Attributes & SE_GROUP_ENABLED) ||
  610. (DenyAce && (TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY))) {
  611. return TRUE;
  612. } else {
  613. return FALSE;
  614. }
  615. }
  616. }
  617. TokenSid += 1;
  618. }
  619. return FALSE;
  620. }
  621. BOOLEAN
  622. SepSidInTokenEx (
  623. IN PACCESS_TOKEN AToken,
  624. IN PSID PrincipalSelfSid,
  625. IN PSID Sid,
  626. IN BOOLEAN DenyAce,
  627. IN BOOLEAN Restricted
  628. )
  629. /*++
  630. Routine Description:
  631. Checks to see if a given restricted SID is in the given token.
  632. N.B. The code to compute the length of a SID and test for equality
  633. is duplicated from the security runtime since this is such a
  634. frequently used routine.
  635. Arguments:
  636. Token - Pointer to the token to be examined
  637. PrincipalSelfSid - If the object being access checked is an object which
  638. represents a principal (e.g., a user object), this parameter should
  639. be the SID of the object. Any ACE containing the constant
  640. PRINCIPAL_SELF_SID is replaced by this SID.
  641. The parameter should be NULL if the object does not represent a principal.
  642. Sid - Pointer to the SID of interest
  643. DenyAce - The ACE being evaluated is a DENY or ACCESS DENIED ace
  644. Restricted - The access check being performed uses the restricted sids.
  645. Return Value:
  646. A value of TRUE indicates that the SID is in the token, FALSE
  647. otherwise.
  648. --*/
  649. {
  650. ULONG i;
  651. PISID MatchSid;
  652. ULONG SidLength;
  653. PTOKEN Token;
  654. PSID_AND_ATTRIBUTES TokenSid;
  655. ULONG UserAndGroupCount;
  656. PAGED_CODE();
  657. #if DBG
  658. SepDumpTokenInfo(AToken);
  659. #endif
  660. //
  661. // If Sid is the constant PrincipalSelfSid,
  662. // replace it with the passed in PrincipalSelfSid.
  663. //
  664. if ( PrincipalSelfSid != NULL &&
  665. RtlEqualSid( SePrincipalSelfSid, Sid ) ) {
  666. Sid = PrincipalSelfSid;
  667. }
  668. //
  669. // Get the length of the source SID since this only needs to be computed
  670. // once.
  671. //
  672. SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount);
  673. //
  674. // Get address of user/group array and number of user/groups.
  675. //
  676. Token = (PTOKEN)AToken;
  677. if (Restricted) {
  678. TokenSid = Token->RestrictedSids;
  679. UserAndGroupCount = Token->RestrictedSidCount;
  680. } else {
  681. TokenSid = Token->UserAndGroups;
  682. UserAndGroupCount = Token->UserAndGroupCount;
  683. }
  684. //
  685. // Scan through the user/groups and attempt to find a match with the
  686. // specified SID.
  687. //
  688. for (i = 0; i < UserAndGroupCount ; i += 1) {
  689. MatchSid = (PISID)TokenSid->Sid;
  690. //
  691. // If the SID revision and length matches, then compare the SIDs
  692. // for equality.
  693. //
  694. if ((((PISID)Sid)->Revision == MatchSid->Revision) &&
  695. (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) {
  696. if (RtlEqualMemory(Sid, MatchSid, SidLength)) {
  697. //
  698. // If this is the first one in the list and not deny-only it
  699. // is not a restricted token then it is the User, and return
  700. // success immediately.
  701. //
  702. // If this is not the first one, then it represents a group,
  703. // and we must make sure the group is currently enabled before
  704. // we can say that the group is "in" the token.
  705. //
  706. if ((!Restricted && (i == 0) && ((TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY) == 0)) ||
  707. (TokenSid->Attributes & SE_GROUP_ENABLED) ||
  708. (DenyAce && (TokenSid->Attributes & SE_GROUP_USE_FOR_DENY_ONLY))) {
  709. return TRUE;
  710. } else {
  711. return FALSE;
  712. }
  713. }
  714. }
  715. TokenSid += 1;
  716. }
  717. return FALSE;
  718. }
  719. VOID
  720. SepMaximumAccessCheck(
  721. IN PTOKEN EToken,
  722. IN PTOKEN PrimaryToken,
  723. IN PACL Dacl,
  724. IN PSID PrincipalSelfSid,
  725. IN ULONG LocalTypeListLength,
  726. IN PIOBJECT_TYPE_LIST LocalTypeList,
  727. IN ULONG ObjectTypeListLength,
  728. IN BOOLEAN Restricted
  729. )
  730. /*++
  731. Routine Description:
  732. Does an access check for maximum allowed or with a result list. If the
  733. Restricted flag is set, it is done for a restricted token. The sids
  734. checked are the restricted sids, not the users and groups. The current
  735. granted access is stored in the Remaining access and then another access
  736. check is run.
  737. Arguments:
  738. EToken - Effective token of caller.
  739. PrimaryToken - Process token of calling process
  740. Dacl - ACL to check
  741. PrincipalSelfSid - Sid to use in replacing the well-known self sid
  742. LocalTypeListLength - Length of list of types.
  743. LocalTypeList - List of types.
  744. ObjectTypeList - Length of caller-supplied list of object types.
  745. Return Value:
  746. none
  747. --*/
  748. {
  749. ULONG i,j;
  750. PVOID Ace;
  751. ULONG AceCount;
  752. ULONG Index;
  753. ULONG ResultListIndex;
  754. //
  755. // The remaining bits are the granted bits for each object type on a
  756. // restricted check
  757. //
  758. if ( Restricted ) {
  759. for ( j=0; j<LocalTypeListLength; j++ ) {
  760. LocalTypeList[j].Remaining = LocalTypeList[j].CurrentGranted;
  761. LocalTypeList[j].CurrentGranted = 0;
  762. }
  763. }
  764. AceCount = Dacl->AceCount;
  765. //
  766. // granted == NUL
  767. // denied == NUL
  768. //
  769. // for each ACE
  770. //
  771. // if grant
  772. // for each SID
  773. // if SID match, then add all that is not denied to grant mask
  774. //
  775. // if deny
  776. // for each SID
  777. // if SID match, then add all that is not granted to deny mask
  778. //
  779. for ( i = 0, Ace = FirstAce( Dacl ) ;
  780. i < AceCount ;
  781. i++, Ace = NextAce( Ace )
  782. ) {
  783. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  784. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) {
  785. if (SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart, FALSE, Restricted )) {
  786. //
  787. // Only grant access types from this mask that have
  788. // not already been denied
  789. //
  790. // Optimize 'normal' case
  791. if ( LocalTypeListLength == 1 ) {
  792. LocalTypeList->CurrentGranted |=
  793. (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  794. } else {
  795. //
  796. // The zeroeth object type represents the object itself.
  797. //
  798. SepAddAccessTypeList(
  799. LocalTypeList, // List to modify
  800. LocalTypeListLength, // Length of list
  801. 0, // Element to update
  802. ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  803. UpdateCurrentGranted );
  804. }
  805. }
  806. //
  807. // Handle an object specific Access Allowed ACE
  808. //
  809. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) {
  810. GUID *ObjectTypeInAce;
  811. //
  812. // If no object type is in the ACE,
  813. // treat this as an ACCESS_ALLOWED_ACE.
  814. //
  815. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  816. if ( ObjectTypeInAce == NULL ) {
  817. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) {
  818. // Optimize 'normal' case
  819. if ( LocalTypeListLength == 1 ) {
  820. LocalTypeList->CurrentGranted |=
  821. (((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  822. } else {
  823. SepAddAccessTypeList(
  824. LocalTypeList, // List to modify
  825. LocalTypeListLength, // Length of list
  826. 0, // Element to update
  827. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  828. UpdateCurrentGranted );
  829. }
  830. }
  831. //
  832. // If no object type list was passed,
  833. // don't grant access to anyone.
  834. //
  835. } else if ( ObjectTypeListLength == 0 ) {
  836. // Drop through
  837. //
  838. // If an object type is in the ACE,
  839. // Find it in the LocalTypeList before using the ACE.
  840. //
  841. } else {
  842. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) {
  843. if ( SepObjectInTypeList( ObjectTypeInAce,
  844. LocalTypeList,
  845. LocalTypeListLength,
  846. &Index ) ) {
  847. SepAddAccessTypeList(
  848. LocalTypeList, // List to modify
  849. LocalTypeListLength, // Length of list
  850. Index, // Element already updated
  851. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  852. UpdateCurrentGranted );
  853. }
  854. }
  855. }
  856. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) {
  857. //
  858. // If we're impersonating, EToken is set to the Client, and if we're not,
  859. // EToken is set to the Primary. According to the DSA architecture, if
  860. // we're asked to evaluate a compound ACE and we're not impersonating,
  861. // pretend we are impersonating ourselves. So we can just use the EToken
  862. // for the client token, since it's already set to the right thing.
  863. //
  864. if ( SepSidInTokenEx(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE, Restricted) &&
  865. SepSidInTokenEx(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE, FALSE)
  866. ) {
  867. //
  868. // Only grant access types from this mask that have
  869. // not already been denied
  870. //
  871. // Optimize 'normal' case
  872. if ( LocalTypeListLength == 1 ) {
  873. LocalTypeList->CurrentGranted |=
  874. (((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask & ~LocalTypeList->CurrentDenied);
  875. } else {
  876. //
  877. // The zeroeth object type represents the object itself.
  878. //
  879. SepAddAccessTypeList(
  880. LocalTypeList, // List to modify
  881. LocalTypeListLength, // Length of list
  882. 0, // Element to update
  883. ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  884. UpdateCurrentGranted );
  885. }
  886. }
  887. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) {
  888. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE, Restricted )) {
  889. //
  890. // Only deny access types from this mask that have
  891. // not already been granted
  892. //
  893. // Optimize 'normal' case
  894. if ( LocalTypeListLength == 1 ) {
  895. LocalTypeList->CurrentDenied |=
  896. (((PACCESS_DENIED_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted);
  897. } else {
  898. //
  899. // The zeroeth object type represents the object itself.
  900. //
  901. SepAddAccessTypeList(
  902. LocalTypeList, // List to modify
  903. LocalTypeListLength, // Length of list
  904. 0, // Element to update
  905. ((PACCESS_DENIED_ACE)Ace)->Mask, // Access denied
  906. UpdateCurrentDenied );
  907. }
  908. }
  909. //
  910. // Handle an object specific Access Denied ACE
  911. //
  912. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) {
  913. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE, Restricted ) ) {
  914. GUID *ObjectTypeInAce;
  915. //
  916. // If there is no object type in the ACE,
  917. // or if the caller didn't specify an object type list,
  918. // apply this deny ACE to the entire object.
  919. //
  920. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  921. if ( ObjectTypeInAce == NULL ) {
  922. if ( LocalTypeListLength == 1 ) {
  923. LocalTypeList->CurrentDenied |=
  924. (((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted);
  925. } else {
  926. //
  927. // The zeroeth object type represents the object itself.
  928. //
  929. SepAddAccessTypeList(
  930. LocalTypeList, // List to modify
  931. LocalTypeListLength, // Length of list
  932. 0,
  933. ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask, // Access denied
  934. UpdateCurrentDenied );
  935. }
  936. //
  937. // If no object type list was passed,
  938. // don't grant access to anyone.
  939. //
  940. } else if ( ObjectTypeListLength == 0 ) {
  941. LocalTypeList->CurrentDenied |=
  942. (((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask & ~LocalTypeList->CurrentGranted);
  943. //
  944. // If an object type is in the ACE,
  945. // Find it in the LocalTypeList before using the ACE.
  946. //
  947. } else if ( SepObjectInTypeList( ObjectTypeInAce,
  948. LocalTypeList,
  949. LocalTypeListLength,
  950. &Index ) ) {
  951. SepAddAccessTypeList(
  952. LocalTypeList, // List to modify
  953. LocalTypeListLength, // Length of list
  954. Index, // Element to update
  955. ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask, // Access denied
  956. UpdateCurrentDenied );
  957. }
  958. }
  959. }
  960. }
  961. }
  962. }
  963. VOID
  964. SepNormalAccessCheck(
  965. IN ACCESS_MASK Remaining,
  966. IN PTOKEN EToken,
  967. IN PTOKEN PrimaryToken,
  968. IN PACL Dacl,
  969. IN PSID PrincipalSelfSid,
  970. IN ULONG LocalTypeListLength,
  971. IN PIOBJECT_TYPE_LIST LocalTypeList,
  972. IN ULONG ObjectTypeListLength,
  973. IN BOOLEAN Restricted
  974. )
  975. /*++
  976. Routine Description:
  977. Does an access check when the caller isn't asking for MAXIMUM_ALLOWED or
  978. a type result list. If the Restricted flag is set, the sids checked are
  979. the restricted sids, not the users and groups. The Remaining field is
  980. reset to the original remaining value and then another access check is run.
  981. Arguments:
  982. Remaining - Remaining access desired after special checks
  983. EToken - Effective token of caller.
  984. PrimaryToken - Process token of calling process
  985. Dacl - ACL to check
  986. PrincipalSelfSid - Sid to use in replacing the well-known self sid
  987. LocalTypeListLength - Length of list of types.
  988. LocalTypeList - List of types.
  989. ObjectTypeList - Length of caller-supplied list of object types.
  990. Restricted - Use the restricted sids for the access check.
  991. Return Value:
  992. none
  993. --*/
  994. {
  995. ULONG i,j;
  996. PVOID Ace;
  997. ULONG AceCount;
  998. ULONG Index;
  999. AceCount = Dacl->AceCount;
  1000. //
  1001. // The remaining bits are "remaining" at all levels
  1002. //
  1003. for ( j=0; j<LocalTypeListLength; j++ ) {
  1004. LocalTypeList[j].Remaining = Remaining;
  1005. }
  1006. //
  1007. // Process the DACL handling individual access bits.
  1008. //
  1009. for ( i = 0, Ace = FirstAce( Dacl ) ;
  1010. ( i < AceCount ) && ( LocalTypeList->Remaining != 0 ) ;
  1011. i++, Ace = NextAce( Ace ) ) {
  1012. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  1013. //
  1014. // Handle an Access Allowed ACE
  1015. //
  1016. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) {
  1017. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE )Ace)->SidStart, FALSE, Restricted ) ) {
  1018. // Optimize 'normal' case
  1019. if ( LocalTypeListLength == 1 ) {
  1020. LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask;
  1021. } else {
  1022. //
  1023. // The zeroeth object type represents the object itself.
  1024. //
  1025. SepAddAccessTypeList(
  1026. LocalTypeList, // List to modify
  1027. LocalTypeListLength, // Length of list
  1028. 0, // Element to update
  1029. ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  1030. UpdateRemaining );
  1031. }
  1032. }
  1033. //
  1034. // Handle an object specific Access Allowed ACE
  1035. //
  1036. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) {
  1037. GUID *ObjectTypeInAce;
  1038. //
  1039. // If no object type is in the ACE,
  1040. // treat this as an ACCESS_ALLOWED_ACE.
  1041. //
  1042. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1043. if ( ObjectTypeInAce == NULL ) {
  1044. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) {
  1045. // Optimize 'normal' case
  1046. if ( LocalTypeListLength == 1 ) {
  1047. LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask;
  1048. } else {
  1049. SepAddAccessTypeList(
  1050. LocalTypeList, // List to modify
  1051. LocalTypeListLength, // Length of list
  1052. 0, // Element to update
  1053. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  1054. UpdateRemaining );
  1055. }
  1056. }
  1057. //
  1058. // If no object type list was passed,
  1059. // don't grant access to anyone.
  1060. //
  1061. } else if ( ObjectTypeListLength == 0 ) {
  1062. // Drop through
  1063. //
  1064. // If an object type is in the ACE,
  1065. // Find it in the LocalTypeList before using the ACE.
  1066. //
  1067. } else {
  1068. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE, Restricted ) ) {
  1069. if ( SepObjectInTypeList( ObjectTypeInAce,
  1070. LocalTypeList,
  1071. LocalTypeListLength,
  1072. &Index ) ) {
  1073. SepAddAccessTypeList(
  1074. LocalTypeList, // List to modify
  1075. LocalTypeListLength, // Length of list
  1076. Index, // Element already updated
  1077. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  1078. UpdateRemaining );
  1079. }
  1080. }
  1081. }
  1082. //
  1083. // Handle a compound Access Allowed ACE
  1084. //
  1085. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) {
  1086. //
  1087. // See comment in MAXIMUM_ALLOWED case as to why we can use EToken here
  1088. // for the client.
  1089. //
  1090. if ( SepSidInTokenEx(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE, Restricted) &&
  1091. SepSidInTokenEx(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE, Restricted) ) {
  1092. // Optimize 'normal' case
  1093. if ( LocalTypeListLength == 1 ) {
  1094. LocalTypeList->Remaining &= ~((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask;
  1095. } else {
  1096. SepAddAccessTypeList(
  1097. LocalTypeList, // List to modify
  1098. LocalTypeListLength, // Length of list
  1099. 0, // Element to update
  1100. ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  1101. UpdateRemaining );
  1102. }
  1103. }
  1104. //
  1105. // Handle an Access Denied ACE
  1106. //
  1107. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) {
  1108. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE, Restricted ) ) {
  1109. //
  1110. // The zeroeth element represents the object itself.
  1111. // Just check that element.
  1112. //
  1113. if (LocalTypeList->Remaining & ((PACCESS_DENIED_ACE)Ace)->Mask) {
  1114. break;
  1115. }
  1116. }
  1117. //
  1118. // Handle an object specific Access Denied ACE
  1119. //
  1120. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) {
  1121. if ( SepSidInTokenEx( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE, Restricted ) ) {
  1122. GUID *ObjectTypeInAce;
  1123. //
  1124. // If there is no object type in the ACE,
  1125. // or if the caller didn't specify an object type list,
  1126. // apply this deny ACE to the entire object.
  1127. //
  1128. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1129. if ( ObjectTypeInAce == NULL ||
  1130. ObjectTypeListLength == 0 ) {
  1131. //
  1132. // The zeroeth element represents the object itself.
  1133. // Just check that element.
  1134. //
  1135. if (LocalTypeList->Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) {
  1136. break;
  1137. }
  1138. //
  1139. // Otherwise apply the deny ACE to the object specified
  1140. // in the ACE.
  1141. //
  1142. } else if ( SepObjectInTypeList( ObjectTypeInAce,
  1143. LocalTypeList,
  1144. LocalTypeListLength,
  1145. &Index ) ) {
  1146. if (LocalTypeList[Index].Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) {
  1147. break;
  1148. }
  1149. }
  1150. }
  1151. }
  1152. }
  1153. }
  1154. }
  1155. VOID
  1156. SeMaximumAuditMask(
  1157. IN PACL Sacl,
  1158. IN ACCESS_MASK GrantedAccess,
  1159. IN PACCESS_TOKEN Token,
  1160. OUT PACCESS_MASK pAuditMask
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. This routine takes the passed security descriptor and applies the
  1165. "MAXIMUM_ALLOWED" algorithm to the SACL contained in the security
  1166. descriptor if one exists. This mask represents all the success audits
  1167. that can occur from the passed subject context accessing the passed
  1168. security descriptor.
  1169. The code walks the SACL and for each SYSTEM_AUDIT_ACE found that
  1170. matches the passed subject context, keeps a running total of the
  1171. access bits in the ACE. The resulting mask is then masked by the
  1172. passed GrantedAccess mask, since we're only interested in the
  1173. bits that the object is actually being opened for.
  1174. Arguments:
  1175. Sacl - The Sacl to be examined.
  1176. GrantedAccess - The access that has been granted to the object.
  1177. Token - Supplies to effective token for the access attempt.
  1178. pAuditMask - Returns the mask of bits to be audited (if any).
  1179. Return Value:
  1180. None
  1181. --*/
  1182. {
  1183. USHORT AceCount = 0;
  1184. PACE_HEADER Ace = NULL;
  1185. ACCESS_MASK AccessMask = (ACCESS_MASK)0;
  1186. UCHAR AceFlags = 0;
  1187. USHORT i;
  1188. //
  1189. // Initialize OUT parameters
  1190. //
  1191. *pAuditMask = (ACCESS_MASK)0;
  1192. //
  1193. // Determine if there is an SACL in the security descriptor.
  1194. // If not, nothing to do.
  1195. //
  1196. if (0 == (AceCount = Sacl->AceCount)) {
  1197. return;
  1198. }
  1199. //
  1200. // Iterate through the ACEs on the Sacl until either we reach
  1201. // the end or discover that we have to take all possible actions,
  1202. // in which case it doesn't pay to look any further
  1203. //
  1204. for ( i = 0, Ace = FirstAce( Sacl ) ;
  1205. (i < AceCount) ;
  1206. i++, Ace = NextAce( Ace ) ) {
  1207. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  1208. if ( (((PACE_HEADER)Ace)->AceType == SYSTEM_AUDIT_ACE_TYPE) ) {
  1209. AccessMask = ((PSYSTEM_AUDIT_ACE)Ace)->Mask;
  1210. AceFlags = ((PACE_HEADER)Ace)->AceFlags;
  1211. if ((AccessMask & GrantedAccess) && (AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)) {
  1212. if ( SepSidInToken( (PACCESS_TOKEN)Token, NULL, &((PSYSTEM_AUDIT_ACE)Ace)->SidStart, FALSE ) ) {
  1213. *pAuditMask |= (AccessMask & GrantedAccess);
  1214. }
  1215. }
  1216. }
  1217. }
  1218. }
  1219. }
  1220. BOOLEAN
  1221. SepAccessCheck (
  1222. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1223. IN PSID PrincipalSelfSid,
  1224. IN PTOKEN PrimaryToken,
  1225. IN PTOKEN ClientToken OPTIONAL,
  1226. IN ACCESS_MASK DesiredAccess,
  1227. IN PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  1228. IN ULONG ObjectTypeListLength,
  1229. IN PGENERIC_MAPPING GenericMapping,
  1230. IN ACCESS_MASK PreviouslyGrantedAccess,
  1231. IN KPROCESSOR_MODE PreviousMode,
  1232. OUT PACCESS_MASK GrantedAccess,
  1233. OUT PPRIVILEGE_SET *Privileges OPTIONAL,
  1234. OUT PNTSTATUS AccessStatus,
  1235. IN BOOLEAN ReturnResultList,
  1236. OUT PBOOLEAN ReturnSomeAccessGranted,
  1237. OUT PBOOLEAN ReturnSomeAccessDenied
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. Worker routine for SeAccessCheck and NtAccessCheck. We actually do the
  1242. access checking here.
  1243. Whether or not we actually evaluate the DACL is based on the following
  1244. interaction between the SE_DACL_PRESENT bit in the security descriptor
  1245. and the value of the DACL pointer itself.
  1246. SE_DACL_PRESENT
  1247. SET CLEAR
  1248. +-------------+-------------+
  1249. | | |
  1250. NULL | GRANT | GRANT |
  1251. | ALL | ALL |
  1252. DACL | | |
  1253. Pointer +-------------+-------------+
  1254. | | |
  1255. !NULL | EVALUATE | GRANT |
  1256. | ACL | ALL |
  1257. | | |
  1258. +-------------+-------------+
  1259. Arguments:
  1260. SecurityDescriptor - Pointer to the security descriptor from the object
  1261. being accessed.
  1262. PrincipalSelfSid - If the object being access checked is an object which
  1263. represents a principal (e.g., a user object), this parameter should
  1264. be the SID of the object. Any ACE containing the constant
  1265. PRINCIPAL_SELF_SID is replaced by this SID.
  1266. The parameter should be NULL if the object does not represent a principal.
  1267. Token - Pointer to user's token object.
  1268. TokenLocked - Boolean describing whether or not there is a read lock
  1269. on the token.
  1270. DesiredAccess - Access mask describing the user's desired access to the
  1271. object. This mask is assumed not to contain generic access types.
  1272. ObjectTypeList - Supplies a list of GUIDs representing the object (and
  1273. sub-objects) being accessed. If no list is present, AccessCheckByType
  1274. behaves identically to AccessCheck.
  1275. ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
  1276. GenericMapping - Supplies a pointer to the generic mapping associated
  1277. with this object type.
  1278. PreviouslyGrantedAccess - Access mask indicating any access' that have
  1279. already been granted by higher level routines
  1280. PrivilgedAccessMask - Mask describing access types that may not be
  1281. granted without a privilege.
  1282. GrantedAccess - Returns an access mask describing all granted access',
  1283. or NULL.
  1284. Privileges - Optionally supplies a pointer in which will be returned
  1285. any privileges that were used for the access. If this is null,
  1286. it will be assumed that privilege checks have been done already.
  1287. AccessStatus - Returns STATUS_SUCCESS or other error code to be
  1288. propogated back to the caller
  1289. ReturnResultList - If true, GrantedAccess and AccessStatus is actually
  1290. an array of entries ObjectTypeListLength elements long.
  1291. ReturnSomeAccessGranted - Returns a value of TRUE to indicate that some access'
  1292. were granted, FALSE otherwise.
  1293. ReturnSomeAccessDenied - Returns a value of FALSE if some of the requested
  1294. access was not granted. This will alway be an inverse of SomeAccessGranted
  1295. unless ReturnResultList is TRUE. In that case,
  1296. Return Value:
  1297. A value of TRUE indicates that some access' were granted, FALSE
  1298. otherwise.
  1299. --*/
  1300. {
  1301. NTSTATUS Status;
  1302. ACCESS_MASK Remaining;
  1303. BOOLEAN RetVal = TRUE;
  1304. PACL Dacl;
  1305. PVOID Ace;
  1306. ULONG AceCount;
  1307. ULONG i;
  1308. ULONG j;
  1309. ULONG Index;
  1310. ULONG PrivilegeCount = 0;
  1311. BOOLEAN Success = FALSE;
  1312. BOOLEAN SystemSecurity = FALSE;
  1313. BOOLEAN WriteOwner = FALSE;
  1314. PTOKEN EToken;
  1315. IOBJECT_TYPE_LIST FixedTypeList;
  1316. PIOBJECT_TYPE_LIST LocalTypeList;
  1317. ULONG LocalTypeListLength;
  1318. ULONG ResultListIndex;
  1319. PAGED_CODE();
  1320. #if DBG
  1321. SepDumpSecurityDescriptor(
  1322. SecurityDescriptor,
  1323. "Input to SeAccessCheck\n"
  1324. );
  1325. if (ARGUMENT_PRESENT( ClientToken )) {
  1326. SepDumpTokenInfo( ClientToken );
  1327. }
  1328. SepDumpTokenInfo( PrimaryToken );
  1329. #endif
  1330. EToken = ARGUMENT_PRESENT( ClientToken ) ? ClientToken : PrimaryToken;
  1331. //
  1332. // Assert that there are no generic accesses in the DesiredAccess
  1333. //
  1334. SeAssertMappedCanonicalAccess( DesiredAccess );
  1335. Remaining = DesiredAccess;
  1336. //
  1337. // Check for ACCESS_SYSTEM_SECURITY here,
  1338. // fail if he's asking for it and doesn't have
  1339. // the privilege.
  1340. //
  1341. if ( Remaining & ACCESS_SYSTEM_SECURITY ) {
  1342. //
  1343. // Bugcheck if we weren't given a pointer to return privileges
  1344. // into. Our caller was supposed to have taken care of this
  1345. // in that case.
  1346. //
  1347. ASSERT( ARGUMENT_PRESENT( Privileges ));
  1348. Success = SepSinglePrivilegeCheck (
  1349. SeSecurityPrivilege,
  1350. EToken,
  1351. PreviousMode
  1352. );
  1353. if (!Success) {
  1354. PreviouslyGrantedAccess = 0;
  1355. Status = STATUS_PRIVILEGE_NOT_HELD;
  1356. goto ReturnOneStatus;
  1357. }
  1358. //
  1359. // Success, remove ACCESS_SYSTEM_SECURITY from remaining, add it
  1360. // to PreviouslyGrantedAccess
  1361. //
  1362. Remaining &= ~ACCESS_SYSTEM_SECURITY;
  1363. PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
  1364. PrivilegeCount++;
  1365. SystemSecurity = TRUE;
  1366. if ( Remaining == 0 ) {
  1367. Status = STATUS_SUCCESS;
  1368. goto ReturnOneStatus;
  1369. }
  1370. }
  1371. //
  1372. // Get pointer to client SID's
  1373. //
  1374. Dacl = RtlpDaclAddrSecurityDescriptor( (PISECURITY_DESCRIPTOR)SecurityDescriptor );
  1375. //
  1376. // If the SE_DACL_PRESENT bit is not set, the object has no
  1377. // security, so all accesses are granted. If he's asking for
  1378. // MAXIMUM_ALLOWED, return the GENERIC_ALL field from the generic
  1379. // mapping.
  1380. //
  1381. // Also grant all access if the Dacl is NULL.
  1382. //
  1383. if ( !RtlpAreControlBitsSet(
  1384. (PISECURITY_DESCRIPTOR)SecurityDescriptor,
  1385. SE_DACL_PRESENT) || (Dacl == NULL)) {
  1386. //
  1387. // Restricted tokens treat a NULL dacl the same as a DACL with no
  1388. // ACEs.
  1389. //
  1390. #ifdef SECURE_NULL_DACLS
  1391. if (SeTokenIsRestricted( EToken )) {
  1392. //
  1393. // We know that Remaining != 0 here, because we
  1394. // know it was non-zero coming into this routine,
  1395. // and we've checked it against 0 every time we've
  1396. // cleared a bit.
  1397. //
  1398. ASSERT( Remaining != 0 );
  1399. //
  1400. // There are ungranted accesses. Since there is
  1401. // nothing in the DACL, they will not be granted.
  1402. // If, however, the only ungranted access at this
  1403. // point is MAXIMUM_ALLOWED, and something has been
  1404. // granted in the PreviouslyGranted mask, return
  1405. // what has been granted.
  1406. //
  1407. if ( (Remaining == MAXIMUM_ALLOWED) && (PreviouslyGrantedAccess != (ACCESS_MASK)0) ) {
  1408. Status = STATUS_SUCCESS;
  1409. goto ReturnOneStatus;
  1410. } else {
  1411. PreviouslyGrantedAccess = 0;
  1412. Status = STATUS_ACCESS_DENIED;
  1413. goto ReturnOneStatus;
  1414. }
  1415. }
  1416. #endif //SECURE_NULL_DACLS
  1417. if (DesiredAccess & MAXIMUM_ALLOWED) {
  1418. //
  1419. // Give him:
  1420. // GenericAll
  1421. // Anything else he asked for
  1422. //
  1423. PreviouslyGrantedAccess =
  1424. GenericMapping->GenericAll |
  1425. (DesiredAccess | PreviouslyGrantedAccess) & ~MAXIMUM_ALLOWED;
  1426. } else {
  1427. PreviouslyGrantedAccess |= DesiredAccess;
  1428. }
  1429. Status = STATUS_SUCCESS;
  1430. goto ReturnOneStatus;
  1431. }
  1432. //
  1433. // There is security on this object. Check to see
  1434. // if he's asking for WRITE_OWNER, and perform the
  1435. // privilege check if so.
  1436. //
  1437. if ( (Remaining & WRITE_OWNER) && ARGUMENT_PRESENT( Privileges ) ) {
  1438. Success = SepSinglePrivilegeCheck (
  1439. SeTakeOwnershipPrivilege,
  1440. EToken,
  1441. PreviousMode
  1442. );
  1443. if (Success) {
  1444. //
  1445. // Success, remove WRITE_OWNER from remaining, add it
  1446. // to PreviouslyGrantedAccess
  1447. //
  1448. Remaining &= ~WRITE_OWNER;
  1449. PreviouslyGrantedAccess |= WRITE_OWNER;
  1450. PrivilegeCount++;
  1451. WriteOwner = TRUE;
  1452. if ( Remaining == 0 ) {
  1453. Status = STATUS_SUCCESS;
  1454. goto ReturnOneStatus;
  1455. }
  1456. }
  1457. }
  1458. //
  1459. // If the DACL is empty,
  1460. // deny all access immediately.
  1461. //
  1462. if ((AceCount = Dacl->AceCount) == 0) {
  1463. //
  1464. // We know that Remaining != 0 here, because we
  1465. // know it was non-zero coming into this routine,
  1466. // and we've checked it against 0 every time we've
  1467. // cleared a bit.
  1468. //
  1469. ASSERT( Remaining != 0 );
  1470. //
  1471. // There are ungranted accesses. Since there is
  1472. // nothing in the DACL, they will not be granted.
  1473. // If, however, the only ungranted access at this
  1474. // point is MAXIMUM_ALLOWED, and something has been
  1475. // granted in the PreviouslyGranted mask, return
  1476. // what has been granted.
  1477. //
  1478. if ( (Remaining == MAXIMUM_ALLOWED) && (PreviouslyGrantedAccess != (ACCESS_MASK)0) ) {
  1479. Status = STATUS_SUCCESS;
  1480. goto ReturnOneStatus;
  1481. } else {
  1482. PreviouslyGrantedAccess = 0;
  1483. Status = STATUS_ACCESS_DENIED;
  1484. goto ReturnOneStatus;
  1485. }
  1486. }
  1487. //
  1488. // Fake out a top level ObjectType list if none is passed by the caller.
  1489. //
  1490. if ( ObjectTypeListLength == 0 ) {
  1491. LocalTypeList = &FixedTypeList;
  1492. LocalTypeListLength = 1;
  1493. RtlZeroMemory( &FixedTypeList, sizeof(FixedTypeList) );
  1494. FixedTypeList.ParentIndex = -1;
  1495. } else {
  1496. LocalTypeList = ObjectTypeList;
  1497. LocalTypeListLength = ObjectTypeListLength;
  1498. }
  1499. //
  1500. // If the caller wants the MAXIMUM_ALLOWED or the caller wants the
  1501. // results on all objects and subobjects, use a slower algorithm
  1502. // that traverses all the ACEs.
  1503. //
  1504. if ( (DesiredAccess & MAXIMUM_ALLOWED) != 0 ||
  1505. ReturnResultList ) {
  1506. //
  1507. // Do the normal maximum-allowed access check
  1508. //
  1509. SepMaximumAccessCheck(
  1510. EToken,
  1511. PrimaryToken,
  1512. Dacl,
  1513. PrincipalSelfSid,
  1514. LocalTypeListLength,
  1515. LocalTypeList,
  1516. ObjectTypeListLength,
  1517. FALSE
  1518. );
  1519. //
  1520. // If this is a restricted token, do the additional access check
  1521. //
  1522. if (SeTokenIsRestricted( EToken ) ) {
  1523. SepMaximumAccessCheck(
  1524. EToken,
  1525. PrimaryToken,
  1526. Dacl,
  1527. PrincipalSelfSid,
  1528. LocalTypeListLength,
  1529. LocalTypeList,
  1530. ObjectTypeListLength,
  1531. TRUE
  1532. );
  1533. }
  1534. //
  1535. // If the caller wants to know the individual results of each sub-object,
  1536. // sub-object,
  1537. // break it down for him.
  1538. //
  1539. if ( ReturnResultList ) {
  1540. ACCESS_MASK GrantedAccessMask;
  1541. ACCESS_MASK RequiredAccessMask;
  1542. BOOLEAN SomeAccessGranted = FALSE;
  1543. BOOLEAN SomeAccessDenied = FALSE;
  1544. //
  1545. // Compute mask of Granted access bits to tell the caller about.
  1546. // If he asked for MAXIMUM_ALLOWED,
  1547. // tell him everything,
  1548. // otherwise
  1549. // tell him what he asked about.
  1550. //
  1551. if (DesiredAccess & MAXIMUM_ALLOWED) {
  1552. GrantedAccessMask = (ACCESS_MASK) ~MAXIMUM_ALLOWED;
  1553. RequiredAccessMask = (DesiredAccess | PreviouslyGrantedAccess) & ~MAXIMUM_ALLOWED;
  1554. } else {
  1555. GrantedAccessMask = DesiredAccess | PreviouslyGrantedAccess;
  1556. RequiredAccessMask = DesiredAccess | PreviouslyGrantedAccess;
  1557. }
  1558. //
  1559. // Loop computing the access granted to each object and sub-object.
  1560. //
  1561. for ( ResultListIndex=0;
  1562. ResultListIndex<LocalTypeListLength;
  1563. ResultListIndex++ ) {
  1564. //
  1565. // Return the subset of the access granted that the caller
  1566. // expressed interest in.
  1567. //
  1568. GrantedAccess[ResultListIndex] =
  1569. (LocalTypeList[ResultListIndex].CurrentGranted |
  1570. PreviouslyGrantedAccess ) &
  1571. GrantedAccessMask;
  1572. //
  1573. // If absolutely no access was granted,
  1574. // indicate so.
  1575. //
  1576. if ( GrantedAccess[ResultListIndex] == 0 ) {
  1577. AccessStatus[ResultListIndex] = STATUS_ACCESS_DENIED;
  1578. SomeAccessDenied = TRUE;
  1579. } else {
  1580. //
  1581. // If some requested access is still missing,
  1582. // the bottom line is that access is denied.
  1583. //
  1584. // Note, that ByTypeResultList actually returns the
  1585. // partially granted access mask even though the caller
  1586. // really has no access to the object.
  1587. //
  1588. if ( ((~GrantedAccess[ResultListIndex]) & RequiredAccessMask ) != 0 ) {
  1589. AccessStatus[ResultListIndex] = STATUS_ACCESS_DENIED;
  1590. SomeAccessDenied = TRUE;
  1591. } else {
  1592. AccessStatus[ResultListIndex] = STATUS_SUCCESS;
  1593. SomeAccessGranted = TRUE;
  1594. }
  1595. }
  1596. }
  1597. if ( SomeAccessGranted && PrivilegeCount != 0 ) {
  1598. SepAssemblePrivileges(
  1599. PrivilegeCount,
  1600. SystemSecurity,
  1601. WriteOwner,
  1602. Privileges
  1603. );
  1604. if ( ( Privileges != NULL ) && ( *Privileges == NULL ) ) {
  1605. RetVal = FALSE;
  1606. SomeAccessGranted = FALSE;
  1607. SomeAccessDenied = TRUE;
  1608. for ( ResultListIndex=0;
  1609. ResultListIndex<LocalTypeListLength;
  1610. ResultListIndex++ ) {
  1611. AccessStatus[ResultListIndex] = STATUS_NO_MEMORY;
  1612. GrantedAccess[ResultListIndex] = 0;
  1613. }
  1614. }
  1615. }
  1616. if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) {
  1617. *ReturnSomeAccessGranted = SomeAccessGranted;
  1618. }
  1619. if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) {
  1620. *ReturnSomeAccessDenied = SomeAccessDenied;
  1621. }
  1622. return RetVal;
  1623. //
  1624. // If the caller is only interested in the access to the object itself,
  1625. // just summarize.
  1626. //
  1627. } else {
  1628. //
  1629. // Turn off the MAXIMUM_ALLOWED bit and whatever we found that
  1630. // he was granted. If the user passed in extra bits in addition
  1631. // to MAXIMUM_ALLOWED, make sure that he was granted those access
  1632. // types. If not, he didn't get what he wanted, so return failure.
  1633. //
  1634. Remaining &= ~(MAXIMUM_ALLOWED | LocalTypeList->CurrentGranted);
  1635. if (Remaining != 0) {
  1636. Status = STATUS_ACCESS_DENIED;
  1637. PreviouslyGrantedAccess = 0;
  1638. goto ReturnOneStatus;
  1639. }
  1640. PreviouslyGrantedAccess |= LocalTypeList->CurrentGranted;
  1641. Status = STATUS_SUCCESS;
  1642. goto ReturnOneStatus;
  1643. }
  1644. } // if MAXIMUM_ALLOWED...
  1645. #ifdef notdef
  1646. //
  1647. // The remaining bits are "remaining" at all levels
  1648. for ( j=0; j<LocalTypeListLength; j++ ) {
  1649. LocalTypeList[j].Remaining = Remaining;
  1650. }
  1651. //
  1652. // Process the DACL handling individual access bits.
  1653. //
  1654. for ( i = 0, Ace = FirstAce( Dacl ) ;
  1655. ( i < AceCount ) && ( LocalTypeList->Remaining != 0 ) ;
  1656. i++, Ace = NextAce( Ace ) ) {
  1657. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  1658. //
  1659. // Handle an Access Allowed ACE
  1660. //
  1661. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) {
  1662. if ( SepSidInToken( EToken, PrincipalSelfSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart, FALSE ) ) {
  1663. // Optimize 'normal' case
  1664. if ( LocalTypeListLength == 1 ) {
  1665. LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask;
  1666. } else {
  1667. //
  1668. // The zeroeth object type represents the object itself.
  1669. //
  1670. SepAddAccessTypeList(
  1671. LocalTypeList, // List to modify
  1672. LocalTypeListLength, // Length of list
  1673. 0, // Element to update
  1674. ((PACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  1675. UpdateRemaining );
  1676. }
  1677. }
  1678. //
  1679. // Handle an object specific Access Allowed ACE
  1680. //
  1681. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) {
  1682. GUID *ObjectTypeInAce;
  1683. //
  1684. // If no object type is in the ACE,
  1685. // treat this as an ACCESS_ALLOWED_ACE.
  1686. //
  1687. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1688. if ( ObjectTypeInAce == NULL ) {
  1689. if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE ) ) {
  1690. // Optimize 'normal' case
  1691. if ( LocalTypeListLength == 1 ) {
  1692. LocalTypeList->Remaining &= ~((PACCESS_ALLOWED_ACE)Ace)->Mask;
  1693. } else {
  1694. SepAddAccessTypeList(
  1695. LocalTypeList, // List to modify
  1696. LocalTypeListLength, // Length of list
  1697. 0, // Element to update
  1698. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  1699. UpdateRemaining );
  1700. }
  1701. }
  1702. //
  1703. // If no object type list was passed,
  1704. // don't grant access to anyone.
  1705. //
  1706. } else if ( ObjectTypeListLength == 0 ) {
  1707. // Drop through
  1708. //
  1709. // If an object type is in the ACE,
  1710. // Find it in the LocalTypeList before using the ACE.
  1711. //
  1712. } else {
  1713. if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), FALSE ) ) {
  1714. if ( SepObjectInTypeList( ObjectTypeInAce,
  1715. LocalTypeList,
  1716. LocalTypeListLength,
  1717. &Index ) ) {
  1718. SepAddAccessTypeList(
  1719. LocalTypeList, // List to modify
  1720. LocalTypeListLength, // Length of list
  1721. Index, // Element already updated
  1722. ((PACCESS_ALLOWED_OBJECT_ACE)Ace)->Mask, // Access Granted
  1723. UpdateRemaining );
  1724. }
  1725. }
  1726. }
  1727. //
  1728. // Handle a compound Access Allowed ACE
  1729. //
  1730. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) {
  1731. //
  1732. // See comment in MAXIMUM_ALLOWED case as to why we can use EToken here
  1733. // for the client.
  1734. //
  1735. if ( SepSidInToken(EToken, PrincipalSelfSid, RtlCompoundAceClientSid( Ace ), FALSE) &&
  1736. SepSidInToken(PrimaryToken, NULL, RtlCompoundAceServerSid( Ace ), FALSE) ) {
  1737. // Optimize 'normal' case
  1738. if ( LocalTypeListLength == 1 ) {
  1739. LocalTypeList->Remaining &= ~((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask;
  1740. } else {
  1741. SepAddAccessTypeList(
  1742. LocalTypeList, // List to modify
  1743. LocalTypeListLength, // Length of list
  1744. 0, // Element to update
  1745. ((PCOMPOUND_ACCESS_ALLOWED_ACE)Ace)->Mask, // Access Granted
  1746. UpdateRemaining );
  1747. }
  1748. }
  1749. //
  1750. // Handle an Access Denied ACE
  1751. //
  1752. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) {
  1753. if ( SepSidInToken( EToken, PrincipalSelfSid, &((PACCESS_DENIED_ACE)Ace)->SidStart, TRUE ) ) {
  1754. //
  1755. // The zeroeth element represents the object itself.
  1756. // Just check that element.
  1757. //
  1758. if (LocalTypeList->Remaining & ((PACCESS_DENIED_ACE)Ace)->Mask) {
  1759. break;
  1760. }
  1761. }
  1762. //
  1763. // Handle an object specific Access Denied ACE
  1764. //
  1765. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) {
  1766. if ( SepSidInToken( EToken, PrincipalSelfSid, RtlObjectAceSid(Ace), TRUE ) ) {
  1767. GUID *ObjectTypeInAce;
  1768. //
  1769. // If there is no object type in the ACE,
  1770. // or if the caller didn't specify an object type list,
  1771. // apply this deny ACE to the entire object.
  1772. //
  1773. ObjectTypeInAce = RtlObjectAceObjectType(Ace);
  1774. if ( ObjectTypeInAce == NULL ||
  1775. ObjectTypeListLength == 0 ) {
  1776. //
  1777. // The zeroeth element represents the object itself.
  1778. // Just check that element.
  1779. //
  1780. if (LocalTypeList->Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) {
  1781. break;
  1782. }
  1783. //
  1784. // Otherwise apply the deny ACE to the object specified
  1785. // in the ACE.
  1786. //
  1787. } else if ( SepObjectInTypeList( ObjectTypeInAce,
  1788. LocalTypeList,
  1789. LocalTypeListLength,
  1790. &Index ) ) {
  1791. if (LocalTypeList[Index].Remaining & ((PACCESS_DENIED_OBJECT_ACE)Ace)->Mask) {
  1792. break;
  1793. }
  1794. }
  1795. }
  1796. }
  1797. }
  1798. }
  1799. #endif
  1800. //
  1801. // Do the normal access check first
  1802. //
  1803. SepNormalAccessCheck(
  1804. Remaining,
  1805. EToken,
  1806. PrimaryToken,
  1807. Dacl,
  1808. PrincipalSelfSid,
  1809. LocalTypeListLength,
  1810. LocalTypeList,
  1811. ObjectTypeListLength,
  1812. FALSE
  1813. );
  1814. if (LocalTypeList->Remaining != 0) {
  1815. Status = STATUS_ACCESS_DENIED;
  1816. PreviouslyGrantedAccess = 0;
  1817. goto ReturnOneStatus;
  1818. }
  1819. //
  1820. // If this is a restricted token, do the additional access check
  1821. //
  1822. if (SeTokenIsRestricted( EToken ) ) {
  1823. SepNormalAccessCheck(
  1824. Remaining,
  1825. EToken,
  1826. PrimaryToken,
  1827. Dacl,
  1828. PrincipalSelfSid,
  1829. LocalTypeListLength,
  1830. LocalTypeList,
  1831. ObjectTypeListLength,
  1832. TRUE
  1833. );
  1834. }
  1835. if (LocalTypeList->Remaining != 0) {
  1836. Status = STATUS_ACCESS_DENIED;
  1837. PreviouslyGrantedAccess = 0;
  1838. goto ReturnOneStatus;
  1839. }
  1840. Status = STATUS_SUCCESS;
  1841. PreviouslyGrantedAccess |= DesiredAccess;
  1842. //
  1843. // Return a single status code to the caller.
  1844. //
  1845. ReturnOneStatus:
  1846. if ( Status == STATUS_SUCCESS && PreviouslyGrantedAccess == 0 ) {
  1847. Status = STATUS_ACCESS_DENIED;
  1848. }
  1849. if ( NT_SUCCESS(Status) ) {
  1850. if ( PrivilegeCount > 0 ) {
  1851. SepAssemblePrivileges(
  1852. PrivilegeCount,
  1853. SystemSecurity,
  1854. WriteOwner,
  1855. Privileges
  1856. );
  1857. if ( ( Privileges != NULL ) && ( *Privileges == NULL ) ) {
  1858. RetVal = FALSE;
  1859. Status = STATUS_NO_MEMORY;
  1860. PreviouslyGrantedAccess = 0;
  1861. }
  1862. }
  1863. }
  1864. //
  1865. // If the caller asked for a list of status',
  1866. // duplicate the status all over.
  1867. //
  1868. if ( ReturnResultList ) {
  1869. for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) {
  1870. AccessStatus[ResultListIndex] = Status;
  1871. GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess;
  1872. }
  1873. } else {
  1874. *AccessStatus = Status;
  1875. *GrantedAccess = PreviouslyGrantedAccess;
  1876. }
  1877. if ( NT_SUCCESS(Status) ) {
  1878. if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) {
  1879. *ReturnSomeAccessGranted = TRUE;
  1880. }
  1881. if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) {
  1882. *ReturnSomeAccessDenied = FALSE;
  1883. }
  1884. } else {
  1885. if ( ARGUMENT_PRESENT(ReturnSomeAccessGranted)) {
  1886. *ReturnSomeAccessGranted = FALSE;
  1887. }
  1888. if ( ARGUMENT_PRESENT(ReturnSomeAccessDenied)) {
  1889. *ReturnSomeAccessDenied = TRUE;
  1890. }
  1891. }
  1892. return RetVal;
  1893. }
  1894. NTSTATUS
  1895. NtAccessCheck (
  1896. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1897. IN HANDLE ClientToken,
  1898. IN ACCESS_MASK DesiredAccess,
  1899. IN PGENERIC_MAPPING GenericMapping,
  1900. OUT PPRIVILEGE_SET PrivilegeSet,
  1901. IN OUT PULONG PrivilegeSetLength,
  1902. OUT PACCESS_MASK GrantedAccess,
  1903. OUT PNTSTATUS AccessStatus
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. See module abstract.
  1908. Arguments:
  1909. SecurityDescriptor - Supplies the security descriptor protecting the object
  1910. being accessed
  1911. ClientToken - Supplies the handle of the user's token.
  1912. DesiredAccess - Supplies the desired access mask.
  1913. GenericMapping - Supplies the generic mapping associated with this
  1914. object type.
  1915. PrivilegeSet - A pointer to a buffer that upon return will contain
  1916. any privileges that were used to perform the access validation.
  1917. If no privileges were used, the buffer will contain a privilege
  1918. set consisting of zero privileges.
  1919. PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes.
  1920. GrantedAccess - Returns an access mask describing the granted access.
  1921. AccessStatus - Status value that may be returned indicating the
  1922. reason why access was denied. Routines should avoid hardcoding a
  1923. return value of STATUS_ACCESS_DENIED so that a different value can
  1924. be returned when mandatory access control is implemented.
  1925. Return Value:
  1926. STATUS_SUCCESS - The attempt proceeded normally. This does not
  1927. mean access was granted, rather that the parameters were
  1928. correct.
  1929. STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained
  1930. an unmapped generic access.
  1931. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  1932. to contain the information being returned.
  1933. STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation
  1934. token.
  1935. --*/
  1936. {
  1937. PAGED_CODE();
  1938. return SeAccessCheckByType (
  1939. SecurityDescriptor,
  1940. NULL, // No Principal Self sid
  1941. ClientToken,
  1942. DesiredAccess,
  1943. NULL, // No ObjectType List
  1944. 0, // No ObjectType List
  1945. GenericMapping,
  1946. PrivilegeSet,
  1947. PrivilegeSetLength,
  1948. GrantedAccess,
  1949. AccessStatus,
  1950. FALSE ); // Return a single GrantedAccess and AccessStatus
  1951. }
  1952. NTSTATUS
  1953. NtAccessCheckByType (
  1954. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1955. IN PSID PrincipalSelfSid,
  1956. IN HANDLE ClientToken,
  1957. IN ACCESS_MASK DesiredAccess,
  1958. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  1959. IN ULONG ObjectTypeListLength,
  1960. IN PGENERIC_MAPPING GenericMapping,
  1961. OUT PPRIVILEGE_SET PrivilegeSet,
  1962. IN OUT PULONG PrivilegeSetLength,
  1963. OUT PACCESS_MASK GrantedAccess,
  1964. OUT PNTSTATUS AccessStatus
  1965. )
  1966. /*++
  1967. Routine Description:
  1968. See module abstract.
  1969. Arguments:
  1970. SecurityDescriptor - Supplies the security descriptor protecting the object
  1971. being accessed
  1972. PrincipalSelfSid - If the object being access checked is an object which
  1973. represents a principal (e.g., a user object), this parameter should
  1974. be the SID of the object. Any ACE containing the constant
  1975. PRINCIPAL_SELF_SID is replaced by this SID.
  1976. The parameter should be NULL if the object does not represent a principal.
  1977. ClientToken - Supplies the handle of the user's token.
  1978. DesiredAccess - Supplies the desired access mask.
  1979. ObjectTypeList - Supplies a list of GUIDs representing the object (and
  1980. sub-objects) being accessed. If no list is present, AccessCheckByType
  1981. behaves identically to AccessCheck.
  1982. ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
  1983. GenericMapping - Supplies the generic mapping associated with this
  1984. object type.
  1985. PrivilegeSet - A pointer to a buffer that upon return will contain
  1986. any privileges that were used to perform the access validation.
  1987. If no privileges were used, the buffer will contain a privilege
  1988. set consisting of zero privileges.
  1989. PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes.
  1990. GrantedAccess - Returns an access mask describing the granted access.
  1991. AccessStatus - Status value that may be returned indicating the
  1992. reason why access was denied. Routines should avoid hardcoding a
  1993. return value of STATUS_ACCESS_DENIED so that a different value can
  1994. be returned when mandatory access control is implemented.
  1995. Return Value:
  1996. STATUS_SUCCESS - The attempt proceeded normally. This does not
  1997. mean access was granted, rather that the parameters were
  1998. correct.
  1999. STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained
  2000. an unmapped generic access.
  2001. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  2002. to contain the information being returned.
  2003. STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation
  2004. token.
  2005. --*/
  2006. {
  2007. PAGED_CODE();
  2008. return SeAccessCheckByType (
  2009. SecurityDescriptor,
  2010. PrincipalSelfSid,
  2011. ClientToken,
  2012. DesiredAccess,
  2013. ObjectTypeList,
  2014. ObjectTypeListLength,
  2015. GenericMapping,
  2016. PrivilegeSet,
  2017. PrivilegeSetLength,
  2018. GrantedAccess,
  2019. AccessStatus,
  2020. FALSE ); // Return a single GrantedAccess and AccessStatus
  2021. }
  2022. NTSTATUS
  2023. NtAccessCheckByTypeResultList (
  2024. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2025. IN PSID PrincipalSelfSid,
  2026. IN HANDLE ClientToken,
  2027. IN ACCESS_MASK DesiredAccess,
  2028. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  2029. IN ULONG ObjectTypeListLength,
  2030. IN PGENERIC_MAPPING GenericMapping,
  2031. OUT PPRIVILEGE_SET PrivilegeSet,
  2032. IN OUT PULONG PrivilegeSetLength,
  2033. OUT PACCESS_MASK GrantedAccess,
  2034. OUT PNTSTATUS AccessStatus
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. See module abstract.
  2039. Arguments:
  2040. SecurityDescriptor - Supplies the security descriptor protecting the object
  2041. being accessed
  2042. PrincipalSelfSid - If the object being access checked is an object which
  2043. represents a principal (e.g., a user object), this parameter should
  2044. be the SID of the object. Any ACE containing the constant
  2045. PRINCIPAL_SELF_SID is replaced by this SID.
  2046. The parameter should be NULL if the object does not represent a principal.
  2047. ClientToken - Supplies the handle of the user's token.
  2048. DesiredAccess - Supplies the desired access mask.
  2049. ObjectTypeList - Supplies a list of GUIDs representing the object (and
  2050. sub-objects) being accessed. If no list is present, AccessCheckByType
  2051. behaves identically to AccessCheck.
  2052. ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
  2053. GenericMapping - Supplies the generic mapping associated with this
  2054. object type.
  2055. PrivilegeSet - A pointer to a buffer that upon return will contain
  2056. any privileges that were used to perform the access validation.
  2057. If no privileges were used, the buffer will contain a privilege
  2058. set consisting of zero privileges.
  2059. PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes.
  2060. GrantedAccess - Returns an access mask describing the granted access.
  2061. AccessStatus - Status value that may be returned indicating the
  2062. reason why access was denied. Routines should avoid hardcoding a
  2063. return value of STATUS_ACCESS_DENIED so that a different value can
  2064. be returned when mandatory access control is implemented.
  2065. Return Value:
  2066. STATUS_SUCCESS - The attempt proceeded normally. This does not
  2067. mean access was granted, rather that the parameters were
  2068. correct.
  2069. STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained
  2070. an unmapped generic access.
  2071. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  2072. to contain the information being returned.
  2073. STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation
  2074. token.
  2075. --*/
  2076. {
  2077. PAGED_CODE();
  2078. return SeAccessCheckByType (
  2079. SecurityDescriptor,
  2080. PrincipalSelfSid,
  2081. ClientToken,
  2082. DesiredAccess,
  2083. ObjectTypeList,
  2084. ObjectTypeListLength,
  2085. GenericMapping,
  2086. PrivilegeSet,
  2087. PrivilegeSetLength,
  2088. GrantedAccess,
  2089. AccessStatus,
  2090. TRUE ); // Return an array of GrantedAccess and AccessStatus
  2091. }
  2092. NTSTATUS
  2093. SeAccessCheckByType (
  2094. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2095. IN PSID PrincipalSelfSid,
  2096. IN HANDLE ClientToken,
  2097. IN ACCESS_MASK DesiredAccess,
  2098. IN POBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  2099. IN ULONG ObjectTypeListLength,
  2100. IN PGENERIC_MAPPING GenericMapping,
  2101. OUT PPRIVILEGE_SET PrivilegeSet,
  2102. IN OUT PULONG PrivilegeSetLength,
  2103. OUT PACCESS_MASK GrantedAccess,
  2104. OUT PNTSTATUS AccessStatus,
  2105. IN BOOLEAN ReturnResultList
  2106. )
  2107. /*++
  2108. Routine Description:
  2109. See module abstract.
  2110. Arguments:
  2111. SecurityDescriptor - Supplies the security descriptor protecting the object
  2112. being accessed
  2113. PrincipalSelfSid - If the object being access checked is an object which
  2114. represents a principal (e.g., a user object), this parameter should
  2115. be the SID of the object. Any ACE containing the constant
  2116. PRINCIPAL_SELF_SID is replaced by this SID.
  2117. The parameter should be NULL if the object does not represent a principal.
  2118. ClientToken - Supplies the handle of the user's token.
  2119. DesiredAccess - Supplies the desired access mask.
  2120. ObjectTypeList - Supplies a list of GUIDs representing the object (and
  2121. sub-objects) being accessed. If no list is present, AccessCheckByType
  2122. behaves identically to AccessCheck.
  2123. ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.
  2124. GenericMapping - Supplies the generic mapping associated with this
  2125. object type.
  2126. PrivilegeSet - A pointer to a buffer that upon return will contain
  2127. any privileges that were used to perform the access validation.
  2128. If no privileges were used, the buffer will contain a privilege
  2129. set consisting of zero privileges.
  2130. PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes.
  2131. GrantedAccess - Returns an access mask describing the granted access.
  2132. AccessStatus - Status value that may be returned indicating the
  2133. reason why access was denied. Routines should avoid hardcoding a
  2134. return value of STATUS_ACCESS_DENIED so that a different value can
  2135. be returned when mandatory access control is implemented.
  2136. ReturnResultList - If true, GrantedAccess and AccessStatus are actually
  2137. arrays of entries ObjectTypeListLength elements long.
  2138. Return Value:
  2139. STATUS_SUCCESS - The attempt proceeded normally. This does not
  2140. mean access was granted, rather that the parameters were
  2141. correct.
  2142. STATUS_GENERIC_NOT_MAPPED - The DesiredAccess mask contained
  2143. an unmapped generic access.
  2144. STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
  2145. to contain the information being returned.
  2146. STATUS_NO_IMPERSONTAION_TOKEN - The passed Token was not an impersonation
  2147. token.
  2148. --*/
  2149. {
  2150. ACCESS_MASK LocalGrantedAccess;
  2151. PACCESS_MASK LocalGrantedAccessPointer = NULL;
  2152. NTSTATUS LocalAccessStatus;
  2153. PNTSTATUS LocalAccessStatusPointer = NULL;
  2154. KPROCESSOR_MODE PreviousMode;
  2155. NTSTATUS Status = STATUS_SUCCESS;
  2156. PTOKEN Token = NULL;
  2157. PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
  2158. PSID CapturedPrincipalSelfSid = NULL;
  2159. ACCESS_MASK PreviouslyGrantedAccess = 0;
  2160. GENERIC_MAPPING LocalGenericMapping;
  2161. PIOBJECT_TYPE_LIST LocalObjectTypeList = NULL;
  2162. PPRIVILEGE_SET Privileges = NULL;
  2163. SECURITY_SUBJECT_CONTEXT SubjectContext;
  2164. ULONG LocalPrivilegeSetLength = 0;
  2165. ULONG ResultListIndex = 0;
  2166. PAGED_CODE();
  2167. PreviousMode = KeGetPreviousMode();
  2168. if (PreviousMode == KernelMode) {
  2169. ASSERT( !ReturnResultList );
  2170. *AccessStatus = STATUS_SUCCESS;
  2171. *GrantedAccess = DesiredAccess;
  2172. return(STATUS_SUCCESS);
  2173. }
  2174. try {
  2175. if ( ReturnResultList ) {
  2176. if ( ObjectTypeListLength == 0 ) {
  2177. Status = STATUS_INVALID_PARAMETER;
  2178. leave ;
  2179. }
  2180. if ( !IsValidElementCount( ObjectTypeListLength, OBJECT_TYPE_LIST ) )
  2181. {
  2182. Status = STATUS_INVALID_PARAMETER ;
  2183. leave ;
  2184. }
  2185. ProbeForWrite(
  2186. AccessStatus,
  2187. sizeof(NTSTATUS) * ObjectTypeListLength,
  2188. sizeof(ULONG)
  2189. );
  2190. ProbeForWrite(
  2191. GrantedAccess,
  2192. sizeof(ACCESS_MASK) * ObjectTypeListLength,
  2193. sizeof(ULONG)
  2194. );
  2195. } else {
  2196. ProbeForWriteUlong((PULONG)AccessStatus);
  2197. ProbeForWriteUlong((PULONG)GrantedAccess);
  2198. }
  2199. LocalPrivilegeSetLength = ProbeAndReadUlong( PrivilegeSetLength );
  2200. ProbeForWriteUlong(
  2201. PrivilegeSetLength
  2202. );
  2203. ProbeForWrite(
  2204. PrivilegeSet,
  2205. LocalPrivilegeSetLength,
  2206. sizeof(ULONG)
  2207. );
  2208. ProbeForReadSmallStructure(
  2209. GenericMapping,
  2210. sizeof(GENERIC_MAPPING),
  2211. sizeof(ULONG)
  2212. );
  2213. LocalGenericMapping = *GenericMapping;
  2214. } except (EXCEPTION_EXECUTE_HANDLER) {
  2215. Status = GetExceptionCode();
  2216. }
  2217. if (!NT_SUCCESS( Status ) ) {
  2218. return( Status );
  2219. }
  2220. if (DesiredAccess &
  2221. ( GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL )) {
  2222. Status = STATUS_GENERIC_NOT_MAPPED;
  2223. goto Cleanup;
  2224. }
  2225. //
  2226. // Obtain a pointer to the passed token
  2227. //
  2228. Status = ObReferenceObjectByHandle(
  2229. ClientToken, // Handle
  2230. (ACCESS_MASK)TOKEN_QUERY, // DesiredAccess
  2231. SeTokenObjectType, // ObjectType
  2232. PreviousMode, // AccessMode
  2233. (PVOID *)&Token, // Object
  2234. 0 // GrantedAccess
  2235. );
  2236. if (!NT_SUCCESS(Status)) {
  2237. Token = NULL;
  2238. goto Cleanup;
  2239. }
  2240. //
  2241. // It must be an impersonation token, and at impersonation
  2242. // level of Identification or above.
  2243. //
  2244. if (Token->TokenType != TokenImpersonation) {
  2245. Status = STATUS_NO_IMPERSONATION_TOKEN;
  2246. goto Cleanup;
  2247. }
  2248. if ( Token->ImpersonationLevel < SecurityIdentification ) {
  2249. Status = STATUS_BAD_IMPERSONATION_LEVEL;
  2250. goto Cleanup;
  2251. }
  2252. //
  2253. // Capture any Object type list
  2254. //
  2255. Status = SeCaptureObjectTypeList( ObjectTypeList,
  2256. ObjectTypeListLength,
  2257. PreviousMode,
  2258. &LocalObjectTypeList );
  2259. if (!NT_SUCCESS(Status)) {
  2260. goto Cleanup;
  2261. }
  2262. //
  2263. // Compare the DesiredAccess with the privileges in the
  2264. // passed token, and see if we can either satisfy the requested
  2265. // access with a privilege, or bomb out immediately because
  2266. // we don't have a privilege we need.
  2267. //
  2268. Status = SePrivilegePolicyCheck(
  2269. &DesiredAccess,
  2270. &PreviouslyGrantedAccess,
  2271. NULL,
  2272. (PACCESS_TOKEN)Token,
  2273. &Privileges,
  2274. PreviousMode
  2275. );
  2276. if (!NT_SUCCESS( Status )) {
  2277. try {
  2278. if ( ReturnResultList ) {
  2279. for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) {
  2280. AccessStatus[ResultListIndex] = Status;
  2281. GrantedAccess[ResultListIndex] = 0;
  2282. }
  2283. } else {
  2284. *AccessStatus = Status;
  2285. *GrantedAccess = 0;
  2286. }
  2287. Status = STATUS_SUCCESS;
  2288. } except(EXCEPTION_EXECUTE_HANDLER) {
  2289. Status = GetExceptionCode();
  2290. }
  2291. goto Cleanup;
  2292. }
  2293. //
  2294. // Make sure the passed privileges buffer is large enough for
  2295. // whatever we have to put into it.
  2296. //
  2297. if (Privileges != NULL) {
  2298. if ( ((ULONG)SepPrivilegeSetSize( Privileges )) > LocalPrivilegeSetLength ) {
  2299. try {
  2300. *PrivilegeSetLength = SepPrivilegeSetSize( Privileges );
  2301. Status = STATUS_BUFFER_TOO_SMALL;
  2302. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  2303. Status = GetExceptionCode();
  2304. }
  2305. SeFreePrivileges( Privileges );
  2306. goto Cleanup;
  2307. } else {
  2308. try {
  2309. RtlCopyMemory(
  2310. PrivilegeSet,
  2311. Privileges,
  2312. SepPrivilegeSetSize( Privileges )
  2313. );
  2314. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  2315. SeFreePrivileges( Privileges );
  2316. Status = GetExceptionCode();
  2317. goto Cleanup;
  2318. }
  2319. }
  2320. SeFreePrivileges( Privileges );
  2321. } else {
  2322. //
  2323. // No privileges were used, construct an empty privilege set
  2324. //
  2325. if ( LocalPrivilegeSetLength < sizeof(PRIVILEGE_SET) ) {
  2326. try {
  2327. *PrivilegeSetLength = sizeof(PRIVILEGE_SET);
  2328. Status = STATUS_BUFFER_TOO_SMALL;
  2329. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  2330. Status = GetExceptionCode();
  2331. }
  2332. goto Cleanup;
  2333. }
  2334. try {
  2335. PrivilegeSet->PrivilegeCount = 0;
  2336. PrivilegeSet->Control = 0;
  2337. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  2338. Status = GetExceptionCode();
  2339. goto Cleanup;
  2340. }
  2341. }
  2342. //
  2343. // Capture the PrincipalSelfSid.
  2344. //
  2345. if ( PrincipalSelfSid != NULL ) {
  2346. Status = SeCaptureSid(
  2347. PrincipalSelfSid,
  2348. PreviousMode,
  2349. NULL, 0,
  2350. PagedPool,
  2351. TRUE,
  2352. &CapturedPrincipalSelfSid );
  2353. if (!NT_SUCCESS(Status)) {
  2354. CapturedPrincipalSelfSid = NULL;
  2355. goto Cleanup;
  2356. }
  2357. }
  2358. //
  2359. // Capture the passed security descriptor.
  2360. //
  2361. // SeCaptureSecurityDescriptor probes the input security descriptor,
  2362. // so we don't have to
  2363. //
  2364. Status = SeCaptureSecurityDescriptor (
  2365. SecurityDescriptor,
  2366. PreviousMode,
  2367. PagedPool,
  2368. FALSE,
  2369. &CapturedSecurityDescriptor
  2370. );
  2371. if (!NT_SUCCESS(Status)) {
  2372. goto Cleanup;
  2373. }
  2374. //
  2375. // If there's no security descriptor, then we've been
  2376. // called without all the parameters we need.
  2377. // Return invalid security descriptor.
  2378. //
  2379. if ( CapturedSecurityDescriptor == NULL ) {
  2380. Status = STATUS_INVALID_SECURITY_DESCR;
  2381. goto Cleanup;
  2382. }
  2383. //
  2384. // A valid security descriptor must have an owner and a group
  2385. //
  2386. if ( RtlpOwnerAddrSecurityDescriptor(
  2387. (PISECURITY_DESCRIPTOR)CapturedSecurityDescriptor
  2388. ) == NULL ||
  2389. RtlpGroupAddrSecurityDescriptor(
  2390. (PISECURITY_DESCRIPTOR)CapturedSecurityDescriptor
  2391. ) == NULL ) {
  2392. SeReleaseSecurityDescriptor (
  2393. CapturedSecurityDescriptor,
  2394. PreviousMode,
  2395. FALSE
  2396. );
  2397. Status = STATUS_INVALID_SECURITY_DESCR;
  2398. goto Cleanup;
  2399. }
  2400. SeCaptureSubjectContext( &SubjectContext );
  2401. SepAcquireTokenReadLock( Token );
  2402. //
  2403. // If the user in the token is the owner of the object, we
  2404. // must automatically grant ReadControl and WriteDac access
  2405. // if desired. If the DesiredAccess mask is empty after
  2406. // these bits are turned off, we don't have to do any more
  2407. // access checking (ref section 4, DSA ACL Arch)
  2408. //
  2409. if ( DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED) ) {
  2410. if (SepTokenIsOwner( Token, CapturedSecurityDescriptor, TRUE )) {
  2411. if ( DesiredAccess & MAXIMUM_ALLOWED ) {
  2412. PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
  2413. } else {
  2414. PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
  2415. }
  2416. DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
  2417. }
  2418. }
  2419. if (DesiredAccess == 0) {
  2420. try {
  2421. if ( ReturnResultList ) {
  2422. for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) {
  2423. AccessStatus[ResultListIndex] = STATUS_SUCCESS;
  2424. GrantedAccess[ResultListIndex] = PreviouslyGrantedAccess;
  2425. }
  2426. } else {
  2427. *AccessStatus = STATUS_SUCCESS;
  2428. *GrantedAccess = PreviouslyGrantedAccess;
  2429. }
  2430. Status = STATUS_SUCCESS;
  2431. } except (EXCEPTION_EXECUTE_HANDLER) {
  2432. Status = GetExceptionCode();
  2433. }
  2434. SepReleaseTokenReadLock( Token );
  2435. SeReleaseSubjectContext( &SubjectContext );
  2436. SeReleaseSecurityDescriptor (
  2437. CapturedSecurityDescriptor,
  2438. PreviousMode,
  2439. FALSE
  2440. );
  2441. goto Cleanup;
  2442. }
  2443. //
  2444. // Finally, handle the case where we actually have to check the DACL.
  2445. //
  2446. if ( ReturnResultList ) {
  2447. LocalGrantedAccessPointer =
  2448. ExAllocatePoolWithTag( PagedPool, (sizeof(ACCESS_MASK)+sizeof(NTSTATUS)) * ObjectTypeListLength, 'aGeS' );
  2449. if (LocalGrantedAccessPointer == NULL) {
  2450. SepReleaseTokenReadLock( Token );
  2451. SeReleaseSubjectContext( &SubjectContext );
  2452. SeReleaseSecurityDescriptor (
  2453. CapturedSecurityDescriptor,
  2454. PreviousMode,
  2455. FALSE
  2456. );
  2457. Status = STATUS_INSUFFICIENT_RESOURCES;
  2458. goto Cleanup;
  2459. }
  2460. LocalAccessStatusPointer = (PNTSTATUS)(LocalGrantedAccessPointer + ObjectTypeListLength);
  2461. } else {
  2462. LocalGrantedAccessPointer = &LocalGrantedAccess;
  2463. LocalAccessStatusPointer = &LocalAccessStatus;
  2464. }
  2465. //
  2466. // This does not ask for privilege set to be returned so we can ignore
  2467. // the return value of the call.
  2468. //
  2469. (VOID) SepAccessCheck (
  2470. CapturedSecurityDescriptor,
  2471. CapturedPrincipalSelfSid,
  2472. SubjectContext.PrimaryToken,
  2473. Token,
  2474. DesiredAccess,
  2475. LocalObjectTypeList,
  2476. ObjectTypeListLength,
  2477. &LocalGenericMapping,
  2478. PreviouslyGrantedAccess,
  2479. PreviousMode,
  2480. LocalGrantedAccessPointer,
  2481. NULL,
  2482. LocalAccessStatusPointer,
  2483. ReturnResultList,
  2484. NULL,
  2485. NULL );
  2486. SepReleaseTokenReadLock( Token );
  2487. SeReleaseSubjectContext( &SubjectContext );
  2488. SeReleaseSecurityDescriptor (
  2489. CapturedSecurityDescriptor,
  2490. PreviousMode,
  2491. FALSE
  2492. );
  2493. try {
  2494. if ( ReturnResultList ) {
  2495. for ( ResultListIndex=0; ResultListIndex<ObjectTypeListLength; ResultListIndex++ ) {
  2496. AccessStatus[ResultListIndex] = LocalAccessStatusPointer[ResultListIndex];
  2497. GrantedAccess[ResultListIndex] = LocalGrantedAccessPointer[ResultListIndex];
  2498. }
  2499. } else {
  2500. *AccessStatus = *LocalAccessStatusPointer;
  2501. *GrantedAccess = *LocalGrantedAccessPointer;
  2502. }
  2503. Status = STATUS_SUCCESS;
  2504. } except (EXCEPTION_EXECUTE_HANDLER) {
  2505. Status = GetExceptionCode();
  2506. }
  2507. if ( ReturnResultList ) {
  2508. if ( LocalGrantedAccessPointer != NULL ) {
  2509. ExFreePool( LocalGrantedAccessPointer );
  2510. }
  2511. }
  2512. //
  2513. // Free locally used resources.
  2514. //
  2515. Cleanup:
  2516. if ( Token != NULL ) {
  2517. ObDereferenceObject( Token );
  2518. }
  2519. if ( LocalObjectTypeList != NULL ) {
  2520. SeFreeCapturedObjectTypeList( LocalObjectTypeList );
  2521. }
  2522. if (CapturedPrincipalSelfSid != NULL) {
  2523. SeReleaseSid( CapturedPrincipalSelfSid, PreviousMode, TRUE);
  2524. }
  2525. return Status;
  2526. }
  2527. VOID
  2528. SeFreePrivileges(
  2529. IN PPRIVILEGE_SET Privileges
  2530. )
  2531. /*++
  2532. Routine Description:
  2533. This routine frees a privilege set returned by SeAccessCheck.
  2534. Arguments:
  2535. Privileges - Supplies a pointer to the privilege set to be freed.
  2536. Return Value:
  2537. None.
  2538. --*/
  2539. {
  2540. PAGED_CODE();
  2541. ExFreePool( Privileges );
  2542. }
  2543. BOOLEAN
  2544. SeAccessCheck (
  2545. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2546. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
  2547. IN BOOLEAN SubjectContextLocked,
  2548. IN ACCESS_MASK DesiredAccess,
  2549. IN ACCESS_MASK PreviouslyGrantedAccess,
  2550. OUT PPRIVILEGE_SET *Privileges OPTIONAL,
  2551. IN PGENERIC_MAPPING GenericMapping,
  2552. IN KPROCESSOR_MODE AccessMode,
  2553. OUT PACCESS_MASK GrantedAccess,
  2554. OUT PNTSTATUS AccessStatus
  2555. )
  2556. /*++
  2557. Routine Description:
  2558. See module abstract
  2559. This routine MAY perform tests for the following
  2560. privileges:
  2561. SeTakeOwnershipPrivilege
  2562. SeSecurityPrivilege
  2563. depending upon the accesses being requested.
  2564. This routine may also check to see if the subject is the owner
  2565. of the object (to grant WRITE_DAC access).
  2566. Arguments:
  2567. SecurityDescriptor - Supplies the security descriptor protecting the
  2568. object being accessed
  2569. SubjectSecurityContext - A pointer to the subject's captured security
  2570. context
  2571. SubjectContextLocked - Supplies a flag indiciating whether or not
  2572. the user's subject context is locked, so that it does not have
  2573. to be locked again.
  2574. DesiredAccess - Supplies the access mask that the user is attempting to
  2575. acquire
  2576. PreviouslyGrantedAccess - Supplies any accesses that the user has
  2577. already been granted, for example, as a result of holding a
  2578. privilege.
  2579. Privileges - Supplies a pointer in which will be returned a privilege
  2580. set indicating any privileges that were used as part of the
  2581. access validation.
  2582. GenericMapping - Supplies the generic mapping associated with this
  2583. object type.
  2584. AccessMode - Supplies the access mode to be used in the check
  2585. GrantedAccess - Pointer to a returned access mask indicatating the
  2586. granted access
  2587. AccessStatus - Status value that may be returned indicating the
  2588. reason why access was denied. Routines should avoid hardcoding a
  2589. return value of STATUS_ACCESS_DENIED so that a different value can
  2590. be returned when mandatory access control is implemented.
  2591. Return Value:
  2592. BOOLEAN - TRUE if access is allowed and FALSE otherwise
  2593. --*/
  2594. {
  2595. BOOLEAN Success;
  2596. PAGED_CODE();
  2597. if (AccessMode == KernelMode) {
  2598. if (DesiredAccess & MAXIMUM_ALLOWED) {
  2599. //
  2600. // Give him:
  2601. // GenericAll
  2602. // Anything else he asked for
  2603. //
  2604. *GrantedAccess = GenericMapping->GenericAll;
  2605. *GrantedAccess |= (DesiredAccess & ~MAXIMUM_ALLOWED);
  2606. *GrantedAccess |= PreviouslyGrantedAccess;
  2607. } else {
  2608. *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
  2609. }
  2610. *AccessStatus = STATUS_SUCCESS;
  2611. return(TRUE);
  2612. }
  2613. //
  2614. // If the object doesn't have a security descriptor (and it's supposed
  2615. // to), return access denied.
  2616. //
  2617. if ( SecurityDescriptor == NULL) {
  2618. *AccessStatus = STATUS_ACCESS_DENIED;
  2619. return( FALSE );
  2620. }
  2621. //
  2622. // If we're impersonating a client, we have to be at impersonation level
  2623. // of SecurityImpersonation or above.
  2624. //
  2625. if ( (SubjectSecurityContext->ClientToken != NULL) &&
  2626. (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation)
  2627. ) {
  2628. *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
  2629. return( FALSE );
  2630. }
  2631. if ( DesiredAccess == 0 ) {
  2632. if ( PreviouslyGrantedAccess == 0 ) {
  2633. *AccessStatus = STATUS_ACCESS_DENIED;
  2634. return( FALSE );
  2635. }
  2636. *GrantedAccess = PreviouslyGrantedAccess;
  2637. *AccessStatus = STATUS_SUCCESS;
  2638. *Privileges = NULL;
  2639. return( TRUE );
  2640. }
  2641. SeAssertMappedCanonicalAccess( DesiredAccess );
  2642. //
  2643. // If the caller did not lock the subject context for us,
  2644. // lock it here to keep lower level routines from having
  2645. // to lock it.
  2646. //
  2647. if ( !SubjectContextLocked ) {
  2648. SeLockSubjectContext( SubjectSecurityContext );
  2649. }
  2650. //
  2651. // If the user in the token is the owner of the object, we
  2652. // must automatically grant ReadControl and WriteDac access
  2653. // if desired. If the DesiredAccess mask is empty after
  2654. // these bits are turned off, we don't have to do any more
  2655. // access checking (ref section 4, DSA ACL Arch)
  2656. //
  2657. if ( DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED) ) {
  2658. if ( SepTokenIsOwner(
  2659. EffectiveToken( SubjectSecurityContext ),
  2660. SecurityDescriptor,
  2661. TRUE
  2662. ) ) {
  2663. if ( DesiredAccess & MAXIMUM_ALLOWED ) {
  2664. PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
  2665. } else {
  2666. PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
  2667. }
  2668. DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
  2669. }
  2670. }
  2671. if (DesiredAccess == 0) {
  2672. if ( !SubjectContextLocked ) {
  2673. SeUnlockSubjectContext( SubjectSecurityContext );
  2674. }
  2675. *GrantedAccess = PreviouslyGrantedAccess;
  2676. *AccessStatus = STATUS_SUCCESS;
  2677. return( TRUE );
  2678. } else {
  2679. BOOLEAN b = SepAccessCheck(
  2680. SecurityDescriptor,
  2681. NULL, // No PrincipalSelfSid
  2682. SubjectSecurityContext->PrimaryToken,
  2683. SubjectSecurityContext->ClientToken,
  2684. DesiredAccess,
  2685. NULL, // No object type list
  2686. 0, // No object type list
  2687. GenericMapping,
  2688. PreviouslyGrantedAccess,
  2689. AccessMode,
  2690. GrantedAccess,
  2691. Privileges,
  2692. AccessStatus,
  2693. FALSE, // Don't return a list
  2694. &Success,
  2695. NULL
  2696. );
  2697. #if DBG
  2698. if (!Success && SepShowAccessFail) {
  2699. DbgPrint("SE: Access check failed, DesiredAccess = 0x%x\n",
  2700. DesiredAccess);
  2701. SepDumpSD = TRUE;
  2702. SepDumpSecurityDescriptor(
  2703. SecurityDescriptor,
  2704. "Input to SeAccessCheck\n"
  2705. );
  2706. SepDumpSD = FALSE;
  2707. SepDumpToken = TRUE;
  2708. SepDumpTokenInfo( EffectiveToken( SubjectSecurityContext ) );
  2709. SepDumpToken = FALSE;
  2710. }
  2711. #endif
  2712. //
  2713. // If we locked it in this routine, unlock it before we
  2714. // leave.
  2715. //
  2716. if ( !SubjectContextLocked ) {
  2717. SeUnlockSubjectContext( SubjectSecurityContext );
  2718. }
  2719. //
  2720. // We return failure if any of the following is TRUE
  2721. // 1. The user was really not granted access.
  2722. // 2. The resource manager asked for the list of privileges used to
  2723. // determine granted access and we failed to allocate memory
  2724. // required to return these.
  2725. //
  2726. return( b && Success );
  2727. }
  2728. }
  2729. NTSTATUS
  2730. SePrivilegePolicyCheck(
  2731. IN OUT PACCESS_MASK RemainingDesiredAccess,
  2732. IN OUT PACCESS_MASK PreviouslyGrantedAccess,
  2733. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext OPTIONAL,
  2734. IN PACCESS_TOKEN ExplicitToken OPTIONAL,
  2735. OUT PPRIVILEGE_SET *PrivilegeSet,
  2736. IN KPROCESSOR_MODE PreviousMode
  2737. )
  2738. /*++
  2739. Routine Description:
  2740. This routine implements privilege policy by examining the bits in
  2741. a DesiredAccess mask and adjusting them based on privilege checks.
  2742. Currently, a request for ACCESS_SYSTEM_SECURITY may only be satisfied
  2743. by the caller having SeSecurityPrivilege. WRITE_OWNER may optionally
  2744. be satisfied via SeTakeOwnershipPrivilege.
  2745. Arguments:
  2746. RemainingDesiredAccess - The desired access for the current operation.
  2747. Bits may be cleared in this if the subject has particular privileges.
  2748. PreviouslyGrantedAccess - Supplies an access mask describing any
  2749. accesses that have already been granted. Bits may be set in
  2750. here as a result of privilge checks.
  2751. SubjectSecurityContext - Optionally provides the subject's security
  2752. context.
  2753. ExplicitToken - Optionally provides the token to be examined.
  2754. PrivilegeSet - Supplies a pointer to a location in which will be
  2755. returned a pointer to a privilege set.
  2756. PreviousMode - The previous processor mode.
  2757. Return Value:
  2758. STATUS_SUCCESS - Any access requests that could be satisfied via
  2759. privileges were done.
  2760. STATUS_PRIVILEGE_NOT_HELD - An access type was being requested that
  2761. requires a privilege, and the current subject did not have the
  2762. privilege.
  2763. --*/
  2764. {
  2765. BOOLEAN Success;
  2766. PTOKEN Token;
  2767. BOOLEAN WriteOwner = FALSE;
  2768. BOOLEAN SystemSecurity = FALSE;
  2769. ULONG PrivilegeNumber = 0;
  2770. ULONG PrivilegeCount = 0;
  2771. ULONG SizeRequired;
  2772. PAGED_CODE();
  2773. if (ARGUMENT_PRESENT( SubjectSecurityContext )) {
  2774. Token = (PTOKEN)EffectiveToken( SubjectSecurityContext );
  2775. } else {
  2776. Token = (PTOKEN)ExplicitToken;
  2777. }
  2778. if (*RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY) {
  2779. Success = SepSinglePrivilegeCheck (
  2780. SeSecurityPrivilege,
  2781. Token,
  2782. PreviousMode
  2783. );
  2784. if (!Success) {
  2785. return( STATUS_PRIVILEGE_NOT_HELD );
  2786. }
  2787. PrivilegeCount++;
  2788. SystemSecurity = TRUE;
  2789. *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
  2790. *PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
  2791. }
  2792. if (*RemainingDesiredAccess & WRITE_OWNER) {
  2793. Success = SepSinglePrivilegeCheck (
  2794. SeTakeOwnershipPrivilege,
  2795. Token,
  2796. PreviousMode
  2797. );
  2798. if (Success) {
  2799. PrivilegeCount++;
  2800. WriteOwner = TRUE;
  2801. *RemainingDesiredAccess &= ~WRITE_OWNER;
  2802. *PreviouslyGrantedAccess |= WRITE_OWNER;
  2803. }
  2804. }
  2805. if (PrivilegeCount > 0) {
  2806. SizeRequired = sizeof(PRIVILEGE_SET) +
  2807. (PrivilegeCount - ANYSIZE_ARRAY) *
  2808. (ULONG)sizeof(LUID_AND_ATTRIBUTES);
  2809. *PrivilegeSet = ExAllocatePoolWithTag( PagedPool, SizeRequired, 'rPeS' );
  2810. if ( *PrivilegeSet == NULL ) {
  2811. return( STATUS_INSUFFICIENT_RESOURCES );
  2812. }
  2813. (*PrivilegeSet)->PrivilegeCount = PrivilegeCount;
  2814. (*PrivilegeSet)->Control = 0;
  2815. if (WriteOwner) {
  2816. (*PrivilegeSet)->Privilege[PrivilegeNumber].Luid = SeTakeOwnershipPrivilege;
  2817. (*PrivilegeSet)->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
  2818. PrivilegeNumber++;
  2819. }
  2820. if (SystemSecurity) {
  2821. (*PrivilegeSet)->Privilege[PrivilegeNumber].Luid = SeSecurityPrivilege;
  2822. (*PrivilegeSet)->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
  2823. }
  2824. }
  2825. return( STATUS_SUCCESS );
  2826. }
  2827. BOOLEAN
  2828. SepTokenIsOwner(
  2829. IN PACCESS_TOKEN EffectiveToken,
  2830. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2831. IN BOOLEAN TokenLocked
  2832. )
  2833. /*++
  2834. Routine Description:
  2835. This routine will determine of the Owner of the passed security descriptor
  2836. is in the passed token. If the token is restricted it cannot be the
  2837. owner.
  2838. Arguments:
  2839. Token - The token representing the current user.
  2840. SecurityDescriptor - The security descriptor for the object being
  2841. accessed.
  2842. TokenLocked - A boolean describing whether the caller has taken
  2843. a read lock for the token.
  2844. Return Value:
  2845. TRUE - The user of the token is the owner of the object.
  2846. FALSE - The user of the token is not the owner of the object.
  2847. --*/
  2848. {
  2849. PSID Owner;
  2850. BOOLEAN rc;
  2851. PISECURITY_DESCRIPTOR ISecurityDescriptor;
  2852. PTOKEN Token;
  2853. PAGED_CODE();
  2854. ISecurityDescriptor = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
  2855. Token = (PTOKEN)EffectiveToken;
  2856. Owner = RtlpOwnerAddrSecurityDescriptor( ISecurityDescriptor );
  2857. ASSERT( Owner != NULL );
  2858. if (!TokenLocked) {
  2859. SepAcquireTokenReadLock( Token );
  2860. }
  2861. rc = SepSidInToken( Token, NULL, Owner, FALSE );
  2862. //
  2863. // For restricted tokens, check the restricted sids too.
  2864. //
  2865. if (rc && (Token->TokenFlags & TOKEN_IS_RESTRICTED) != 0) {
  2866. rc = SepSidInTokenEx( Token, NULL, Owner, FALSE, TRUE );
  2867. }
  2868. if (!TokenLocked) {
  2869. SepReleaseTokenReadLock( Token );
  2870. }
  2871. return( rc );
  2872. }
  2873. BOOLEAN
  2874. SeFastTraverseCheck(
  2875. PSECURITY_DESCRIPTOR SecurityDescriptor,
  2876. ACCESS_MASK TraverseAccess,
  2877. KPROCESSOR_MODE AccessMode
  2878. )
  2879. /*++
  2880. Routine Description:
  2881. This routine will examine the DACL of the passed Security Descriptor
  2882. to see if WORLD has Traverse access. If so, no further access checking
  2883. is necessary.
  2884. Note that the SubjectContext for the client process does not have
  2885. to be locked to make this call, since it does not examine any data
  2886. structures in the Token.
  2887. Arguments:
  2888. SecurityDescriptor - The Security Descriptor protecting the container
  2889. object being traversed.
  2890. TraverseAccess - Access mask describing Traverse access for this
  2891. object type.
  2892. AccessMode - Supplies the access mode to be used in the check
  2893. Return Value:
  2894. TRUE - WORLD has Traverse access to this container. FALSE
  2895. otherwise.
  2896. --*/
  2897. {
  2898. PACL Dacl;
  2899. ULONG i;
  2900. PVOID Ace;
  2901. ULONG AceCount;
  2902. PAGED_CODE();
  2903. if ( AccessMode == KernelMode ) {
  2904. return( TRUE );
  2905. }
  2906. if (SecurityDescriptor == NULL) {
  2907. return( FALSE );
  2908. }
  2909. //
  2910. // See if there is a valid DACL in the passed Security Descriptor.
  2911. // No DACL, no security, all is granted.
  2912. //
  2913. Dacl = RtlpDaclAddrSecurityDescriptor( (PISECURITY_DESCRIPTOR)SecurityDescriptor );
  2914. //
  2915. // If the SE_DACL_PRESENT bit is not set, the object has no
  2916. // security, so all accesses are granted.
  2917. //
  2918. // Also grant all access if the Dacl is NULL.
  2919. //
  2920. if ( !RtlpAreControlBitsSet(
  2921. (PISECURITY_DESCRIPTOR)SecurityDescriptor, SE_DACL_PRESENT
  2922. )
  2923. || (Dacl == NULL)) {
  2924. return(TRUE);
  2925. }
  2926. //
  2927. // There is security on this object. If the DACL is empty,
  2928. // deny all access immediately
  2929. //
  2930. if ((AceCount = Dacl->AceCount) == 0) {
  2931. return( FALSE );
  2932. }
  2933. //
  2934. // There's stuff in the DACL, walk down the list and see
  2935. // if WORLD has been granted TraverseAccess
  2936. //
  2937. for ( i = 0, Ace = FirstAce( Dacl ) ;
  2938. i < AceCount ;
  2939. i++, Ace = NextAce( Ace )
  2940. ) {
  2941. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  2942. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) {
  2943. if ( (TraverseAccess & ((PACCESS_ALLOWED_ACE)Ace)->Mask) ) {
  2944. if ( RtlEqualSid( SeWorldSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart ) ) {
  2945. return( TRUE );
  2946. }
  2947. }
  2948. } else {
  2949. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) {
  2950. if ( (TraverseAccess & ((PACCESS_DENIED_ACE)Ace)->Mask) ) {
  2951. if ( RtlEqualSid( SeWorldSid, &((PACCESS_DENIED_ACE)Ace)->SidStart ) ) {
  2952. return( FALSE );
  2953. }
  2954. }
  2955. }
  2956. }
  2957. }
  2958. }
  2959. return( FALSE );
  2960. }
  2961. #ifdef SE_NTFS_WORLD_CACHE
  2962. /*++
  2963. Note: Do not delete SeGetWorldRights. It might be used by NTFS in future.
  2964. When that happens:
  2965. - Add this line to #ifdef ALLOC_PRAGMA.
  2966. #pragma alloc_text(PAGE,SeGetWorldRights)
  2967. - Uncomment the function prototype declaration in ntos\inc\se.h
  2968. KedarD - 07/05/2000
  2969. --*/
  2970. VOID
  2971. SeGetWorldRights (
  2972. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  2973. IN PGENERIC_MAPPING GenericMapping,
  2974. OUT PACCESS_MASK GrantedAccess
  2975. )
  2976. /*++
  2977. Routine Descriptions:
  2978. This call acquires the minimum rights that are available to all tokens.
  2979. This takes into account all deny access ACE(s) that would reduce the
  2980. rights granted to an ACE for Everyone.
  2981. Arguments:
  2982. SecurityDescriptor - Supplies the security descriptor protecting the
  2983. object being accessed
  2984. GenericMapping - Supplies a pointer to the generic mapping associated
  2985. with this object type.
  2986. GrantedAccess - Returns an access mask describing the granted access.
  2987. Return Value:
  2988. None.
  2989. --*/
  2990. {
  2991. ACCESS_MASK AlreadyDenied;
  2992. PACL Dacl;
  2993. PVOID Ace;
  2994. ULONG AceCount = 0;
  2995. ULONG Index;
  2996. PAGED_CODE();
  2997. *GrantedAccess = 0;
  2998. //
  2999. // Get a pointer to the ACL.
  3000. //
  3001. Dacl = RtlpDaclAddrSecurityDescriptor( (PISECURITY_DESCRIPTOR)SecurityDescriptor );
  3002. //
  3003. // If the SE_DACL_PRESENT bit is not set, the object has no
  3004. // security, so all accesses are granted. If he's asking for
  3005. // MAXIMUM_ALLOWED, return the GENERIC_ALL field from the generic
  3006. // mapping.
  3007. //
  3008. // Also grant all access if the Dacl is NULL.
  3009. //
  3010. if ( (Dacl == NULL) ||
  3011. !RtlpAreControlBitsSet( (PISECURITY_DESCRIPTOR)SecurityDescriptor,
  3012. SE_DACL_PRESENT) ) {
  3013. #ifndef SECURE_NULL_DACLS
  3014. //
  3015. // Grant all access.
  3016. //
  3017. *GrantedAccess = GenericMapping->GenericAll;
  3018. #endif //!SECURE_NULL_DACLS
  3019. } else {
  3020. AceCount = Dacl->AceCount;
  3021. }
  3022. for ( Index = 0, Ace = FirstAce( Dacl ), AlreadyDenied = 0 ;
  3023. Index < AceCount ;
  3024. Index += 1, Ace = NextAce( Ace )
  3025. ) {
  3026. if ( !(((PACE_HEADER)Ace)->AceFlags & INHERIT_ONLY_ACE)) {
  3027. if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_ACE_TYPE) ) {
  3028. if ( RtlEqualSid( SeWorldSid, &((PACCESS_ALLOWED_ACE)Ace)->SidStart ) ) {
  3029. //
  3030. // Only grant access types from this mask that have
  3031. // not already been denied
  3032. //
  3033. *GrantedAccess |=
  3034. (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~AlreadyDenied);
  3035. }
  3036. //
  3037. // Handle an object specific Access Allowed ACE
  3038. //
  3039. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_OBJECT_ACE_TYPE) ) {
  3040. //
  3041. // If no object type is in the ACE,
  3042. // treat this as an ACCESS_ALLOWED_ACE.
  3043. //
  3044. if ( RtlObjectAceObjectType( Ace ) == NULL ) {
  3045. if ( RtlEqualSid( SeWorldSid, RtlObjectAceSid(Ace) ) ) {
  3046. *GrantedAccess |=
  3047. (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~AlreadyDenied);
  3048. }
  3049. }
  3050. } else if ( (((PACE_HEADER)Ace)->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE) ) {
  3051. if ( RtlEqualSid( SeWorldSid, RtlCompoundAceClientSid(Ace) ) &&
  3052. RtlEqualSid( SeWorldSid, RtlCompoundAceServerSid(Ace) ) ) {
  3053. //
  3054. // Only grant access types from this mask that have
  3055. // not already been denied
  3056. //
  3057. *GrantedAccess |=
  3058. (((PACCESS_ALLOWED_ACE)Ace)->Mask & ~AlreadyDenied);
  3059. }
  3060. } else if ( ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_ACE_TYPE) ) ||
  3061. ( (((PACE_HEADER)Ace)->AceType == ACCESS_DENIED_OBJECT_ACE_TYPE) ) ) {
  3062. //
  3063. // We include all of the deny access ACE(s), regardless of to
  3064. // what SID they apply.
  3065. //
  3066. //
  3067. // Only deny access types from this mask that have
  3068. // not already been granted
  3069. //
  3070. AlreadyDenied |= (((PACCESS_DENIED_ACE)Ace)->Mask & ~*GrantedAccess);
  3071. }
  3072. }
  3073. }
  3074. return;
  3075. }
  3076. #endif