/*++ Copyright (c) 1989 Microsoft Corporation Module Name: Seassign.c Abstract: This Module implements the SeAssignSecurity procedure. For a description of the pool allocation strategy please see the comments in semethod.c Author: Gary Kimura (GaryKi) 9-Nov-1989 Environment: Kernel Mode Revision History: Richard Ward (RichardW) 14-April-92 Robert Reichel (RobertRe) 28-February-95 Added Compound ACEs --*/ #include "pch.h" #pragma hdrstop // // Local macros and procedures // NTSTATUS SepInheritAcl ( IN PACL Acl, IN BOOLEAN IsDirectoryObject, IN PSID OwnerSid, IN PSID GroupSid, IN PSID ServerSid OPTIONAL, IN PSID ClientSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN POOL_TYPE PoolType, OUT PACL *NewAcl ); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,SeAssignSecurity) #pragma alloc_text(PAGE,SeAssignSecurityEx) #pragma alloc_text(PAGE,SeDeassignSecurity) #pragma alloc_text(PAGE,SepInheritAcl) #pragma alloc_text(PAGE,SeAssignWorldSecurityDescriptor) #if DBG #pragma alloc_text(PAGE,SepDumpSecurityDescriptor) #pragma alloc_text(PAGE,SepPrintAcl) #pragma alloc_text(PAGE,SepPrintSid) #pragma alloc_text(PAGE,SepDumpTokenInfo) #pragma alloc_text(PAGE,SepSidTranslation) #endif //DBG #endif // // These variables control whether security descriptors and token // information are dumped by their dump routines. This allows // selective turning on and off of debugging output by both program // control and via the kernel debugger. // #if DBG BOOLEAN SepDumpSD = FALSE; BOOLEAN SepDumpToken = FALSE; #endif NTSTATUS SeAssignSecurity ( IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL, OUT PSECURITY_DESCRIPTOR *NewDescriptor, IN BOOLEAN IsDirectoryObject, IN PSECURITY_SUBJECT_CONTEXT SubjectContext, IN PGENERIC_MAPPING GenericMapping, IN POOL_TYPE PoolType ) /*++ Routine Description: This routine assumes privilege checking HAS NOT yet been performed and so will be performed by this routine. This procedure is used to build a security descriptor for a new object given the security descriptor of its parent directory and any originally requested security for the object. The final security descriptor returned to the caller may contain a mix of information, some explicitly provided other from the new object's parent. See RtlpNewSecurityObject for a descriptor of how the NewDescriptor is built. Arguments: ParentDescriptor - Optionally supplies the security descriptor of the parent directory under which this new object is being created. ExplicitDescriptor - Supplies the address of a pointer to the security descriptor as specified by the user that is to be applied to the new object. NewDescriptor - Returns the actual security descriptor for the new object that has been modified according to above rules. IsDirectoryObject - Specifies if the new object is itself a directory object. A value of TRUE indicates the object is a container of other objects. SubjectContext - Supplies the security context of the subject creating the object. This is used to retrieve default security information for the new object, such as default owner, primary group, and discretionary access control. GenericMapping - Supplies a pointer to an array of access mask values denoting the mapping between each generic right to non-generic rights. PoolType - Specifies the pool type to use to when allocating a new security descriptor. Return Value: STATUS_SUCCESS - indicates the operation was successful. STATUS_INVALID_OWNER - The owner SID provided as the owner of the target security descriptor is not one the caller is authorized to assign as the owner of an object. STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege necessary to explicitly assign the specified system ACL. SeSecurityPrivilege privilege is needed to explicitly assign system ACLs to objects. --*/ { NTSTATUS Status; ULONG AutoInherit = 0; PAGED_CODE(); #if DBG if ( ARGUMENT_PRESENT( ExplicitDescriptor) ) { SepDumpSecurityDescriptor( ExplicitDescriptor, "\nSeAssignSecurity: Input security descriptor = \n" ); } if (ARGUMENT_PRESENT( ParentDescriptor )) { SepDumpSecurityDescriptor( ParentDescriptor, "\nSeAssignSecurity: Parent security descriptor = \n" ); } #endif // DBG // // If the Parent SD was created via AutoInheritance, // and this object is being created with no explicit descriptor, // then we can safely create this object as AutoInherit. // if ( ParentDescriptor != NULL ) { if ( (ExplicitDescriptor == NULL || (((PISECURITY_DESCRIPTOR)ExplicitDescriptor)->Control & SE_DACL_PRESENT) == 0 ) && (((PISECURITY_DESCRIPTOR)ParentDescriptor)->Control & SE_DACL_AUTO_INHERITED) != 0 ) { AutoInherit |= SEF_DACL_AUTO_INHERIT; } if ( (ExplicitDescriptor == NULL || (((PISECURITY_DESCRIPTOR)ExplicitDescriptor)->Control & SE_SACL_PRESENT) == 0 ) && (((PISECURITY_DESCRIPTOR)ParentDescriptor)->Control & SE_SACL_AUTO_INHERITED) != 0 ) { AutoInherit |= SEF_SACL_AUTO_INHERIT; } } Status = RtlpNewSecurityObject ( ParentDescriptor OPTIONAL, ExplicitDescriptor OPTIONAL, NewDescriptor, NULL, // No object type 0, IsDirectoryObject, AutoInherit, (HANDLE) SubjectContext, GenericMapping ); #if DBG if ( NT_SUCCESS(Status)) { SepDumpSecurityDescriptor( *NewDescriptor, "SeAssignSecurity: Final security descriptor = \n" ); } #endif return Status; // RtlpNewSecurityObject always uses PagedPool. UNREFERENCED_PARAMETER( PoolType ); } NTSTATUS SeAssignSecurityEx ( IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR ExplicitDescriptor OPTIONAL, OUT PSECURITY_DESCRIPTOR *NewDescriptor, IN GUID *ObjectType OPTIONAL, IN BOOLEAN IsDirectoryObject, IN ULONG AutoInheritFlags, IN PSECURITY_SUBJECT_CONTEXT SubjectContext, IN PGENERIC_MAPPING GenericMapping, IN POOL_TYPE PoolType ) /*++ Routine Description: This routine assumes privilege checking HAS NOT yet been performed and so will be performed by this routine. This procedure is used to build a security descriptor for a new object given the security descriptor of its parent directory and any originally requested security for the object. The final security descriptor returned to the caller may contain a mix of information, some explicitly provided other from the new object's parent. See RtlpNewSecurityObject for a descriptor of how the NewDescriptor is built. Arguments: ParentDescriptor - Optionally supplies the security descriptor of the parent directory under which this new object is being created. ExplicitDescriptor - Supplies the address of a pointer to the security descriptor as specified by the user that is to be applied to the new object. NewDescriptor - Returns the actual security descriptor for the new object that has been modified according to above rules. ObjectType - GUID of the object type being created. If the object being created has no GUID associated with it, then this argument is specified as NULL. IsDirectoryObject - Specifies if the new object is itself a directory object. A value of TRUE indicates the object is a container of other objects. AutoInheritFlags - Controls automatic inheritance of ACES from the Parent Descriptor. Valid values are a bits mask of the logical OR of one or more of the following bits: SEF_DACL_AUTO_INHERIT - If set, inherit ACEs from the DACL ParentDescriptor are inherited to NewDescriptor in addition to any explicit ACEs specified by the CreatorDescriptor. SEF_SACL_AUTO_INHERIT - If set, inherit ACEs from the SACL ParentDescriptor are inherited to NewDescriptor in addition to any explicit ACEs specified by the CreatorDescriptor. SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT - If set, the CreatorDescriptor is the default descriptor for ObjectType. As such, the CreatorDescriptor will be ignored if any ObjectType specific ACEs are inherited from the parent. If no such ACEs are inherited, the CreatorDescriptor is handled as though this flag were not specified. SEF_AVOID_PRIVILEGE_CHECK - If set, no privilege checking is done by this routine. This flag is useful while implementing automatic inheritance to avoid checking privileges on each child updated. SubjectContext - Supplies the security context of the subject creating the object. This is used to retrieve default security information for the new object, such as default owner, primary group, and discretionary access control. GenericMapping - Supplies a pointer to an array of access mask values denoting the mapping between each generic right to non-generic rights. PoolType - Specifies the pool type to use to when allocating a new security descriptor. Return Value: STATUS_SUCCESS - indicates the operation was successful. STATUS_INVALID_OWNER - The owner SID provided as the owner of the target security descriptor is not one the caller is authorized to assign as the owner of an object. STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege necessary to explicitly assign the specified system ACL. SeSecurityPrivilege privilege is needed to explicitly assign system ACLs to objects. --*/ { NTSTATUS Status; PAGED_CODE(); #if DBG if ( ARGUMENT_PRESENT( ExplicitDescriptor) ) { SepDumpSecurityDescriptor( ExplicitDescriptor, "\nSeAssignSecurityEx: Input security descriptor = \n" ); } if (ARGUMENT_PRESENT( ParentDescriptor )) { SepDumpSecurityDescriptor( ParentDescriptor, "\nSeAssignSecurityEx: Parent security descriptor = \n" ); } #endif // DBG Status = RtlpNewSecurityObject ( ParentDescriptor OPTIONAL, ExplicitDescriptor OPTIONAL, NewDescriptor, ObjectType ? &ObjectType : NULL, ObjectType ? 1 : 0, IsDirectoryObject, AutoInheritFlags, (HANDLE) SubjectContext, GenericMapping ); #if DBG if ( NT_SUCCESS(Status)) { SepDumpSecurityDescriptor( *NewDescriptor, "SeAssignSecurityEx: Final security descriptor = \n" ); } #endif return Status; // RtlpNewSecurityObject always uses PagedPool. UNREFERENCED_PARAMETER( PoolType ); } NTSTATUS SeDeassignSecurity ( IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor ) /*++ Routine Description: This routine deallocates the memory associated with a security descriptor that was assigned using SeAssignSecurity. Arguments: SecurityDescriptor - Supplies the address of a pointer to the security descriptor being deleted. Return Value: STATUS_SUCCESS - The deallocation was successful. --*/ { PAGED_CODE(); if ((*SecurityDescriptor) != NULL) { ExFreePool( (*SecurityDescriptor) ); } // // And zero out the pointer to it for safety sake // (*SecurityDescriptor) = NULL; return( STATUS_SUCCESS ); } NTSTATUS SepInheritAcl ( IN PACL Acl, IN BOOLEAN IsDirectoryObject, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN POOL_TYPE PoolType, OUT PACL *NewAcl ) /*++ Routine Description: This is a private routine that produces an inherited acl from a parent acl according to the rules of inheritance Arguments: Acl - Supplies the acl being inherited. IsDirectoryObject - Specifies if the new acl is for a directory. OwnerSid - Specifies the owner Sid to use. GroupSid - Specifies the group SID to use. ServerSid - Specifies the Server SID to use. ClientSid - Specifies the Client SID to use. GenericMapping - Specifies the generic mapping to use. PoolType - Specifies the pool type for the new acl. NewAcl - Receives a pointer to the new (inherited) acl. Return Value: STATUS_SUCCESS - An inheritable ACL was successfully generated. STATUS_NO_INHERITANCE - An inheritable ACL was not successfully generated. This is a warning completion status. STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL. This can becaused by a number of things. One of the more probable causes is the replacement of a CreatorId with an SID that didn't fit into the ACE or ACL. STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that is unknown to this routine. --*/ { ////////////////////////////////////////////////////////////////////////////// // // // The logic in the ACL inheritance code must mirror the code for // // inheritance in the user mode runtime (in sertl.c). Do not make changes // // here without also making changes in that module. // // // ////////////////////////////////////////////////////////////////////////////// NTSTATUS Status; ULONG NewAclLength; BOOLEAN NewAclExplicitlyAssigned; ULONG NewGenericControl; PAGED_CODE(); ASSERT( PoolType == PagedPool ); // RtlpInheritAcl assumes paged pool // // First check if the acl is null // if (Acl == NULL) { return STATUS_NO_INHERITANCE; } // // Generating an inheritable ACL. // // Pass all parameters as though there is no auto inheritance. // Status = RtlpInheritAcl( Acl, NULL, // No child ACL since no auto inheritance 0, // No child control since no auto inheritance IsDirectoryObject, FALSE, // Not AutoInherit since no auto inheritance FALSE, // Not DefaultDescriptor since no auto inheritance ClientOwnerSid, ClientGroupSid, ServerOwnerSid, ServerGroupSid, GenericMapping, FALSE, // Isn't a SACL NULL, // No object GUID 0, NewAcl, &NewAclExplicitlyAssigned, &NewGenericControl ); return Status; } NTSTATUS SeAssignWorldSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG Length, IN PSECURITY_INFORMATION SecurityInformation ) /*++ Routine Description: This routine is called by the I/O system to properly initialize a security descriptor for a FAT file. It will take a pointer to a buffer containing an emptry security descriptor, and create in the buffer a self-relative security descriptor with Owner = WorldSid, Group = WorldSid. Thus, a FAT file is accessable to all. Arguments: SecurityDescriptor - Supplies a pointer to a buffer in which will be created a self-relative security descriptor as described above. Length - The length in bytes of the buffer. If the length is too small, it will contain the minimum size required upon exit. Return Value: STATUS_BUFFER_TOO_SMALL - The buffer was not big enough to contain the requested information. --*/ { PCHAR Field; PCHAR Base; ULONG WorldSidLength; PISECURITY_DESCRIPTOR_RELATIVE ISecurityDescriptor; ULONG MinSize; NTSTATUS Status; PAGED_CODE(); if ( !ARGUMENT_PRESENT( SecurityInformation )) { return( STATUS_ACCESS_DENIED ); } WorldSidLength = SeLengthSid( SeWorldSid ); MinSize = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) + 2 * WorldSidLength; if ( *Length < MinSize ) { *Length = MinSize; return( STATUS_BUFFER_TOO_SMALL ); } *Length = MinSize; ISecurityDescriptor = (SECURITY_DESCRIPTOR_RELATIVE *)SecurityDescriptor; Status = RtlCreateSecurityDescriptorRelative( ISecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if (!NT_SUCCESS( Status )) { return( Status ); } Base = (PCHAR)(ISecurityDescriptor); Field = Base + sizeof(SECURITY_DESCRIPTOR_RELATIVE); if ( *SecurityInformation & OWNER_SECURITY_INFORMATION ) { RtlCopyMemory( Field, SeWorldSid, WorldSidLength ); ISecurityDescriptor->Owner = RtlPointerToOffset(Base,Field); Field += WorldSidLength; } if ( *SecurityInformation & GROUP_SECURITY_INFORMATION ) { RtlCopyMemory( Field, SeWorldSid, WorldSidLength ); ISecurityDescriptor->Group = RtlPointerToOffset(Base,Field); } if ( *SecurityInformation & DACL_SECURITY_INFORMATION ) { RtlpSetControlBits( ISecurityDescriptor, SE_DACL_PRESENT ); } if ( *SecurityInformation & SACL_SECURITY_INFORMATION ) { RtlpSetControlBits( ISecurityDescriptor, SE_SACL_PRESENT ); } RtlpSetControlBits( ISecurityDescriptor, SE_SELF_RELATIVE ); return( STATUS_SUCCESS ); } #if DBG VOID SepDumpSecurityDescriptor( IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSZ TitleString ) /*++ Routine Description: Private routine to dump a security descriptor to the debug screen. Arguments: SecurityDescriptor - Supplies the security descriptor to be dumped. TitleString - A null terminated string to print before dumping the security descriptor. Return Value: None. --*/ { PISECURITY_DESCRIPTOR ISecurityDescriptor; UCHAR Revision; SECURITY_DESCRIPTOR_CONTROL Control; PSID Owner; PSID Group; PACL Sacl; PACL Dacl; PAGED_CODE(); if (!SepDumpSD) { return; } if (!ARGUMENT_PRESENT( SecurityDescriptor )) { return; } DbgPrint(TitleString); ISecurityDescriptor = ( PISECURITY_DESCRIPTOR )SecurityDescriptor; Revision = ISecurityDescriptor->Revision; Control = ISecurityDescriptor->Control; Owner = RtlpOwnerAddrSecurityDescriptor( ISecurityDescriptor ); Group = RtlpGroupAddrSecurityDescriptor( ISecurityDescriptor ); Sacl = RtlpSaclAddrSecurityDescriptor( ISecurityDescriptor ); Dacl = RtlpDaclAddrSecurityDescriptor( ISecurityDescriptor ); DbgPrint("\nSECURITY DESCRIPTOR\n"); DbgPrint("Revision = %d\n",Revision); // // Print control info // if (Control & SE_OWNER_DEFAULTED) { DbgPrint("Owner defaulted\n"); } if (Control & SE_GROUP_DEFAULTED) { DbgPrint("Group defaulted\n"); } if (Control & SE_DACL_PRESENT) { DbgPrint("Dacl present\n"); } if (Control & SE_DACL_DEFAULTED) { DbgPrint("Dacl defaulted\n"); } if (Control & SE_SACL_PRESENT) { DbgPrint("Sacl present\n"); } if (Control & SE_SACL_DEFAULTED) { DbgPrint("Sacl defaulted\n"); } if (Control & SE_SELF_RELATIVE) { DbgPrint("Self relative\n"); } if (Control & SE_DACL_UNTRUSTED) { DbgPrint("Dacl untrusted\n"); } if (Control & SE_SERVER_SECURITY) { DbgPrint("Server security\n"); } DbgPrint("Owner "); SepPrintSid( Owner ); DbgPrint("Group "); SepPrintSid( Group ); DbgPrint("Sacl"); SepPrintAcl( Sacl ); DbgPrint("Dacl"); SepPrintAcl( Dacl ); } VOID SepPrintAcl ( IN PACL Acl ) /*++ Routine Description: This routine dumps via (DbgPrint) an Acl for debug purposes. It is specialized to dump standard aces. Arguments: Acl - Supplies the Acl to dump Return Value: None --*/ { ULONG i; PKNOWN_ACE Ace; BOOLEAN KnownType; PAGED_CODE(); DbgPrint("@ %8lx\n", Acl); // // Check if the Acl is null // if (Acl == NULL) { return; } // // Dump the Acl header // DbgPrint(" Revision: %02x", Acl->AclRevision); DbgPrint(" Size: %04x", Acl->AclSize); DbgPrint(" AceCount: %04x\n", Acl->AceCount); // // Now for each Ace we want do dump it // for (i = 0, Ace = FirstAce(Acl); i < Acl->AceCount; i++, Ace = NextAce(Ace) ) { // // print out the ace header // DbgPrint("\n AceHeader: %08lx ", *(PULONG)Ace); // // special case on the standard ace types // if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) || (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) || (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) || (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE) || (Ace->Header.AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE)) { // // The following array is indexed by ace types and must // follow the allowed, denied, audit, alarm seqeuence // PCHAR AceTypes[] = { "Access Allowed", "Access Denied ", "System Audit ", "System Alarm ", "Compound Grant", }; DbgPrint(AceTypes[Ace->Header.AceType]); DbgPrint("\n Access Mask: %08lx ", Ace->Mask); KnownType = TRUE; } else { DbgPrint(" Unknown Ace Type\n"); KnownType = FALSE; } DbgPrint("\n"); DbgPrint(" AceSize = %d\n",Ace->Header.AceSize); DbgPrint(" Ace Flags = "); if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) { DbgPrint("OBJECT_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) { DbgPrint("CONTAINER_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) { DbgPrint("NO_PROPAGATE_INHERIT_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) { DbgPrint("INHERIT_ONLY_ACE\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) { DbgPrint("SUCCESSFUL_ACCESS_ACE_FLAG\n"); DbgPrint(" "); } if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) { DbgPrint("FAILED_ACCESS_ACE_FLAG\n"); DbgPrint(" "); } DbgPrint("\n"); if (KnownType != TRUE) { continue; } if (Ace->Header.AceType != ACCESS_ALLOWED_COMPOUND_ACE_TYPE) { DbgPrint(" Sid = "); SepPrintSid(&Ace->SidStart); } else { DbgPrint(" Server Sid = "); SepPrintSid(RtlCompoundAceServerSid(Ace)); DbgPrint("\n Client Sid = "); SepPrintSid(RtlCompoundAceClientSid( Ace )); } } } VOID SepPrintSid( IN PSID Sid ) /*++ Routine Description: Prints a formatted Sid Arguments: Sid - Provides a pointer to the sid to be printed. Return Value: None. --*/ { UCHAR i; ULONG Tmp; PISID ISid; STRING AccountName; UCHAR Buffer[128]; PAGED_CODE(); if (Sid == NULL) { DbgPrint("Sid is NULL\n"); return; } Buffer[0] = 0; AccountName.MaximumLength = 127; AccountName.Length = 0; AccountName.Buffer = (PVOID)&Buffer[0]; if (SepSidTranslation( Sid, &AccountName )) { DbgPrint("%s ", AccountName.Buffer ); } ISid = (PISID)Sid; DbgPrint("S-%lu-", (USHORT)ISid->Revision ); if ( (ISid->IdentifierAuthority.Value[0] != 0) || (ISid->IdentifierAuthority.Value[1] != 0) ){ DbgPrint("0x%02hx%02hx%02hx%02hx%02hx%02hx", (USHORT)ISid->IdentifierAuthority.Value[0], (USHORT)ISid->IdentifierAuthority.Value[1], (USHORT)ISid->IdentifierAuthority.Value[2], (USHORT)ISid->IdentifierAuthority.Value[3], (USHORT)ISid->IdentifierAuthority.Value[4], (USHORT)ISid->IdentifierAuthority.Value[5] ); } else { Tmp = (ULONG)ISid->IdentifierAuthority.Value[5] + (ULONG)(ISid->IdentifierAuthority.Value[4] << 8) + (ULONG)(ISid->IdentifierAuthority.Value[3] << 16) + (ULONG)(ISid->IdentifierAuthority.Value[2] << 24); DbgPrint("%lu", Tmp); } for (i=0;iSubAuthorityCount ;i++ ) { DbgPrint("-%lu", ISid->SubAuthority[i]); } DbgPrint("\n"); } VOID SepDumpTokenInfo( IN PACCESS_TOKEN Token ) /*++ Routine Description: Prints interesting information in a token. Arguments: Token - Provides the token to be examined. Return Value: None. --*/ { ULONG UserAndGroupCount; PSID_AND_ATTRIBUTES TokenSid; ULONG i; PTOKEN IToken; PAGED_CODE(); if (!SepDumpToken) { return; } IToken = (TOKEN *)Token; UserAndGroupCount = IToken->UserAndGroupCount; DbgPrint("\n\nToken Address=%lx\n",IToken); DbgPrint("Token User and Groups Array:\n\n"); for ( i = 0 , TokenSid = IToken->UserAndGroups; i < UserAndGroupCount ; i++, TokenSid++ ) { SepPrintSid( TokenSid->Sid ); } if ( IToken->RestrictedSids ) { UserAndGroupCount = IToken->RestrictedSidCount; DbgPrint("Restricted Sids Array:\n\n"); for ( i = 0 , TokenSid = IToken->RestrictedSids; i < UserAndGroupCount ; i++, TokenSid++ ) { SepPrintSid( TokenSid->Sid ); } } } BOOLEAN SepSidTranslation( PSID Sid, PSTRING AccountName ) /*++ Routine Description: This routine translates well-known SIDs into English names. Arguments: Sid - Provides the sid to be examined. AccountName - Provides a string buffer in which to place the translated name. Return Value: None --*/ // AccountName is expected to have a large maximum length { PAGED_CODE(); if (RtlEqualSid(Sid, SeWorldSid)) { RtlInitString( AccountName, "WORLD "); return(TRUE); } if (RtlEqualSid(Sid, SeLocalSid)) { RtlInitString( AccountName, "LOCAL "); return(TRUE); } if (RtlEqualSid(Sid, SeNetworkSid)) { RtlInitString( AccountName, "NETWORK "); return(TRUE); } if (RtlEqualSid(Sid, SeBatchSid)) { RtlInitString( AccountName, "BATCH "); return(TRUE); } if (RtlEqualSid(Sid, SeInteractiveSid)) { RtlInitString( AccountName, "INTERACTIVE "); return(TRUE); } if (RtlEqualSid(Sid, SeLocalSystemSid)) { RtlInitString( AccountName, "SYSTEM "); return(TRUE); } if (RtlEqualSid(Sid, SeCreatorOwnerSid)) { RtlInitString( AccountName, "CREATOR_OWNER "); return(TRUE); } if (RtlEqualSid(Sid, SeCreatorGroupSid)) { RtlInitString( AccountName, "CREATOR_GROUP "); return(TRUE); } if (RtlEqualSid(Sid, SeCreatorOwnerServerSid)) { RtlInitString( AccountName, "CREATOR_OWNER_SERVER "); return(TRUE); } if (RtlEqualSid(Sid, SeCreatorGroupServerSid)) { RtlInitString( AccountName, "CREATOR_GROUP_SERVER "); return(TRUE); } return(FALSE); } // // End debug only routines // #endif //DBG