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.

1135 lines
29 KiB

  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 "pch.h"
  18. #pragma hdrstop
  19. //
  20. // Local macros and procedures
  21. //
  22. NTSTATUS
  23. SepInheritAcl (
  24. IN PACL Acl,
  25. IN BOOLEAN IsDirectoryObject,
  26. IN PSID OwnerSid,
  27. IN PSID GroupSid,
  28. IN PSID ServerSid OPTIONAL,
  29. IN PSID ClientSid OPTIONAL,
  30. IN PGENERIC_MAPPING GenericMapping,
  31. IN POOL_TYPE PoolType,
  32. OUT PACL *NewAcl
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(PAGE,SeAssignSecurity)
  36. #pragma alloc_text(PAGE,SeAssignSecurityEx)
  37. #pragma alloc_text(PAGE,SeDeassignSecurity)
  38. #pragma alloc_text(PAGE,SepInheritAcl)
  39. #pragma alloc_text(PAGE,SeAssignWorldSecurityDescriptor)
  40. #if DBG
  41. #pragma alloc_text(PAGE,SepDumpSecurityDescriptor)
  42. #pragma alloc_text(PAGE,SepPrintAcl)
  43. #pragma alloc_text(PAGE,SepPrintSid)
  44. #pragma alloc_text(PAGE,SepDumpTokenInfo)
  45. #pragma alloc_text(PAGE,SepSidTranslation)
  46. #endif //DBG
  47. #endif
  48. //
  49. // These variables control whether security descriptors and token
  50. // information are dumped by their dump routines. This allows
  51. // selective turning on and off of debugging output by both program
  52. // control and via the kernel debugger.
  53. //
  54. #if DBG
  55. BOOLEAN SepDumpSD = FALSE;
  56. BOOLEAN SepDumpToken = FALSE;
  57. #endif
  58. NTSTATUS
  59. SeAssignSecurity (
  60. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  61. IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
  62. OUT PSECURITY_DESCRIPTOR *NewDescriptor,
  63. IN BOOLEAN IsDirectoryObject,
  64. IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
  65. IN PGENERIC_MAPPING GenericMapping,
  66. IN POOL_TYPE PoolType
  67. )
  68. /*++
  69. Routine Description:
  70. This routine assumes privilege checking HAS NOT yet been performed
  71. and so will be performed by this routine.
  72. This procedure is used to build a security descriptor for a new object
  73. given the security descriptor of its parent directory and any originally
  74. requested security for the object. The final security descriptor
  75. returned to the caller may contain a mix of information, some explicitly
  76. provided other from the new object's parent.
  77. See RtlpNewSecurityObject for a descriptor of how the NewDescriptor is
  78. built.
  79. Arguments:
  80. ParentDescriptor - Optionally supplies the security descriptor of the
  81. parent directory under which this new object is being created.
  82. ExplicitDescriptor - Supplies the address of a pointer to the security
  83. descriptor as specified by the user that is to be applied to
  84. the new object.
  85. NewDescriptor - Returns the actual security descriptor for the new
  86. object that has been modified according to above rules.
  87. IsDirectoryObject - Specifies if the new object is itself a directory
  88. object. A value of TRUE indicates the object is a container of other
  89. objects.
  90. SubjectContext - Supplies the security context of the subject creating the
  91. object. This is used to retrieve default security information for the
  92. new object, such as default owner, primary group, and discretionary
  93. access control.
  94. GenericMapping - Supplies a pointer to an array of access mask values
  95. denoting the mapping between each generic right to non-generic rights.
  96. PoolType - Specifies the pool type to use to when allocating a new
  97. security descriptor.
  98. Return Value:
  99. STATUS_SUCCESS - indicates the operation was successful.
  100. STATUS_INVALID_OWNER - The owner SID provided as the owner of the
  101. target security descriptor is not one the caller is authorized
  102. to assign as the owner of an object.
  103. STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege
  104. necessary to explicitly assign the specified system ACL.
  105. SeSecurityPrivilege privilege is needed to explicitly assign
  106. system ACLs to objects.
  107. --*/
  108. {
  109. NTSTATUS Status;
  110. ULONG AutoInherit = 0;
  111. PAGED_CODE();
  112. #if DBG
  113. if ( ARGUMENT_PRESENT( ExplicitDescriptor) ) {
  114. SepDumpSecurityDescriptor( ExplicitDescriptor,
  115. "\nSeAssignSecurity: Input security descriptor = \n"
  116. );
  117. }
  118. if (ARGUMENT_PRESENT( ParentDescriptor )) {
  119. SepDumpSecurityDescriptor( ParentDescriptor,
  120. "\nSeAssignSecurity: Parent security descriptor = \n"
  121. );
  122. }
  123. #endif // DBG
  124. //
  125. // If the Parent SD was created via AutoInheritance,
  126. // and this object is being created with no explicit descriptor,
  127. // then we can safely create this object as AutoInherit.
  128. //
  129. if ( ParentDescriptor != NULL ) {
  130. if ( (ExplicitDescriptor == NULL ||
  131. (((PISECURITY_DESCRIPTOR)ExplicitDescriptor)->Control & SE_DACL_PRESENT) == 0 ) &&
  132. (((PISECURITY_DESCRIPTOR)ParentDescriptor)->Control & SE_DACL_AUTO_INHERITED) != 0 ) {
  133. AutoInherit |= SEF_DACL_AUTO_INHERIT;
  134. }
  135. if ( (ExplicitDescriptor == NULL ||
  136. (((PISECURITY_DESCRIPTOR)ExplicitDescriptor)->Control & SE_SACL_PRESENT) == 0 ) &&
  137. (((PISECURITY_DESCRIPTOR)ParentDescriptor)->Control & SE_SACL_AUTO_INHERITED) != 0 ) {
  138. AutoInherit |= SEF_SACL_AUTO_INHERIT;
  139. }
  140. }
  141. Status = RtlpNewSecurityObject (
  142. ParentDescriptor OPTIONAL,
  143. ExplicitDescriptor OPTIONAL,
  144. NewDescriptor,
  145. NULL, // No object type
  146. 0,
  147. IsDirectoryObject,
  148. AutoInherit,
  149. (HANDLE) SubjectContext,
  150. GenericMapping );
  151. #if DBG
  152. if ( NT_SUCCESS(Status)) {
  153. SepDumpSecurityDescriptor( *NewDescriptor,
  154. "SeAssignSecurity: Final security descriptor = \n"
  155. );
  156. }
  157. #endif
  158. return Status;
  159. // RtlpNewSecurityObject always uses PagedPool.
  160. UNREFERENCED_PARAMETER( PoolType );
  161. }
  162. NTSTATUS
  163. SeAssignSecurityEx (
  164. IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
  165. IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL,
  166. OUT PSECURITY_DESCRIPTOR *NewDescriptor,
  167. IN GUID *ObjectType OPTIONAL,
  168. IN BOOLEAN IsDirectoryObject,
  169. IN ULONG AutoInheritFlags,
  170. IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
  171. IN PGENERIC_MAPPING GenericMapping,
  172. IN POOL_TYPE PoolType
  173. )
  174. /*++
  175. Routine Description:
  176. This routine assumes privilege checking HAS NOT yet been performed
  177. and so will be performed by this routine.
  178. This procedure is used to build a security descriptor for a new object
  179. given the security descriptor of its parent directory and any originally
  180. requested security for the object. The final security descriptor
  181. returned to the caller may contain a mix of information, some explicitly
  182. provided other from the new object's parent.
  183. See RtlpNewSecurityObject for a descriptor of how the NewDescriptor is
  184. built.
  185. Arguments:
  186. ParentDescriptor - Optionally supplies the security descriptor of the
  187. parent directory under which this new object is being created.
  188. ExplicitDescriptor - Supplies the address of a pointer to the security
  189. descriptor as specified by the user that is to be applied to
  190. the new object.
  191. NewDescriptor - Returns the actual security descriptor for the new
  192. object that has been modified according to above rules.
  193. ObjectType - GUID of the object type being created. If the object being
  194. created has no GUID associated with it, then this argument is
  195. specified as NULL.
  196. IsDirectoryObject - Specifies if the new object is itself a directory
  197. object. A value of TRUE indicates the object is a container of other
  198. objects.
  199. AutoInheritFlags - Controls automatic inheritance of ACES from the Parent
  200. Descriptor. Valid values are a bits mask of the logical OR of
  201. one or more of the following bits:
  202. SEF_DACL_AUTO_INHERIT - If set, inherit ACEs from the
  203. DACL ParentDescriptor are inherited to NewDescriptor in addition
  204. to any explicit ACEs specified by the CreatorDescriptor.
  205. SEF_SACL_AUTO_INHERIT - If set, inherit ACEs from the
  206. SACL ParentDescriptor are inherited to NewDescriptor in addition
  207. to any explicit ACEs specified by the CreatorDescriptor.
  208. SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT - If set, the CreatorDescriptor
  209. is the default descriptor for ObjectType. As such, the
  210. CreatorDescriptor will be ignored if any ObjectType specific
  211. ACEs are inherited from the parent. If no such ACEs are inherited,
  212. the CreatorDescriptor is handled as though this flag were not
  213. specified.
  214. SEF_AVOID_PRIVILEGE_CHECK - If set, no privilege checking is done by this
  215. routine. This flag is useful while implementing automatic inheritance
  216. to avoid checking privileges on each child updated.
  217. SubjectContext - Supplies the security context of the subject creating the
  218. object. This is used to retrieve default security information for the
  219. new object, such as default owner, primary group, and discretionary
  220. access control.
  221. GenericMapping - Supplies a pointer to an array of access mask values
  222. denoting the mapping between each generic right to non-generic rights.
  223. PoolType - Specifies the pool type to use to when allocating a new
  224. security descriptor.
  225. Return Value:
  226. STATUS_SUCCESS - indicates the operation was successful.
  227. STATUS_INVALID_OWNER - The owner SID provided as the owner of the
  228. target security descriptor is not one the caller is authorized
  229. to assign as the owner of an object.
  230. STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege
  231. necessary to explicitly assign the specified system ACL.
  232. SeSecurityPrivilege privilege is needed to explicitly assign
  233. system ACLs to objects.
  234. --*/
  235. {
  236. NTSTATUS Status;
  237. PAGED_CODE();
  238. #if DBG
  239. if ( ARGUMENT_PRESENT( ExplicitDescriptor) ) {
  240. SepDumpSecurityDescriptor( ExplicitDescriptor,
  241. "\nSeAssignSecurityEx: Input security descriptor = \n"
  242. );
  243. }
  244. if (ARGUMENT_PRESENT( ParentDescriptor )) {
  245. SepDumpSecurityDescriptor( ParentDescriptor,
  246. "\nSeAssignSecurityEx: Parent security descriptor = \n"
  247. );
  248. }
  249. #endif // DBG
  250. Status = RtlpNewSecurityObject (
  251. ParentDescriptor OPTIONAL,
  252. ExplicitDescriptor OPTIONAL,
  253. NewDescriptor,
  254. ObjectType ? &ObjectType : NULL,
  255. ObjectType ? 1 : 0,
  256. IsDirectoryObject,
  257. AutoInheritFlags,
  258. (HANDLE) SubjectContext,
  259. GenericMapping );
  260. #if DBG
  261. if ( NT_SUCCESS(Status)) {
  262. SepDumpSecurityDescriptor( *NewDescriptor,
  263. "SeAssignSecurityEx: Final security descriptor = \n"
  264. );
  265. }
  266. #endif
  267. return Status;
  268. // RtlpNewSecurityObject always uses PagedPool.
  269. UNREFERENCED_PARAMETER( PoolType );
  270. }
  271. NTSTATUS
  272. SeDeassignSecurity (
  273. IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor
  274. )
  275. /*++
  276. Routine Description:
  277. This routine deallocates the memory associated with a security descriptor
  278. that was assigned using SeAssignSecurity.
  279. Arguments:
  280. SecurityDescriptor - Supplies the address of a pointer to the security
  281. descriptor being deleted.
  282. Return Value:
  283. STATUS_SUCCESS - The deallocation was successful.
  284. --*/
  285. {
  286. PAGED_CODE();
  287. if ((*SecurityDescriptor) != NULL) {
  288. ExFreePool( (*SecurityDescriptor) );
  289. }
  290. //
  291. // And zero out the pointer to it for safety sake
  292. //
  293. (*SecurityDescriptor) = NULL;
  294. return( STATUS_SUCCESS );
  295. }
  296. NTSTATUS
  297. SepInheritAcl (
  298. IN PACL Acl,
  299. IN BOOLEAN IsDirectoryObject,
  300. IN PSID ClientOwnerSid,
  301. IN PSID ClientGroupSid,
  302. IN PSID ServerOwnerSid OPTIONAL,
  303. IN PSID ServerGroupSid OPTIONAL,
  304. IN PGENERIC_MAPPING GenericMapping,
  305. IN POOL_TYPE PoolType,
  306. OUT PACL *NewAcl
  307. )
  308. /*++
  309. Routine Description:
  310. This is a private routine that produces an inherited acl from
  311. a parent acl according to the rules of inheritance
  312. Arguments:
  313. Acl - Supplies the acl being inherited.
  314. IsDirectoryObject - Specifies if the new acl is for a directory.
  315. OwnerSid - Specifies the owner Sid to use.
  316. GroupSid - Specifies the group SID to use.
  317. ServerSid - Specifies the Server SID to use.
  318. ClientSid - Specifies the Client SID to use.
  319. GenericMapping - Specifies the generic mapping to use.
  320. PoolType - Specifies the pool type for the new acl.
  321. NewAcl - Receives a pointer to the new (inherited) acl.
  322. Return Value:
  323. STATUS_SUCCESS - An inheritable ACL was successfully generated.
  324. STATUS_NO_INHERITANCE - An inheritable ACL was not successfully generated.
  325. This is a warning completion status.
  326. STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL.
  327. This can becaused by a number of things. One of the more probable
  328. causes is the replacement of a CreatorId with an SID that didn't fit
  329. into the ACE or ACL.
  330. STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that
  331. is unknown to this routine.
  332. --*/
  333. {
  334. //////////////////////////////////////////////////////////////////////////////
  335. // //
  336. // The logic in the ACL inheritance code must mirror the code for //
  337. // inheritance in the user mode runtime (in sertl.c). Do not make changes //
  338. // here without also making changes in that module. //
  339. // //
  340. //////////////////////////////////////////////////////////////////////////////
  341. NTSTATUS Status;
  342. ULONG NewAclLength;
  343. BOOLEAN NewAclExplicitlyAssigned;
  344. ULONG NewGenericControl;
  345. PAGED_CODE();
  346. ASSERT( PoolType == PagedPool ); // RtlpInheritAcl assumes paged pool
  347. //
  348. // First check if the acl is null
  349. //
  350. if (Acl == NULL) {
  351. return STATUS_NO_INHERITANCE;
  352. }
  353. //
  354. // Generating an inheritable ACL.
  355. //
  356. // Pass all parameters as though there is no auto inheritance.
  357. //
  358. Status = RtlpInheritAcl(
  359. Acl,
  360. NULL, // No child ACL since no auto inheritance
  361. 0, // No child control since no auto inheritance
  362. IsDirectoryObject,
  363. FALSE, // Not AutoInherit since no auto inheritance
  364. FALSE, // Not DefaultDescriptor since no auto inheritance
  365. ClientOwnerSid,
  366. ClientGroupSid,
  367. ServerOwnerSid,
  368. ServerGroupSid,
  369. GenericMapping,
  370. FALSE, // Isn't a SACL
  371. NULL, // No object GUID
  372. 0,
  373. NewAcl,
  374. &NewAclExplicitlyAssigned,
  375. &NewGenericControl );
  376. return Status;
  377. }
  378. NTSTATUS
  379. SeAssignWorldSecurityDescriptor(
  380. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  381. IN OUT PULONG Length,
  382. IN PSECURITY_INFORMATION SecurityInformation
  383. )
  384. /*++
  385. Routine Description:
  386. This routine is called by the I/O system to properly initialize a
  387. security descriptor for a FAT file. It will take a pointer to a
  388. buffer containing an emptry security descriptor, and create in the
  389. buffer a self-relative security descriptor with
  390. Owner = WorldSid,
  391. Group = WorldSid.
  392. Thus, a FAT file is accessable to all.
  393. Arguments:
  394. SecurityDescriptor - Supplies a pointer to a buffer in which will be
  395. created a self-relative security descriptor as described above.
  396. Length - The length in bytes of the buffer. If the length is too
  397. small, it will contain the minimum size required upon exit.
  398. Return Value:
  399. STATUS_BUFFER_TOO_SMALL - The buffer was not big enough to contain
  400. the requested information.
  401. --*/
  402. {
  403. PCHAR Field;
  404. PCHAR Base;
  405. ULONG WorldSidLength;
  406. PISECURITY_DESCRIPTOR_RELATIVE ISecurityDescriptor;
  407. ULONG MinSize;
  408. NTSTATUS Status;
  409. PAGED_CODE();
  410. if ( !ARGUMENT_PRESENT( SecurityInformation )) {
  411. return( STATUS_ACCESS_DENIED );
  412. }
  413. WorldSidLength = SeLengthSid( SeWorldSid );
  414. MinSize = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) + 2 * WorldSidLength;
  415. if ( *Length < MinSize ) {
  416. *Length = MinSize;
  417. return( STATUS_BUFFER_TOO_SMALL );
  418. }
  419. *Length = MinSize;
  420. ISecurityDescriptor = (SECURITY_DESCRIPTOR_RELATIVE *)SecurityDescriptor;
  421. Status = RtlCreateSecurityDescriptorRelative( ISecurityDescriptor,
  422. SECURITY_DESCRIPTOR_REVISION );
  423. if (!NT_SUCCESS( Status )) {
  424. return( Status );
  425. }
  426. Base = (PCHAR)(ISecurityDescriptor);
  427. Field = Base + sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  428. if ( *SecurityInformation & OWNER_SECURITY_INFORMATION ) {
  429. RtlCopyMemory( Field, SeWorldSid, WorldSidLength );
  430. ISecurityDescriptor->Owner = RtlPointerToOffset(Base,Field);
  431. Field += WorldSidLength;
  432. }
  433. if ( *SecurityInformation & GROUP_SECURITY_INFORMATION ) {
  434. RtlCopyMemory( Field, SeWorldSid, WorldSidLength );
  435. ISecurityDescriptor->Group = RtlPointerToOffset(Base,Field);
  436. }
  437. if ( *SecurityInformation & DACL_SECURITY_INFORMATION ) {
  438. RtlpSetControlBits( ISecurityDescriptor, SE_DACL_PRESENT );
  439. }
  440. if ( *SecurityInformation & SACL_SECURITY_INFORMATION ) {
  441. RtlpSetControlBits( ISecurityDescriptor, SE_SACL_PRESENT );
  442. }
  443. RtlpSetControlBits( ISecurityDescriptor, SE_SELF_RELATIVE );
  444. return( STATUS_SUCCESS );
  445. }
  446. #if DBG
  447. VOID
  448. SepDumpSecurityDescriptor(
  449. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  450. IN PSZ TitleString
  451. )
  452. /*++
  453. Routine Description:
  454. Private routine to dump a security descriptor to the debug
  455. screen.
  456. Arguments:
  457. SecurityDescriptor - Supplies the security descriptor to be dumped.
  458. TitleString - A null terminated string to print before dumping
  459. the security descriptor.
  460. Return Value:
  461. None.
  462. --*/
  463. {
  464. PISECURITY_DESCRIPTOR ISecurityDescriptor;
  465. UCHAR Revision;
  466. SECURITY_DESCRIPTOR_CONTROL Control;
  467. PSID Owner;
  468. PSID Group;
  469. PACL Sacl;
  470. PACL Dacl;
  471. PAGED_CODE();
  472. if (!SepDumpSD) {
  473. return;
  474. }
  475. if (!ARGUMENT_PRESENT( SecurityDescriptor )) {
  476. return;
  477. }
  478. DbgPrint(TitleString);
  479. ISecurityDescriptor = ( PISECURITY_DESCRIPTOR )SecurityDescriptor;
  480. Revision = ISecurityDescriptor->Revision;
  481. Control = ISecurityDescriptor->Control;
  482. Owner = RtlpOwnerAddrSecurityDescriptor( ISecurityDescriptor );
  483. Group = RtlpGroupAddrSecurityDescriptor( ISecurityDescriptor );
  484. Sacl = RtlpSaclAddrSecurityDescriptor( ISecurityDescriptor );
  485. Dacl = RtlpDaclAddrSecurityDescriptor( ISecurityDescriptor );
  486. DbgPrint("\nSECURITY DESCRIPTOR\n");
  487. DbgPrint("Revision = %d\n",Revision);
  488. //
  489. // Print control info
  490. //
  491. if (Control & SE_OWNER_DEFAULTED) {
  492. DbgPrint("Owner defaulted\n");
  493. }
  494. if (Control & SE_GROUP_DEFAULTED) {
  495. DbgPrint("Group defaulted\n");
  496. }
  497. if (Control & SE_DACL_PRESENT) {
  498. DbgPrint("Dacl present\n");
  499. }
  500. if (Control & SE_DACL_DEFAULTED) {
  501. DbgPrint("Dacl defaulted\n");
  502. }
  503. if (Control & SE_SACL_PRESENT) {
  504. DbgPrint("Sacl present\n");
  505. }
  506. if (Control & SE_SACL_DEFAULTED) {
  507. DbgPrint("Sacl defaulted\n");
  508. }
  509. if (Control & SE_SELF_RELATIVE) {
  510. DbgPrint("Self relative\n");
  511. }
  512. if (Control & SE_DACL_UNTRUSTED) {
  513. DbgPrint("Dacl untrusted\n");
  514. }
  515. if (Control & SE_SERVER_SECURITY) {
  516. DbgPrint("Server security\n");
  517. }
  518. DbgPrint("Owner ");
  519. SepPrintSid( Owner );
  520. DbgPrint("Group ");
  521. SepPrintSid( Group );
  522. DbgPrint("Sacl");
  523. SepPrintAcl( Sacl );
  524. DbgPrint("Dacl");
  525. SepPrintAcl( Dacl );
  526. }
  527. VOID
  528. SepPrintAcl (
  529. IN PACL Acl
  530. )
  531. /*++
  532. Routine Description:
  533. This routine dumps via (DbgPrint) an Acl for debug purposes. It is
  534. specialized to dump standard aces.
  535. Arguments:
  536. Acl - Supplies the Acl to dump
  537. Return Value:
  538. None
  539. --*/
  540. {
  541. ULONG i;
  542. PKNOWN_ACE Ace;
  543. BOOLEAN KnownType;
  544. PAGED_CODE();
  545. DbgPrint("@ %8lx\n", Acl);
  546. //
  547. // Check if the Acl is null
  548. //
  549. if (Acl == NULL) {
  550. return;
  551. }
  552. //
  553. // Dump the Acl header
  554. //
  555. DbgPrint(" Revision: %02x", Acl->AclRevision);
  556. DbgPrint(" Size: %04x", Acl->AclSize);
  557. DbgPrint(" AceCount: %04x\n", Acl->AceCount);
  558. //
  559. // Now for each Ace we want do dump it
  560. //
  561. for (i = 0, Ace = FirstAce(Acl);
  562. i < Acl->AceCount;
  563. i++, Ace = NextAce(Ace) ) {
  564. //
  565. // print out the ace header
  566. //
  567. DbgPrint("\n AceHeader: %08lx ", *(PULONG)Ace);
  568. //
  569. // special case on the standard ace types
  570. //
  571. if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
  572. (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
  573. (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
  574. (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE) ||
  575. (Ace->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE)) {
  576. //
  577. // The following array is indexed by ace types and must
  578. // follow the allowed, denied, audit, alarm seqeuence
  579. //
  580. PCHAR AceTypes[] = { "Access Allowed",
  581. "Access Denied ",
  582. "System Audit ",
  583. "System Alarm ",
  584. "Compound Grant",
  585. };
  586. DbgPrint(AceTypes[Ace->Header.AceType]);
  587. DbgPrint("\n Access Mask: %08lx ", Ace->Mask);
  588. KnownType = TRUE;
  589. } else {
  590. DbgPrint(" Unknown Ace Type\n");
  591. KnownType = FALSE;
  592. }
  593. DbgPrint("\n");
  594. DbgPrint(" AceSize = %d\n",Ace->Header.AceSize);
  595. DbgPrint(" Ace Flags = ");
  596. if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
  597. DbgPrint("OBJECT_INHERIT_ACE\n");
  598. DbgPrint(" ");
  599. }
  600. if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
  601. DbgPrint("CONTAINER_INHERIT_ACE\n");
  602. DbgPrint(" ");
  603. }
  604. if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
  605. DbgPrint("NO_PROPAGATE_INHERIT_ACE\n");
  606. DbgPrint(" ");
  607. }
  608. if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
  609. DbgPrint("INHERIT_ONLY_ACE\n");
  610. DbgPrint(" ");
  611. }
  612. if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
  613. DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n");
  614. DbgPrint(" ");
  615. }
  616. if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
  617. DbgPrint("FAILED_ACCESS_ACE_FLAG\n");
  618. DbgPrint(" ");
  619. }
  620. DbgPrint("\n");
  621. if (KnownType != TRUE) {
  622. continue;
  623. }
  624. if (Ace->Header.AceType != ACCESS_ALLOWED_COMPOUND_ACE_TYPE) {
  625. DbgPrint(" Sid = ");
  626. SepPrintSid(&Ace->SidStart);
  627. } else {
  628. DbgPrint(" Server Sid = ");
  629. SepPrintSid(RtlCompoundAceServerSid(Ace));
  630. DbgPrint("\n Client Sid = ");
  631. SepPrintSid(RtlCompoundAceClientSid( Ace ));
  632. }
  633. }
  634. }
  635. VOID
  636. SepPrintSid(
  637. IN PSID Sid
  638. )
  639. /*++
  640. Routine Description:
  641. Prints a formatted Sid
  642. Arguments:
  643. Sid - Provides a pointer to the sid to be printed.
  644. Return Value:
  645. None.
  646. --*/
  647. {
  648. UCHAR i;
  649. ULONG Tmp;
  650. PISID ISid;
  651. STRING AccountName;
  652. UCHAR Buffer[128];
  653. PAGED_CODE();
  654. if (Sid == NULL) {
  655. DbgPrint("Sid is NULL\n");
  656. return;
  657. }
  658. Buffer[0] = 0;
  659. AccountName.MaximumLength = 127;
  660. AccountName.Length = 0;
  661. AccountName.Buffer = (PVOID)&Buffer[0];
  662. if (SepSidTranslation( Sid, &AccountName )) {
  663. DbgPrint("%s ", AccountName.Buffer );
  664. }
  665. ISid = (PISID)Sid;
  666. DbgPrint("S-%lu-", (USHORT)ISid->Revision );
  667. if ( (ISid->IdentifierAuthority.Value[0] != 0) ||
  668. (ISid->IdentifierAuthority.Value[1] != 0) ){
  669. DbgPrint("0x%02hx%02hx%02hx%02hx%02hx%02hx",
  670. (USHORT)ISid->IdentifierAuthority.Value[0],
  671. (USHORT)ISid->IdentifierAuthority.Value[1],
  672. (USHORT)ISid->IdentifierAuthority.Value[2],
  673. (USHORT)ISid->IdentifierAuthority.Value[3],
  674. (USHORT)ISid->IdentifierAuthority.Value[4],
  675. (USHORT)ISid->IdentifierAuthority.Value[5] );
  676. } else {
  677. Tmp = (ULONG)ISid->IdentifierAuthority.Value[5] +
  678. (ULONG)(ISid->IdentifierAuthority.Value[4] << 8) +
  679. (ULONG)(ISid->IdentifierAuthority.Value[3] << 16) +
  680. (ULONG)(ISid->IdentifierAuthority.Value[2] << 24);
  681. DbgPrint("%lu", Tmp);
  682. }
  683. for (i=0;i<ISid->SubAuthorityCount ;i++ ) {
  684. DbgPrint("-%lu", ISid->SubAuthority[i]);
  685. }
  686. DbgPrint("\n");
  687. }
  688. VOID
  689. SepDumpTokenInfo(
  690. IN PACCESS_TOKEN Token
  691. )
  692. /*++
  693. Routine Description:
  694. Prints interesting information in a token.
  695. Arguments:
  696. Token - Provides the token to be examined.
  697. Return Value:
  698. None.
  699. --*/
  700. {
  701. ULONG UserAndGroupCount;
  702. PSID_AND_ATTRIBUTES TokenSid;
  703. ULONG i;
  704. PTOKEN IToken;
  705. PAGED_CODE();
  706. if (!SepDumpToken) {
  707. return;
  708. }
  709. IToken = (TOKEN *)Token;
  710. UserAndGroupCount = IToken->UserAndGroupCount;
  711. DbgPrint("\n\nToken Address=%lx\n",IToken);
  712. DbgPrint("Token User and Groups Array:\n\n");
  713. for ( i = 0 , TokenSid = IToken->UserAndGroups;
  714. i < UserAndGroupCount ;
  715. i++, TokenSid++
  716. ) {
  717. SepPrintSid( TokenSid->Sid );
  718. }
  719. if ( IToken->RestrictedSids ) {
  720. UserAndGroupCount = IToken->RestrictedSidCount;
  721. DbgPrint("Restricted Sids Array:\n\n");
  722. for ( i = 0 , TokenSid = IToken->RestrictedSids;
  723. i < UserAndGroupCount ;
  724. i++, TokenSid++
  725. ) {
  726. SepPrintSid( TokenSid->Sid );
  727. }
  728. }
  729. }
  730. BOOLEAN
  731. SepSidTranslation(
  732. PSID Sid,
  733. PSTRING AccountName
  734. )
  735. /*++
  736. Routine Description:
  737. This routine translates well-known SIDs into English names.
  738. Arguments:
  739. Sid - Provides the sid to be examined.
  740. AccountName - Provides a string buffer in which to place the
  741. translated name.
  742. Return Value:
  743. None
  744. --*/
  745. // AccountName is expected to have a large maximum length
  746. {
  747. PAGED_CODE();
  748. if (RtlEqualSid(Sid, SeWorldSid)) {
  749. RtlInitString( AccountName, "WORLD ");
  750. return(TRUE);
  751. }
  752. if (RtlEqualSid(Sid, SeLocalSid)) {
  753. RtlInitString( AccountName, "LOCAL ");
  754. return(TRUE);
  755. }
  756. if (RtlEqualSid(Sid, SeNetworkSid)) {
  757. RtlInitString( AccountName, "NETWORK ");
  758. return(TRUE);
  759. }
  760. if (RtlEqualSid(Sid, SeBatchSid)) {
  761. RtlInitString( AccountName, "BATCH ");
  762. return(TRUE);
  763. }
  764. if (RtlEqualSid(Sid, SeInteractiveSid)) {
  765. RtlInitString( AccountName, "INTERACTIVE ");
  766. return(TRUE);
  767. }
  768. if (RtlEqualSid(Sid, SeLocalSystemSid)) {
  769. RtlInitString( AccountName, "SYSTEM ");
  770. return(TRUE);
  771. }
  772. if (RtlEqualSid(Sid, SeCreatorOwnerSid)) {
  773. RtlInitString( AccountName, "CREATOR_OWNER ");
  774. return(TRUE);
  775. }
  776. if (RtlEqualSid(Sid, SeCreatorGroupSid)) {
  777. RtlInitString( AccountName, "CREATOR_GROUP ");
  778. return(TRUE);
  779. }
  780. if (RtlEqualSid(Sid, SeCreatorOwnerServerSid)) {
  781. RtlInitString( AccountName, "CREATOR_OWNER_SERVER ");
  782. return(TRUE);
  783. }
  784. if (RtlEqualSid(Sid, SeCreatorGroupServerSid)) {
  785. RtlInitString( AccountName, "CREATOR_GROUP_SERVER ");
  786. return(TRUE);
  787. }
  788. return(FALSE);
  789. }
  790. //
  791. // End debug only routines
  792. //
  793. #endif //DBG