Windows NT 4.0 source code leak
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.

1924 lines
50 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Seassign.c
  5. Abstract:
  6. This Module implements the SeAssignSecurity procedure. For a description
  7. of the pool allocation strategy please see the comments in semethod.c
  8. Author:
  9. Gary Kimura (GaryKi) 9-Nov-1989
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. Richard Ward (RichardW) 14-April-92
  14. Robert Reichel (RobertRe) 28-February-95
  15. Added Compound ACEs
  16. --*/
  17. #include "sep.h"
  18. #include "tokenp.h"
  19. #include "sertlp.h"
  20. #include "zwapi.h"
  21. //
  22. // Local macros and procedures
  23. //
  24. //
  25. // Macros to determine if an ACE contains one of the Creator SIDs
  26. //
  27. #define ContainsCreatorOwnerSid(Ace) ( \
  28. RtlEqualSid( &((PKNOWN_ACE)( Ace ))->SidStart, SeCreatorOwnerSid ) \
  29. )
  30. #define ContainsCreatorGroupSid(Ace) ( \
  31. RtlEqualSid( &((PKNOWN_ACE)( Ace ))->SidStart, SeCreatorGroupSid ) \
  32. )
  33. VOID
  34. SepApplyAclToObject (
  35. IN PACL Acl,
  36. IN PGENERIC_MAPPING GenericMapping
  37. );
  38. NTSTATUS
  39. SepInheritAcl (
  40. IN PACL Acl,
  41. IN BOOLEAN IsDirectoryObject,
  42. IN PSID OwnerSid,
  43. IN PSID GroupSid,
  44. IN PSID ServerSid OPTIONAL,
  45. IN PSID ClientSid OPTIONAL,
  46. IN PGENERIC_MAPPING GenericMapping,
  47. IN POOL_TYPE PoolType,
  48. OUT PACL *NewAcl
  49. );
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text(PAGE,SeAssignSecurity)
  52. #pragma alloc_text(PAGE,SeDeassignSecurity)
  53. #pragma alloc_text(PAGE,SepApplyAclToObject)
  54. #pragma alloc_text(PAGE,SepInheritAcl)
  55. #pragma alloc_text(PAGE,SeAssignWorldSecurityDescriptor)
  56. #pragma alloc_text(PAGE,SepDumpSecurityDescriptor)
  57. #pragma alloc_text(PAGE,SepPrintAcl)
  58. #pragma alloc_text(PAGE,SepPrintSid)
  59. #pragma alloc_text(PAGE,SepDumpTokenInfo)
  60. #pragma alloc_text(PAGE,SepSidTranslation)
  61. #endif
  62. //
  63. // These variables control whether security descriptors and token
  64. // information are dumped by their dump routines. This allows
  65. // selective turning on and off of debugging output by both program
  66. // control and via the kernel debugger.
  67. //
  68. #if DBG
  69. BOOLEAN SepDumpSD = FALSE;
  70. BOOLEAN SepDumpToken = FALSE;
  71. #endif
  72. NTSTATUS
  73. SeAssignSecurity (
  74. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  75. IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
  76. OUT PSECURITY_DESCRIPTOR *NewDescriptor,
  77. IN BOOLEAN IsDirectoryObject,
  78. IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
  79. IN PGENERIC_MAPPING GenericMapping,
  80. IN POOL_TYPE PoolType
  81. )
  82. /*++
  83. Routine Description:
  84. This routine assumes privilege checking HAS NOT yet been performed
  85. and so will be performed by this routine.
  86. This procedure is used to build a security descriptor for a new object
  87. given the security descriptor of its parent directory and any originally
  88. requested security for the object. The final security descriptor
  89. returned to the caller may contain a mix of information, some explicitly
  90. provided other from the new object's parent.
  91. System and Discretionary ACL Assignment
  92. ---------------------------------------
  93. The assignment of system and discretionary ACLs is governed by the
  94. logic illustrated in the following table (numbers in the cells refer
  95. to comments in the code):
  96. | Explicit | Explicit |
  97. | (non-default) | Default | No
  98. | Acl | Acl | Acl
  99. | Specified | Specified | Specified
  100. -------------+----------------+---------------+--------------
  101. | (1)| (3)| (5)
  102. Inheritable | Assign | Assign | Assign
  103. Acl From | Specified | Inherited | Inherited
  104. Parent | Acl | Acl | Acl
  105. | | |
  106. -------------+----------------+---------------+--------------
  107. No | (2)| (4)| (6)
  108. Inheritable | Assign | Assign | Assign
  109. Acl From | Specified | Default | No Acl
  110. Parent | Acl | Acl |
  111. | | |
  112. -------------+----------------+---------------+--------------
  113. Note that an explicitly specified ACL, whether a default ACL or
  114. not, may be empty or null.
  115. If the caller is explicitly assigning a system acl, default or
  116. non-default, the caller must either be a kernel mode client or
  117. must be appropriately privileged.
  118. Owner and Group Assignment
  119. --------------------------
  120. The assignment of the new object's owner and group is governed
  121. by the following logic:
  122. 1) If the passed security descriptor includes an owner, it
  123. is assigned as the new object's owner. Otherwise, the
  124. caller's token is looked in for the owner. Within the
  125. token, if there is a default owner, it is assigned.
  126. Otherwise, the caller's user ID is assigned.
  127. 2) If the passed security descriptor includes a group, it
  128. is assigned as the new object's group. Otherwise, the
  129. caller's token is looked in for the group. Within the
  130. token, if there is a default group, it is assigned.
  131. Otherwise, the caller's primary group ID is assigned.
  132. Arguments:
  133. ParentDescriptor - Optionally supplies the security descriptor of the
  134. parent directory under which this new object is being created.
  135. ExplicitDescriptor - Supplies the address of a pointer to the security
  136. descriptor as specified by the user that is to be applied to
  137. the new object.
  138. NewDescriptor - Returns the actual security descriptor for the new
  139. object that has been modified according to above rules.
  140. IsDirectoryObject - Specifies if the new object is itself a directory
  141. object. A value of TRUE indicates the object is a container of other
  142. objects.
  143. SubjectContext - Supplies the security context of the subject creating the
  144. object. This is used to retrieve default security information for the
  145. new object, such as default owner, primary group, and discretionary
  146. access control.
  147. GenericMapping - Supplies a pointer to an array of access mask values
  148. denoting the mapping between each generic right to non-generic rights.
  149. PoolType - Specifies the pool type to use to when allocating a new
  150. security descriptor.
  151. Return Value:
  152. STATUS_SUCCESS - indicates the operation was successful.
  153. STATUS_INVALID_OWNER - The owner SID provided as the owner of the
  154. target security descriptor is not one the caller is authorized
  155. to assign as the owner of an object.
  156. STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege
  157. necessary to explicitly assign the specified system ACL.
  158. SeSecurityPrivilege privilege is needed to explicitly assign
  159. system ACLs to objects.
  160. --*/
  161. {
  162. KPROCESSOR_MODE RequestorMode;
  163. SECURITY_DESCRIPTOR *CapturedDescriptor;
  164. SECURITY_DESCRIPTOR InCaseOneNotPassed;
  165. BOOLEAN SecurityDescriptorPassed;
  166. NTSTATUS Status;
  167. BOOLEAN RequestorCanAssignDescriptor = TRUE;
  168. PACL NewSacl = NULL;
  169. BOOLEAN NewSaclPresent = FALSE;
  170. BOOLEAN NewSaclInherited = FALSE;
  171. PACL NewDacl = NULL;
  172. BOOLEAN NewDaclPresent = FALSE;
  173. BOOLEAN NewDaclInherited = FALSE;
  174. PACL ServerDacl = NULL;
  175. BOOLEAN ServerDaclAllocated = FALSE;
  176. PSID NewOwner = NULL;
  177. PSID NewGroup = NULL;
  178. BOOLEAN CleanUp = FALSE;
  179. BOOLEAN SaclExplicitlyAssigned = FALSE;
  180. BOOLEAN DaclExplicitlyAssigned = FALSE;
  181. BOOLEAN OwnerExplicitlyAssigned = FALSE;
  182. BOOLEAN ServerObject;
  183. BOOLEAN DaclUntrusted;
  184. BOOLEAN HasPrivilege;
  185. PSID SubjectContextOwner;
  186. PSID SubjectContextGroup;
  187. PSID SubjectContextServerOwner;
  188. PSID SubjectContextServerGroup;
  189. PACL SubjectContextDacl;
  190. ULONG AllocationSize;
  191. ULONG NewOwnerSize;
  192. ULONG NewGroupSize;
  193. ULONG NewSaclSize;
  194. ULONG NewDaclSize;
  195. PCHAR Field;
  196. PCHAR Base;
  197. PAGED_CODE();
  198. PoolType = PagedPool;
  199. //
  200. // The desired end result is to build a self-relative security descriptor.
  201. // This means that a single block of memory will be allocated and all
  202. // security information copied into it. To minimize work along the way,
  203. // it is desirable to reference (rather than copy) each field as we
  204. // determine its source. This can not be done with inherited ACLs, however,
  205. // since they must be built from another ACL. So, explicitly assigned
  206. // and defaulted SIDs and ACLs are just referenced until they are copied
  207. // into the self-relative descriptor. Inherited ACLs are built in a
  208. // temporary buffer which must be deallocated after being copied to the
  209. // self-relative descriptor.
  210. //
  211. //
  212. // Get the previous mode of the caller
  213. //
  214. RequestorMode = KeGetPreviousMode();
  215. //
  216. // If a security descriptor has been passed, capture it, otherwise
  217. // cobble up a fake one to simplify the code that follows.
  218. //
  219. if (ARGUMENT_PRESENT(ExplicitDescriptor)) {
  220. CapturedDescriptor = ExplicitDescriptor;
  221. SecurityDescriptorPassed = TRUE;
  222. } else {
  223. //
  224. // No descriptor passed, make a fake one
  225. //
  226. SecurityDescriptorPassed = FALSE;
  227. RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)&InCaseOneNotPassed,
  228. SECURITY_DESCRIPTOR_REVISION);
  229. CapturedDescriptor = &InCaseOneNotPassed;
  230. }
  231. #if DBG
  232. SepDumpSecurityDescriptor( (PSECURITY_DESCRIPTOR)CapturedDescriptor,
  233. "\nSeAssignSecurity: Input security descriptor = \n"
  234. );
  235. if (ARGUMENT_PRESENT( ParentDescriptor )) {
  236. SepDumpSecurityDescriptor( (PSECURITY_DESCRIPTOR)ParentDescriptor,
  237. "\nSeAssignSecurity: Parent security descriptor = \n"
  238. );
  239. }
  240. #endif // DBG
  241. //
  242. // Grab pointers to the default owner, primary group, and
  243. // discretionary ACL.
  244. //
  245. //
  246. // Lock the subject context for read access so that the pointers
  247. // we copy out of it don't disappear on us at random
  248. //
  249. SeLockSubjectContext( SubjectContext );
  250. SepGetDefaultsSubjectContext(
  251. SubjectContext,
  252. &SubjectContextOwner,
  253. &SubjectContextGroup,
  254. &SubjectContextServerOwner,
  255. &SubjectContextServerGroup,
  256. &SubjectContextDacl
  257. );
  258. if ( CapturedDescriptor->Control & SE_SERVER_SECURITY ) {
  259. ServerObject = TRUE;
  260. } else {
  261. ServerObject = FALSE;
  262. }
  263. if ( CapturedDescriptor->Control & SE_DACL_UNTRUSTED ) {
  264. DaclUntrusted = TRUE;
  265. } else {
  266. DaclUntrusted = FALSE;
  267. }
  268. if (!CleanUp) {
  269. //
  270. // Establish System Acl
  271. //
  272. if ( (CapturedDescriptor->Control & SE_SACL_PRESENT) &&
  273. !(CapturedDescriptor->Control & SE_SACL_DEFAULTED) ) {
  274. //
  275. // Explicitly provided, not defaulted (Cases 1 and 2)
  276. //
  277. NewSacl = SepSaclAddrSecurityDescriptor(CapturedDescriptor);
  278. NewSaclPresent = TRUE;
  279. SaclExplicitlyAssigned = TRUE;
  280. } else {
  281. //
  282. // See if there is an inheritable ACL (copy it if there is one.)
  283. // This maps all ACEs for the target object type too.
  284. //
  285. Status = STATUS_SUCCESS;
  286. if (ARGUMENT_PRESENT(ParentDescriptor) &&
  287. NT_SUCCESS(Status = SepInheritAcl(
  288. SepSaclAddrSecurityDescriptor(
  289. ((SECURITY_DESCRIPTOR *)ParentDescriptor)
  290. ),
  291. IsDirectoryObject,
  292. SubjectContextOwner,
  293. SubjectContextGroup,
  294. SubjectContextServerOwner,
  295. SubjectContextServerGroup,
  296. GenericMapping,
  297. PoolType,
  298. &NewSacl )
  299. )) {
  300. //
  301. // There is an inheritable ACL from the parent. Assign
  302. // it. (Cases 3 and 5)
  303. //
  304. NewSaclPresent = TRUE;
  305. NewSaclInherited = TRUE;
  306. } else if (!ARGUMENT_PRESENT(ParentDescriptor) || (Status == STATUS_NO_INHERITANCE)) {
  307. //
  308. // No inheritable ACL - check for a defaulted one
  309. // (Cases 4 and 6)
  310. //
  311. if ( (CapturedDescriptor->Control & SE_SACL_PRESENT) &&
  312. (CapturedDescriptor->Control & SE_SACL_DEFAULTED) ) {
  313. //
  314. // Reference the default ACL (case 4)
  315. //
  316. NewSacl = SepSaclAddrSecurityDescriptor(CapturedDescriptor);
  317. NewSaclPresent = TRUE;
  318. //
  319. // Set SaclExplicitlyAssigned, because the caller
  320. // must have SeSecurityPrivilege to do this. We
  321. // will examine this flag and check for this privilege
  322. // later.
  323. //
  324. SaclExplicitlyAssigned = TRUE;
  325. }
  326. } else {
  327. //
  328. // Some unusual error occured
  329. //
  330. CleanUp = TRUE;
  331. }
  332. }
  333. }
  334. if (!CleanUp) {
  335. //
  336. // Establish Discretionary Acl
  337. //
  338. if ( (CapturedDescriptor->Control & SE_DACL_PRESENT) &&
  339. !(CapturedDescriptor->Control & SE_DACL_DEFAULTED) ) {
  340. //
  341. // Explicitly provided, not defaulted (Cases 1 and 2)
  342. //
  343. NewDacl = SepDaclAddrSecurityDescriptor(CapturedDescriptor);
  344. NewDaclPresent = TRUE;
  345. DaclExplicitlyAssigned = TRUE;
  346. } else {
  347. //
  348. // See if there is an inheritable ACL (copy it if there is one.)
  349. // This maps the ACEs to the target object type too.
  350. //
  351. Status = STATUS_SUCCESS;
  352. if (ARGUMENT_PRESENT(ParentDescriptor) &&
  353. NT_SUCCESS(Status = SepInheritAcl(
  354. SepDaclAddrSecurityDescriptor(
  355. ((SECURITY_DESCRIPTOR *)ParentDescriptor)
  356. ),
  357. IsDirectoryObject,
  358. SubjectContextOwner,
  359. SubjectContextGroup,
  360. SubjectContextServerOwner,
  361. SubjectContextServerGroup,
  362. GenericMapping,
  363. PoolType,
  364. &NewDacl )
  365. )) {
  366. //
  367. // There is an inheritable ACL from the parent. Assign
  368. // it. (Cases 3 and 5)
  369. //
  370. NewDaclPresent = TRUE;
  371. NewDaclInherited = TRUE;
  372. } else if (!ARGUMENT_PRESENT(ParentDescriptor) || (Status == STATUS_NO_INHERITANCE)) {
  373. //
  374. // No inheritable ACL - check for a defaulted one in the
  375. // security descriptor. If there isn't one there, then look
  376. // for one in the subject's security context (Cases 4 and 6)
  377. //
  378. if ( (CapturedDescriptor->Control & SE_DACL_PRESENT) &&
  379. (CapturedDescriptor->Control & SE_DACL_DEFAULTED) ) {
  380. //
  381. // reference the default ACL (Case 4)
  382. //
  383. NewDacl = SepDaclAddrSecurityDescriptor(CapturedDescriptor);
  384. NewDaclPresent = TRUE;
  385. //
  386. // This counts as an explicit assignment.
  387. //
  388. DaclExplicitlyAssigned = TRUE;
  389. } else {
  390. if (ARGUMENT_PRESENT(SubjectContextDacl)) {
  391. NewDacl = SubjectContextDacl;
  392. NewDaclPresent = TRUE;
  393. }
  394. }
  395. } else {
  396. //
  397. // Some unusual error occured
  398. //
  399. CleanUp = TRUE;
  400. }
  401. }
  402. }
  403. if (!CleanUp) {
  404. //
  405. // Establish an owner SID
  406. //
  407. if ((CapturedDescriptor->Owner) != NULL) {
  408. //
  409. // Use the specified owner
  410. //
  411. NewOwner = SepOwnerAddrSecurityDescriptor(CapturedDescriptor);
  412. OwnerExplicitlyAssigned = TRUE;
  413. } else {
  414. //
  415. // Pick up the default from the subject's security context.
  416. //
  417. // This does NOT constitute explicit assignment of owner
  418. // and does not have to be checked as an ID that can be
  419. // assigned as owner. This is because a default can not
  420. // be established in a token unless the user of the token
  421. // can assign it as an owner.
  422. //
  423. //
  424. // If we've been asked to create a ServerObject, we need to
  425. // make sure to pick up the new owner from the Primary token,
  426. // not the client token. If we're not impersonating, they will
  427. // end up being the same.
  428. //
  429. NewOwner = ServerObject ? SubjectContextServerOwner : SubjectContextOwner;
  430. }
  431. }
  432. if (!CleanUp) {
  433. //
  434. // Establish a Group SID
  435. //
  436. if ((CapturedDescriptor->Group) != NULL) {
  437. //
  438. // Use the specified Group
  439. //
  440. NewGroup = SepGroupAddrSecurityDescriptor(CapturedDescriptor);
  441. } else {
  442. //
  443. // Pick up the primary group from the subject's security context.
  444. //
  445. // If we're creating a Server object, use the group from the server
  446. // context.
  447. //
  448. NewGroup = ServerObject ? SubjectContextServerGroup : SubjectContextGroup;
  449. }
  450. }
  451. if (!CleanUp) {
  452. //
  453. // Now make sure that the caller has the right to assign
  454. // everything in the descriptor. If requestor is kernel mode,
  455. // then anything is legitimate. Otherwise, the requestor
  456. // is subjected to privilege and restriction tests for some
  457. // assignments.
  458. //
  459. if (RequestorMode == UserMode) {
  460. //
  461. // Anybody can assign any Discretionary ACL or group that they want to.
  462. //
  463. //
  464. // See if the system ACL was explicitly specified
  465. //
  466. if (SaclExplicitlyAssigned) {
  467. //
  468. // Check for appropriate Privileges
  469. // Audit/Alarm messages need to be generated due to the attempt
  470. // to perform a privileged operation.
  471. //
  472. HasPrivilege = SeSinglePrivilegeCheck(
  473. SeSecurityPrivilege,
  474. RequestorMode
  475. );
  476. if (!HasPrivilege) {
  477. RequestorCanAssignDescriptor = FALSE;
  478. Status = STATUS_PRIVILEGE_NOT_HELD;
  479. }
  480. }
  481. //
  482. // See if the owner field is one the requestor can assign
  483. //
  484. if (OwnerExplicitlyAssigned) {
  485. if (!SepValidOwnerSubjectContext(
  486. SubjectContext,
  487. NewOwner,
  488. ServerObject)
  489. ) {
  490. RequestorCanAssignDescriptor = FALSE;
  491. Status = STATUS_INVALID_OWNER;
  492. }
  493. }
  494. if (DaclExplicitlyAssigned) {
  495. //
  496. // Perform analysis of compound ACEs to make sure they're all
  497. // legitimate.
  498. //
  499. if (ServerObject) {
  500. //
  501. // Pass in the Server Owner as the default server SID.
  502. //
  503. Status = SepCreateServerAcl(
  504. NewDacl,
  505. DaclUntrusted,
  506. SubjectContextServerOwner,
  507. &ServerDacl,
  508. &ServerDaclAllocated
  509. );
  510. if (!NT_SUCCESS( Status )) {
  511. RequestorCanAssignDescriptor = FALSE;
  512. } else {
  513. NewDacl = ServerDacl;
  514. }
  515. }
  516. }
  517. }
  518. if (RequestorCanAssignDescriptor) {
  519. //
  520. // Everything is assignable by the requestor.
  521. // Calculate the memory needed to house all the information in
  522. // a self-relative security descriptor.
  523. //
  524. // Also map the ACEs for application to the target object
  525. // type, if they haven't already been mapped.
  526. //
  527. NewOwnerSize = (ULONG)LongAlign(SeLengthSid(NewOwner));
  528. if (NewGroup != NULL) {
  529. NewGroupSize = (ULONG)LongAlign(SeLengthSid(NewGroup));
  530. } else {
  531. NewGroupSize = 0;
  532. }
  533. if (NewSaclPresent && (NewSacl != NULL)) {
  534. NewSaclSize = (ULONG)LongAlign(NewSacl->AclSize);
  535. } else {
  536. NewSaclSize = 0;
  537. }
  538. if (NewDaclPresent && (NewDacl != NULL)) {
  539. NewDaclSize = (ULONG)LongAlign(NewDacl->AclSize);
  540. } else {
  541. NewDaclSize = 0;
  542. }
  543. AllocationSize = (ULONG)LongAlign(sizeof(SECURITY_DESCRIPTOR)) +
  544. NewOwnerSize +
  545. NewGroupSize +
  546. NewSaclSize +
  547. NewDaclSize;
  548. //
  549. // Allocate and initialize the security descriptor as
  550. // self-relative form.
  551. //
  552. *NewDescriptor = (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag( PoolType, AllocationSize, 'dSeS');
  553. if ((*NewDescriptor) == NULL) {
  554. Status = STATUS_INSUFFICIENT_RESOURCES;
  555. } else {
  556. RtlCreateSecurityDescriptor(
  557. (*NewDescriptor),
  558. SECURITY_DESCRIPTOR_REVISION
  559. );
  560. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Control |=
  561. SE_SELF_RELATIVE;
  562. Base = (PCHAR)(*NewDescriptor);
  563. Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR);
  564. //
  565. // Map and Copy in the Sacl
  566. //
  567. if (NewSaclPresent) {
  568. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Control |=
  569. SE_SACL_PRESENT;
  570. if (NewSacl != NULL) {
  571. RtlMoveMemory( Field, NewSacl, NewSacl->AclSize );
  572. if (!NewSaclInherited) {
  573. SepApplyAclToObject( (PACL)Field, GenericMapping );
  574. }
  575. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Sacl = (PACL)RtlPointerToOffset(Base,Field);
  576. Field += NewSaclSize;
  577. } else {
  578. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Sacl = NULL;
  579. }
  580. }
  581. //
  582. // Map and Copy in the Dacl
  583. //
  584. if (NewDaclPresent) {
  585. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Control |=
  586. SE_DACL_PRESENT;
  587. if (NewDacl != NULL) {
  588. RtlMoveMemory( Field, NewDacl, NewDacl->AclSize );
  589. if (!NewDaclInherited) {
  590. SepApplyAclToObject( (PACL)Field, GenericMapping );
  591. }
  592. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Dacl = (PACL)RtlPointerToOffset(Base,Field);
  593. Field += NewDaclSize;
  594. } else {
  595. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Dacl = NULL;
  596. }
  597. }
  598. //
  599. // Assign the owner
  600. //
  601. RtlMoveMemory( Field, NewOwner, SeLengthSid(NewOwner) );
  602. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Owner = (PSID)RtlPointerToOffset(Base,Field);
  603. Field += NewOwnerSize;
  604. if (NewGroup != NULL) {
  605. RtlMoveMemory( Field, NewGroup, SeLengthSid(NewGroup) );
  606. }
  607. ((SECURITY_DESCRIPTOR *)(*NewDescriptor))->Group = (PSID)RtlPointerToOffset(Base,Field);
  608. Status = STATUS_SUCCESS;
  609. }
  610. }
  611. }
  612. //
  613. // If we allocated memory for a Server DACL, free it now.
  614. //
  615. if (ServerDaclAllocated) {
  616. ExFreePool( ServerDacl );
  617. }
  618. //
  619. // Either an error was encountered or the requestor the assignment has
  620. // completed successfully. In either case, we have to clean up any
  621. // memory.
  622. //
  623. SeUnlockSubjectContext( SubjectContext );
  624. if (NewSaclInherited) {
  625. ExFreePool( NewSacl );
  626. }
  627. if (NewDaclInherited) {
  628. ExFreePool( NewDacl );
  629. }
  630. #if DBG
  631. SepDumpSecurityDescriptor( *NewDescriptor,
  632. "SeAssignSecurity: Final security descriptor = \n"
  633. );
  634. #endif
  635. return Status;
  636. }
  637. NTSTATUS
  638. SeDeassignSecurity (
  639. IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor
  640. )
  641. /*++
  642. Routine Description:
  643. This routine deallocates the memory associated with a security descriptor
  644. that was assigned using SeAssignSecurity.
  645. Arguments:
  646. SecurityDescriptor - Supplies the address of a pointer to the security
  647. descriptor being deleted.
  648. Return Value:
  649. STATUS_SUCCESS - The deallocation was successful.
  650. --*/
  651. {
  652. PAGED_CODE();
  653. if ((*SecurityDescriptor) != NULL) {
  654. ExFreePool( (*SecurityDescriptor) );
  655. }
  656. //
  657. // And zero out the pointer to it for safety sake
  658. //
  659. (*SecurityDescriptor) = NULL;
  660. return( STATUS_SUCCESS );
  661. }
  662. VOID
  663. SepApplyAclToObject (
  664. IN PACL Acl,
  665. IN PGENERIC_MAPPING GenericMapping
  666. )
  667. /*++
  668. Routine Description:
  669. This is a private routine that maps Access Masks of an ACL so that
  670. they are applicable to the object type the ACL is being applied to.
  671. Only known DSA ACEs are mapped. Unknown ACE types are ignored.
  672. Only access types in the GenericAll mapping for the target object
  673. type will be non-zero upon return.
  674. Arguments:
  675. Acl - Supplies the acl being applied.
  676. GenericMapping - Specifies the generic mapping to use.
  677. Return Value:
  678. None.
  679. --*/
  680. {
  681. //////////////////////////////////////////////////////////////////////////////
  682. // //
  683. // The logic in the ACL inheritance code must mirror the code for //
  684. // inheritance in the user mode runtime (in sertl.c). Do not make changes //
  685. // here without also making changes in that module. //
  686. // //
  687. //////////////////////////////////////////////////////////////////////////////
  688. ULONG i;
  689. PACE_HEADER Ace;
  690. PAGED_CODE();
  691. //
  692. // First check if the acl is null
  693. //
  694. if (Acl == NULL) {
  695. return;
  696. }
  697. //
  698. // Now walk the ACL, mapping each ACE as we go.
  699. //
  700. for (i = 0, Ace = FirstAce(Acl);
  701. i < Acl->AceCount;
  702. i += 1, Ace = NextAce(Ace)) {
  703. if (IsMSAceType( Ace )) {
  704. RtlApplyAceToObject( Ace, GenericMapping );
  705. }
  706. }
  707. return;
  708. }
  709. NTSTATUS
  710. SepInheritAcl (
  711. IN PACL Acl,
  712. IN BOOLEAN IsDirectoryObject,
  713. IN PSID ClientOwnerSid,
  714. IN PSID ClientGroupSid,
  715. IN PSID ServerOwnerSid OPTIONAL,
  716. IN PSID ServerGroupSid OPTIONAL,
  717. IN PGENERIC_MAPPING GenericMapping,
  718. IN POOL_TYPE PoolType,
  719. OUT PACL *NewAcl
  720. )
  721. /*++
  722. Routine Description:
  723. This is a private routine that produces an inherited acl from
  724. a parent acl according to the rules of inheritance
  725. Arguments:
  726. Acl - Supplies the acl being inherited.
  727. IsDirectoryObject - Specifies if the new acl is for a directory.
  728. OwnerSid - Specifies the owner Sid to use.
  729. GroupSid - Specifies the group SID to use.
  730. ServerSid - Specifies the Server SID to use.
  731. ClientSid - Specifies the Client SID to use.
  732. GenericMapping - Specifies the generic mapping to use.
  733. PoolType - Specifies the pool type for the new acl.
  734. NewAcl - Receives a pointer to the new (inherited) acl.
  735. Return Value:
  736. STATUS_SUCCESS - An inheritable ACL was successfully generated.
  737. STATUS_NO_INHERITANCE - An inheritable ACL was not successfully generated.
  738. This is a warning completion status.
  739. STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL.
  740. This can becaused by a number of things. One of the more probable
  741. causes is the replacement of a CreatorId with an SID that didn't fit
  742. into the ACE or ACL.
  743. STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that
  744. is unknown to this routine.
  745. --*/
  746. {
  747. //////////////////////////////////////////////////////////////////////////////
  748. // //
  749. // The logic in the ACL inheritance code must mirror the code for //
  750. // inheritance in the user mode runtime (in sertl.c). Do not make changes //
  751. // here without also making changes in that module. //
  752. // //
  753. //////////////////////////////////////////////////////////////////////////////
  754. NTSTATUS Status;
  755. ULONG NewAclLength;
  756. PAGED_CODE();
  757. //
  758. // First check if the acl is null
  759. //
  760. if (Acl == NULL) {
  761. return STATUS_NO_INHERITANCE;
  762. }
  763. if (Acl->AclRevision != ACL_REVISION2 && Acl->AclRevision != ACL_REVISION3) {
  764. return STATUS_UNKNOWN_REVISION;
  765. }
  766. //
  767. // Generating an inheritable ACL is a two-pass operation.
  768. // First you must see if there is anything to inherit, and if so,
  769. // allocate enough room to hold it. then you must actually copy
  770. // the generated ACEs.
  771. //
  772. Status = RtlpLengthInheritAcl(
  773. Acl,
  774. IsDirectoryObject,
  775. ClientOwnerSid,
  776. ClientGroupSid,
  777. ServerOwnerSid,
  778. ServerGroupSid,
  779. GenericMapping,
  780. &NewAclLength
  781. );
  782. if ( !NT_SUCCESS(Status) ) {
  783. return Status;
  784. }
  785. if (NewAclLength == 0) {
  786. return STATUS_NO_INHERITANCE;
  787. }
  788. (*NewAcl) = (PACL)ExAllocatePoolWithTag( PoolType, NewAclLength, 'cAeS' );
  789. if ((*NewAcl) == NULL) {
  790. return STATUS_INSUFFICIENT_RESOURCES;
  791. }
  792. RtlCreateAcl( (*NewAcl), NewAclLength, Acl->AclRevision );
  793. Status = RtlpGenerateInheritAcl(
  794. Acl,
  795. IsDirectoryObject,
  796. ClientOwnerSid,
  797. ClientGroupSid,
  798. ServerOwnerSid,
  799. ServerGroupSid,
  800. GenericMapping,
  801. (*NewAcl)
  802. );
  803. if (!NT_SUCCESS(Status)) {
  804. ExFreePool( (*NewAcl) );
  805. }
  806. return Status;
  807. }
  808. NTSTATUS
  809. SeAssignWorldSecurityDescriptor(
  810. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  811. IN OUT PULONG Length,
  812. IN PSECURITY_INFORMATION SecurityInformation
  813. )
  814. /*++
  815. Routine Description:
  816. This routine is called by the I/O system to properly initialize a
  817. security descriptor for a FAT file. It will take a pointer to a
  818. buffer containing an emptry security descriptor, and create in the
  819. buffer a self-relative security descriptor with
  820. Owner = WorldSid,
  821. Group = WorldSid.
  822. Thus, a FAT file is accessable to all.
  823. Arguments:
  824. SecurityDescriptor - Supplies a pointer to a buffer in which will be
  825. created a self-relative security descriptor as described above.
  826. Length - The length in bytes of the buffer. If the length is too
  827. small, it will contain the minimum size required upon exit.
  828. Return Value:
  829. STATUS_BUFFER_TOO_SMALL - The buffer was not big enough to contain
  830. the requested information.
  831. --*/
  832. {
  833. PCHAR Field;
  834. PCHAR Base;
  835. ULONG WorldSidLength;
  836. PISECURITY_DESCRIPTOR ISecurityDescriptor;
  837. ULONG MinSize;
  838. NTSTATUS Status;
  839. PAGED_CODE();
  840. if ( !ARGUMENT_PRESENT( SecurityInformation )) {
  841. return( STATUS_ACCESS_DENIED );
  842. }
  843. WorldSidLength = SeLengthSid( SeWorldSid );
  844. MinSize = sizeof( SECURITY_DESCRIPTOR ) + 2 * WorldSidLength;
  845. if ( *Length < MinSize ) {
  846. *Length = MinSize;
  847. return( STATUS_BUFFER_TOO_SMALL );
  848. }
  849. *Length = MinSize;
  850. ISecurityDescriptor = (SECURITY_DESCRIPTOR *)SecurityDescriptor;
  851. Status = RtlCreateSecurityDescriptor( ISecurityDescriptor,
  852. SECURITY_DESCRIPTOR_REVISION );
  853. if (!NT_SUCCESS( Status )) {
  854. return( Status );
  855. }
  856. Base = (PCHAR)(ISecurityDescriptor);
  857. Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR);
  858. if ( *SecurityInformation & OWNER_SECURITY_INFORMATION ) {
  859. RtlMoveMemory( Field, SeWorldSid, WorldSidLength );
  860. ISecurityDescriptor->Owner = (PSID)RtlPointerToOffset(Base,Field);
  861. Field += WorldSidLength;
  862. }
  863. if ( *SecurityInformation & GROUP_SECURITY_INFORMATION ) {
  864. RtlMoveMemory( Field, SeWorldSid, WorldSidLength );
  865. ISecurityDescriptor->Group = (PSID)RtlPointerToOffset(Base,Field);
  866. }
  867. if ( *SecurityInformation & DACL_SECURITY_INFORMATION ) {
  868. SepSetControlBits( ISecurityDescriptor, SE_DACL_PRESENT );
  869. }
  870. if ( *SecurityInformation & SACL_SECURITY_INFORMATION ) {
  871. SepSetControlBits( ISecurityDescriptor, SE_SACL_PRESENT );
  872. }
  873. SepSetControlBits( ISecurityDescriptor, SE_SELF_RELATIVE );
  874. return( STATUS_SUCCESS );
  875. }
  876. NTSTATUS
  877. SepCreateServerAcl(
  878. IN PACL Acl,
  879. IN BOOLEAN AclUntrusted,
  880. IN PSID ServerSid,
  881. OUT PACL *ServerAcl,
  882. OUT BOOLEAN *ServerAclAllocated
  883. )
  884. /*++
  885. Routine Description:
  886. This routine takes an ACL and converts it into a server ACL.
  887. Currently, that means converting all of the GRANT ACEs into
  888. Compount Grants, and if necessary sanitizing any Compound
  889. Grants that are encountered.
  890. Arguments:
  891. Return Value:
  892. --*/
  893. {
  894. USHORT RequiredSize = sizeof(ACL);
  895. USHORT AceSizeAdjustment;
  896. USHORT ServerSidSize;
  897. PACE_HEADER Ace;
  898. ULONG i;
  899. PVOID Target;
  900. PVOID AcePosition;
  901. PSID UntrustedSid;
  902. PSID ClientSid;
  903. NTSTATUS Status;
  904. if (Acl == NULL) {
  905. *ServerAclAllocated = FALSE;
  906. *ServerAcl = NULL;
  907. return( STATUS_SUCCESS );
  908. }
  909. AceSizeAdjustment = sizeof( KNOWN_COMPOUND_ACE ) - sizeof( KNOWN_ACE );
  910. ASSERT( sizeof( KNOWN_COMPOUND_ACE ) >= sizeof( KNOWN_ACE ) );
  911. ServerSidSize = (USHORT)SeLengthSid( ServerSid );
  912. //
  913. // Do this in two passes. First, determine how big the final
  914. // result is going to be, and then allocate the space and make
  915. // the changes.
  916. //
  917. for (i = 0, Ace = FirstAce(Acl);
  918. i < Acl->AceCount;
  919. i += 1, Ace = NextAce(Ace)) {
  920. //
  921. // If it's an ACCESS_ALLOWED_ACE_TYPE, we'll need to add in the
  922. // size of the Server SID.
  923. //
  924. if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE) {
  925. //
  926. // Simply add the size of the new Server SID plus whatever
  927. // adjustment needs to be made to increase the size of the ACE.
  928. //
  929. RequiredSize += ( ServerSidSize + AceSizeAdjustment );
  930. } else {
  931. if (AclUntrusted && Ace->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE ) {
  932. //
  933. // Since the Acl is untrusted, we don't care what is in the
  934. // server SID, we're going to replace it.
  935. //
  936. UntrustedSid = RtlCompoundAceServerSid( Ace );
  937. if ((USHORT)SeLengthSid(UntrustedSid) > ServerSidSize) {
  938. RequiredSize += ((USHORT)SeLengthSid(UntrustedSid) - ServerSidSize);
  939. } else {
  940. RequiredSize += (ServerSidSize - (USHORT)SeLengthSid(UntrustedSid));
  941. }
  942. }
  943. }
  944. RequiredSize += Ace->AceSize;
  945. }
  946. (*ServerAcl) = (PACL)ExAllocatePoolWithTag( PagedPool, RequiredSize, 'cAeS' );
  947. if ((*ServerAcl) == NULL) {
  948. return STATUS_INSUFFICIENT_RESOURCES;
  949. }
  950. //
  951. // Mark as allocated so caller knows to free it.
  952. //
  953. *ServerAclAllocated = TRUE;
  954. Status = RtlCreateAcl( (*ServerAcl), RequiredSize, ACL_REVISION3 );
  955. ASSERT( NT_SUCCESS( Status ));
  956. for (i = 0, Ace = FirstAce(Acl), Target=FirstAce( *ServerAcl );
  957. i < Acl->AceCount;
  958. i += 1, Ace = NextAce(Ace)) {
  959. //
  960. // If it's an ACCESS_ALLOWED_ACE_TYPE, convert to a Server ACE.
  961. //
  962. if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE ||
  963. (AclUntrusted && Ace->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE )) {
  964. AcePosition = Target;
  965. if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE) {
  966. ClientSid = &((PKNOWN_ACE)Ace)->SidStart;
  967. } else {
  968. ClientSid = RtlCompoundAceClientSid( Ace );
  969. }
  970. //
  971. // Copy up to the access mask.
  972. //
  973. RtlMoveMemory(
  974. Target,
  975. Ace,
  976. FIELD_OFFSET(KNOWN_ACE, SidStart)
  977. );
  978. //
  979. // Now copy the correct Server SID
  980. //
  981. Target = (PVOID)((ULONG)Target + (UCHAR)(FIELD_OFFSET(KNOWN_COMPOUND_ACE, SidStart)));
  982. RtlMoveMemory(
  983. Target,
  984. ServerSid,
  985. SeLengthSid(ServerSid)
  986. );
  987. Target = (PVOID)((ULONG)Target + (UCHAR)SeLengthSid(ServerSid));
  988. //
  989. // Now copy in the correct client SID. We can copy this right out of
  990. // the original ACE.
  991. //
  992. RtlMoveMemory(
  993. Target,
  994. ClientSid,
  995. SeLengthSid(ClientSid)
  996. );
  997. Target = (PVOID)((ULONG)Target + SeLengthSid(ClientSid));
  998. //
  999. // Set the size of the ACE accordingly
  1000. //
  1001. ((PKNOWN_COMPOUND_ACE)AcePosition)->Header.AceSize =
  1002. (USHORT)FIELD_OFFSET(KNOWN_COMPOUND_ACE, SidStart) +
  1003. (USHORT)SeLengthSid(ServerSid) +
  1004. (USHORT)SeLengthSid(ClientSid);
  1005. //
  1006. // Set the type
  1007. //
  1008. ((PKNOWN_COMPOUND_ACE)AcePosition)->Header.AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE;
  1009. ((PKNOWN_COMPOUND_ACE)AcePosition)->CompoundAceType = COMPOUND_ACE_IMPERSONATION;
  1010. } else {
  1011. //
  1012. // Just copy the ACE as is.
  1013. //
  1014. RtlMoveMemory( Target, Ace, Ace->AceSize );
  1015. Target = (PVOID)((ULONG)Target + Ace->AceSize);
  1016. }
  1017. }
  1018. (*ServerAcl)->AceCount = Acl->AceCount;
  1019. return( STATUS_SUCCESS );
  1020. }
  1021. //
  1022. // BUGWARNING The following routines should be in a debug only kernel, since
  1023. // all they do is dump stuff to a debug terminal as appropriate. The same
  1024. // goes for the declarations of the variables SepDumpSD and SepDumpToken
  1025. //
  1026. VOID
  1027. SepDumpSecurityDescriptor(
  1028. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  1029. IN PSZ TitleString
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. Private routine to dump a security descriptor to the debug
  1034. screen.
  1035. Arguments:
  1036. SecurityDescriptor - Supplies the security descriptor to be dumped.
  1037. TitleString - A null terminated string to print before dumping
  1038. the security descriptor.
  1039. Return Value:
  1040. None.
  1041. --*/
  1042. {
  1043. #if DBG
  1044. PISECURITY_DESCRIPTOR ISecurityDescriptor;
  1045. UCHAR Revision;
  1046. SECURITY_DESCRIPTOR_CONTROL Control;
  1047. PSID Owner;
  1048. PSID Group;
  1049. PACL Sacl;
  1050. PACL Dacl;
  1051. PAGED_CODE();
  1052. if (!SepDumpSD) {
  1053. return;
  1054. }
  1055. if (!ARGUMENT_PRESENT( SecurityDescriptor )) {
  1056. return;
  1057. }
  1058. DbgPrint(TitleString);
  1059. ISecurityDescriptor = ( PISECURITY_DESCRIPTOR )SecurityDescriptor;
  1060. Revision = ISecurityDescriptor->Revision;
  1061. Control = ISecurityDescriptor->Control;
  1062. Owner = SepOwnerAddrSecurityDescriptor( ISecurityDescriptor );
  1063. Group = SepGroupAddrSecurityDescriptor( ISecurityDescriptor );
  1064. Sacl = SepSaclAddrSecurityDescriptor( ISecurityDescriptor );
  1065. Dacl = SepDaclAddrSecurityDescriptor( ISecurityDescriptor );
  1066. DbgPrint("\nSECURITY DESCRIPTOR\n");
  1067. DbgPrint("Revision = %d\n",Revision);
  1068. //
  1069. // Print control info
  1070. //
  1071. if (Control & SE_OWNER_DEFAULTED) {
  1072. DbgPrint("Owner defaulted\n");
  1073. }
  1074. if (Control & SE_GROUP_DEFAULTED) {
  1075. DbgPrint("Group defaulted\n");
  1076. }
  1077. if (Control & SE_DACL_PRESENT) {
  1078. DbgPrint("Dacl present\n");
  1079. }
  1080. if (Control & SE_DACL_DEFAULTED) {
  1081. DbgPrint("Dacl defaulted\n");
  1082. }
  1083. if (Control & SE_SACL_PRESENT) {
  1084. DbgPrint("Sacl present\n");
  1085. }
  1086. if (Control & SE_SACL_DEFAULTED) {
  1087. DbgPrint("Sacl defaulted\n");
  1088. }
  1089. if (Control & SE_SELF_RELATIVE) {
  1090. DbgPrint("Self relative\n");
  1091. }
  1092. if (Control & SE_DACL_UNTRUSTED) {
  1093. DbgPrint("Dacl untrusted\n");
  1094. }
  1095. if (Control & SE_SERVER_SECURITY) {
  1096. DbgPrint("Server security\n");
  1097. }
  1098. DbgPrint("Owner ");
  1099. SepPrintSid( Owner );
  1100. DbgPrint("Group ");
  1101. SepPrintSid( Group );
  1102. DbgPrint("Sacl");
  1103. SepPrintAcl( Sacl );
  1104. DbgPrint("Dacl");
  1105. SepPrintAcl( Dacl );
  1106. #endif
  1107. }
  1108. VOID
  1109. SepPrintAcl (
  1110. IN PACL Acl
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. This routine dumps via (DbgPrint) an Acl for debug purposes. It is
  1115. specialized to dump standard aces.
  1116. Arguments:
  1117. Acl - Supplies the Acl to dump
  1118. Return Value:
  1119. None
  1120. --*/
  1121. {
  1122. #if DBG
  1123. ULONG i;
  1124. PKNOWN_ACE Ace;
  1125. BOOLEAN KnownType;
  1126. PAGED_CODE();
  1127. DbgPrint("@ %8lx\n", Acl);
  1128. //
  1129. // Check if the Acl is null
  1130. //
  1131. if (Acl == NULL) {
  1132. return;
  1133. }
  1134. //
  1135. // Dump the Acl header
  1136. //
  1137. DbgPrint(" Revision: %02x", Acl->AclRevision);
  1138. DbgPrint(" Size: %04x", Acl->AclSize);
  1139. DbgPrint(" AceCount: %04x\n", Acl->AceCount);
  1140. //
  1141. // Now for each Ace we want do dump it
  1142. //
  1143. for (i = 0, Ace = FirstAce(Acl);
  1144. i < Acl->AceCount;
  1145. i++, Ace = NextAce(Ace) ) {
  1146. //
  1147. // print out the ace header
  1148. //
  1149. DbgPrint("\n AceHeader: %08lx ", *(PULONG)Ace);
  1150. //
  1151. // special case on the standard ace types
  1152. //
  1153. if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
  1154. (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
  1155. (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
  1156. (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE) ||
  1157. (Ace->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE)) {
  1158. //
  1159. // The following array is indexed by ace types and must
  1160. // follow the allowed, denied, audit, alarm seqeuence
  1161. //
  1162. PCHAR AceTypes[] = { "Access Allowed",
  1163. "Access Denied ",
  1164. "System Audit ",
  1165. "System Alarm ",
  1166. "Compound Grant",
  1167. };
  1168. DbgPrint(AceTypes[Ace->Header.AceType]);
  1169. DbgPrint("\n Access Mask: %08lx ", Ace->Mask);
  1170. KnownType = TRUE;
  1171. } else {
  1172. DbgPrint(" Unknown Ace Type\n");
  1173. KnownType = FALSE;
  1174. }
  1175. DbgPrint("\n");
  1176. DbgPrint(" AceSize = %d\n",Ace->Header.AceSize);
  1177. DbgPrint(" Ace Flags = ");
  1178. if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
  1179. DbgPrint("OBJECT_INHERIT_ACE\n");
  1180. DbgPrint(" ");
  1181. }
  1182. if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
  1183. DbgPrint("CONTAINER_INHERIT_ACE\n");
  1184. DbgPrint(" ");
  1185. }
  1186. if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
  1187. DbgPrint("NO_PROPAGATE_INHERIT_ACE\n");
  1188. DbgPrint(" ");
  1189. }
  1190. if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
  1191. DbgPrint("INHERIT_ONLY_ACE\n");
  1192. DbgPrint(" ");
  1193. }
  1194. if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
  1195. DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n");
  1196. DbgPrint(" ");
  1197. }
  1198. if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
  1199. DbgPrint("FAILED_ACCESS_ACE_FLAG\n");
  1200. DbgPrint(" ");
  1201. }
  1202. DbgPrint("\n");
  1203. if (KnownType != TRUE) {
  1204. continue;
  1205. }
  1206. if (Ace->Header.AceType != ACCESS_ALLOWED_COMPOUND_ACE_TYPE) {
  1207. DbgPrint(" Sid = ");
  1208. SepPrintSid(&Ace->SidStart);
  1209. } else {
  1210. DbgPrint(" Server Sid = ");
  1211. SepPrintSid(RtlCompoundAceServerSid(Ace));
  1212. DbgPrint("\n Client Sid = ");
  1213. SepPrintSid(RtlCompoundAceClientSid( Ace ));
  1214. }
  1215. }
  1216. #endif
  1217. }
  1218. VOID
  1219. SepPrintSid(
  1220. IN PSID Sid
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. Prints a formatted Sid
  1225. Arguments:
  1226. Sid - Provides a pointer to the sid to be printed.
  1227. Return Value:
  1228. None.
  1229. --*/
  1230. {
  1231. #if DBG
  1232. UCHAR i;
  1233. ULONG Tmp;
  1234. PISID ISid;
  1235. STRING AccountName;
  1236. UCHAR Buffer[128];
  1237. PAGED_CODE();
  1238. if (Sid == NULL) {
  1239. DbgPrint("Sid is NULL\n");
  1240. return;
  1241. }
  1242. Buffer[0] = 0;
  1243. AccountName.MaximumLength = 127;
  1244. AccountName.Length = 0;
  1245. AccountName.Buffer = (PVOID)&Buffer[0];
  1246. if (SepSidTranslation( Sid, &AccountName )) {
  1247. DbgPrint("%s ", AccountName.Buffer );
  1248. }
  1249. ISid = (PISID)Sid;
  1250. DbgPrint("S-%lu-", (USHORT)ISid->Revision );
  1251. if ( (ISid->IdentifierAuthority.Value[0] != 0) ||
  1252. (ISid->IdentifierAuthority.Value[1] != 0) ){
  1253. DbgPrint("0x%02hx%02hx%02hx%02hx%02hx%02hx",
  1254. (USHORT)ISid->IdentifierAuthority.Value[0],
  1255. (USHORT)ISid->IdentifierAuthority.Value[1],
  1256. (USHORT)ISid->IdentifierAuthority.Value[2],
  1257. (USHORT)ISid->IdentifierAuthority.Value[3],
  1258. (USHORT)ISid->IdentifierAuthority.Value[4],
  1259. (USHORT)ISid->IdentifierAuthority.Value[5] );
  1260. } else {
  1261. Tmp = (ULONG)ISid->IdentifierAuthority.Value[5] +
  1262. (ULONG)(ISid->IdentifierAuthority.Value[4] << 8) +
  1263. (ULONG)(ISid->IdentifierAuthority.Value[3] << 16) +
  1264. (ULONG)(ISid->IdentifierAuthority.Value[2] << 24);
  1265. DbgPrint("%lu", Tmp);
  1266. }
  1267. for (i=0;i<ISid->SubAuthorityCount ;i++ ) {
  1268. DbgPrint("-%lu", ISid->SubAuthority[i]);
  1269. }
  1270. DbgPrint("\n");
  1271. #endif
  1272. }
  1273. VOID
  1274. SepDumpTokenInfo(
  1275. IN PACCESS_TOKEN Token
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. Prints interesting information in a token.
  1280. Arguments:
  1281. Token - Provides the token to be examined.
  1282. Return Value:
  1283. None.
  1284. --*/
  1285. {
  1286. #if DBG
  1287. ULONG UserAndGroupCount;
  1288. PSID_AND_ATTRIBUTES TokenSid;
  1289. ULONG i;
  1290. PTOKEN IToken;
  1291. PAGED_CODE();
  1292. if (!SepDumpToken) {
  1293. return;
  1294. }
  1295. IToken = (TOKEN *)Token;
  1296. UserAndGroupCount = IToken->UserAndGroupCount;
  1297. DbgPrint("\n\nToken User and Groups Array:\n\n");
  1298. for ( i = 0 , TokenSid = IToken->UserAndGroups;
  1299. i < UserAndGroupCount ;
  1300. i++, TokenSid++
  1301. ) {
  1302. SepPrintSid( TokenSid->Sid );
  1303. }
  1304. #endif
  1305. }
  1306. BOOLEAN
  1307. SepSidTranslation(
  1308. PSID Sid,
  1309. PSTRING AccountName
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. This routine translates well-known SIDs into English names.
  1314. Arguments:
  1315. Sid - Provides the sid to be examined.
  1316. AccountName - Provides a string buffer in which to place the
  1317. translated name.
  1318. Return Value:
  1319. None
  1320. --*/
  1321. // AccountName is expected to have a large maximum length
  1322. {
  1323. PAGED_CODE();
  1324. if (RtlEqualSid(Sid, SeWorldSid)) {
  1325. RtlInitString( AccountName, "WORLD ");
  1326. return(TRUE);
  1327. }
  1328. if (RtlEqualSid(Sid, SeLocalSid)) {
  1329. RtlInitString( AccountName, "LOCAL ");
  1330. return(TRUE);
  1331. }
  1332. if (RtlEqualSid(Sid, SeNetworkSid)) {
  1333. RtlInitString( AccountName, "NETWORK ");
  1334. return(TRUE);
  1335. }
  1336. if (RtlEqualSid(Sid, SeBatchSid)) {
  1337. RtlInitString( AccountName, "BATCH ");
  1338. return(TRUE);
  1339. }
  1340. if (RtlEqualSid(Sid, SeInteractiveSid)) {
  1341. RtlInitString( AccountName, "INTERACTIVE ");
  1342. return(TRUE);
  1343. }
  1344. if (RtlEqualSid(Sid, SeLocalSystemSid)) {
  1345. RtlInitString( AccountName, "SYSTEM ");
  1346. return(TRUE);
  1347. }
  1348. if (RtlEqualSid(Sid, SeCreatorOwnerSid)) {
  1349. RtlInitString( AccountName, "CREATOR_OWNER ");
  1350. return(TRUE);
  1351. }
  1352. if (RtlEqualSid(Sid, SeCreatorGroupSid)) {
  1353. RtlInitString( AccountName, "CREATOR_GROUP ");
  1354. return(TRUE);
  1355. }
  1356. if (RtlEqualSid(Sid, SeCreatorOwnerServerSid)) {
  1357. RtlInitString( AccountName, "CREATOR_OWNER_SERVER ");
  1358. return(TRUE);
  1359. }
  1360. if (RtlEqualSid(Sid, SeCreatorGroupServerSid)) {
  1361. RtlInitString( AccountName, "CREATOR_GROUP_SERVER ");
  1362. return(TRUE);
  1363. }
  1364. return(FALSE);
  1365. }
  1366. //
  1367. // End debug only routines
  1368. //