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

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