Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

sertl.c File Reference

#include "ntrtlp.h"
#include <stdio.h>
#include "seopaque.h"
#include "sertlp.h"
#include <..\dll\ldrp.h>

Go to the source code of this file.

Defines

#define CREATOR_SID_SIZE   12
#define max(a, b)   (((a) > (b)) ? (a) : (b))
#define SE_VALID_CONTROL_BITS
#define ProbeAndReadUlongUM(Address)   (*(volatile ULONG *)(Address))
#define MAX_CHILD_SID_GROUP_SIZE   3
#define EFFECTIVE_ACE   INHERIT_ONLY_ACE
#define AceFlagsInAce(_Ace)

Enumerations

enum  ACE_TYPE_TO_COPY { CopyInheritedAces, CopyNonInheritedAces, CopyAllAces }

Functions

ULONG RtlLengthUsedSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor)
NTSYSAPI BOOLEAN NTAPI RtlEqualLuid (PLUID Luid1, PLUID Luid2)
NTSTATUS RtlpConvertAclToAutoInherit (IN PACL ParentAcl OPTIONAL, IN PACL ChildAcl, IN GUID *ObjectType OPTIONAL, IN BOOLEAN IsDirectoryObject, IN PSID OwnerSid, IN PSID GroupSid, IN PGENERIC_MAPPING GenericMapping, OUT PACL *NewAcl, OUT PULONG NewGenericControl)
BOOLEAN RtlpCopyEffectiveAce (IN PACE_HEADER OldAce, IN BOOLEAN AutoInherit, IN BOOLEAN WillGenerateInheritAce, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN GUID *NewObjectType OPTIONAL, IN OUT PVOID *AcePosition, OUT PULONG NewAceLength, OUT PACL NewAcl, OUT PBOOLEAN ObjectAceInherited OPTIONAL, OUT PBOOLEAN EffectiveAceMapped, OUT PBOOLEAN AclOverflowed)
NTSTATUS RtlpCopyAces (IN PACL Acl, IN PGENERIC_MAPPING GenericMapping, IN ACE_TYPE_TO_COPY AceTypeToCopy, IN UCHAR AceFlagsToReset, IN BOOLEAN MapSids, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, OUT PULONG NewAclSizeParam, OUT PACL NewAcl)
NTSTATUS RtlpGenerateInheritedAce (IN PACE_HEADER OldAce, IN BOOLEAN IsDirectoryObject, IN BOOLEAN AutoInherit, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN GUID *NewObjectType OPTIONAL, OUT PULONG NewAceLength, OUT PACL NewAcl, OUT PULONG NewAceExtraLength, OUT PBOOLEAN ObjectAceInherited)
NTSTATUS RtlpGenerateInheritAcl (IN PACL Acl, IN BOOLEAN IsDirectoryObject, IN BOOLEAN AutoInherit, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN GUID *NewObjectType OPTIONAL, OUT PULONG NewAclSizeParam, OUT PACL NewAcl, OUT PBOOLEAN ObjectAceInherited)
NTSTATUS RtlpInheritAcl2 (IN PACL DirectoryAcl, IN PACL ChildAcl, IN ULONG ChildGenericControl, IN BOOLEAN IsDirectoryObject, IN BOOLEAN AutoInherit, IN BOOLEAN DefaultDescriptorForObject, IN PSID OwnerSid, IN PSID GroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN IsSacl, IN GUID *NewObjectType OPTIONAL, IN PULONG AclBufferSize, IN OUT PUCHAR AclBuffer, OUT PBOOLEAN NewAclExplicitlyAssigned, OUT PULONG NewGenericControl)
NTSTATUS RtlpComputeMergedAcl (IN PACL CurrentAcl, IN ULONG CurrentGenericControl, IN PACL ModificationAcl, IN ULONG ModificationGenericControl, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN IsSacl, OUT PACL *NewAcl, OUT PULONG NewGenericControl)
NTSTATUS RtlpComputeMergedAcl2 (IN PACL CurrentAcl, IN ULONG CurrentGenericControl, IN PACL ModificationAcl, IN ULONG ModificationGenericControl, IN PSID ClientOwnerSid, IN PSID ClientGroupSid, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN IsSacl, IN PULONG AclBufferSize, IN OUT PUCHAR AclBuffer, OUT PULONG NewGenericControl)
BOOLEAN RtlpCompareAces (IN PKNOWN_ACE InheritedAce, IN PKNOWN_ACE ChildAce, IN PSID OwnerSid, IN PSID GroupSid)
BOOLEAN RtlpCompareKnownObjectAces (IN PKNOWN_OBJECT_ACE InheritedAce, IN PKNOWN_OBJECT_ACE ChildAce, IN PSID OwnerSid OPTIONAL, IN PSID GroupSid OPTIONAL)
BOOLEAN RtlpCompareKnownAces (IN PKNOWN_ACE InheritedAce, IN PKNOWN_ACE ChildAce, IN PSID OwnerSid OPTIONAL, IN PSID GroupSid OPTIONAL)
BOOLEAN RtlpIsDuplicateAce (IN PACL Acl, IN PKNOWN_ACE NewAce, IN GUID *ObjectType OPTIONAL)
NTSTATUS RtlpCreateServerAcl (IN PACL Acl, IN BOOLEAN AclUntrusted, IN PSID ServerSid, OUT PACL *ServerAcl, OUT BOOLEAN *ServerAclAllocated)
NTSTATUS RtlpGetDefaultsSubjectContext (HANDLE ClientToken, OUT PTOKEN_OWNER *OwnerInfo, OUT PTOKEN_PRIMARY_GROUP *GroupInfo, OUT PTOKEN_DEFAULT_DACL *DefaultDaclInfo, OUT PTOKEN_OWNER *ServerOwner, OUT PTOKEN_PRIMARY_GROUP *ServerGroup)
BOOLEAN RtlpValidateSDOffsetAndSize (IN ULONG Offset, IN ULONG Length, IN ULONG MinLength, OUT PULONG MaxLength)
BOOLEAN RtlValidRelativeSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, IN ULONG SecurityDescriptorLength, IN SECURITY_INFORMATION RequiredInformation)
VOID RtlRunEncodeUnicodeString (PUCHAR Seed OPTIONAL, PUNICODE_STRING String)
VOID RtlRunDecodeUnicodeString (UCHAR Seed, PUNICODE_STRING String)
VOID RtlEraseUnicodeString (PUNICODE_STRING String)
NTSTATUS RtlAdjustPrivilege (ULONG Privilege, BOOLEAN Enable, BOOLEAN Client, PBOOLEAN WasEnabled)
BOOLEAN RtlValidSid (IN PSID Sid)
BOOLEAN RtlEqualSid (IN PSID Sid1, IN PSID Sid2)
BOOLEAN RtlEqualPrefixSid (IN PSID Sid1, IN PSID Sid2)
ULONG RtlLengthRequiredSid (IN ULONG SubAuthorityCount)
NTSTATUS RtlAllocateAndInitializeSid (IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid)
NTSTATUS RtlInitializeSid (IN PSID Sid, IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount)
PVOID RtlFreeSid (IN PSID Sid)
PSID_IDENTIFIER_AUTHORITY RtlIdentifierAuthoritySid (IN PSID Sid)
PULONG RtlSubAuthoritySid (IN PSID Sid, IN ULONG SubAuthority)
PUCHAR RtlSubAuthorityCountSid (IN PSID Sid)
ULONG RtlLengthSid (IN PSID Sid)
NTSTATUS RtlCopySid (IN ULONG DestinationSidLength, OUT PSID DestinationSid, IN PSID SourceSid)
NTSTATUS RtlCopySidAndAttributesArray (IN ULONG ArrayLength, IN PSID_AND_ATTRIBUTES Source, IN ULONG TargetSidBufferSize, OUT PSID_AND_ATTRIBUTES TargetArrayElement, OUT PSID TargetSid, OUT PSID *NextTargetSid, OUT PULONG RemainingTargetSidBufferSize)
NTSTATUS RtlLengthSidAsUnicodeString (PSID Sid, PULONG StringLength)
NTSTATUS RtlConvertSidToUnicodeString (PUNICODE_STRING UnicodeString, PSID Sid, BOOLEAN AllocateDestinationString)
BOOLEAN RtlEqualLuid (IN PLUID Luid1, IN PLUID Luid2)
VOID RtlCopyLuid (OUT PLUID DestinationLuid, IN PLUID SourceLuid)
VOID RtlCopyLuidAndAttributesArray (IN ULONG ArrayLength, IN PLUID_AND_ATTRIBUTES Source, OUT PLUID_AND_ATTRIBUTES Target)
NTSTATUS RtlCreateSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Revision)
NTSTATUS RtlCreateSecurityDescriptorRelative (IN PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, IN ULONG Revision)
BOOLEAN RtlValidSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor)
ULONG RtlLengthSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor)
NTSTATUS RtlSetAttributesSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision)
NTSTATUS RtlGetControlSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSECURITY_DESCRIPTOR_CONTROL Control, OUT PULONG Revision)
NTSTATUS RtlSetControlSecurityDescriptor (IN PSECURITY_DESCRIPTOR pSecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
NTSTATUS RtlSetDaclSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN DaclPresent, IN PACL Dacl OPTIONAL, IN BOOLEAN DaclDefaulted OPTIONAL)
NTSTATUS RtlGetDaclSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN DaclPresent, OUT PACL *Dacl, OUT PBOOLEAN DaclDefaulted)
NTSTATUS RtlSetSaclSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN SaclPresent, IN PACL Sacl OPTIONAL, IN BOOLEAN SaclDefaulted OPTIONAL)
NTSTATUS RtlGetSaclSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PBOOLEAN SaclPresent, OUT PACL *Sacl, OUT PBOOLEAN SaclDefaulted)
NTSTATUS RtlSetOwnerSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Owner OPTIONAL, IN BOOLEAN OwnerDefaulted OPTIONAL)
NTSTATUS RtlGetOwnerSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
NTSTATUS RtlSetGroupSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group OPTIONAL, IN BOOLEAN GroupDefaulted OPTIONAL)
NTSTATUS RtlGetGroupSecurityDescriptor (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Group, OUT PBOOLEAN GroupDefaulted)
BOOLEAN RtlAreAllAccessesGranted (IN ACCESS_MASK GrantedAccess, IN ACCESS_MASK DesiredAccess)
BOOLEAN RtlAreAnyAccessesGranted (IN ACCESS_MASK GrantedAccess, IN ACCESS_MASK DesiredAccess)
VOID RtlMapGenericMask (IN OUT PACCESS_MASK AccessMask, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS RtlImpersonateSelf (IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
BOOLEAN RtlpValidOwnerSubjectContext (IN HANDLE Token, IN PSID Owner, IN BOOLEAN ServerObject, OUT PNTSTATUS ReturnStatus)
VOID RtlpApplyAclToObject (IN PACL Acl, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS RtlpInheritAcl (IN PACL DirectoryAcl, IN PACL ChildAcl, IN ULONG ChildGenericControl, IN BOOLEAN IsDirectoryObject, IN BOOLEAN AutoInherit, IN BOOLEAN DefaultDescriptorForObject, IN PSID OwnerSid, IN PSID GroupSid, IN PSID ServerOwnerSid OPTIONAL, IN PSID ServerGroupSid OPTIONAL, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN IsSacl, IN GUID *NewObjectType OPTIONAL, OUT PACL *NewAcl, OUT PBOOLEAN NewAclExplicitlyAssigned, OUT PULONG NewGenericControl)
NTSTATUS RtlpConvertToAutoInheritSecurityObject (IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR CurrentSecurityDescriptor, OUT PSECURITY_DESCRIPTOR *NewSecurityDescriptor, IN GUID *ObjectType OPTIONAL, IN BOOLEAN IsDirectoryObject, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS RtlpNewSecurityObject (IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL, OUT PSECURITY_DESCRIPTOR *NewDescriptor, IN GUID *ObjectType OPTIONAL, IN BOOLEAN IsDirectoryObject, IN ULONG AutoInheritFlags, IN HANDLE Token OPTIONAL, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS RtlpSetSecurityObject (IN PVOID Object OPTIONAL, IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR ModificationDescriptor, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, IN ULONG AutoInheritFlags, IN ULONG PoolType, IN PGENERIC_MAPPING GenericMapping, IN HANDLE Token OPTIONAL)
BOOLEAN RtlGetSecurityDescriptorRMControl (IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PUCHAR RMControl)
VOID RtlSetSecurityDescriptorRMControl (IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PUCHAR RMControl OPTIONAL)

Variables

UCHAR RtlBaseAceType []
UCHAR RtlIsSystemAceType []
BOOLEAN RtlpVerboseConvert = FALSE


Define Documentation

#define AceFlagsInAce _Ace   ) 
 

Value:

(((PACE_HEADER)(_Ace))->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE) | \ (((PACE_HEADER)(_Ace))->AceFlags & INHERIT_ONLY_ACE) ^ INHERIT_ONLY_ACE )

Definition at line 6966 of file sertl.c.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), and RtlpConvertAclToAutoInherit().

#define CREATOR_SID_SIZE   12
 

Definition at line 330 of file sertl.c.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpConvertAclToAutoInherit(), RtlpCopyEffectiveAce(), and RtlpGenerateInheritedAce().

#define EFFECTIVE_ACE   INHERIT_ONLY_ACE
 

Definition at line 6965 of file sertl.c.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), and RtlpConvertAclToAutoInherit().

#define max a,
 )     (((a) > (b)) ? (a) : (b))
 

Definition at line 332 of file sertl.c.

Referenced by _CreateEmptyCursorObject(), _MapWindowPoints(), ArbGetNextAllocationRange(), CalcSBStuff2(), CheckPlacementBounds(), ComboBoxWndProcWorker(), CommandListPopup(), ComputeSecPerCluster(), ConvertToFullScreen(), Create_LH_ProfileSet(), CreateRedirectionBitmap(), CreateScreenBuffer(), DrawCommandListPopup(), DrawStateW(), ECCalcChangeSelection(), ECFindXORblks(), ECImeComposition(), ECSetPasswordChar(), ECTabTheTextOut(), FdGetMinimumSizeMB(), GetDeskWallpaperName(), GetWallpaperCenterRect(), GetWindowLimits(), HorizontalScroll(), InitCreateUserSubsystem(), IntersectRect(), InvertPixels(), IopCreateArcNames(), IopMakeGloballyUniqueId(), IopStartNetworkForRemoteBoot(), KeConnectInterrupt(), KeDisconnectInterrupt(), KeSetTimeIncrement(), KiIpiGenericCall(), LastFullVisible(), LBCalcItemRowsAndColumns(), LBPage(), ListBoxWndProcWorker(), MLBuildchLines(), MLCalcXOffset(), MLDeleteText(), MLDrawText(), MLEditWndProc(), MLIchToLine(), MLInsertText(), MLMouseToIch(), MLScroll(), MLSetCaretPosition(), ParkIcon(), PositionConsoleWindow(), ProcessDeviceChanges(), RtlpComputeMergedAcl2(), RtlpConvertAclToAutoInherit(), RtlpGenerateInheritAcl(), RtlpGenerateInheritedAce(), RtlpInheritAcl2(), RW_RegisterControls(), SelectInputContext(), SetIconMetrics(), SetMinMetrics(), SLCalcXOffsetSpecial(), SLChar(), SLDrawLine(), SLSetCaretPosition(), SmoothScrollWindowEx(), SoftModalMessageBox(), StreamScrollRegion(), UnionRect(), UpdateUserScreen(), VerticalScroll(), WowGetDefWindowProcBits(), WWSB_ConsolePolyTextOut(), WWSB_WriteRegionToScreen(), WWSB_WriteToScreen(), xxxAdjustSize(), xxxAlterHilite(), xxxAnimateCaption(), xxxArrangeIconicWindows(), xxxBNDrawText(), xxxCBCalcControlRects(), xxxCBSetEditItemHeight(), xxxCBShowListBoxWindow(), xxxDrawMenuBarTemp(), xxxDrawMenuItem(), xxxDrawState(), xxxInitSendValidateMinMaxInfo(), xxxInsureVisible(), xxxLBBinarySearchString(), xxxLBSelRange(), xxxLBSize(), xxxMNCompute(), xxxMNItemSize(), xxxMNPositionHierarchy(), xxxMouseEventDirect(), xxxMS_TrackMove(), xxxNextAniIconStep(), xxxRealDrawMenuItem(), xxxSetLBScrollParms(), xxxSetNCFonts(), xxxSetStaticImage(), xxxSetWindowNCMetrics(), xxxSystemParametersInfo(), xxxTrackMouse(), and zzzClipCursor().

#define MAX_CHILD_SID_GROUP_SIZE   3
 

Definition at line 6964 of file sertl.c.

#define ProbeAndReadUlongUM Address   )     (*(volatile ULONG *)(Address))
 

Referenced by RtlValidSid().

#define SE_VALID_CONTROL_BITS
 

Value:

( SE_DACL_UNTRUSTED | \ SE_SERVER_SECURITY | \ SE_DACL_AUTO_INHERIT_REQ | \ SE_SACL_AUTO_INHERIT_REQ | \ SE_DACL_AUTO_INHERITED | \ SE_SACL_AUTO_INHERITED | \ SE_DACL_PROTECTED | \ SE_SACL_PROTECTED )

Definition at line 370 of file sertl.c.

Referenced by RtlSetAttributesSecurityDescriptor(), and RtlSetControlSecurityDescriptor().


Enumeration Type Documentation

enum ACE_TYPE_TO_COPY
 

Enumeration values:
CopyInheritedAces 
CopyNonInheritedAces 
CopyAllAces 

Definition at line 89 of file sertl.c.

Referenced by RtlpInheritAcl2().


Function Documentation

NTSTATUS RtlAdjustPrivilege ULONG  Privilege,
BOOLEAN  Enable,
BOOLEAN  Client,
PBOOLEAN  WasEnabled
 

Definition at line 639 of file sertl.c.

References ANYSIZE_ARRAY, ASSERT, Buffer1, Buffer2, FALSE, NT_SUCCESS, NtAdjustPrivilegesToken(), NtClose(), NtOpenProcessToken(), NtOpenThreadToken(), NTSTATUS(), RTL_PAGED_CODE, Status, Token, and TRUE.

Referenced by main().

00648 : 00649 00650 This procedure enables or disables a privilege process-wide. 00651 00652 Arguments: 00653 00654 Privilege - The lower 32-bits of the privilege ID to be enabled or 00655 disabled. The upper 32-bits is assumed to be zero. 00656 00657 Enable - A boolean indicating whether the privilege is to be enabled 00658 or disabled. TRUE indicates the privilege is to be enabled. 00659 FALSE indicates the privilege is to be disabled. 00660 00661 Client - A boolean indicating whether the privilege should be adjusted 00662 in a client token or the process's own token. TRUE indicates 00663 the client's token should be used (and an error returned if there 00664 is no client token). FALSE indicates the process's token should 00665 be used. 00666 00667 WasEnabled - points to a boolean to receive an indication of whether 00668 the privilege was previously enabled or disabled. TRUE indicates 00669 the privilege was previously enabled. FALSE indicates the privilege 00670 was previoulsy disabled. This value is useful for returning the 00671 privilege to its original state after using it. 00672 00673 00674 Return Value: 00675 00676 STATUS_SUCCESS - The privilege has been sucessfully enabled or disabled. 00677 00678 STATUS_PRIVILEGE_NOT_HELD - The privilege is not held by the specified context. 00679 00680 Other status values as may be returned by: 00681 00682 NtOpenProcessToken() 00683 NtAdjustPrivilegesToken() 00684 00685 00686 --*/ 00687 00688 { 00689 NTSTATUS 00690 Status, 00691 TmpStatus; 00692 00693 HANDLE 00694 Token; 00695 00696 LUID 00697 LuidPrivilege; 00698 00699 PTOKEN_PRIVILEGES 00700 NewPrivileges, 00701 OldPrivileges; 00702 00703 ULONG 00704 Length; 00705 00706 UCHAR 00707 Buffer1[sizeof(TOKEN_PRIVILEGES)+ 00708 ((1-ANYSIZE_ARRAY)*sizeof(LUID_AND_ATTRIBUTES))], 00709 Buffer2[sizeof(TOKEN_PRIVILEGES)+ 00710 ((1-ANYSIZE_ARRAY)*sizeof(LUID_AND_ATTRIBUTES))]; 00711 00712 00713 RTL_PAGED_CODE(); 00714 00715 NewPrivileges = (PTOKEN_PRIVILEGES)Buffer1; 00716 OldPrivileges = (PTOKEN_PRIVILEGES)Buffer2; 00717 00718 // 00719 // Open the appropriate token... 00720 // 00721 00722 if (Client == TRUE) { 00723 Status = NtOpenThreadToken( 00724 NtCurrentThread(), 00725 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 00726 FALSE, 00727 &Token 00728 ); 00729 } else { 00730 00731 Status = NtOpenProcessToken( 00732 NtCurrentProcess(), 00733 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 00734 &Token 00735 ); 00736 } 00737 00738 if (!NT_SUCCESS(Status)) { 00739 return(Status); 00740 } 00741 00742 00743 00744 // 00745 // Initialize the privilege adjustment structure 00746 // 00747 00748 LuidPrivilege = RtlConvertUlongToLuid(Privilege); 00749 00750 00751 NewPrivileges->PrivilegeCount = 1; 00752 NewPrivileges->Privileges[0].Luid = LuidPrivilege; 00753 NewPrivileges->Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0; 00754 00755 00756 00757 // 00758 // Adjust the privilege 00759 // 00760 00761 Status = NtAdjustPrivilegesToken( 00762 Token, // TokenHandle 00763 FALSE, // DisableAllPrivileges 00764 NewPrivileges, // NewPrivileges 00765 sizeof(Buffer1), // BufferLength 00766 OldPrivileges, // PreviousState (OPTIONAL) 00767 &Length // ReturnLength 00768 ); 00769 00770 00771 TmpStatus = NtClose(Token); 00772 ASSERT(NT_SUCCESS(TmpStatus)); 00773 00774 00775 // 00776 // Map the success code NOT_ALL_ASSIGNED to an appropriate error 00777 // since we're only trying to adjust the one privilege. 00778 // 00779 00780 if (Status == STATUS_NOT_ALL_ASSIGNED) { 00781 Status = STATUS_PRIVILEGE_NOT_HELD; 00782 } 00783 00784 00785 if (NT_SUCCESS(Status)) { 00786 00787 // 00788 // If there are no privileges in the previous state, there were 00789 // no changes made. The previous state of the privilege 00790 // is whatever we tried to change it to. 00791 // 00792 00793 if (OldPrivileges->PrivilegeCount == 0) { 00794 00795 (*WasEnabled) = Enable; 00796 00797 } else { 00798 00799 (*WasEnabled) = 00800 (OldPrivileges->Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) 00801 ? TRUE : FALSE; 00802 } 00803 } 00804 00805 return(Status); 00806 }

NTSTATUS RtlAllocateAndInitializeSid IN PSID_IDENTIFIER_AUTHORITY  IdentifierAuthority,
IN UCHAR  SubAuthorityCount,
IN ULONG  SubAuthority0,
IN ULONG  SubAuthority1,
IN ULONG  SubAuthority2,
IN ULONG  SubAuthority3,
IN ULONG  SubAuthority4,
IN ULONG  SubAuthority5,
IN ULONG  SubAuthority6,
IN ULONG  SubAuthority7,
OUT PSID *  Sid
 

Definition at line 1062 of file sertl.c.

References NULL, RTL_PAGED_CODE, RtlAllocateHeap, and RtlLengthRequiredSid().

Referenced by CreateBSMEventSD(), and CsrpConnectToServer().

01078 : 01079 01080 This function allocates and initializes a sid with the specified 01081 number of sub-authorities (up to 8). A sid allocated with this 01082 routine must be freed using RtlFreeSid(). 01083 01084 THIS ROUTINE IS CURRENTLY NOT CALLABLE FROM KERNEL MODE. 01085 01086 Arguments: 01087 01088 IdentifierAuthority - Pointer to the Identifier Authority value to 01089 set in the SID. 01090 01091 SubAuthorityCount - The number of sub-authorities to place in the SID. 01092 This also identifies how many of the SubAuthorityN parameters 01093 have meaningful values. This must contain a value from 0 through 01094 8. 01095 01096 SubAuthority0-7 - Provides the corresponding sub-authority value to 01097 place in the SID. For example, a SubAuthorityCount value of 3 01098 indicates that SubAuthority0, SubAuthority1, and SubAuthority0 01099 have meaningful values and the rest are to be ignored. 01100 01101 Sid - Receives a pointer to the SID data structure to initialize. 01102 01103 Return Value: 01104 01105 STATUS_SUCCESS - The SID has been allocated and initialized. 01106 01107 STATUS_NO_MEMORY - The attempt to allocate memory for the SID 01108 failed. 01109 01110 STATUS_INVALID_SID - The number of sub-authorities specified did 01111 not fall in the valid range for this api (0 through 8). 01112 01113 01114 --*/ 01115 { 01116 PISID ISid; 01117 01118 RTL_PAGED_CODE(); 01119 01120 if ( SubAuthorityCount > 8 ) { 01121 return( STATUS_INVALID_SID ); 01122 } 01123 01124 ISid = RtlAllocateHeap( RtlProcessHeap(), 0, 01125 RtlLengthRequiredSid(SubAuthorityCount) 01126 ); 01127 if (ISid == NULL) { 01128 return(STATUS_NO_MEMORY); 01129 } 01130 01131 ISid->SubAuthorityCount = (UCHAR)SubAuthorityCount; 01132 ISid->Revision = 1; 01133 ISid->IdentifierAuthority = *IdentifierAuthority; 01134 01135 switch (SubAuthorityCount) { 01136 01137 case 8: 01138 ISid->SubAuthority[7] = SubAuthority7; 01139 case 7: 01140 ISid->SubAuthority[6] = SubAuthority6; 01141 case 6: 01142 ISid->SubAuthority[5] = SubAuthority5; 01143 case 5: 01144 ISid->SubAuthority[4] = SubAuthority4; 01145 case 4: 01146 ISid->SubAuthority[3] = SubAuthority3; 01147 case 3: 01148 ISid->SubAuthority[2] = SubAuthority2; 01149 case 2: 01150 ISid->SubAuthority[1] = SubAuthority1; 01151 case 1: 01152 ISid->SubAuthority[0] = SubAuthority0; 01153 case 0: 01154 ; 01155 } 01156 01157 (*Sid) = ISid; 01158 return( STATUS_SUCCESS ); 01159 01160 } #endif // NTOS_KERNEL_RUNTIME

BOOLEAN RtlAreAllAccessesGranted IN ACCESS_MASK  GrantedAccess,
IN ACCESS_MASK  DesiredAccess
 

Definition at line 3309 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by _BlockInput(), CheckGrantedAccess(), CheckWinstaWriteAttributesAccess(), InitiateShutdown(), xxxInternalKeyEventDirect(), xxxSetProcessWindowStation(), and zzzSetWindowsHookEx().

03316 : 03317 03318 This routine is used to check a desired access mask against a 03319 granted access mask. It is used by the Object Management 03320 component when dereferencing a handle. 03321 03322 Arguments: 03323 03324 GrantedAccess - Specifies the granted access mask. 03325 03326 DesiredAccess - Specifies the desired access mask. 03327 03328 Return Value: 03329 03330 BOOLEAN - TRUE if the GrantedAccess mask has all the bits set 03331 that the DesiredAccess mask has set. That is, TRUE is 03332 returned if all of the desired accesses have been granted. 03333 03334 --*/ 03335 03336 { 03337 RTL_PAGED_CODE(); 03338 03339 return ((BOOLEAN)((~(GrantedAccess) & (DesiredAccess)) == 0)); 03340 }

BOOLEAN RtlAreAnyAccessesGranted IN ACCESS_MASK  GrantedAccess,
IN ACCESS_MASK  DesiredAccess
 

Definition at line 3344 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by NtUserGetAsyncKeyState().

03351 : 03352 03353 This routine is used to test whether any of a set of desired 03354 accesses are granted by a granted access mask. It is used by 03355 components other than the the Object Management component for 03356 checking access mask subsets. 03357 03358 Arguments: 03359 03360 GrantedAccess - Specifies the granted access mask. 03361 03362 DesiredAccess - Specifies the desired access mask. 03363 03364 Return Value: 03365 03366 BOOLEAN - TRUE if the GrantedAccess mask contains any of the bits 03367 specified in the DesiredAccess mask. That is, if any of the 03368 desired accesses have been granted, TRUE is returned. 03369 03370 03371 --*/ 03372 03373 { 03374 RTL_PAGED_CODE(); 03375 03376 return ((BOOLEAN)(((GrantedAccess) & (DesiredAccess)) != 0)); 03377 }

NTSTATUS RtlConvertSidToUnicodeString PUNICODE_STRING  UnicodeString,
PSID  Sid,
BOOLEAN  AllocateDestinationString
 

Definition at line 1611 of file sertl.c.

References L, NT_SUCCESS, NTSTATUS(), Offset, RTL_PAGED_CODE, RtlCopyUnicodeString(), RtlCreateUnicodeString(), RtlIntegerToUnicode(), RtlLargeIntegerToUnicode(), RtlValidSid(), Status, TRUE, and USHORT.

Referenced by RtlFormatCurrentUserKeyPath().

01619 : 01620 01621 01622 This function generates a printable unicode string representation 01623 of a SID. 01624 01625 The resulting string will take one of two forms. If the 01626 IdentifierAuthority value is not greater than 2^32, then 01627 the SID will be in the form: 01628 01629 01630 S-1-281736-12-72-9-110 01631 ^ ^^ ^^ ^ ^^^ 01632 | | | | | 01633 +-----+--+-+--+---- Decimal 01634 01635 01636 01637 Otherwise it will take the form: 01638 01639 01640 S-1-0x173495281736-12-72-9-110 01641 ^^^^^^^^^^^^^^ ^^ ^^ ^ ^^^ 01642 Hexidecimal | | | | 01643 +--+-+--+---- Decimal 01644 01645 01646 01647 01648 01649 01650 Arguments: 01651 01652 01653 01654 UnicodeString - Returns a unicode string that is equivalent to 01655 the SID. The maximum length field is only set if 01656 AllocateDestinationString is TRUE. 01657 01658 Sid - Supplies the SID that is to be converted to unicode. 01659 01660 AllocateDestinationString - Supplies a flag that controls whether or 01661 not this API allocates the buffer space for the destination 01662 string. If it does, then the buffer must be deallocated using 01663 RtlFreeUnicodeString (note that only storage for 01664 DestinationString->Buffer is allocated by this API). 01665 01666 Return Value: 01667 01668 SUCCESS - The conversion was successful 01669 01670 STATUS_INVALID_SID - The sid provided does not have a valid structure, 01671 or has too many sub-authorities (more than SID_MAX_SUB_AUTHORITIES). 01672 01673 STATUS_NO_MEMORY - There was not sufficient memory to allocate the 01674 target string. This is returned only if AllocateDestinationString 01675 is specified as TRUE. 01676 01677 STATUS_BUFFER_OVERFLOW - This is returned only if 01678 AllocateDestinationString is specified as FALSE. 01679 01680 01681 --*/ 01682 01683 { 01684 NTSTATUS Status; 01685 WCHAR UniBuffer[ 256 ]; 01686 PWSTR Offset ; 01687 UNICODE_STRING LocalString ; 01688 01689 UCHAR i; 01690 ULONG Tmp; 01691 LARGE_INTEGER Auth ; 01692 01693 PISID iSid = (PISID)Sid; // pointer to opaque structure 01694 01695 01696 RTL_PAGED_CODE(); 01697 01698 if (RtlValidSid( Sid ) != TRUE) { 01699 return(STATUS_INVALID_SID); 01700 } 01701 01702 if ( iSid->Revision != SID_REVISION ) 01703 { 01704 return STATUS_INVALID_SID ; 01705 } 01706 01707 wcscpy( UniBuffer, L"S-1-" ); 01708 01709 Offset = &UniBuffer[ 4 ]; 01710 01711 if ( (iSid->IdentifierAuthority.Value[0] != 0) || 01712 (iSid->IdentifierAuthority.Value[1] != 0) ){ 01713 01714 // 01715 // Ugly hex dump. 01716 // 01717 01718 Auth.HighPart = (LONG) (iSid->IdentifierAuthority.Value[ 0 ] << 8) + 01719 (LONG) iSid->IdentifierAuthority.Value[ 1 ] ; 01720 01721 Auth.LowPart = (ULONG)iSid->IdentifierAuthority.Value[5] + 01722 (ULONG)(iSid->IdentifierAuthority.Value[4] << 8) + 01723 (ULONG)(iSid->IdentifierAuthority.Value[3] << 16) + 01724 (ULONG)(iSid->IdentifierAuthority.Value[2] << 24); 01725 01726 Status = RtlLargeIntegerToUnicode( 01727 &Auth, 01728 16, 01729 256 - (LONG) (Offset - UniBuffer), 01730 Offset ); 01731 01732 01733 } else { 01734 01735 Tmp = (ULONG)iSid->IdentifierAuthority.Value[5] + 01736 (ULONG)(iSid->IdentifierAuthority.Value[4] << 8) + 01737 (ULONG)(iSid->IdentifierAuthority.Value[3] << 16) + 01738 (ULONG)(iSid->IdentifierAuthority.Value[2] << 24); 01739 01740 Status = RtlIntegerToUnicode( 01741 Tmp, 01742 10, 01743 256 - (LONG) (Offset - UniBuffer), 01744 Offset ); 01745 01746 } 01747 01748 if ( !NT_SUCCESS( Status ) ) 01749 { 01750 return Status ; 01751 } 01752 01753 01754 for (i=0;i<iSid->SubAuthorityCount ;i++ ) { 01755 01756 while ( *Offset && ( Offset < &UniBuffer[ 255 ] ) ) 01757 { 01758 Offset++ ; 01759 } 01760 01761 *Offset++ = L'-' ; 01762 01763 Status = RtlIntegerToUnicode( 01764 iSid->SubAuthority[ i ], 01765 10, 01766 256 - (LONG) (Offset - UniBuffer), 01767 Offset ); 01768 01769 if ( !NT_SUCCESS( Status ) ) 01770 { 01771 return Status ; 01772 } 01773 } 01774 01775 if ( AllocateDestinationString ) 01776 { 01777 if ( RtlCreateUnicodeString( UnicodeString, 01778 UniBuffer ) ) 01779 { 01780 Status = STATUS_SUCCESS ; 01781 } 01782 else 01783 { 01784 Status = STATUS_NO_MEMORY ; 01785 } 01786 01787 } 01788 else 01789 { 01790 01791 while ( *Offset && ( Offset < &UniBuffer[ 255 ] ) ) 01792 { 01793 Offset++ ; 01794 } 01795 01796 Tmp = (ULONG) (Offset - UniBuffer) * sizeof( WCHAR ); 01797 01798 if ( Tmp < UnicodeString->MaximumLength ) 01799 { 01800 LocalString.Length = (USHORT) Tmp ; 01801 LocalString.MaximumLength = LocalString.Length + sizeof( WCHAR ); 01802 LocalString.Buffer = UniBuffer ; 01803 01804 RtlCopyUnicodeString( 01805 UnicodeString, 01806 &LocalString ); 01807 01808 Status = STATUS_SUCCESS ; 01809 } 01810 else 01811 { 01812 Status = STATUS_BUFFER_OVERFLOW ; 01813 } 01814 01815 } 01816 01817 return(Status); 01818 }

VOID RtlCopyLuid OUT PLUID  DestinationLuid,
IN PLUID  SourceLuid
 

Definition at line 1863 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by NtCreateToken().

01870 : 01871 01872 This routine copies the value of the source LUID to the 01873 destination LUID. 01874 01875 Arguments: 01876 01877 DestinationLuid - Receives a copy of the source Luid value. 01878 01879 SourceLuid - Supplies the Luid value to be copied. This LUID is 01880 assumed to be structurally valid. 01881 01882 Return Value: 01883 01884 None. 01885 01886 --*/ 01887 01888 { 01889 RTL_PAGED_CODE(); 01890 01891 (*DestinationLuid) = (*SourceLuid); 01892 return; 01893 }

VOID RtlCopyLuidAndAttributesArray IN ULONG  ArrayLength,
IN PLUID_AND_ATTRIBUTES  Source,
OUT PLUID_AND_ATTRIBUTES  Target
 

Definition at line 1896 of file sertl.c.

References Index, and RTL_PAGED_CODE.

Referenced by NtQueryInformationToken(), SepFilterToken(), and SeQueryInformationToken().

01904 : 01905 01906 This routine copies the value of the source LUID_AND_ATTRIBUTES array 01907 to the target. 01908 01909 Arguments: 01910 01911 ArrayLength - Number of elements in the source array to copy. 01912 01913 Source - The source array. 01914 01915 Target - Indicates where the array elements are to be copied to. 01916 01917 01918 Return Value: 01919 01920 None. 01921 01922 01923 --*/ 01924 01925 { 01926 01927 ULONG Index = 0; 01928 01929 RTL_PAGED_CODE(); 01930 01931 while (Index < ArrayLength) { 01932 01933 Target[Index] = Source[Index]; 01934 01935 Index += 1; 01936 01937 } //end_while 01938 01939 01940 return; 01941 01942 }

NTSTATUS RtlCopySid IN ULONG  DestinationSidLength,
OUT PSID  DestinationSid,
IN PSID  SourceSid
 

Definition at line 1380 of file sertl.c.

References RTL_PAGED_CODE, and SeLengthSid.

Referenced by AllocAce(), CreateDAclToken(), GenerateDescriptor(), GetSiteSidFromToken(), NtCloseObjectAuditAlarm(), NtDeleteObjectAuditAlarm(), NtQueryInformationToken(), RtlAddCompoundAce(), RtlCopySidAndAttributesArray(), RtlpAddKnownAce(), RtlpAddKnownObjectAce(), RtlpInitializeAllowedAce(), RtlpInitializeAuditAce(), RtlpInitializeDeniedAce(), RtlpNewSecurityObject(), SepAdjustGroups(), SepCreateToken(), SeQueryInformationToken(), TestSeAclRtl(), TestSeSid(), TSeVariableInitialization(), and xxxCreateWindowStation().

01388 : 01389 01390 This routine copies the value of the source SID to the destination 01391 SID. 01392 01393 Arguments: 01394 01395 DestinationSidLength - Indicates the length, in bytes, of the 01396 destination SID buffer. 01397 01398 DestinationSid - Pointer to a buffer to receive a copy of the 01399 source Sid value. 01400 01401 SourceSid - Supplies the Sid value to be copied. 01402 01403 Return Value: 01404 01405 STATUS_SUCCESS - Indicates the SID was successfully copied. 01406 01407 STATUS_BUFFER_TOO_SMALL - Indicates the target buffer wasn't 01408 large enough to receive a copy of the SID. 01409 01410 01411 --*/ 01412 01413 { 01414 ULONG SidLength = SeLengthSid(SourceSid); 01415 01416 RTL_PAGED_CODE(); 01417 01418 if (SidLength > DestinationSidLength) { 01419 01420 return STATUS_BUFFER_TOO_SMALL; 01421 01422 } 01423 01424 // 01425 // Buffer is large enough 01426 // 01427 01428 RtlMoveMemory( DestinationSid, SourceSid, SidLength ); 01429 01430 return STATUS_SUCCESS; 01431 01432 }

NTSTATUS RtlCopySidAndAttributesArray IN ULONG  ArrayLength,
IN PSID_AND_ATTRIBUTES  Source,
IN ULONG  TargetSidBufferSize,
OUT PSID_AND_ATTRIBUTES  TargetArrayElement,
OUT PSID  TargetSid,
OUT PSID *  NextTargetSid,
OUT PULONG  RemainingTargetSidBufferSize
 

Definition at line 1436 of file sertl.c.

References Index, LongAlign, RTL_PAGED_CODE, RtlCopySid(), and SeLengthSid.

Referenced by NtQueryInformationJobObject(), NtQueryInformationToken(), SepCreateToken(), SepFilterToken(), SeQueryInformationToken(), and TestSeSid().

01448 : 01449 01450 This routine copies the value of the source SID_AND_ATTRIBUTES array 01451 to the target. The actual SID values are placed according to a separate 01452 parameter. This allows multiple arrays to be merged using this service 01453 to copy each. 01454 01455 Arguments: 01456 01457 ArrayLength - Number of elements in the source array to copy. 01458 01459 Source - Pointer to the source array. 01460 01461 TargetSidBufferSize - Indicates the length, in bytes, of the buffer 01462 to receive the actual SID values. If this value is less than 01463 the actual amount needed, then STATUS_BUFFER_TOO_SMALL is returned. 01464 01465 TargetArrayElement - Indicates where the array elements are to be 01466 copied to (but not the SID values themselves). 01467 01468 TargetSid - Indicates where the target SID values s are to be copied. This 01469 is assumed to be ULONG aligned. Each SID value will be copied 01470 into this buffer. Each SID will be ULONG aligned. 01471 01472 NextTargetSid - On completion, will be set to point to the ULONG 01473 aligned address following the last SID copied. 01474 01475 RemainingTargetSidBufferSize - On completion, receives an indicatation 01476 of how much of the SID buffer is still unused. 01477 01478 01479 Return Value: 01480 01481 STATUS_SUCCESS - The call completed successfully. 01482 01483 STATUS_BUFFER_TOO_SMALL - Indicates the buffer to receive the SID 01484 values wasn't large enough. 01485 01486 01487 01488 --*/ 01489 01490 { 01491 01492 ULONG Index = 0; 01493 PSID NextSid = TargetSid; 01494 ULONG NextSidLength; 01495 ULONG AlignedSidLength; 01496 ULONG RemainingLength = TargetSidBufferSize; 01497 01498 RTL_PAGED_CODE(); 01499 01500 while (Index < ArrayLength) { 01501 01502 NextSidLength = SeLengthSid( Source[Index].Sid ); 01503 AlignedSidLength = PtrToUlong(LongAlign(NextSidLength)); 01504 01505 if (NextSidLength > RemainingLength) { 01506 return STATUS_BUFFER_TOO_SMALL; 01507 } 01508 01509 RemainingLength -= AlignedSidLength; 01510 01511 TargetArrayElement[Index].Sid = NextSid; 01512 TargetArrayElement[Index].Attributes = Source[Index].Attributes; 01513 01514 RtlCopySid( NextSidLength, NextSid, Source[Index].Sid ); 01515 01516 NextSid = (PSID)((PCHAR)NextSid + AlignedSidLength); 01517 01518 Index += 1; 01519 01520 } //end_while 01521 01522 (*NextTargetSid) = NextSid; 01523 (*RemainingTargetSidBufferSize) = RemainingLength; 01524 01525 return STATUS_SUCCESS; 01526 01527 }

NTSTATUS RtlCreateSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN ULONG  Revision
 

Definition at line 1945 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by CmpHiveRootSecurityDescriptor(), CreateBSMEventSD(), CreateDAclToken(), CreateSecurityDescriptor(), GenerateDescriptor(), InternalCreateCallbackThread(), IoCreateUnprotectedSymbolicLink(), IopApplySystemPartitionProt(), IopCreateDefaultDeviceSecurityDescriptor(), IopInitializePlugPlayServices(), IopOpenDeviceParametersSubkey(), NtOpenThreadToken(), ObInitSystem(), ObpGetDosDevicesProtection(), RtlCreateAndSetSD(), RtlpNewSecurityObject(), RtlQuerySecurityObject(), SeMakeAnonymousLogonToken(), SeMakeSystemToken(), SepInitializationPhase1(), SepInitSystemDacls(), SeRmInitPhase1(), SmbTraceStart(), TestSeAccess(), TestSeNamedCreate(), TestSeSecurityDescriptor(), and TestTokenInitialize().

01952 : 01953 01954 This procedure initializes a new "absolute format" security descriptor. 01955 After the procedure call the security descriptor is initialized with no 01956 system ACL, no discretionary ACL, no owner, no primary group and 01957 all control flags set to false (null). 01958 01959 Arguments: 01960 01961 01962 SecurityDescriptor - Supplies the security descriptor to 01963 initialize. 01964 01965 Revision - Provides the revision level to assign to the security 01966 descriptor. This should be one (1) for this release. 01967 01968 Return Value: 01969 01970 STATUS_SUCCESS - Indicates the call completed successfully. 01971 01972 STATUS_UNKNOWN_REVISION - Indicates the revision level provided 01973 is not supported by this routine. 01974 01975 --*/ 01976 01977 { 01978 RTL_PAGED_CODE(); 01979 01980 // 01981 // Check the requested revision 01982 // 01983 01984 if (Revision == SECURITY_DESCRIPTOR_REVISION) { 01985 01986 // 01987 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 01988 // 01989 01990 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 01991 01992 RtlZeroMemory( ISecurityDescriptor, sizeof(SECURITY_DESCRIPTOR)); 01993 01994 ISecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION; 01995 01996 return STATUS_SUCCESS; 01997 } 01998 01999 return STATUS_UNKNOWN_REVISION; 02000 }

NTSTATUS RtlCreateSecurityDescriptorRelative IN PISECURITY_DESCRIPTOR_RELATIVE  SecurityDescriptor,
IN ULONG  Revision
 

Definition at line 2004 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by RtlpConvertToAutoInheritSecurityObject(), RtlpNewSecurityObject(), RtlpSetSecurityObject(), SeAssignWorldSecurityDescriptor(), and SeQuerySecurityDescriptorInfo().

02011 : 02012 02013 This procedure initializes a new "relative format" security descriptor. 02014 After the procedure call the security descriptor is initialized with no 02015 system ACL, no discretionary ACL, no owner, no primary group and 02016 all control flags set to false (null). 02017 02018 Arguments: 02019 02020 02021 SecurityDescriptor - Supplies the security descriptor to 02022 initialize. 02023 02024 Revision - Provides the revision level to assign to the security 02025 descriptor. This should be one (1) for this release. 02026 02027 Return Value: 02028 02029 STATUS_SUCCESS - Indicates the call completed successfully. 02030 02031 STATUS_UNKNOWN_REVISION - Indicates the revision level provided 02032 is not supported by this routine. 02033 02034 Note: 02035 Warning, this code assume the caller allocated a relative security 02036 descriptor rather than a relative one. Absolute is larger on systems 02037 with 64-bit pointers. 02038 02039 --*/ 02040 02041 { 02042 RTL_PAGED_CODE(); 02043 02044 // 02045 // Check the requested revision 02046 // 02047 02048 if (Revision == SECURITY_DESCRIPTOR_REVISION) { 02049 02050 // 02051 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02052 // 02053 02054 RtlZeroMemory( SecurityDescriptor, sizeof(SECURITY_DESCRIPTOR_RELATIVE)); 02055 02056 SecurityDescriptor->Revision = SECURITY_DESCRIPTOR_REVISION; 02057 02058 return STATUS_SUCCESS; 02059 } 02060 02061 return STATUS_UNKNOWN_REVISION; 02062 }

BOOLEAN RtlEqualLuid IN PLUID  Luid1,
IN PLUID  Luid2
 

Definition at line 1824 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by _UserTestForWinStaAccess(), CheckAllowForeground(), EndShutdown(), InitiateShutdown(), InitPreviousUserString(), NotifyLogon(), NtUserPostThreadMessage(), OpenDesktopCompletion(), RtlNewInstanceSecurityObject(), SeIsChildToken(), SeIsChildTokenByPointer(), SeMarkLogonSessionForTerminationNotification(), SepAdjustPrivileges(), SepCreateLogonSessionTrack(), SepCreateToken(), SepDeleteLogonSessionTrack(), SepDeReferenceLogonSession(), SepFilterPrivilegeAudits(), SepPrivilegeCheck(), SepReferenceLogonSession(), SepRemoveDisabledGroupsAndPrivileges(), SetWindowStationUser(), TestForInteractiveUser(), TestpCompareDuplicateToken(), TestTokenOpenPrimary(), TestTokenQuery(), xxxCallHook2(), xxxCreateDesktop2(), xxxProcessNotifyWinEvent(), xxxUpdatePerUserAccessPackSettings(), and zzzSetWindowsHookEx().

01831 : 01832 01833 This procedure test two LUID values for equality. 01834 01835 This routine is here for backwards compatibility only. New code 01836 should use the macro. 01837 01838 Arguments: 01839 01840 Luid1, Luid2 - Supply pointers to the two LUID values to compare. 01841 01842 Return Value: 01843 01844 BOOLEAN - TRUE if the value of Luid1 is equal to Luid2, and FALSE 01845 otherwise. 01846 01847 01848 --*/ 01849 01850 { 01851 LUID UNALIGNED * TempLuid1; 01852 LUID UNALIGNED * TempLuid2; 01853 01854 RTL_PAGED_CODE(); 01855 01856 return((Luid1->HighPart == Luid2->HighPart) && 01857 (Luid1->LowPart == Luid2->LowPart)); 01858 01859 }

NTSYSAPI BOOLEAN NTAPI RtlEqualLuid PLUID  Luid1,
PLUID  Luid2
 

BOOLEAN RtlEqualPrefixSid IN PSID  Sid1,
IN PSID  Sid2
 

Definition at line 924 of file sertl.c.

References FALSE, Index, RTL_PAGED_CODE, and TRUE.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), and RtlpCopyEffectiveAce().

00931 : 00932 00933 This procedure tests two SID prefix values for equality. 00934 00935 An SID prefix is the entire SID except for the last sub-authority 00936 value. 00937 00938 Arguments: 00939 00940 Sid1, Sid2 - Supply pointers to the two SID values to compare. 00941 The SID structures are assumed to be valid. 00942 00943 Return Value: 00944 00945 BOOLEAN - TRUE if the prefix value of Sid1 is equal to Sid2, and FALSE 00946 otherwise. 00947 00948 --*/ 00949 00950 00951 { 00952 LONG Index; 00953 00954 // 00955 // Typecast to the opaque SID structures. 00956 // 00957 00958 SID *ISid1 = Sid1; 00959 SID *ISid2 = Sid2; 00960 00961 RTL_PAGED_CODE(); 00962 00963 // 00964 // Make sure they are the same revision 00965 // 00966 00967 if (ISid1->Revision == ISid2->Revision ) { 00968 00969 // 00970 // Compare IdentifierAuthority values 00971 // 00972 00973 if ( (ISid1->IdentifierAuthority.Value[0] == 00974 ISid2->IdentifierAuthority.Value[0]) && 00975 (ISid1->IdentifierAuthority.Value[1]== 00976 ISid2->IdentifierAuthority.Value[1]) && 00977 (ISid1->IdentifierAuthority.Value[2] == 00978 ISid2->IdentifierAuthority.Value[2]) && 00979 (ISid1->IdentifierAuthority.Value[3] == 00980 ISid2->IdentifierAuthority.Value[3]) && 00981 (ISid1->IdentifierAuthority.Value[4] == 00982 ISid2->IdentifierAuthority.Value[4]) && 00983 (ISid1->IdentifierAuthority.Value[5] == 00984 ISid2->IdentifierAuthority.Value[5]) 00985 ) { 00986 00987 // 00988 // Compare SubAuthorityCount values 00989 // 00990 00991 if (ISid1->SubAuthorityCount == ISid2->SubAuthorityCount) { 00992 00993 if (ISid1->SubAuthorityCount == 0) { 00994 return TRUE; 00995 } 00996 00997 Index = 0; 00998 while (Index < (ISid1->SubAuthorityCount - 1)) { 00999 if ((ISid1->SubAuthority[Index]) != (ISid2->SubAuthority[Index])) { 01000 01001 // 01002 // Found some SubAuthority values that weren't equal. 01003 // 01004 01005 return FALSE; 01006 } 01007 Index += 1; 01008 } 01009 01010 // 01011 // All SubAuthority values are equal. 01012 // 01013 01014 return TRUE; 01015 } 01016 } 01017 } 01018 01019 // 01020 // Either the Revision, SubAuthorityCount, or IdentifierAuthority values 01021 // weren't equal. 01022 // 01023 01024 return FALSE; 01025 }

BOOLEAN RtlEqualSid IN PSID  Sid1,
IN PSID  Sid2
 

Definition at line 871 of file sertl.c.

References FALSE, RTL_PAGED_CODE, RtlSubAuthorityCountSid(), and SeLengthSid.

Referenced by IopCreateDefaultDeviceSecurityDescriptor(), IopOpenDeviceParametersSubkey(), NtSecureConnectPort(), NtSetInformationToken(), RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpValidOwnerSubjectContext(), SeFastTraverseCheck(), SepAdjustGroups(), SepAdtPrivilegeObjectAuditAlarm(), SepCreateToken(), SepIdAssignableAsGroup(), SepMakeTokenEffectiveOnly(), SepRemoveDisabledGroupsAndPrivileges(), SePrivilegedServiceAuditAlarm(), SepSidInSidAndAttributes(), SepSidInToken(), SepSidInTokenEx(), SepSidTranslation(), SepValidOwnerSubjectContext(), SidTranslation(), TestpCompareDuplicateToken(), TestSeAclRtl(), TestSeSid(), TestTokenQuery(), and TestTokenSet().

00878 : 00879 00880 This procedure tests two SID values for equality. 00881 00882 Arguments: 00883 00884 Sid1, Sid2 - Supply pointers to the two SID values to compare. 00885 The SID structures are assumed to be valid. 00886 00887 Return Value: 00888 00889 BOOLEAN - TRUE if the value of Sid1 is equal to Sid2, and FALSE 00890 otherwise. 00891 00892 --*/ 00893 00894 { 00895 ULONG SidLength; 00896 00897 RTL_PAGED_CODE(); 00898 00899 // 00900 // Make sure they are the same revision 00901 // 00902 00903 if ( ((SID *)Sid1)->Revision == ((SID *)Sid2)->Revision ) { 00904 00905 // 00906 // Check the SubAuthorityCount first, because it's fast and 00907 // can help us exit faster. 00908 // 00909 00910 if ( *RtlSubAuthorityCountSid( Sid1 ) == *RtlSubAuthorityCountSid( Sid2 )) { 00911 00912 SidLength = SeLengthSid( Sid1 ); 00913 return( (BOOLEAN)RtlEqualMemory( Sid1, Sid2, SidLength) ); 00914 } 00915 } 00916 00917 return( FALSE ); 00918 00919 }

VOID RtlEraseUnicodeString PUNICODE_STRING  String  ) 
 

Definition at line 596 of file sertl.c.

References NULL, RTL_PAGED_CODE, and String.

00601 : 00602 00603 This function scrubs the passed string by over-writing all 00604 characters in the string. The entire string (i.e., MaximumLength) 00605 is erased, not just the current length. 00606 00607 00608 Argumen ts: 00609 00610 String - The string to be erased. 00611 00612 00613 Return Value: 00614 00615 None - Nothing can really go wrong unless the caller passes bogus 00616 parameters. In this case, the caller can catch the access 00617 violation. 00618 00619 00620 --*/ 00621 00622 { 00623 RTL_PAGED_CODE(); 00624 00625 if ((String->Buffer == NULL) || (String->MaximumLength == 0)) { 00626 return; 00627 } 00628 00629 RtlZeroMemory( (PVOID)String->Buffer, (ULONG)String->MaximumLength ); 00630 00631 String->Length = 0; 00632 00633 return; 00634 }

PVOID RtlFreeSid IN PSID  Sid  ) 
 

Definition at line 1218 of file sertl.c.

References NULL, RTL_PAGED_CODE, and RtlFreeHeap.

Referenced by CreateBSMEventSD(), CsrpConnectToServer(), and InitializeRestrictedStuff().

01224 : 01225 01226 This function is used to free a SID previously allocated using 01227 RtlAllocateAndInitializeSid(). 01228 01229 THIS ROUTINE IS CURRENTLY NOT CALLABLE FROM KERNEL MODE. 01230 01231 Arguments: 01232 01233 Sid - Pointer to the SID to free. 01234 01235 Return Value: 01236 01237 None. 01238 01239 01240 --*/ 01241 { 01242 RTL_PAGED_CODE(); 01243 01244 if (RtlFreeHeap( RtlProcessHeap(), 0, Sid )) 01245 return NULL; 01246 else 01247 return Sid; 01248 } #endif // NTOS_KERNEL_RUNTIME

NTSTATUS RtlGetControlSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PSECURITY_DESCRIPTOR_CONTROL  Control,
OUT PULONG  Revision
 

Definition at line 2415 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by TestSeSecurityDescriptor().

02423 : 02424 02425 This procedure retrieves the control information from a security descriptor. 02426 02427 Arguments: 02428 02429 SecurityDescriptor - Supplies the security descriptor. 02430 02431 Control - Receives the control information. 02432 02433 Revision - Receives the revision of the security descriptor. 02434 This value will always be returned, even if an error 02435 is returned by this routine. 02436 02437 Return Value: 02438 02439 STATUS_SUCCESS - Indicates the call completed successfully. 02440 02441 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 02442 descriptor is not known to the routine. It may be a newer 02443 revision than the routine knows about. 02444 02445 02446 --*/ 02447 02448 { 02449 RTL_PAGED_CODE(); 02450 02451 // 02452 // Always return the revision value - even if this isn't a valid 02453 // security descriptor 02454 // 02455 02456 *Revision = ((SECURITY_DESCRIPTOR *)SecurityDescriptor)->Revision; 02457 02458 02459 if ( ((SECURITY_DESCRIPTOR *)SecurityDescriptor)->Revision 02460 != SECURITY_DESCRIPTOR_REVISION ) { 02461 return STATUS_UNKNOWN_REVISION; 02462 } 02463 02464 02465 *Control = ((SECURITY_DESCRIPTOR *)SecurityDescriptor)->Control; 02466 02467 return STATUS_SUCCESS; 02468 02469 }

NTSTATUS RtlGetDaclSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PBOOLEAN  DaclPresent,
OUT PACL *  Dacl,
OUT PBOOLEAN  DaclDefaulted
 

Definition at line 2665 of file sertl.c.

References Dacl, and RTL_PAGED_CODE.

Referenced by DumpSecurity(), IopChangeDeviceObjectFromRegistryProperties(), IopOpenDeviceParametersSubkey(), IopSetSecurityObjectFromRegistry(), ObpFreeDosDevicesProtection(), ObpHashSecurityDescriptor(), and TestSeSecurityDescriptor().

02674 : 02675 02676 This procedure retrieves the discretionary ACL information of a 02677 security descriptor. 02678 02679 Arguments: 02680 02681 SecurityDescriptor - Supplies the security descriptor. 02682 02683 DaclPresent - If TRUE, indicates that the security descriptor 02684 does contain a discretionary ACL. In this case, the 02685 remaining OUT parameters will receive valid values. 02686 Otherwise, the security descriptor does not contain a 02687 discretionary ACL and the remaining OUT parameters will not 02688 receive valid values. 02689 02690 Dacl - This value is returned only if the value returned for the 02691 DaclPresent flag is TRUE. In this case, the Dacl parameter 02692 receives the address of the security descriptor's 02693 discretionary ACL. If this value is returned as null, then 02694 the security descriptor has a null discretionary ACL. 02695 02696 DaclDefaulted - This value is returned only if the value returned 02697 for the DaclPresent flag is TRUE. In this case, the 02698 DaclDefaulted parameter receives the value of the security 02699 descriptor's DaclDefaulted control flag. 02700 02701 Return Value: 02702 02703 STATUS_SUCCESS - Indicates the call completed successfully. 02704 02705 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 02706 descriptor is not known to the routine. It may be a newer 02707 revision than the routine knows about. 02708 02709 02710 --*/ 02711 02712 { 02713 // 02714 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02715 // 02716 02717 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 02718 02719 RTL_PAGED_CODE(); 02720 02721 // 02722 // Check the revision 02723 // 02724 02725 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 02726 return STATUS_UNKNOWN_REVISION; 02727 } 02728 02729 // 02730 // Assign the DaclPresent flag value 02731 // 02732 02733 *DaclPresent = RtlpAreControlBitsSet( ISecurityDescriptor, SE_DACL_PRESENT ); 02734 02735 if (*DaclPresent) { 02736 02737 // 02738 // Assign the ACL address. 02739 // 02740 02741 *Dacl = RtlpDaclAddrSecurityDescriptor(ISecurityDescriptor); 02742 02743 // 02744 // Assign DaclDefaulted flag. 02745 // 02746 02747 *DaclDefaulted = RtlpAreControlBitsSet( ISecurityDescriptor, SE_DACL_DEFAULTED ); 02748 } 02749 02750 return STATUS_SUCCESS; 02751 02752 }

NTSTATUS RtlGetGroupSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PSID *  Group,
OUT PBOOLEAN  GroupDefaulted
 

Definition at line 3232 of file sertl.c.

References Group, and RTL_PAGED_CODE.

Referenced by IopChangeDeviceObjectFromRegistryProperties(), IopSetSecurityObjectFromRegistry(), ObpHashSecurityDescriptor(), and TestSeSecurityDescriptor().

03240 : 03241 03242 This procedure retrieves the primary group information of a 03243 security descriptor. 03244 03245 Arguments: 03246 03247 SecurityDescriptor - Supplies the security descriptor. 03248 03249 Group - Receives a pointer to the primary group SID. If the 03250 security descriptor does not currently contain a primary 03251 group, then this value will be returned as null. In this 03252 case, the remaining OUT parameters are not given valid return 03253 values. Otherwise, this parameter points to an SID and the 03254 remaining OUT parameters are provided valid return values. 03255 03256 GroupDefaulted - This value is returned only if the value 03257 returned for the Group parameter is not null. In this case, 03258 the GroupDefaulted parameter receives the value of the 03259 security descriptor's GroupDefaulted control flag. 03260 03261 Return Value: 03262 03263 STATUS_SUCCESS - Indicates the call completed successfully. 03264 03265 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 03266 descriptor is not known to the routine. It may be a newer 03267 revision than the routine knows about. 03268 03269 03270 --*/ 03271 03272 { 03273 03274 // 03275 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 03276 // 03277 03278 SECURITY_DESCRIPTOR *ISecurityDescriptor = 03279 (SECURITY_DESCRIPTOR *)SecurityDescriptor; 03280 03281 RTL_PAGED_CODE(); 03282 03283 // 03284 // Check the revision 03285 // 03286 03287 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 03288 return STATUS_UNKNOWN_REVISION; 03289 } 03290 03291 // 03292 // Return the Group field value. 03293 // 03294 03295 *Group = RtlpGroupAddrSecurityDescriptor(ISecurityDescriptor); 03296 03297 // 03298 // Return the GroupDefaulted flag value. 03299 // 03300 03301 *GroupDefaulted = RtlpAreControlBitsSet( ISecurityDescriptor, SE_GROUP_DEFAULTED ); 03302 03303 return STATUS_SUCCESS; 03304 03305 }

NTSTATUS RtlGetOwnerSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PSID *  Owner,
OUT PBOOLEAN  OwnerDefaulted
 

Definition at line 3059 of file sertl.c.

References Owner, and RTL_PAGED_CODE.

Referenced by IopChangeDeviceObjectFromRegistryProperties(), IopSetSecurityObjectFromRegistry(), ObpHashSecurityDescriptor(), and TestSeSecurityDescriptor().

03067 : 03068 03069 This procedure retrieves the owner information of a security 03070 descriptor. 03071 03072 Arguments: 03073 03074 SecurityDescriptor - Supplies the security descriptor. 03075 03076 Owner - Receives a pointer to the owner SID. If the security 03077 descriptor does not currently contain an owner, then this 03078 value will be returned as null. In this case, the remaining 03079 OUT parameters are not given valid return values. Otherwise, 03080 this parameter points to an SID and the remaining OUT 03081 parameters are provided valid return values. 03082 03083 OwnerDefaulted - This value is returned only if the value 03084 returned for the Owner parameter is not null. In this case, 03085 the OwnerDefaulted parameter receives the value of the 03086 security descriptor's OwnerDefaulted control flag. 03087 03088 Return Value: 03089 03090 STATUS_SUCCESS - Indicates the call completed successfully. 03091 03092 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 03093 descriptor is not known to the routine. It may be a newer 03094 revision than the routine knows about. 03095 03096 03097 --*/ 03098 03099 { 03100 03101 // 03102 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 03103 // 03104 03105 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 03106 03107 RTL_PAGED_CODE(); 03108 03109 // 03110 // Check the revision 03111 // 03112 03113 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 03114 return STATUS_UNKNOWN_REVISION; 03115 } 03116 03117 // 03118 // Return the Owner field value. 03119 // 03120 03121 *Owner = RtlpOwnerAddrSecurityDescriptor(ISecurityDescriptor); 03122 03123 // 03124 // Return the OwnerDefaulted flag value. 03125 // 03126 03127 *OwnerDefaulted = RtlpAreControlBitsSet( ISecurityDescriptor, SE_OWNER_DEFAULTED ); 03128 03129 return STATUS_SUCCESS; 03130 03131 }

NTSTATUS RtlGetSaclSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PBOOLEAN  SaclPresent,
OUT PACL *  Sacl,
OUT PBOOLEAN  SaclDefaulted
 

Definition at line 2871 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by IopChangeDeviceObjectFromRegistryProperties(), IopSetSecurityObjectFromRegistry(), ObpHashSecurityDescriptor(), and TestSeSecurityDescriptor().

02880 : 02881 02882 This procedure retrieves the system ACL information of a security 02883 descriptor. 02884 02885 Arguments: 02886 02887 SecurityDescriptor - Supplies the security descriptor. 02888 02889 SaclPresent - If TRUE, indicates that the security descriptor 02890 does contain a system ACL. In this case, the remaining OUT 02891 parameters will receive valid values. Otherwise, the 02892 security descriptor does not contain a system ACL and the 02893 remaining OUT parameters will not receive valid values. 02894 02895 Sacl - This value is returned only if the value returned for the 02896 SaclPresent flag is TRUE. In this case, the Sacl parameter 02897 receives the address of the security descriptor's system ACL. 02898 If this value is returned as null, then the security 02899 descriptor has a null system ACL. 02900 02901 SaclDefaulted - This value is returned only if the value returned 02902 for the SaclPresent flag is TRUE. In this case, the 02903 SaclDefaulted parameter receives the value of the security 02904 descriptor's SaclDefaulted control flag. 02905 02906 Return Value: 02907 02908 STATUS_SUCCESS - Indicates the call completed successfully. 02909 02910 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 02911 descriptor is not known to the routine. It may be a newer 02912 revision than the routine knows about. 02913 02914 02915 --*/ 02916 02917 { 02918 02919 // 02920 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02921 // 02922 02923 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 02924 02925 RTL_PAGED_CODE(); 02926 02927 // 02928 // Check the revision 02929 // 02930 02931 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 02932 return STATUS_UNKNOWN_REVISION; 02933 } 02934 02935 // 02936 // Assign the SaclPresent flag value 02937 // 02938 02939 *SaclPresent = RtlpAreControlBitsSet( ISecurityDescriptor, SE_SACL_PRESENT ); 02940 02941 if (*SaclPresent) { 02942 02943 // 02944 // Assign the ACL address. 02945 // 02946 02947 *Sacl = RtlpSaclAddrSecurityDescriptor(ISecurityDescriptor); 02948 02949 // 02950 // Assign SaclDefaulted flag. 02951 // 02952 02953 *SaclDefaulted = RtlpAreControlBitsSet( ISecurityDescriptor, SE_SACL_DEFAULTED ); 02954 02955 } 02956 02957 return STATUS_SUCCESS; 02958 02959 }

BOOLEAN RtlGetSecurityDescriptorRMControl IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
OUT PUCHAR  RMControl
 

Definition at line 11323 of file sertl.c.

References FALSE, and TRUE.

11330 : 11331 11332 This procedure returns the RM Control flags from a SecurityDescriptor if 11333 SE_RM_CONTROL_VALID flags is present in the control field. 11334 11335 Arguments: 11336 11337 SecurityDescriptor - Pointer to the SECURITY_DESCRIPTOR structure 11338 RMControl - Returns the flags in the SecurityDescriptor if 11339 SE_RM_CONTROL_VALID is set in the control bits of the 11340 SecurityDescriptor. 11341 11342 11343 Return Value: 11344 11345 BOOLEAN - TRUE if SE_RM_CONTROL_VALID is set in the Control bits of the 11346 SecurityDescriptor. 11347 11348 Note: 11349 Parameter validation has already been done in Advapi. 11350 11351 11352 --*/ 11353 11354 { 11355 PISECURITY_DESCRIPTOR ISecurityDescriptor = (PISECURITY_DESCRIPTOR) SecurityDescriptor; 11356 11357 if (!(ISecurityDescriptor->Control & SE_RM_CONTROL_VALID)) 11358 { 11359 *RMControl = 0; 11360 return FALSE; 11361 } 11362 11363 *RMControl = ISecurityDescriptor->Sbz1; 11364 11365 return TRUE; 11366 }

PSID_IDENTIFIER_AUTHORITY RtlIdentifierAuthoritySid IN PSID  Sid  ) 
 

Definition at line 1253 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by DisplayAccountSid().

01258 : 01259 01260 This function returns the address of an SID's IdentifierAuthority field. 01261 01262 Arguments: 01263 01264 Sid - Pointer to the SID data structure. 01265 01266 Return Value: 01267 01268 01269 --*/ 01270 { 01271 PISID ISid; 01272 01273 RTL_PAGED_CODE(); 01274 01275 // 01276 // Typecast to the opaque SID 01277 // 01278 01279 ISid = (PISID)Sid; 01280 01281 return &(ISid->IdentifierAuthority); 01282 01283 }

NTSTATUS RtlImpersonateSelf IN SECURITY_IMPERSONATION_LEVEL  ImpersonationLevel  ) 
 

Definition at line 3446 of file sertl.c.

References FALSE, NT_SUCCESS, NtClose(), NtDuplicateToken(), NtOpenProcessToken(), NtSetInformationThread(), NTSTATUS(), NULL, ObjectAttributes, RTL_PAGED_CODE, and Status.

03452 : 03453 03454 This routine may be used to obtain an Impersonation token representing 03455 your own process's context. This may be useful for enabling a privilege 03456 for a single thread rather than for the entire process; or changing 03457 the default DACL for a single thread. 03458 03459 The token is assigned to the callers thread. 03460 03461 03462 03463 Arguments: 03464 03465 ImpersonationLevel - The level to make the impersonation token. 03466 03467 03468 03469 Return Value: 03470 03471 STATUS_SUCCESS - The thread is now impersonating the calling process. 03472 03473 Other - Status values returned by: 03474 03475 NtOpenProcessToken() 03476 NtDuplicateToken() 03477 NtSetInformationThread() 03478 03479 --*/ 03480 03481 { 03482 NTSTATUS 03483 Status, 03484 IgnoreStatus; 03485 03486 HANDLE 03487 Token1, 03488 Token2; 03489 03490 OBJECT_ATTRIBUTES 03491 ObjectAttributes; 03492 03493 SECURITY_QUALITY_OF_SERVICE 03494 Qos; 03495 03496 03497 RTL_PAGED_CODE(); 03498 03499 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL); 03500 03501 Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 03502 Qos.ImpersonationLevel = ImpersonationLevel; 03503 Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 03504 Qos.EffectiveOnly = FALSE; 03505 ObjectAttributes.SecurityQualityOfService = &Qos; 03506 03507 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE, &Token1 ); 03508 03509 if (NT_SUCCESS(Status)) { 03510 Status = NtDuplicateToken( 03511 Token1, 03512 TOKEN_IMPERSONATE, 03513 &ObjectAttributes, 03514 FALSE, //EffectiveOnly 03515 TokenImpersonation, 03516 &Token2 03517 ); 03518 if (NT_SUCCESS(Status)) { 03519 Status = NtSetInformationThread( 03520 NtCurrentThread(), 03521 ThreadImpersonationToken, 03522 &Token2, 03523 sizeof(HANDLE) 03524 ); 03525 03526 IgnoreStatus = NtClose( Token2 ); 03527 } 03528 03529 03530 IgnoreStatus = NtClose( Token1 ); 03531 } 03532 03533 03534 return(Status); 03535 03536 }

NTSTATUS RtlInitializeSid IN PSID  Sid,
IN PSID_IDENTIFIER_AUTHORITY  IdentifierAuthority,
IN UCHAR  SubAuthorityCount
 

Definition at line 1166 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by CmpHiveRootSecurityDescriptor(), GenerateDescriptor(), InitVars(), RtlDefaultNpAcl(), RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpConvertAclToAutoInherit(), RtlpCopyEffectiveAce(), SepVariableInitialization(), TestSeAclRtl(), TestTokenSet(), and TSeVariableInitialization().

01173 : 01174 01175 This function initializes an SID data structure. It does not, however, 01176 set the sub-authority values. This must be done separately. 01177 01178 Arguments: 01179 01180 Sid - Pointer to the SID data structure to initialize. 01181 01182 IdentifierAuthority - Pointer to the Identifier Authority value to 01183 set in the SID. 01184 01185 SubAuthorityCount - The number of sub-authorities that will be placed in 01186 the SID (a separate action). 01187 01188 Return Value: 01189 01190 01191 --*/ 01192 { 01193 PISID ISid; 01194 01195 RTL_PAGED_CODE(); 01196 01197 // 01198 // Typecast to the opaque SID 01199 // 01200 01201 ISid = (PISID)Sid; 01202 01203 if ( SubAuthorityCount > SID_MAX_SUB_AUTHORITIES ) { 01204 return( STATUS_INVALID_PARAMETER ); 01205 } 01206 01207 ISid->SubAuthorityCount = (UCHAR)SubAuthorityCount; 01208 ISid->Revision = 1; 01209 ISid->IdentifierAuthority = *IdentifierAuthority; 01210 01211 return( STATUS_SUCCESS ); 01212 01213 }

ULONG RtlLengthRequiredSid IN ULONG  SubAuthorityCount  ) 
 

Definition at line 1030 of file sertl.c.

References L, and RTL_PAGED_CODE.

Referenced by CmpHiveRootSecurityDescriptor(), GenerateDescriptor(), InitVars(), NtQueryQuotaInformationFile(), RtlAllocateAndInitializeSid(), RtlDefaultNpAcl(), RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpConvertAclToAutoInherit(), RtlpCopyEffectiveAce(), RtlpGenerateInheritedAce(), RtlpSetSecurityObject(), SeCaptureSecurityDescriptor(), SeCaptureSid(), SeCaptureSidAndAttributesArray(), SepCreateToken(), SepVariableInitialization(), TestSeAclRtl(), TestSeSid(), TestTokenSet(), and TSeVariableInitialization().

01036 : 01037 01038 This routine returns the length, in bytes, required to store an SID 01039 with the specified number of Sub-Authorities. 01040 01041 Arguments: 01042 01043 SubAuthorityCount - The number of sub-authorities to be stored in the SID. 01044 01045 Return Value: 01046 01047 ULONG - The length, in bytes, required to store the SID. 01048 01049 01050 --*/ 01051 01052 { 01053 RTL_PAGED_CODE(); 01054 01055 return (8L + (4 * SubAuthorityCount)); 01056 01057 }

ULONG RtlLengthSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor  ) 
 

Definition at line 2165 of file sertl.c.

References NULL, RTL_PAGED_CODE, and SeLengthSid.

Referenced by CmpAssignSecurityDescriptor(), CmpFindMatchingDescriptorCell(), CmpSetSecurityDescriptorInfo(), EhpAttachSecurity(), NtQueryObject(), ObpCompareSecurityDescriptors(), ObpCreateCacheEntry(), and TestSeSecurityDescriptor().

02171 : 02172 02173 This routine returns the length, in bytes, necessary to capture a 02174 structurally valid SECURITY_DESCRIPTOR. The length includes the length 02175 of all associated data structures (like SIDs and ACLs). The length also 02176 takes into account the alignment requirements of each component. 02177 02178 The minimum length of a security descriptor (one which has no associated 02179 SIDs or ACLs) is SECURITY_DESCRIPTOR_MIN_LENGTH. 02180 02181 02182 Arguments: 02183 02184 SecurityDescriptor - Points to the SECURITY_DESCRIPTOR whose 02185 length is to be returned. The SECURITY_DESCRIPTOR's 02186 structure is assumed to be valid. 02187 02188 Return Value: 02189 02190 ULONG - The length, in bytes, of the SECURITY_DESCRIPTOR. 02191 02192 02193 --*/ 02194 02195 { 02196 ULONG sum; 02197 PVOID Temp; 02198 02199 02200 // 02201 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02202 // 02203 02204 SECURITY_DESCRIPTOR *ISecurityDescriptor = (SECURITY_DESCRIPTOR *)SecurityDescriptor; 02205 02206 RTL_PAGED_CODE(); 02207 02208 // 02209 // The length is the sum of the following: 02210 // 02211 // SECURITY_DESCRIPTOR_MIN_LENGTH (or sizeof(SECURITY_DESCRIPTOR)) 02212 // length of Owner SID (if present) 02213 // length of Group SID (if present) 02214 // length of Discretionary ACL (if present and non-null) 02215 // length of System ACL (if present and non-null) 02216 // 02217 02218 sum = ISecurityDescriptor->Control & SE_SELF_RELATIVE ? 02219 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 02220 sizeof(SECURITY_DESCRIPTOR); 02221 02222 // 02223 // Add in length of Owner SID 02224 // 02225 02226 Temp = RtlpOwnerAddrSecurityDescriptor(ISecurityDescriptor); 02227 if (Temp != NULL) { 02228 sum += LongAlignSize(SeLengthSid(Temp)); 02229 } 02230 02231 // 02232 // Add in length of Group SID 02233 // 02234 02235 Temp = RtlpGroupAddrSecurityDescriptor(ISecurityDescriptor); 02236 if (Temp != NULL) { 02237 sum += LongAlignSize(SeLengthSid(Temp)); 02238 } 02239 02240 // 02241 // Add in used length of Discretionary ACL 02242 // 02243 02244 Temp = RtlpDaclAddrSecurityDescriptor(ISecurityDescriptor); 02245 if ( Temp != NULL ) { 02246 02247 sum += LongAlignSize(((PACL) Temp)->AclSize ); 02248 } 02249 02250 // 02251 // Add in used length of System Acl 02252 // 02253 02254 Temp = RtlpSaclAddrSecurityDescriptor(ISecurityDescriptor); 02255 if ( Temp != NULL ) { 02256 02257 sum += LongAlignSize(((PACL) Temp)->AclSize ); 02258 } 02259 02260 return sum; 02261 }

ULONG RtlLengthSid IN PSID  Sid  ) 
 

Definition at line 1350 of file sertl.c.

References RTL_PAGED_CODE, and SeLengthSid.

Referenced by _GetUserObjectInformation(), AllocAce(), CreateBSMEventSD(), GetSiteSidFromToken(), IoCheckQuotaBufferValidity(), IopCheckGetQuotaBufferValidity(), IopInitializePlugPlayServices(), IopOpenDeviceParametersSubkey(), ObpGetDosDevicesProtection(), ObpHashSecurityDescriptor(), RtlCreateAndSetSD(), RtlDefaultNpAcl(), RtlpInitializeAllowedAce(), RtlpInitializeAuditAce(), RtlpInitializeDeniedAce(), SeCaptureSidAndAttributesArray(), and xxxCreateWindowStation().

01356 : 01357 01358 This routine returns the length, in bytes, of a structurally valid SID. 01359 01360 Arguments: 01361 01362 Sid - Points to the SID whose length is to be returned. The 01363 SID's structure is assumed to be valid. 01364 01365 Return Value: 01366 01367 ULONG - The length, in bytes, of the SID. 01368 01369 01370 --*/ 01371 01372 { 01373 RTL_PAGED_CODE(); 01374 01375 return SeLengthSid(Sid); 01376 }

NTSTATUS RtlLengthSidAsUnicodeString PSID  Sid,
PULONG  StringLength
 

Definition at line 1532 of file sertl.c.

References RTL_PAGED_CODE, RtlValidSid(), StringLength(), and TRUE.

Referenced by RtlFormatCurrentUserKeyPath().

01539 : 01540 01541 01542 This function returns the maximum length of the string needed 01543 to represent the SID supplied. The actual string may be shorter, 01544 but this is intended to be a quick calculation. 01545 01546 Arguments: 01547 01548 01549 Sid - Supplies the SID that is to be converted to unicode. 01550 01551 StringLength - Receives the max length required in bytes. 01552 01553 Return Value: 01554 01555 SUCCESS - The conversion was successful 01556 01557 STATUS_INVALID_SID - The sid provided does not have a valid structure, 01558 or has too many sub-authorities (more than SID_MAX_SUB_AUTHORITIES). 01559 01560 --*/ 01561 01562 { 01563 ULONG i ; 01564 01565 PISID iSid = (PISID)Sid; // pointer to opaque structure 01566 01567 01568 RTL_PAGED_CODE(); 01569 01570 if ( RtlValidSid( Sid ) != TRUE) 01571 { 01572 return(STATUS_INVALID_SID); 01573 } 01574 01575 // 01576 // if the SID's IA value has 5 or 6 significant bytes, the 01577 // representation will be in hex, with a 0x preceding. Otherwise 01578 // it will be in decimal, with at most 10 characters. 01579 // 01580 01581 if ( (iSid->IdentifierAuthority.Value[0] != 0) || 01582 (iSid->IdentifierAuthority.Value[1] != 0) ) 01583 { 01584 i = 14 ; // 0x665544332211 01585 01586 } 01587 else 01588 { 01589 i = 10 ; // 4294967295 is the max ulong, at 10 chars 01590 } 01591 01592 i += 4 ; // room for the S-1- 01593 01594 // 01595 // for each sub authority, it is a max of 10 chars (for a ulong), 01596 // plus the - separator 01597 // 01598 01599 i += 11 * iSid->SubAuthorityCount ; 01600 01601 *StringLength = i * sizeof( WCHAR ); 01602 01603 return STATUS_SUCCESS ; 01604 01605 }

ULONG RtlLengthUsedSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor  ) 
 

Definition at line 2265 of file sertl.c.

References NULL, RTL_PAGED_CODE, RtlQueryInformationAcl(), and SeLengthSid.

02271 : 02272 02273 This routine returns the length, in bytes, in use in a structurally valid 02274 SECURITY_DESCRIPTOR. 02275 02276 This is the number of bytes necessary to capture the security descriptor, 02277 which may be less the the current actual length of the security descriptor 02278 (RtlLengthSecurityDescriptor() is used to retrieve the actual length). 02279 02280 Notice that the used length and actual length may differ if either the SACL 02281 or DACL include padding bytes. 02282 02283 The length includes the length of all associated data structures (like SIDs 02284 and ACLs). The length also takes into account the alignment requirements 02285 of each component. 02286 02287 The minimum length of a security descriptor (one which has no associated 02288 SIDs or ACLs) is SECURITY_DESCRIPTOR_MIN_LENGTH. 02289 02290 02291 Arguments: 02292 02293 SecurityDescriptor - Points to the SECURITY_DESCRIPTOR whose used 02294 length is to be returned. The SECURITY_DESCRIPTOR's 02295 structure is assumed to be valid. 02296 02297 Return Value: 02298 02299 ULONG - Number of bytes of the SECURITY_DESCRIPTOR that are in use. 02300 02301 02302 --*/ 02303 02304 { 02305 ULONG sum; 02306 02307 ACL_SIZE_INFORMATION AclSize; 02308 PVOID Temp; 02309 02310 // 02311 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02312 // 02313 02314 SECURITY_DESCRIPTOR *ISecurityDescriptor = (SECURITY_DESCRIPTOR *)SecurityDescriptor; 02315 02316 RTL_PAGED_CODE(); 02317 02318 // 02319 // The length is the sum of the following: 02320 // 02321 // SECURITY_DESCRIPTOR_MIN_LENGTH (or sizeof(SECURITY_DESCRIPTOR)) 02322 // length of Owner SID (if present) 02323 // length of Group SID (if present) 02324 // length of Discretionary ACL (if present and non-null) 02325 // length of System ACL (if present and non-null) 02326 // 02327 02328 sum = ISecurityDescriptor->Control & SE_SELF_RELATIVE ? 02329 sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 02330 sizeof(SECURITY_DESCRIPTOR); 02331 02332 // 02333 // Add in length of Owner SID 02334 // 02335 02336 Temp = RtlpOwnerAddrSecurityDescriptor(ISecurityDescriptor); 02337 if (Temp != NULL) { 02338 sum += LongAlignSize(SeLengthSid(Temp)); 02339 } 02340 02341 // 02342 // Add in length of Group SID 02343 // 02344 02345 Temp = RtlpGroupAddrSecurityDescriptor(ISecurityDescriptor); 02346 if (Temp != NULL) { 02347 sum += LongAlignSize(SeLengthSid(Temp)); 02348 } 02349 02350 // 02351 // Add in used length of Discretionary ACL 02352 // 02353 02354 Temp = RtlpDaclAddrSecurityDescriptor(ISecurityDescriptor); 02355 if ( Temp != NULL ) { 02356 02357 RtlQueryInformationAcl( Temp, 02358 (PVOID)&AclSize, 02359 sizeof(AclSize), 02360 AclSizeInformation ); 02361 02362 sum += LongAlignSize(AclSize.AclBytesInUse); 02363 } 02364 02365 // 02366 // Add in used length of System Acl 02367 // 02368 02369 Temp = RtlpSaclAddrSecurityDescriptor(ISecurityDescriptor); 02370 if ( Temp != NULL ) { 02371 02372 RtlQueryInformationAcl( Temp, 02373 (PVOID)&AclSize, 02374 sizeof(AclSize), 02375 AclSizeInformation ); 02376 02377 sum += LongAlignSize(AclSize.AclBytesInUse); 02378 } 02379 02380 return sum; 02381 }

VOID RtlMapGenericMask IN OUT PACCESS_MASK  AccessMask,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 3381 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by IoCheckDesiredAccess(), IopParseDevice(), NtDuplicateObject(), ObpIncrementHandleCount(), ObpIncrementUnnamedHandleCount(), RtlNewSecurityGrantedAccess(), RtlpConvertAclToAutoInherit(), SeCreateAccessState(), SeOpenObjectAuditAlarm(), SeOpenObjectForDeleteAuditAlarm(), and xxxCreateDesktop2().

03388 : 03389 03390 This routine maps all generic accesses in the provided access mask 03391 to specific and standard accesses according to the provided 03392 GenericMapping. 03393 03394 Arguments: 03395 03396 AccessMask - Points to the access mask to be mapped. 03397 03398 GenericMapping - The mapping of generic to specific and standard 03399 access types. 03400 03401 Return Value: 03402 03403 None. 03404 03405 --*/ 03406 03407 { 03408 RTL_PAGED_CODE(); 03409 03410 // // 03411 // // Make sure the pointer is properly aligned 03412 // // 03413 // 03414 // ASSERT( ((ULONG)AccessMask >> 2) << 2 == (ULONG)AccessMask ); 03415 03416 if (*AccessMask & GENERIC_READ) { 03417 03418 *AccessMask |= GenericMapping->GenericRead; 03419 } 03420 03421 if (*AccessMask & GENERIC_WRITE) { 03422 03423 *AccessMask |= GenericMapping->GenericWrite; 03424 } 03425 03426 if (*AccessMask & GENERIC_EXECUTE) { 03427 03428 *AccessMask |= GenericMapping->GenericExecute; 03429 } 03430 03431 if (*AccessMask & GENERIC_ALL) { 03432 03433 *AccessMask |= GenericMapping->GenericAll; 03434 } 03435 03436 // 03437 // Now clear the generic flags 03438 // 03439 03440 *AccessMask &= ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); 03441 03442 return; 03443 }

VOID RtlpApplyAclToObject IN PACL  Acl,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 3812 of file sertl.c.

References FirstAce, NextAce, NULL, and RTL_PAGED_CODE.

Referenced by RtlpNewSecurityObject(), and RtlpSetSecurityObject().

03819 : 03820 03821 This is a private routine that maps Access Masks of an ACL so that 03822 they are applicable to the object type the ACL is being applied to. 03823 03824 Only known DSA ACEs are mapped. Unknown ACE types are ignored. 03825 03826 Only access types in the GenericAll mapping for the target object 03827 type will be non-zero upon return. 03828 03829 Arguments: 03830 03831 Acl - Supplies the acl being applied. 03832 03833 GenericMapping - Specifies the generic mapping to use. 03834 03835 03836 Return Value: 03837 03838 None. 03839 03840 --*/ 03841 03842 { 03843 ULONG i; 03844 03845 PACE_HEADER Ace; 03846 03847 RTL_PAGED_CODE(); 03848 03849 // 03850 // First check if the acl is null 03851 // 03852 03853 if (Acl == NULL) { 03854 03855 return; 03856 03857 } 03858 03859 03860 // 03861 // Now walk the ACL, mapping each ACE as we go. 03862 // 03863 03864 for (i = 0, Ace = FirstAce(Acl); 03865 i < Acl->AceCount; 03866 i += 1, Ace = NextAce(Ace)) { 03867 03868 if (IsMSAceType( Ace )) { 03869 03870 RtlApplyAceToObject( Ace, GenericMapping ); 03871 } 03872 03873 } 03874 03875 return; 03876 }

BOOLEAN RtlpCompareAces IN PKNOWN_ACE  InheritedAce,
IN PKNOWN_ACE  ChildAce,
IN PSID  OwnerSid,
IN PSID  GroupSid
 

Definition at line 6972 of file sertl.c.

References FALSE, RtlpCompareKnownAces(), and RtlpCompareKnownObjectAces().

Referenced by RtlpConvertAclToAutoInherit(), and RtlpIsDuplicateAce().

06980 : 06981 06982 Compare two aces to see if they are "substantially" the same. 06983 06984 Arguments: 06985 06986 InheritedAce - Computed ACE as inherited from DirectoryAcl. 06987 06988 ChildAce - The current acl on the object. This ACL must be a revision 2 ACL. 06989 06990 ObjectType - GUID of the object type being created. If the object being 06991 created has no GUID associated with it, then this argument is 06992 specified as NULL. 06993 06994 OwnerSid - Specifies the owner Sid to use. 06995 If not specified, the owner sid is not treated as special. 06996 06997 GroupSid - Specifies the group SID to use. 06998 If not specified, the group sid is not treated as special. 06999 07000 Return Value: 07001 07002 TRUE - The ACEs are substantially the same. 07003 FALSE - The ACEs are not substantially the same. 07004 07005 --*/ 07006 { 07007 BOOLEAN AcesCompare = FALSE; 07008 07009 if (IsObjectAceType(InheritedAce) && IsObjectAceType(ChildAce)) { 07010 07011 AcesCompare = RtlpCompareKnownObjectAces( (PKNOWN_OBJECT_ACE)InheritedAce, 07012 (PKNOWN_OBJECT_ACE)ChildAce, 07013 OwnerSid, 07014 GroupSid 07015 ); 07016 } else { 07017 07018 if (!IsObjectAceType(InheritedAce) && !IsObjectAceType(ChildAce)) { 07019 07020 AcesCompare = RtlpCompareKnownAces( InheritedAce, 07021 ChildAce, 07022 OwnerSid, 07023 GroupSid 07024 ); 07025 } 07026 } 07027 07028 return( AcesCompare ); 07029 }

BOOLEAN RtlpCompareKnownAces IN PKNOWN_ACE  InheritedAce,
IN PKNOWN_ACE  ChildAce,
IN PSID OwnerSid  OPTIONAL,
IN PSID GroupSid  OPTIONAL
 

Definition at line 7033 of file sertl.c.

References AceFlagsInAce, ASSERT, CREATOR_SID_SIZE, CreatorSid, EFFECTIVE_ACE, FALSE, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlBaseAceType, RtlEqualPrefixSid(), RtlEqualSid(), RtlInitializeSid(), RtlIsSystemAceType, RtlLengthRequiredSid(), RtlpVerboseConvert, Status, and TRUE.

Referenced by RtlpCompareAces().

07042 : 07043 07044 Compare two aces to see if they are "substantially" the same. 07045 07046 Arguments: 07047 07048 InheritedAce - Computed ACE as inherited from DirectoryAcl. 07049 07050 ChildAce - The current acl on the object. This ACL must be a revision 2 ACL. 07051 07052 OwnerSid - Specifies the owner Sid to use. 07053 If not specified, the owner sid is not treated as special. 07054 07055 GroupSid - Specifies the group SID to use. 07056 If not specified, the group sid is not treated as special. 07057 07058 Return Value: 07059 07060 TRUE - The ACEs are substantially the same. 07061 FALSE - The ACEs are not substantially the same. 07062 07063 --*/ 07064 07065 { 07066 NTSTATUS Status; 07067 ACE_HEADER volatile *InheritedAceHdr = &InheritedAce->Header; 07068 07069 RTL_PAGED_CODE(); 07070 07071 ASSERT(!IsObjectAceType(InheritedAce)); 07072 ASSERT(!IsObjectAceType(ChildAce)); 07073 07074 // 07075 // If the Ace types are different, 07076 // we don't match. 07077 // 07078 if ( RtlBaseAceType[ChildAce->Header.AceType] != RtlBaseAceType[InheritedAceHdr->AceType] ) { 07079 #if DBG 07080 if ( RtlpVerboseConvert ) { 07081 KdPrint(("AceType mismatch")); 07082 } 07083 #endif // DBG 07084 return FALSE; 07085 } 07086 07087 // 07088 // If this is a system ACE, 07089 // ensure the SUCCESS/FAILURE flags match. 07090 // 07091 07092 if ( RtlIsSystemAceType[ChildAce->Header.AceType] ) { 07093 if ( (ChildAce->Header.AceFlags & (SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG)) != 07094 (InheritedAceHdr->AceFlags & (SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG)) ) { 07095 #if DBG 07096 if ( RtlpVerboseConvert ) { 07097 KdPrint(("System ace success/fail mismatch")); 07098 } 07099 #endif // DBG 07100 return FALSE; 07101 } 07102 } 07103 07104 // 07105 // If the SID of the inherited ACE doesn't match, 07106 // we don't match. 07107 // 07108 07109 if ( !RtlEqualSid( (PSID)&ChildAce->SidStart, (PSID)&InheritedAce->SidStart )) { 07110 07111 // 07112 // The inheritance algorithm only does SID mapping when building the effective 07113 // ace. So, we only check for a mapped SID if the child ACE is an effective ACE. 07114 // 07115 07116 if ( AceFlagsInAce(ChildAce) != EFFECTIVE_ACE ) { 07117 #if DBG 07118 if ( RtlpVerboseConvert ) { 07119 KdPrint(("SID mismatch")); 07120 } 07121 #endif // DBG 07122 return FALSE; 07123 } 07124 07125 // 07126 // In the case of CreatorOwner and CreatorGroup, the SIDs don't have to 07127 // exactly match. When the InheritedAce was generated, care was taken 07128 // to NOT map these sids. The SID may (or may not) have been mapped in 07129 // the ChildAce. We want to compare equal in both cases. 07130 // 07131 // If the InheritedAce contains a CreatorOwner/Group SID, 07132 // do the another comparison of the SID in the child ACE with the 07133 // real owner/group from the child security descriptor. 07134 // 07135 07136 if ( OwnerSid != NULL || GroupSid != NULL ) { 07137 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; 07138 ULONG CreatorSid[CREATOR_SID_SIZE]; 07139 07140 // 07141 // Allocate and initialize the universal SIDs we're going to need 07142 // to look for inheritable ACEs. 07143 // 07144 07145 ASSERT(RtlLengthRequiredSid( 1 ) == CREATOR_SID_SIZE); 07146 RtlInitializeSid( (PSID)CreatorSid, &CreatorSidAuthority, 1 ); 07147 *(RtlpSubAuthoritySid( (PSID)CreatorSid, 0 )) = SECURITY_CREATOR_OWNER_RID; 07148 07149 if (RtlEqualPrefixSid ( (PSID)&InheritedAce->SidStart, CreatorSid )) { 07150 ULONG Rid; 07151 07152 Rid = *RtlpSubAuthoritySid( (PSID)&InheritedAce->SidStart, 0 ); 07153 switch (Rid) { 07154 case SECURITY_CREATOR_OWNER_RID: 07155 if ( OwnerSid == NULL || 07156 !RtlEqualSid( (PSID)&ChildAce->SidStart, OwnerSid )) { 07157 #if DBG 07158 if ( RtlpVerboseConvert ) { 07159 KdPrint(("SID mismatch (Creator Owner)")); 07160 } 07161 #endif // DBG 07162 return FALSE; 07163 } 07164 break; 07165 case SECURITY_CREATOR_GROUP_RID: 07166 if ( GroupSid == NULL || 07167 !RtlEqualSid( (PSID)&ChildAce->SidStart, GroupSid )) { 07168 #if DBG 07169 if ( RtlpVerboseConvert ) { 07170 KdPrint(("SID mismatch (Creator Group)")); 07171 } 07172 #endif // DBG 07173 return FALSE; 07174 } 07175 break; 07176 default: 07177 #if DBG 07178 if ( RtlpVerboseConvert ) { 07179 KdPrint(("SID mismatch (Creator)")); 07180 } 07181 #endif // DBG 07182 return FALSE; 07183 } 07184 07185 } else { 07186 #if DBG 07187 if ( RtlpVerboseConvert ) { 07188 KdPrint(("SID mismatch")); 07189 } 07190 #endif // DBG 07191 return FALSE; 07192 } 07193 } else { 07194 #if DBG 07195 if ( RtlpVerboseConvert ) { 07196 KdPrint(("SID mismatch")); 07197 } 07198 #endif // DBG 07199 return FALSE; 07200 } 07201 } 07202 07203 return TRUE; 07204 07205 }

BOOLEAN RtlpCompareKnownObjectAces IN PKNOWN_OBJECT_ACE  InheritedAce,
IN PKNOWN_OBJECT_ACE  ChildAce,
IN PSID OwnerSid  OPTIONAL,
IN PSID GroupSid  OPTIONAL
 

Definition at line 7209 of file sertl.c.

References AceFlagsInAce, ASSERT, CREATOR_SID_SIZE, CreatorSid, EFFECTIVE_ACE, FALSE, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlBaseAceType, RtlEqualPrefixSid(), RtlEqualSid(), RtlInitializeSid(), RtlIsSystemAceType, RtlLengthRequiredSid(), RtlpVerboseConvert, Status, and TRUE.

Referenced by RtlpCompareAces().

07218 : 07219 07220 Compare two aces to see if they are "substantially" the same. 07221 07222 Arguments: 07223 07224 InheritedAce - Computed ACE as inherited from DirectoryAcl. 07225 07226 ChildAce - The current acl on the object. This ACL must be a revision 2 ACL. 07227 07228 ObjectType - GUID of the object type being created. If the object being 07229 created has no GUID associated with it, then this argument is 07230 specified as NULL. 07231 07232 OwnerSid - Specifies the owner Sid to use. 07233 If not specified, the owner sid is not treated as special. 07234 07235 GroupSid - Specifies the group SID to use. 07236 If not specified, the group sid is not treated as special. 07237 07238 Return Value: 07239 07240 TRUE - The ACEs are substantially the same. 07241 FALSE - The ACEs are not substantially the same. 07242 07243 --*/ 07244 07245 { 07246 NTSTATUS Status; 07247 BOOLEAN DoingObjectAces; 07248 GUID *ChildObjectGuid; 07249 GUID *InhObjectGuid; 07250 GUID *ChildInheritedObjectGuid; 07251 GUID *InhInheritedObjectGuid; 07252 ACE_HEADER volatile *InheritedAceHdr = &InheritedAce->Header; 07253 07254 RTL_PAGED_CODE(); 07255 07256 ASSERT(IsObjectAceType(InheritedAce)); 07257 ASSERT(IsObjectAceType(ChildAce)); 07258 // 07259 // If the Ace types are different, 07260 // we don't match. 07261 // 07262 if ( RtlBaseAceType[ChildAce->Header.AceType] != RtlBaseAceType[InheritedAceHdr->AceType] ) { 07263 #if DBG 07264 if ( RtlpVerboseConvert ) { 07265 KdPrint(("AceType mismatch")); 07266 } 07267 #endif // DBG 07268 return FALSE; 07269 } 07270 07271 // 07272 // If this is a system ACE, 07273 // ensure the SUCCESS/FAILURE flags match. 07274 // 07275 07276 if ( RtlIsSystemAceType[ChildAce->Header.AceType] ) { 07277 if ( (ChildAce->Header.AceFlags & (SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG)) != 07278 (InheritedAceHdr->AceFlags & (SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG)) ) { 07279 #if DBG 07280 if ( RtlpVerboseConvert ) { 07281 KdPrint(("System ace success/fail mismatch")); 07282 } 07283 #endif // DBG 07284 return FALSE; 07285 } 07286 } 07287 07288 // 07289 // Get the GUIDs from the Object Aces 07290 // 07291 07292 ChildObjectGuid = RtlObjectAceObjectType(ChildAce); 07293 ChildInheritedObjectGuid = RtlObjectAceInheritedObjectType(ChildAce); 07294 07295 InhObjectGuid = RtlObjectAceObjectType(InheritedAce); 07296 InhInheritedObjectGuid = RtlObjectAceInheritedObjectType(InheritedAce); 07297 07298 // 07299 // If the InheritedObjectGuid is present in either ACE, 07300 // they must be equal. 07301 // 07302 07303 if ( ChildInheritedObjectGuid != NULL || InhInheritedObjectGuid != NULL ) { 07304 07305 if ( ChildInheritedObjectGuid == NULL || 07306 InhInheritedObjectGuid == NULL || 07307 !RtlpIsEqualGuid( ChildInheritedObjectGuid, InhInheritedObjectGuid )) { 07308 #if DBG 07309 if ( RtlpVerboseConvert ) { 07310 KdPrint(("InheritedObject GUID mismatch")); 07311 } 07312 #endif // DBG 07313 return FALSE; 07314 } 07315 } 07316 07317 // 07318 // If the ObjectGUID is present in either ACE, 07319 // they must be equal. 07320 // 07321 // Any missing object GUID defaults to the passed in object GUID. 07322 // 07323 07324 if ( (ChildObjectGuid != NULL) && (InhObjectGuid != NULL) ) { 07325 07326 if (!RtlpIsEqualGuid( ChildObjectGuid, InhObjectGuid )) { 07327 #if DBG 07328 if ( RtlpVerboseConvert ) { 07329 KdPrint(("Object GUID mismatch")); 07330 } 07331 #endif // DBG 07332 07333 return( FALSE ); 07334 } 07335 } else { 07336 07337 // 07338 // One or both is NULL, if it's only one, they don't match. 07339 // 07340 07341 if ( !((ChildObjectGuid == NULL) && (InhObjectGuid == NULL)) ) { 07342 #if DBG 07343 if ( RtlpVerboseConvert ) { 07344 KdPrint(("Object GUID mismatch")); 07345 } 07346 #endif // DBG 07347 07348 return( FALSE ); 07349 } 07350 } 07351 07352 // 07353 // If the SID of the inherited ACE doesn't match, 07354 // we don't match. 07355 // 07356 07357 if ( !RtlEqualSid( RtlObjectAceSid(ChildAce), RtlObjectAceSid(InheritedAce))) { 07358 07359 // 07360 // The inheritance algorithm only does SID mapping when building the effective 07361 // ace. So, we only check for a mapped SID if the child ACE is an effective ACE. 07362 // 07363 07364 if ( AceFlagsInAce(ChildAce) != EFFECTIVE_ACE ) { 07365 #if DBG 07366 if ( RtlpVerboseConvert ) { 07367 KdPrint(("SID mismatch")); 07368 } 07369 #endif // DBG 07370 return FALSE; 07371 } 07372 07373 07374 07375 // 07376 // In the case of CreatorOwner and CreatorGroup, the SIDs don't have to 07377 // exactly match. When the InheritedAce was generated, care was taken 07378 // to NOT map these sids. The SID may (or may not) have been mapped in 07379 // the ChildAce. We want to compare equal in both cases. 07380 // 07381 // If the InheritedAce contains a CreatorOwner/Group SID, 07382 // do the another comparison of the SID in the child ACE with the 07383 // real owner/group from the child security descriptor. 07384 // 07385 07386 if ( OwnerSid != NULL || GroupSid != NULL ) { 07387 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; 07388 ULONG CreatorSid[CREATOR_SID_SIZE]; 07389 07390 // 07391 // Allocate and initialize the universal SIDs we're going to need 07392 // to look for inheritable ACEs. 07393 // 07394 07395 ASSERT(RtlLengthRequiredSid( 1 ) == CREATOR_SID_SIZE); 07396 RtlInitializeSid( (PSID)CreatorSid, &CreatorSidAuthority, 1 ); 07397 *(RtlpSubAuthoritySid( (PSID)CreatorSid, 0 )) = SECURITY_CREATOR_OWNER_RID; 07398 07399 if (RtlEqualPrefixSid ( RtlObjectAceSid(InheritedAce), CreatorSid )) { 07400 ULONG Rid; 07401 07402 Rid = *RtlpSubAuthoritySid( RtlObjectAceSid(InheritedAce), 0 ); 07403 switch (Rid) { 07404 case SECURITY_CREATOR_OWNER_RID: 07405 if ( OwnerSid == NULL || 07406 !RtlEqualSid( RtlObjectAceSid(ChildAce), OwnerSid )) { 07407 #if DBG 07408 if ( RtlpVerboseConvert ) { 07409 KdPrint(("SID mismatch (Creator Owner)")); 07410 } 07411 #endif // DBG 07412 return FALSE; 07413 } 07414 break; 07415 case SECURITY_CREATOR_GROUP_RID: 07416 if ( GroupSid == NULL || 07417 !RtlEqualSid( RtlObjectAceSid(ChildAce), GroupSid )) { 07418 #if DBG 07419 if ( RtlpVerboseConvert ) { 07420 KdPrint(("SID mismatch (Creator Group)")); 07421 } 07422 #endif // DBG 07423 return FALSE; 07424 } 07425 break; 07426 default: 07427 #if DBG 07428 if ( RtlpVerboseConvert ) { 07429 KdPrint(("SID mismatch (Creator)")); 07430 } 07431 #endif // DBG 07432 return FALSE; 07433 } 07434 07435 } else { 07436 #if DBG 07437 if ( RtlpVerboseConvert ) { 07438 KdPrint(("SID mismatch")); 07439 } 07440 #endif // DBG 07441 return FALSE; 07442 } 07443 } else { 07444 #if DBG 07445 if ( RtlpVerboseConvert ) { 07446 KdPrint(("SID mismatch")); 07447 } 07448 #endif // DBG 07449 return FALSE; 07450 } 07451 } 07452 07453 return TRUE; 07454 07455 }

NTSTATUS RtlpComputeMergedAcl IN PACL  CurrentAcl,
IN ULONG  CurrentGenericControl,
IN PACL  ModificationAcl,
IN ULONG  ModificationGenericControl,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PGENERIC_MAPPING  GenericMapping,
IN BOOLEAN  IsSacl,
OUT PACL *  NewAcl,
OUT PULONG  NewGenericControl
 

Definition at line 6266 of file sertl.c.

References ExAllocatePoolWithTag, ExFreePool(), HeapHandle, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RTL_PAGED_CODE, RtlAllocateHeap, RtlFreeHeap, RtlpComputeMergedAcl2(), and Status.

Referenced by RtlpSetSecurityObject().

06281 : 06282 06283 This routine builds the actual ACL that should be set on an object. 06284 The built ACL is a composite of the previous ACL on an object and 06285 the newly set ACL on the object. The New ACL is built as follows: 06286 06287 If SEP_ACL_PROTECTED is set in neither CurrentAcl nor ModificationAcl, 06288 the NewAcl is constructed from the inherited ACEs from the 06289 CurrentAcl and the non-inherited ACEs from the ModificationAcl. 06290 (That is, it is impossible to edit an inherited ACE by changing the 06291 ACL on an object.) 06292 06293 If SEP_ACL_PROTECTED is set on ModificationAcl, CurrentAcl is ignored. 06294 NewAcl is built as a copy of ModificationAcl with any INHERITED_ACE 06295 bits turned off. 06296 06297 If SEP_ACL_PROTECTED is set on CurrentAcl and not ModificationAcl, the 06298 CurrentAcl is ignored. NewAcl is built as a copy of 06299 ModificationDescriptor. It is the callers responsibility to ensure 06300 that the correct ACEs have the INHERITED_ACE bit turned on. 06301 06302 Arguments: 06303 06304 CurrentAcl - The current ACL on the object. 06305 06306 CurrentGenericControl - Specifies the control flags from the SecurityDescriptor 06307 describing the CurrentAcl. 06308 06309 ModificationAcl - The ACL being applied to the object. 06310 06311 ModificationGenericControl - Specifies the control flags from the SecurityDescriptor 06312 describing the CurrentAcl. 06313 06314 ClientOwnerSid - Specifies the owner Sid to use 06315 06316 ClientGroupSid - Specifies the new Group Sid to use 06317 06318 GenericMapping - The mapping of generic to specific and standard 06319 access types. 06320 06321 IsSacl - True if this is the SACL. False if this is the DACL. 06322 06323 NewAcl - Receives a pointer to the new resultant acl. 06324 06325 NewGenericControl - Specifies the control flags for the newly 06326 generated ACL. 06327 06328 Only the Protected and AutoInherited bits are returned. 06329 06330 Return Value: 06331 06332 STATUS_SUCCESS - An ACL was successfully generated. 06333 06334 STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that 06335 is unknown to this routine. 06336 06337 --*/ 06338 06339 { 06340 NTSTATUS Status; 06341 ULONG AclBufferSize; 06342 ULONG i; 06343 #ifndef NTOS_KERNEL_RUNTIME 06344 PVOID HeapHandle; 06345 #endif // NTOS_KERNEL_RUNTIME 06346 06347 RTL_PAGED_CODE(); 06348 06349 // 06350 // Get the handle to the current process heap 06351 // 06352 06353 #ifndef NTOS_KERNEL_RUNTIME 06354 HeapHandle = RtlProcessHeap(); 06355 #endif // NTOS_KERNEL_RUNTIME 06356 06357 06358 // 06359 // Implement a two pass strategy. 06360 // 06361 // First try to create the ACL in a fixed length buffer. 06362 // If that is too small, 06363 // then use the buffer size determined on the first pass 06364 // 06365 06366 AclBufferSize = 1024; 06367 for ( i=0; i<2 ; i++ ) { 06368 06369 // 06370 // Allocate heap for the new ACL. 06371 // 06372 06373 #ifdef NTOS_KERNEL_RUNTIME 06374 (*NewAcl) = ExAllocatePoolWithTag( 06375 PagedPool, 06376 AclBufferSize, 06377 'cAeS' ); 06378 #else // NTOS_KERNEL_RUNTIME 06379 (*NewAcl) = RtlAllocateHeap( HeapHandle, 0, AclBufferSize ); 06380 #endif // NTOS_KERNEL_RUNTIME 06381 if ((*NewAcl) == NULL ) { 06382 return( STATUS_NO_MEMORY ); 06383 } 06384 06385 // 06386 // Merge the ACLs 06387 // 06388 06389 Status = RtlpComputeMergedAcl2 ( 06390 CurrentAcl, 06391 CurrentGenericControl, 06392 ModificationAcl, 06393 ModificationGenericControl, 06394 ClientOwnerSid, 06395 ClientGroupSid, 06396 GenericMapping, 06397 IsSacl, 06398 &AclBufferSize, 06399 (PUCHAR) *NewAcl, 06400 NewGenericControl ); 06401 06402 06403 if ( NT_SUCCESS(Status) ) { 06404 06405 // 06406 // If a NULL ACL should be used, 06407 // tell the caller. 06408 // 06409 06410 if ( AclBufferSize == 0 ) { 06411 #ifdef NTOS_KERNEL_RUNTIME 06412 ExFreePool( *NewAcl ); 06413 #else // NTOS_KERNEL_RUNTIME 06414 RtlFreeHeap( HeapHandle, 0, *NewAcl ); 06415 #endif // NTOS_KERNEL_RUNTIME 06416 *NewAcl = NULL; 06417 } 06418 06419 break; 06420 06421 } else { 06422 #ifdef NTOS_KERNEL_RUNTIME 06423 ExFreePool( *NewAcl ); 06424 #else // NTOS_KERNEL_RUNTIME 06425 RtlFreeHeap( HeapHandle, 0, *NewAcl ); 06426 #endif // NTOS_KERNEL_RUNTIME 06427 *NewAcl = NULL; 06428 06429 if ( Status != STATUS_BUFFER_TOO_SMALL ) { 06430 break; 06431 } 06432 } 06433 } 06434 06435 06436 return Status; 06437 }

NTSTATUS RtlpComputeMergedAcl2 IN PACL  CurrentAcl,
IN ULONG  CurrentGenericControl,
IN PACL  ModificationAcl,
IN ULONG  ModificationGenericControl,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PGENERIC_MAPPING  GenericMapping,
IN BOOLEAN  IsSacl,
IN PULONG  AclBufferSize,
IN OUT PUCHAR  AclBuffer,
OUT PULONG  NewGenericControl
 

Definition at line 5893 of file sertl.c.

References CopyAllAces, CopyInheritedAces, CopyNonInheritedAces, FALSE, max, NT_SUCCESS, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlCreateAcl(), RtlpCopyAces(), Status, TRUE, and USHORT.

Referenced by RtlpComputeMergedAcl().

05909 : 05910 05911 This routine implements the 'set' semantics for auto inheritance. 05912 05913 This routine builds the actual ACL that should be set on an object. 05914 The built ACL is a composite of the previous ACL on an object and 05915 the newly set ACL on the object. The New ACL is built as follows: 05916 05917 If SEP_ACL_PROTECTED is set in neither CurrentAcl nor ModificationAcl, 05918 the NewAcl is constructed from the inherited ACEs from the 05919 CurrentAcl and the non-inherited ACEs from the ModificationAcl. 05920 (That is, it is impossible to edit an inherited ACE by changing the 05921 ACL on an object.) 05922 05923 If SEP_ACL_PROTECTED is set on ModificationAcl, CurrentAcl is ignored. 05924 NewAcl is built as a copy of ModificationAcl with any INHERITED_ACE 05925 bits turned off. 05926 05927 If SEP_ACL_PROTECTED is set on CurrentAcl and not ModificationAcl, the 05928 CurrentAcl is ignored. NewAcl is built as a copy of 05929 ModificationDescriptor. It is the callers responsibility to ensure 05930 that the correct ACEs have the INHERITED_ACE bit turned on. 05931 05932 Arguments: 05933 05934 CurrentAcl - The current ACL on the object. 05935 05936 CurrentGenericControl - Specifies the control flags from the SecurityDescriptor 05937 describing the CurrentAcl. 05938 05939 ModificationAcl - The ACL being applied to the object. 05940 05941 ModificationGenericControl - Specifies the control flags from the SecurityDescriptor 05942 describing the CurrentAcl. 05943 05944 ClientOwnerSid - Specifies the owner Sid to use 05945 05946 ClientGroupSid - Specifies the new Group Sid to use 05947 05948 GenericMapping - The mapping of generic to specific and standard 05949 access types. 05950 05951 IsSacl - True if this is the SACL. False if this is the DACL. 05952 05953 AclBufferSize - On input, specifies the size of AclBuffer. 05954 On output, on success, returns the used size of AclBuffer. 05955 On output, if the buffer is too small, returns the required size of AclBuffer. 05956 05957 AclBuffer - Receives a pointer to the new (inherited) acl. 05958 05959 NewGenericControl - Specifies the control flags for the newly 05960 generated ACL. 05961 05962 Only the Protected and AutoInherited bits are returned. 05963 05964 Return Value: 05965 05966 STATUS_SUCCESS - An ACL was successfully generated. 05967 05968 STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that 05969 is unknown to this routine. 05970 05971 --*/ 05972 05973 { 05974 NTSTATUS Status; 05975 ULONG ModificationNewAclSize = 0; 05976 ULONG CurrentNewAclSize = 0; 05977 ULONG AclRevision; 05978 BOOLEAN AclOverflowed = FALSE; 05979 BOOLEAN NullAclOk = TRUE; 05980 05981 RTL_PAGED_CODE(); 05982 05983 05984 // 05985 // Assume the ACL revision. 05986 // 05987 05988 AclRevision = ACL_REVISION; 05989 RtlCreateAcl( (PACL)AclBuffer, *AclBufferSize, AclRevision ); 05990 05991 // 05992 // This routine is only called for the AutoInheritance case. 05993 // 05994 05995 *NewGenericControl = SEP_ACL_AUTO_INHERITED; 05996 05997 // 05998 // If the new ACL is protected, 05999 // simply use the new ACL with the INHERITED_ACE bits turned off. 06000 // 06001 06002 if ( (ModificationGenericControl & SEP_ACL_PROTECTED) != 0 ) { 06003 06004 // 06005 // Set the Control bits for the resultant descriptor. 06006 // 06007 06008 *NewGenericControl |= SEP_ACL_PROTECTED; 06009 06010 // 06011 // Only copy the ACL if it is actually present 06012 // 06013 06014 if ( ModificationAcl != NULL ) { 06015 06016 AclRevision = max( AclRevision, ModificationAcl->AclRevision ); 06017 06018 // 06019 // Copy all ACES, turn off the inherited bit, and generic map them. 06020 // 06021 06022 Status = RtlpCopyAces( 06023 ModificationAcl, 06024 GenericMapping, 06025 CopyAllAces, 06026 INHERITED_ACE, // Turn off all INHERITED_ACE flags 06027 TRUE, // Map sids as needed 06028 ClientOwnerSid, 06029 ClientGroupSid, 06030 ClientOwnerSid, // Not technically correct. s.b. server sid 06031 ClientGroupSid, // Not technically correct. s.b. server sid 06032 &ModificationNewAclSize, 06033 (PACL)AclBuffer ); 06034 06035 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 06036 AclOverflowed = TRUE; 06037 Status = STATUS_SUCCESS; 06038 } 06039 06040 if ( !NT_SUCCESS(Status) ) { 06041 return Status; 06042 } 06043 06044 // 06045 // If the caller specified an ACL with no ACES, 06046 // make sure we generate an ACL with no ACES. 06047 // 06048 06049 NullAclOk = FALSE; 06050 } 06051 06052 // 06053 // If the old ACL is protected but the new one isn't, 06054 // simply use the new ACL as is. 06055 // 06056 // Rely on the caller to get the INHERITED_ACE bits right. 06057 // 06058 06059 } else if ( (CurrentGenericControl & SEP_ACL_PROTECTED) != 0 ) { 06060 06061 // 06062 // Only do the copy if the new ACL is specified. 06063 // 06064 06065 if ( ModificationAcl != NULL ) { 06066 AclRevision = max( AclRevision, ModificationAcl->AclRevision ); 06067 06068 // 06069 // Copy all ACES, and generic map them. 06070 // 06071 06072 Status = RtlpCopyAces( 06073 ModificationAcl, 06074 GenericMapping, 06075 CopyAllAces, 06076 0, 06077 TRUE, // Map sids as needed 06078 ClientOwnerSid, 06079 ClientGroupSid, 06080 ClientOwnerSid, // Not technically correct. s.b. server sid 06081 ClientGroupSid, // Not technically correct. s.b. server sid 06082 &ModificationNewAclSize, 06083 (PACL)AclBuffer ); 06084 06085 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 06086 AclOverflowed = TRUE; 06087 Status = STATUS_SUCCESS; 06088 } 06089 06090 if ( !NT_SUCCESS(Status) ) { 06091 return Status; 06092 } 06093 06094 // 06095 // If the caller specified an ACL with no ACES, 06096 // make sure we generate an ACL with no ACES. 06097 // 06098 06099 NullAclOk = FALSE; 06100 06101 // 06102 // Since the ACL isn't protected, 06103 // don't allow NULL ACL semantics. 06104 // (those semantics are ambiguous for auto inheritance) 06105 // 06106 } else if ( !IsSacl ) { 06107 return STATUS_INVALID_ACL; 06108 } 06109 06110 06111 // 06112 // If neither are protected, 06113 // use the non-inherited ACEs from the new ACL, and 06114 // preserve the inherited ACEs from the old ACL. 06115 // 06116 06117 } else { 06118 06119 // 06120 // NULL ACLs are always OK for a SACL. 06121 // NULL ACLs are never OK for a non-protected DACL. 06122 // 06123 06124 NullAclOk = IsSacl; 06125 06126 06127 // 06128 // Only do the copy if the new ACL is specified. 06129 // 06130 06131 if ( ModificationAcl != NULL ) { 06132 AclRevision = max( AclRevision, ModificationAcl->AclRevision ); 06133 06134 // 06135 // Copy the non-inherited ACES, and generic map them. 06136 // 06137 06138 Status = RtlpCopyAces( 06139 ModificationAcl, 06140 GenericMapping, 06141 CopyNonInheritedAces, 06142 0, 06143 TRUE, // Map sids as needed 06144 ClientOwnerSid, 06145 ClientGroupSid, 06146 ClientOwnerSid, // Not technically correct. s.b. server sid 06147 ClientGroupSid, // Not technically correct. s.b. server sid 06148 &ModificationNewAclSize, 06149 (PACL)AclBuffer ); 06150 06151 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 06152 AclOverflowed = TRUE; 06153 Status = STATUS_SUCCESS; 06154 } 06155 06156 if ( !NT_SUCCESS(Status) ) { 06157 return Status; 06158 } 06159 06160 // 06161 // If the caller specified an ACL with no ACES, 06162 // make sure we generate an ACL with no ACES. 06163 // 06164 // If inherited aces were deleted, leave the flag alone allowing 06165 // a NULL SACL to be generated. 06166 // 06167 06168 if ( ModificationAcl->AceCount == 0 ) { 06169 NullAclOk = FALSE; 06170 } 06171 06172 // 06173 // Since the ACL isn't protected, 06174 // don't allow NULL ACL semantics. 06175 // (those semantics are ambiguous for auto inheritance) 06176 // 06177 } else if ( !IsSacl ) { 06178 return STATUS_INVALID_ACL; 06179 } 06180 06181 06182 // 06183 // Only do the copy if the old ACL is specified. 06184 // 06185 06186 if ( CurrentAcl != NULL ) { 06187 06188 AclRevision = max( AclRevision, CurrentAcl->AclRevision ); 06189 06190 06191 // 06192 // Copy the inherited ACES, and generic map them. 06193 // 06194 // Don't bother mapping the sids in these ACEs. They got mapped 06195 // during inheritance. 06196 // 06197 06198 Status = RtlpCopyAces( 06199 CurrentAcl, 06200 GenericMapping, 06201 CopyInheritedAces, 06202 0, 06203 FALSE, // Don't map the sids, 06204 NULL, 06205 NULL, 06206 NULL, 06207 NULL, 06208 &CurrentNewAclSize, 06209 (PACL)AclBuffer ); 06210 06211 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 06212 AclOverflowed = TRUE; 06213 Status = STATUS_SUCCESS; 06214 } 06215 06216 if ( !NT_SUCCESS(Status) ) { 06217 return Status; 06218 } 06219 } 06220 } 06221 06222 // 06223 // If this routine didn't build the ACL, 06224 // tell the caller to use an explict NULL ACL 06225 // 06226 06227 if ( ModificationNewAclSize + CurrentNewAclSize == 0) { 06228 // 06229 // If the Acl was explictly assigned, 06230 // generate a NULL ACL based on the path taken above. 06231 // 06232 06233 if ( NullAclOk ) { 06234 *AclBufferSize = 0; 06235 return STATUS_SUCCESS; 06236 } 06237 } 06238 06239 06240 // 06241 // And make sure we don't exceed the length limitations of an ACL (WORD) 06242 // 06243 06244 if ( ModificationNewAclSize + CurrentNewAclSize + sizeof(ACL) > 0xFFFF) { 06245 return(STATUS_BAD_INHERITANCE_ACL); 06246 } 06247 06248 (*AclBufferSize) = ModificationNewAclSize + CurrentNewAclSize + sizeof(ACL); 06249 06250 if ( AclOverflowed ) { 06251 return STATUS_BUFFER_TOO_SMALL; 06252 } 06253 06254 // 06255 // Patch the real ACL size and revision into the ACL 06256 // 06257 06258 ((PACL)AclBuffer)->AclSize = (USHORT) *AclBufferSize; 06259 ((PACL)AclBuffer)->AclRevision = (UCHAR) AclRevision; 06260 06261 return STATUS_SUCCESS; 06262 }

NTSTATUS RtlpConvertAclToAutoInherit IN PACL ParentAcl  OPTIONAL,
IN PACL  ChildAcl,
IN GUID *ObjectType  OPTIONAL,
IN BOOLEAN  IsDirectoryObject,
IN PSID  OwnerSid,
IN PSID  GroupSid,
IN PGENERIC_MAPPING  GenericMapping,
OUT PACL *  NewAcl,
OUT PULONG  NewGenericControl
 

Definition at line 7461 of file sertl.c.

References AceFlagsInAce, ASSERT, CREATOR_SID_SIZE, CreatorOwnerSid, EFFECTIVE_ACE, ExAllocatePoolWithTag, ExFreePool(), FALSE, FirstAce, _KNOWN_ACE::Header, HeapHandle, MAKE_TAG, _KNOWN_ACE::Mask, max, NextAce, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RTL_PAGED_CODE, RtlAllocateHeap, RtlBaseAceType, RtlCreateAcl(), RtlFreeHeap, RtlInitializeSid(), RtlLengthRequiredSid(), RtlMapGenericMask(), RtlpCompareAces(), RtlpInheritAcl(), RtlpVerboseConvert, RtlValidAcl(), SE_TAG, Status, and TRUE.

Referenced by RtlpConvertToAutoInheritSecurityObject().

07475 : 07476 07477 This is a private routine that produces an auto inherited acl from 07478 a ChildAcl that is not marked as auto inherited. The passed in InheritedAcl 07479 is computed as the pure inherited ACL of Parent ACL of the object. 07480 07481 See comments for RtlConvertToAutoInheritSecurityObject. 07482 07483 Arguments: 07484 07485 ParentAcl - Supplies the ACL of the parent object. 07486 07487 ChildAcl - Supplies the acl associated with the object. This 07488 is the current acl on the object. 07489 07490 ObjectType - GUID of the object type being created. If the object being 07491 created has no GUID associated with it, then this argument is 07492 specified as NULL. 07493 07494 IsDirectoryObject - Specifies if the object is a 07495 directory object. A value of TRUE indicates the object is a 07496 container of other objects. 07497 07498 OwnerSid - Specifies the owner Sid to use. 07499 07500 GroupSid - Specifies the group SID to use. 07501 07502 GenericMapping - Specifies the generic mapping to use. 07503 07504 NewAcl - Receives a pointer to the new (auto inherited) acl. 07505 The ACL must be deallocated using the pool (kernel mode) or 07506 heap (user mode) deallocator. 07507 07508 NewGenericControl - Specifies the control flags for the newly 07509 generated ACL. 07510 07511 SEP_ACL_PRESENT: Specifies that the ACL is explictly supplied by 07512 the caller. ?? Ever set? 07513 07514 SEP_ACL_DEFAULTED: Specifies that the ACL was supplied by some 07515 defaulting mechanism. ?? Ever set 07516 07517 SEP_ACL_AUTO_INHERITED: Set if the ACL was generated using the 07518 Automatic Inheritance algorithm. 07519 07520 SEP_ACL_PROTECTED: Specifies that the ACL is protected and 07521 was not inherited from the parent ACL. 07522 07523 Return Value: 07524 07525 STATUS_SUCCESS - An inheritable ACL was successfully generated. 07526 07527 STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that 07528 is unknown to this routine. 07529 07530 STATUS_INVALID_ACL - The structure of one of the ACLs in invalid. 07531 07532 --*/ 07533 07534 { 07535 NTSTATUS Status; 07536 07537 PACL InheritedAcl = NULL; 07538 PACL RealInheritedAcl = NULL; 07539 BOOLEAN AclExplicitlyAssigned; 07540 ULONG GenericControl; 07541 07542 PKNOWN_ACE ChildAce = NULL; 07543 PKNOWN_ACE InheritedAce; 07544 07545 LONG ChildAceIndex; 07546 LONG InheritedAceIndex; 07547 07548 BOOLEAN InheritedAllowFound; 07549 BOOLEAN InheritedDenyFound; 07550 07551 BOOLEAN AcesCompare; 07552 07553 ACCESS_MASK InheritedContainerInheritMask; 07554 ACCESS_MASK InheritedObjectInheritMask; 07555 ACCESS_MASK InheritedEffectiveMask; 07556 ACCESS_MASK OriginalInheritedContainerInheritMask; 07557 ACCESS_MASK OriginalInheritedObjectInheritMask; 07558 ACCESS_MASK OriginalInheritedEffectiveMask; 07559 07560 ULONG InheritedAceFlags; 07561 ULONG MatchedFlags; 07562 ULONG NonInheritedAclSize; 07563 07564 07565 PACE_HEADER AceHeader; 07566 PUCHAR Where; 07567 07568 // ULONG i; 07569 07570 // 07571 // This routine maintains an array of the structure below (one element per ACE in 07572 // the ChildAcl). 07573 // 07574 // The ACE is broken down into its component parts. The access mask is triplicated. 07575 // That is, if the ACE is a ContainerInherit ACE, the access mask is remembered as 07576 // being a "ContainerInheritMask". The same is true if the ACE is an ObjectInherit ACE 07577 // on an effective ACE. This is done since each of the resultant 96 bits are 07578 // individually matched against corresponding bits in the computed inherited ACE. 07579 // 07580 // Each of the above mentioned masks are maintained in two forms. The first is never 07581 // changed and represents the bits as the originally appeared in the child ACL. 07582 // This second is modified as the corresponding bits are matched in the inherited ACL. 07583 // When the algorithm is completed, bits that haven't been matched represent ACEs 07584 // that weren't inherited from the parent. 07585 // 07586 07587 typedef struct { 07588 ACCESS_MASK OriginalContainerInheritMask; 07589 ACCESS_MASK OriginalObjectInheritMask; 07590 ACCESS_MASK OriginalEffectiveMask; 07591 07592 ACCESS_MASK ContainerInheritMask; 07593 ACCESS_MASK ObjectInheritMask; 07594 ACCESS_MASK EffectiveMask; 07595 } ACE_INFO, *PACE_INFO; 07596 07597 PACE_INFO ChildAceInfo = NULL; 07598 07599 ULONG CreatorOwnerSid[CREATOR_SID_SIZE]; 07600 ULONG CreatorGroupSid[CREATOR_SID_SIZE]; 07601 07602 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; 07603 07604 #ifndef NTOS_KERNEL_RUNTIME 07605 PVOID HeapHandle; 07606 #endif // NTOS_KERNEL_RUNTIME 07607 07608 RTL_PAGED_CODE(); 07609 07610 // 07611 // Get the handle to the current process heap 07612 // 07613 07614 #ifndef NTOS_KERNEL_RUNTIME 07615 HeapHandle = RtlProcessHeap(); 07616 #endif // NTOS_KERNEL_RUNTIME 07617 07618 // 07619 // Allocate and initialize the universal SIDs we're going to need 07620 // to look for inheritable ACEs. 07621 // 07622 07623 ASSERT(RtlLengthRequiredSid( 1 ) == CREATOR_SID_SIZE); 07624 RtlInitializeSid( (PSID)CreatorOwnerSid, &CreatorSidAuthority, 1 ); 07625 *(RtlpSubAuthoritySid( (PSID)CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID; 07626 07627 RtlInitializeSid( (PSID)CreatorGroupSid, &CreatorSidAuthority, 1 ); 07628 *(RtlpSubAuthoritySid( (PSID)CreatorGroupSid, 0 )) = SECURITY_CREATOR_GROUP_RID; 07629 07630 // 07631 // Ensure the passed in ACLs are valid. 07632 // 07633 07634 *NewGenericControl = SEP_ACL_AUTO_INHERITED; 07635 *NewAcl = NULL; 07636 07637 if ( ParentAcl != NULL && !RtlValidAcl( ParentAcl ) ) { 07638 Status = STATUS_INVALID_ACL; 07639 goto Cleanup; 07640 } 07641 07642 if (!RtlValidAcl( ChildAcl ) ) { 07643 Status = STATUS_INVALID_ACL; 07644 goto Cleanup; 07645 } 07646 07647 07648 // 07649 // Compute what the inherited ACL "should" look like. 07650 // 07651 // The inherited ACL is computed to NOT SID-map Creator Owner and Creator Group. 07652 // This allows use to later recognize the constant SIDs and special case them 07653 // rather than mistakenly confuse them with the mapped SID. 07654 // 07655 07656 Status = RtlpInheritAcl ( 07657 ParentAcl, 07658 NULL, // No explicit child ACL 07659 0, // No Child Generic Control 07660 IsDirectoryObject, 07661 TRUE, // AutoInherit the DACL 07662 FALSE, // Not default descriptor for object 07663 CreatorOwnerSid, // Subsitute a constant SID 07664 CreatorGroupSid, // Subsitute a constant SID 07665 CreatorOwnerSid, // Server Owner (Technically incorrect, but OK since we don't support compound ACEs) 07666 CreatorGroupSid, // Server Group 07667 GenericMapping, 07668 TRUE, // Is a SACL 07669 ObjectType, 07670 &InheritedAcl, 07671 &AclExplicitlyAssigned, 07672 &GenericControl ); 07673 07674 if ( Status == STATUS_NO_INHERITANCE ) { 07675 *NewGenericControl |= SEP_ACL_PROTECTED; 07676 #if DBG 07677 if ( RtlpVerboseConvert ) { 07678 KdPrint(("NO_INHERITANCE of the parent ACL\n" )); 07679 } 07680 #endif // DBG 07681 Status = STATUS_SUCCESS; 07682 goto Cleanup; 07683 } 07684 07685 if ( !NT_SUCCESS(Status) ) { 07686 #if DBG 07687 if ( RtlpVerboseConvert ) { 07688 KdPrint(("Can't build inherited ACL %lX\n", Status )); 07689 } 07690 #endif // DBG 07691 goto Cleanup; 07692 } 07693 07694 07695 07696 07697 07698 // 07699 // Allocate a work buffer describing the ChildAcl 07700 // 07701 07702 #ifdef NTOS_KERNEL_RUNTIME 07703 ChildAceInfo = ExAllocatePoolWithTag( 07704 PagedPool, 07705 ChildAcl->AceCount * sizeof(ACE_INFO), 07706 'cAeS' ); 07707 #else // NTOS_KERNEL_RUNTIME 07708 ChildAceInfo = RtlAllocateHeap( 07709 HeapHandle, 07710 MAKE_TAG(SE_TAG), 07711 ChildAcl->AceCount * sizeof(ACE_INFO) ); 07712 #endif // NTOS_KERNEL_RUNTIME 07713 07714 if (ChildAceInfo == NULL ) { 07715 Status = STATUS_NO_MEMORY; 07716 goto Cleanup; 07717 } 07718 07719 for (ChildAceIndex = 0, ChildAce = FirstAce(ChildAcl); 07720 ChildAceIndex < ChildAcl->AceCount; 07721 ChildAceIndex += 1, ChildAce = NextAce(ChildAce)) { 07722 ACCESS_MASK LocalMask; 07723 ULONG ChildAceFlags; 07724 07725 if ( !IsV4AceType(ChildAce) || IsCompoundAceType(ChildAce)) { 07726 *NewGenericControl |= SEP_ACL_PROTECTED; 07727 #if DBG 07728 if ( RtlpVerboseConvert ) { 07729 KdPrint(("Inherited Ace type (%ld) not known\n", ChildAce->Header.AceType )); 07730 } 07731 #endif // DBG 07732 Status = STATUS_SUCCESS; 07733 goto Cleanup; 07734 } 07735 07736 // 07737 // Compute the generic mapped mask for use in all comparisons. The 07738 // generic mapping will be undone if needed later. 07739 // 07740 // All V4 aces have an access mask in the same location. 07741 // 07742 LocalMask = ((PKNOWN_ACE)(ChildAce))->Mask; 07743 RtlApplyGenericMask( ChildAce, &LocalMask, GenericMapping); 07744 07745 07746 // 07747 // Break the ACE into its component parts. 07748 // 07749 ChildAceFlags = AceFlagsInAce( ChildAce ); 07750 if ( ChildAceFlags & CONTAINER_INHERIT_ACE ) { 07751 ChildAceInfo[ChildAceIndex].OriginalContainerInheritMask = LocalMask; 07752 ChildAceInfo[ChildAceIndex].ContainerInheritMask = LocalMask; 07753 } else { 07754 ChildAceInfo[ChildAceIndex].OriginalContainerInheritMask = 0; 07755 ChildAceInfo[ChildAceIndex].ContainerInheritMask = 0; 07756 } 07757 07758 if ( ChildAceFlags & OBJECT_INHERIT_ACE ) { 07759 ChildAceInfo[ChildAceIndex].OriginalObjectInheritMask = LocalMask; 07760 ChildAceInfo[ChildAceIndex].ObjectInheritMask = LocalMask; 07761 } else { 07762 ChildAceInfo[ChildAceIndex].OriginalObjectInheritMask = 0; 07763 ChildAceInfo[ChildAceIndex].ObjectInheritMask = 0; 07764 } 07765 07766 if ( ChildAceFlags & EFFECTIVE_ACE ) { 07767 ChildAceInfo[ChildAceIndex].OriginalEffectiveMask = LocalMask; 07768 ChildAceInfo[ChildAceIndex].EffectiveMask = LocalMask; 07769 } else { 07770 ChildAceInfo[ChildAceIndex].OriginalEffectiveMask = 0; 07771 ChildAceInfo[ChildAceIndex].EffectiveMask = 0; 07772 } 07773 07774 } 07775 07776 07777 // 07778 // Walk through the computed inherited ACL one ACE at a time. 07779 // 07780 07781 for (InheritedAceIndex = 0, InheritedAce = FirstAce(InheritedAcl); 07782 InheritedAceIndex < InheritedAcl->AceCount; 07783 InheritedAceIndex += 1, InheritedAce = NextAce(InheritedAce)) { 07784 07785 ACCESS_MASK LocalMask; 07786 07787 // 07788 // If the ACE isn't a valid version 4 ACE, 07789 // this isn't an ACL we're interested in handling. 07790 // 07791 07792 if ( !IsV4AceType(InheritedAce) || IsCompoundAceType(InheritedAce)) { 07793 *NewGenericControl |= SEP_ACL_PROTECTED; 07794 #if DBG 07795 if ( RtlpVerboseConvert ) { 07796 KdPrint(("Inherited Ace type (%ld) not known\n", InheritedAce->Header.AceType )); 07797 } 07798 #endif // DBG 07799 Status = STATUS_SUCCESS; 07800 goto Cleanup; 07801 } 07802 07803 // 07804 // Compute the generic mapped mask for use in all comparisons. The 07805 // generic mapping will be undone if needed later. 07806 // 07807 // All V4 aces have an access mask in the same location. 07808 // 07809 LocalMask = ((PKNOWN_ACE)(InheritedAce))->Mask; 07810 RtlApplyGenericMask( InheritedAce, &LocalMask, GenericMapping); 07811 07812 if ( LocalMask == 0 ) { 07813 #if DBG 07814 if ( RtlpVerboseConvert ) { 07815 KdPrint(("Worthless INH ACE: %ld 0x%8.8lx\n", InheritedAceIndex, LocalMask )); 07816 } 07817 #endif // DBG 07818 continue; 07819 } 07820 07821 // 07822 // This ACE is some combination of an effective ACE, a container 07823 // inherit ACE and an object inherit ACE. Process each of those 07824 // attributes separately since they might be represented separately 07825 // in the ChildAcl. 07826 // 07827 07828 InheritedAceFlags = AceFlagsInAce( InheritedAce ); 07829 07830 if ( InheritedAceFlags == 0 ) { 07831 #if DBG 07832 if ( RtlpVerboseConvert ) { 07833 KdPrint(("Worthless INH ACE: %ld 0x%lx\n", InheritedAceIndex, InheritedAceFlags )); 07834 } 07835 #endif // DBG 07836 continue; 07837 } 07838 07839 if ( InheritedAceFlags & CONTAINER_INHERIT_ACE ) { 07840 OriginalInheritedContainerInheritMask = InheritedContainerInheritMask = LocalMask; 07841 } else { 07842 OriginalInheritedContainerInheritMask = InheritedContainerInheritMask = 0; 07843 } 07844 07845 if ( InheritedAceFlags & OBJECT_INHERIT_ACE ) { 07846 OriginalInheritedObjectInheritMask = InheritedObjectInheritMask = LocalMask; 07847 } else { 07848 OriginalInheritedObjectInheritMask = InheritedObjectInheritMask = 0; 07849 } 07850 07851 if ( InheritedAceFlags & EFFECTIVE_ACE ) { 07852 OriginalInheritedEffectiveMask = InheritedEffectiveMask = LocalMask; 07853 } else { 07854 OriginalInheritedEffectiveMask = InheritedEffectiveMask = 0; 07855 } 07856 07857 #if DBG 07858 if ( RtlpVerboseConvert ) { 07859 KdPrint(("Doing INH ACE: %ld %8.8lX %8.8lX %8.8lX\n", InheritedAceIndex, InheritedEffectiveMask, InheritedContainerInheritMask, InheritedObjectInheritMask )); 07860 } 07861 #endif // DBG 07862 07863 07864 // 07865 // Loop through the entire child ACL comparing each inherited ACE with 07866 // each child ACE. Don't stop simply because we've matched once. 07867 // Multiple ACEs in the one ACL may have been condensed into a single ACE 07868 // in the other ACL in any combination (by any of our friendly ACL editors). 07869 // In all cases, it is better to compute a resultant auto inherited ACL 07870 // than it is to compute a protected ACL. 07871 // 07872 07873 for (ChildAceIndex = 0, ChildAce = FirstAce(ChildAcl); 07874 ChildAceIndex < ChildAcl->AceCount; 07875 ChildAceIndex += 1, ChildAce = NextAce(ChildAce)) { 07876 07877 07878 // 07879 // Ensure the ACE represents the same principal and object, 07880 // 07881 07882 #if DBG 07883 if ( RtlpVerboseConvert ) { 07884 KdPrint(("Compare Child Ace: %ld ", ChildAceIndex )); 07885 } 07886 #endif // DBG 07887 07888 if ( !RtlpCompareAces( InheritedAce, 07889 ChildAce, 07890 OwnerSid, 07891 GroupSid ) ) { 07892 #if DBG 07893 if ( RtlpVerboseConvert ) { 07894 KdPrint(("\n" )); 07895 } 07896 #endif // DBG 07897 continue; 07898 } 07899 #if DBG 07900 if ( RtlpVerboseConvert ) { 07901 KdPrint(("\n" )); 07902 } 07903 #endif // DBG 07904 07905 07906 // 07907 // Match as many access bits in the INH ACE as possible. 07908 // 07909 // Don't pay any attention to whether the bits have been previously matched 07910 // in the CHILD ACE. To do so, would imply that there is a one-to-one 07911 // correspondance between bits in the INH ACL and Child ACL. Unfortunately, 07912 // ACL editors feel free to compress out duplicate bits in both 07913 // the CHILD ACL and PARENT ACL as they see fit. 07914 // 07915 07916 InheritedEffectiveMask &= ~ChildAceInfo[ChildAceIndex].OriginalEffectiveMask; 07917 InheritedContainerInheritMask &= ~ChildAceInfo[ChildAceIndex].OriginalContainerInheritMask; 07918 InheritedObjectInheritMask &= ~ChildAceInfo[ChildAceIndex].OriginalObjectInheritMask; 07919 07920 #if DBG 07921 if ( RtlpVerboseConvert ) { 07922 KdPrint(("New INH MASKs %ld %8.8lX %8.8lX %8.8lX\n", InheritedAceIndex, InheritedEffectiveMask, InheritedContainerInheritMask, InheritedObjectInheritMask )); 07923 } 07924 #endif // DBG 07925 07926 07927 // 07928 // Match as many access bits in the child ACE as possible. 07929 // 07930 // Same reasoning as above. 07931 // 07932 07933 ChildAceInfo[ChildAceIndex].EffectiveMask &= ~OriginalInheritedEffectiveMask; 07934 ChildAceInfo[ChildAceIndex].ContainerInheritMask &= ~OriginalInheritedContainerInheritMask; 07935 ChildAceInfo[ChildAceIndex].ObjectInheritMask &= ~OriginalInheritedObjectInheritMask; 07936 07937 #if DBG 07938 if ( RtlpVerboseConvert ) { 07939 KdPrint(("New Child MASKs %ld %8.8lX %8.8lX %8.8lX\n", ChildAceIndex, ChildAceInfo[ChildAceIndex].EffectiveMask, ChildAceInfo[ChildAceIndex].ContainerInheritMask, ChildAceInfo[ChildAceIndex].ObjectInheritMask )); 07940 } 07941 #endif // DBG 07942 07943 } 07944 07945 07946 // 07947 // If we couldn't process this inherited ACE, 07948 // then the child ACL wasn't inherited. 07949 // 07950 07951 if ( (InheritedEffectiveMask | InheritedContainerInheritMask | InheritedObjectInheritMask) != 0 ) { 07952 *NewGenericControl |= SEP_ACL_PROTECTED; 07953 #if DBG 07954 if ( RtlpVerboseConvert ) { 07955 KdPrint(("INH ACE not completely matched: %ld %8.8lX %8.8lX %8.8lX\n", InheritedAceIndex, InheritedEffectiveMask, InheritedContainerInheritMask, InheritedObjectInheritMask )); 07956 } 07957 #endif // DBG 07958 Status = STATUS_SUCCESS; 07959 goto Cleanup; 07960 } 07961 07962 07963 } 07964 07965 // 07966 // ASSERT: All of the inherited ACEs have been processed. 07967 // 07968 07969 // 07970 // Loop through the Child ACL ensuring we can build a valid auto inherited ACL 07971 // 07972 07973 InheritedAllowFound = FALSE; 07974 InheritedDenyFound = FALSE; 07975 NonInheritedAclSize = 0; 07976 for (ChildAceIndex = 0, ChildAce = FirstAce(ChildAcl); 07977 ChildAceIndex < ChildAcl->AceCount; 07978 ChildAceIndex += 1, ChildAce = NextAce(ChildAce)) { 07979 07980 ACCESS_MASK ResultantMask; 07981 07982 // 07983 // Any Child ACE access bits not eliminated above required than an 07984 // explicit non-inherited ACE by built. That ACE will have an 07985 // access mask that is the combined access mask of the unmatched bit 07986 // in the effective, container inherit, and object inherit categories. 07987 // Even though, the combined mask may include access bits not absolutely 07988 // required (since they were already inherited), this strategy prevents 07989 // us from having to build multiple ACEs (one for each category) for this 07990 // single ACE. 07991 // 07992 07993 ResultantMask = 07994 ChildAceInfo[ChildAceIndex].EffectiveMask | 07995 ChildAceInfo[ChildAceIndex].ContainerInheritMask | 07996 ChildAceInfo[ChildAceIndex].ObjectInheritMask; 07997 07998 07999 // 08000 // Handle an inherited ACE 08001 // 08002 08003 if ( ResultantMask == 0 ) { 08004 08005 // 08006 // Keep track of whether inherited "allow" and "deny" ACEs are found. 08007 // 08008 08009 if ( RtlBaseAceType[ChildAce->Header.AceType] == ACCESS_ALLOWED_ACE_TYPE ) { 08010 InheritedAllowFound = TRUE; 08011 } 08012 08013 if ( RtlBaseAceType[ChildAce->Header.AceType] == ACCESS_DENIED_ACE_TYPE ) { 08014 InheritedDenyFound = TRUE; 08015 } 08016 08017 // 08018 // Handle a non-inherited ACE 08019 // 08020 08021 } else { 08022 08023 // 08024 // Keep a running tab of the size of the non-inherited ACEs. 08025 // 08026 08027 NonInheritedAclSize += ChildAce->Header.AceSize; 08028 08029 // 08030 // Since non-inherited ACEs will be moved to the front of the ACL, 08031 // we have to be careful that we don't move a deny ACE in front of a 08032 // previously found inherited allow ACE (and vice-versa). To do so would 08033 // change the semantics of the ACL. 08034 // 08035 08036 if ( RtlBaseAceType[ChildAce->Header.AceType] == ACCESS_ALLOWED_ACE_TYPE && InheritedDenyFound ) { 08037 *NewGenericControl |= SEP_ACL_PROTECTED; 08038 #if DBG 08039 if ( RtlpVerboseConvert ) { 08040 KdPrint(("Previous deny found Child ACE: %ld\n", ChildAceIndex )); 08041 } 08042 #endif // DBG 08043 Status = STATUS_SUCCESS; 08044 goto Cleanup; 08045 } 08046 08047 if ( RtlBaseAceType[ChildAce->Header.AceType] == ACCESS_DENIED_ACE_TYPE && InheritedAllowFound ) { 08048 *NewGenericControl |= SEP_ACL_PROTECTED; 08049 #if DBG 08050 if ( RtlpVerboseConvert ) { 08051 KdPrint(("Previous allow found Child ACE: %ld\n", ChildAceIndex )); 08052 } 08053 #endif // DBG 08054 Status = STATUS_SUCCESS; 08055 goto Cleanup; 08056 } 08057 08058 } 08059 08060 } 08061 08062 // 08063 // The resultant ACL is composed of the non-inherited ACEs followed by 08064 // the inherited ACE. The inherited ACEs are built by running the 08065 // inheritance algorithm over the Parent ACL. 08066 // 08067 // The Inherited ACL computed below is almost identical to InhertedAcl. 08068 // However, InheritedAcl didn't properly substitute the correct owner and 08069 // group SID. 08070 // 08071 08072 Status = RtlpInheritAcl ( 08073 ParentAcl, 08074 NULL, // No explicit child ACL 08075 0, // No Child Generic Control 08076 IsDirectoryObject, 08077 TRUE, // AutoInherit the DACL 08078 FALSE, // Not default descriptor for object 08079 OwnerSid, // Subsitute a constant SID 08080 GroupSid, // Subsitute a constant SID 08081 OwnerSid, // Server Owner (Technically incorrect, but OK since we don't support compound ACEs) 08082 GroupSid, // Server Group 08083 GenericMapping, 08084 TRUE, // Is a SACL 08085 ObjectType, 08086 &RealInheritedAcl, 08087 &AclExplicitlyAssigned, 08088 &GenericControl ); 08089 08090 if ( !NT_SUCCESS(Status) ) { 08091 #if DBG 08092 if ( RtlpVerboseConvert ) { 08093 KdPrint(("Can't build real inherited ACL %lX\n", Status )); 08094 } 08095 #endif // DBG 08096 goto Cleanup; 08097 } 08098 08099 08100 08101 // 08102 // Allocate a buffer for the inherited ACL 08103 // 08104 08105 #ifdef NTOS_KERNEL_RUNTIME 08106 *NewAcl = ExAllocatePoolWithTag( 08107 PagedPool, 08108 RealInheritedAcl->AclSize + NonInheritedAclSize, 08109 'cAeS' ); 08110 #else // NTOS_KERNEL_RUNTIME 08111 *NewAcl = RtlAllocateHeap( 08112 HeapHandle, 08113 MAKE_TAG(SE_TAG), 08114 RealInheritedAcl->AclSize + NonInheritedAclSize ); 08115 #endif // NTOS_KERNEL_RUNTIME 08116 08117 if ( *NewAcl == NULL ) { 08118 Status = STATUS_NO_MEMORY; 08119 goto Cleanup; 08120 } 08121 08122 // 08123 // All non-inherited ACEs are copied first. 08124 // The inherited ACES are grabbed from real inherited ACL. 08125 // 08126 // Build an ACL Header. 08127 // 08128 08129 Status = RtlCreateAcl( *NewAcl, 08130 RealInheritedAcl->AclSize + NonInheritedAclSize, 08131 max( RealInheritedAcl->AclRevision, ChildAcl->AclRevision ) ); 08132 08133 if ( !NT_SUCCESS(Status) ) { 08134 #if DBG 08135 if ( RtlpVerboseConvert ) { 08136 KdPrint(("Can't create final ACL %lX\n", Status )); 08137 } 08138 #endif // DBG 08139 // 08140 // The only reason for failure would be if the combined ACL is too large. 08141 // So just create a protected ACL (better than a failure). 08142 // 08143 *NewGenericControl |= SEP_ACL_PROTECTED; 08144 Status = STATUS_SUCCESS; 08145 goto Cleanup; 08146 } 08147 08148 // 08149 // Copy the non-inherited ACES. 08150 // 08151 08152 Where = ((PUCHAR)(*NewAcl)) + sizeof(ACL); 08153 for (ChildAceIndex = 0, ChildAce = FirstAce(ChildAcl); 08154 ChildAceIndex < ChildAcl->AceCount; 08155 ChildAceIndex += 1, ChildAce = NextAce(ChildAce)) { 08156 08157 ACCESS_MASK ResultantMask; 08158 08159 // 08160 // Copy the non-inherited ACE from the Child only if there's a non-zero access mask. 08161 // 08162 08163 ResultantMask = 08164 ChildAceInfo[ChildAceIndex].EffectiveMask | 08165 ChildAceInfo[ChildAceIndex].ContainerInheritMask | 08166 ChildAceInfo[ChildAceIndex].ObjectInheritMask; 08167 08168 if ( ResultantMask != 0 ) { 08169 PKNOWN_ACE NewAce; 08170 ULONG GenericBitToTry; 08171 08172 // 08173 // Use the original ChildAce as the template. 08174 // 08175 08176 RtlCopyMemory( Where, ChildAce, ChildAce->Header.AceSize ); 08177 NewAce = (PKNOWN_ACE)Where; 08178 NewAce->Header.AceFlags &= ~INHERITED_ACE; // Clear stray bits 08179 Where += ChildAce->Header.AceSize; 08180 08181 (*NewAcl)->AceCount ++; 08182 08183 // 08184 // The AccessMask on the ACE are those access bits that didn't get matched 08185 // by inherited ACEs. 08186 // 08187 08188 NewAce->Mask = ChildAce->Mask & ResultantMask; 08189 ResultantMask &= ~ChildAce->Mask; 08190 #if DBG 08191 if ( RtlpVerboseConvert ) { 08192 KdPrint(("Original non-inherited: %ld %8.8lX %8.8lX\n", ChildAceIndex, NewAce->Mask, ResultantMask )); 08193 } 08194 #endif // DBG 08195 08196 // 08197 // Map any remaining bits back to generic access bits. 08198 // Doing so might expand the ResultantMask to beyond what was computed above. 08199 // Doing so will never expand the computed ACE to beyond what the original 08200 // ChildAce granted. 08201 // 08202 08203 ASSERT( GENERIC_WRITE == (GENERIC_READ >> 1)); 08204 ASSERT( GENERIC_EXECUTE == (GENERIC_WRITE >> 1)); 08205 ASSERT( GENERIC_ALL == (GENERIC_EXECUTE >> 1)); 08206 08207 GenericBitToTry = GENERIC_READ; 08208 08209 while ( ResultantMask && GenericBitToTry >= GENERIC_ALL ) { 08210 08211 // 08212 // Only map generic bits that are in the ChildAce. 08213 // 08214 08215 if ( GenericBitToTry & ChildAce->Mask ) { 08216 ACCESS_MASK GenericMask; 08217 08218 // 08219 // Compute the real access mask corresponding to the Generic bit. 08220 // 08221 08222 GenericMask = GenericBitToTry; 08223 RtlMapGenericMask( &GenericMask, GenericMapping ); 08224 08225 // 08226 // If the current generic bit matches any of the bits remaining, 08227 // set the generic bit in the current ACE. 08228 // 08229 08230 if ( (ResultantMask & GenericMask) != 0 ) { 08231 NewAce->Mask |= GenericBitToTry; 08232 ResultantMask &= ~GenericMask; 08233 } 08234 #if DBG 08235 if ( RtlpVerboseConvert ) { 08236 KdPrint(("Generic non-inherited: %ld %8.8lX %8.8lX\n", ChildAceIndex, NewAce->Mask, ResultantMask )); 08237 } 08238 #endif // DBG 08239 } 08240 08241 // 08242 // Try the next Generic bit. 08243 // 08244 08245 GenericBitToTry >>= 1; 08246 } 08247 08248 08249 // 08250 // This is really an internal error, but press on regardless. 08251 // 08252 08253 ASSERT(ResultantMask == 0 ); 08254 NewAce->Mask |= ResultantMask; 08255 #if DBG 08256 if ( RtlpVerboseConvert ) { 08257 KdPrint(("Final non-inherited: %ld %8.8lX %8.8lX\n", ChildAceIndex, NewAce->Mask, ResultantMask )); 08258 } 08259 #endif // DBG 08260 08261 } 08262 } 08263 08264 // 08265 // Copy the inherited ACES. 08266 // Simply copy computed Inherited ACL. 08267 // 08268 08269 RtlCopyMemory( Where, 08270 FirstAce(RealInheritedAcl), 08271 RealInheritedAcl->AclSize - (ULONG)(((PUCHAR)FirstAce(RealInheritedAcl)) - (PUCHAR)RealInheritedAcl)); 08272 Where += RealInheritedAcl->AclSize - (ULONG)(((PUCHAR)FirstAce(RealInheritedAcl)) - (PUCHAR)RealInheritedAcl); 08273 08274 (*NewAcl)->AceCount += RealInheritedAcl->AceCount; 08275 ASSERT( (*NewAcl)->AclSize == Where - (PUCHAR)(*NewAcl) ); 08276 08277 08278 Status = STATUS_SUCCESS; 08279 Cleanup: 08280 08281 // 08282 // If successful, 08283 // build the resultant autoinherited ACL. 08284 // 08285 08286 if ( NT_SUCCESS(Status) ) { 08287 08288 // 08289 // If the Child ACL is protected, 08290 // just build it as a copy of the original ACL 08291 // 08292 08293 if ( *NewGenericControl & SEP_ACL_PROTECTED ) { 08294 08295 // 08296 // If we've already allocated a new ACL (and couldn't finish it for some reason), 08297 // free it. 08298 08299 if ( *NewAcl != NULL) { 08300 #ifdef NTOS_KERNEL_RUNTIME 08301 ExFreePool( *NewAcl ); 08302 #else // NTOS_KERNEL_RUNTIME 08303 RtlFreeHeap( HeapHandle, 0, *NewAcl ); 08304 #endif // NTOS_KERNEL_RUNTIME 08305 *NewAcl = NULL; 08306 } 08307 08308 // 08309 // Allocate a buffer for the protected ACL. 08310 // 08311 08312 #ifdef NTOS_KERNEL_RUNTIME 08313 *NewAcl = ExAllocatePoolWithTag( 08314 PagedPool, 08315 ChildAcl->AclSize, 08316 'cAeS' ); 08317 #else // NTOS_KERNEL_RUNTIME 08318 *NewAcl = RtlAllocateHeap( 08319 HeapHandle, 08320 MAKE_TAG(SE_TAG), 08321 ChildAcl->AclSize ); 08322 #endif // NTOS_KERNEL_RUNTIME 08323 08324 if ( *NewAcl == NULL ) { 08325 Status = STATUS_NO_MEMORY; 08326 } else { 08327 RtlCopyMemory( *NewAcl, ChildAcl, ChildAcl->AclSize ); 08328 } 08329 } 08330 08331 } 08332 08333 if ( ChildAceInfo != NULL) { 08334 #ifdef NTOS_KERNEL_RUNTIME 08335 ExFreePool( ChildAceInfo ); 08336 #else // NTOS_KERNEL_RUNTIME 08337 RtlFreeHeap( HeapHandle, 0, ChildAceInfo ); 08338 #endif // NTOS_KERNEL_RUNTIME 08339 } 08340 08341 if ( InheritedAcl != NULL) { 08342 #ifdef NTOS_KERNEL_RUNTIME 08343 ExFreePool( InheritedAcl ); 08344 #else // NTOS_KERNEL_RUNTIME 08345 RtlFreeHeap( HeapHandle, 0, InheritedAcl ); 08346 #endif // NTOS_KERNEL_RUNTIME 08347 } 08348 08349 if ( RealInheritedAcl != NULL) { 08350 #ifdef NTOS_KERNEL_RUNTIME 08351 ExFreePool( RealInheritedAcl ); 08352 #else // NTOS_KERNEL_RUNTIME 08353 RtlFreeHeap( HeapHandle, 0, RealInheritedAcl ); 08354 #endif // NTOS_KERNEL_RUNTIME 08355 } 08356 08357 return Status; 08358 }

NTSTATUS RtlpConvertToAutoInheritSecurityObject IN PSECURITY_DESCRIPTOR ParentDescriptor  OPTIONAL,
IN PSECURITY_DESCRIPTOR  CurrentSecurityDescriptor,
OUT PSECURITY_DESCRIPTOR *  NewSecurityDescriptor,
IN GUID *ObjectType  OPTIONAL,
IN BOOLEAN  IsDirectoryObject,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 6520 of file sertl.c.

References ExAllocatePoolWithTag, ExFreePool(), FALSE, HeapHandle, MAKE_TAG, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, PrimaryToken, RTL_PAGED_CODE, RtlAllocateHeap, RtlCreateSecurityDescriptorRelative(), RtlFreeHeap, RtlpConvertAclToAutoInherit(), RtlValidSecurityDescriptor(), SE_TAG, SeLengthSid, Status, and TRUE.

Referenced by RtlConvertToAutoInheritSecurityObject().

06530 : 06531 06532 This routine a converts a security descriptor whose ACLs are not marked 06533 as AutoInherit to a security descriptor whose ACLs are marked as 06534 AutoInherit. 06535 06536 See comments for RtlConvertToAutoInheritSecurityObject. 06537 06538 Arguments: 06539 06540 ParentDescriptor - Supplies the Security Descriptor for the parent 06541 directory under which a object exists. If there is 06542 no parent directory, then this argument is specified as NULL. 06543 06544 CurrentSecurityDescriptor - Supplies a pointer to the objects security descriptor 06545 that is going to be altered by this procedure. 06546 06547 NewSecurityDescriptor Points to a pointer that is to be made to point to the 06548 newly allocated self-relative security descriptor. When no 06549 longer needed, this descriptor must be freed using 06550 DestroyPrivateObjectSecurity(). 06551 06552 ObjectType - GUID of the object type being created. If the object being 06553 created has no GUID associated with it, then this argument is 06554 specified as NULL. 06555 06556 IsDirectoryObject - Specifies if the object is a 06557 directory object. A value of TRUE indicates the object is a 06558 container of other objects. 06559 06560 GenericMapping - Supplies a pointer to a generic mapping array denoting 06561 the mapping between each generic right to specific rights. 06562 06563 Return Value: 06564 06565 STATUS_SUCCESS - The operation was successful. 06566 06567 See comments for RtlConvertToAutoInheritSecurityObject. 06568 06569 06570 --*/ 06571 { 06572 NTSTATUS Status; 06573 PISECURITY_DESCRIPTOR CurrentDescriptor; 06574 PACL CurrentSacl; 06575 PACL CurrentDacl; 06576 06577 PSID NewOwner; 06578 PSID NewGroup; 06579 06580 PACL NewSacl = NULL; 06581 ULONG NewSaclControl = 0; 06582 BOOLEAN NewSaclAllocated = FALSE; 06583 06584 PACL NewDacl = NULL; 06585 ULONG NewDaclControl = 0; 06586 BOOLEAN NewDaclAllocated = FALSE; 06587 PACL TemplateInheritedDacl = NULL; 06588 ULONG GenericControl; 06589 06590 ULONG AllocationSize; 06591 ULONG NewOwnerSize; 06592 ULONG NewGroupSize; 06593 ULONG NewSaclSize; 06594 ULONG NewDaclSize; 06595 06596 PCHAR Field; 06597 PCHAR Base; 06598 06599 PISECURITY_DESCRIPTOR_RELATIVE INewDescriptor = NULL; 06600 ULONG ReturnLength; 06601 NTSTATUS PassedStatus; 06602 HANDLE PrimaryToken; 06603 06604 #ifndef NTOS_KERNEL_RUNTIME 06605 PVOID HeapHandle; 06606 #endif // NTOS_KERNEL_RUNTIME 06607 06608 RTL_PAGED_CODE(); 06609 06610 // 06611 // Get the handle to the current process heap 06612 // 06613 06614 #ifndef NTOS_KERNEL_RUNTIME 06615 HeapHandle = RtlProcessHeap(); 06616 #endif // NTOS_KERNEL_RUNTIME 06617 06618 06619 06620 // 06621 // 06622 06623 CurrentDescriptor = CurrentSecurityDescriptor; 06624 06625 // 06626 // Validate the incoming security descriptor. 06627 // 06628 06629 if (!RtlValidSecurityDescriptor ( CurrentDescriptor )) { 06630 Status = STATUS_INVALID_SECURITY_DESCR; 06631 goto Cleanup; 06632 } 06633 06634 06635 NewOwner = RtlpOwnerAddrSecurityDescriptor( CurrentDescriptor ); 06636 if ( NewOwner == NULL ) { 06637 Status = STATUS_INVALID_SECURITY_DESCR; 06638 goto Cleanup; 06639 } 06640 06641 NewGroup = RtlpGroupAddrSecurityDescriptor( CurrentDescriptor ); 06642 06643 06644 06645 06646 // 06647 // Handle the SACL. 06648 // 06649 // 06650 // If the SACL isn't present, 06651 // special case it. 06652 // 06653 06654 CurrentSacl = RtlpSaclAddrSecurityDescriptor( CurrentDescriptor ); 06655 06656 if ( CurrentSacl == NULL ) { 06657 PACL ParentSacl; 06658 06659 // Preserve the Acl Present bit and protected bit from the existing descriptor. 06660 NewSaclControl |= CurrentDescriptor->Control & (SE_SACL_PROTECTED|SE_SACL_PRESENT); 06661 06662 // Always set the autoinherited bit. 06663 NewSaclControl |= SE_SACL_AUTO_INHERITED; 06664 06665 06666 // 06667 // If the Parent also has a NULL SACL, 06668 // just consider this SACL as inherited. 06669 // otherwise, this SACL is protected. 06670 // 06671 06672 ParentSacl = ARGUMENT_PRESENT(ParentDescriptor) ? 06673 RtlpSaclAddrSecurityDescriptor( ((SECURITY_DESCRIPTOR *)ParentDescriptor)) : 06674 NULL; 06675 if ( ParentSacl != NULL) { 06676 NewSaclControl |= SE_SACL_PROTECTED; 06677 } 06678 06679 06680 // 06681 // If the SACL is already converted, 06682 // or if this object is at the root of the tree, 06683 // simply leave it alone. 06684 // 06685 // Don't force the Protect bit on at the root of the tree since it is semantically 06686 // a no-op and gets in the way if the object is ever moved. 06687 // 06688 06689 } else if ( RtlpAreControlBitsSet( CurrentDescriptor, SE_SACL_AUTO_INHERITED) || 06690 RtlpAreControlBitsSet( CurrentDescriptor, SE_SACL_PROTECTED ) || 06691 !ARGUMENT_PRESENT(ParentDescriptor) ) { 06692 06693 // Preserve the Acl Present bit and protected bit from the existing descriptor. 06694 NewSaclControl |= CurrentDescriptor->Control & (SE_SACL_PROTECTED|SE_SACL_PRESENT); 06695 06696 // Always set the autoinherited bit. 06697 NewSaclControl |= SE_SACL_AUTO_INHERITED; 06698 06699 NewSacl = CurrentSacl; 06700 06701 06702 // 06703 // If the SACL is present, 06704 // compute a new SACL with appropriate ACEs marked as inherited. 06705 // 06706 06707 } else { 06708 06709 06710 Status = RtlpConvertAclToAutoInherit ( 06711 ARGUMENT_PRESENT(ParentDescriptor) ? 06712 RtlpSaclAddrSecurityDescriptor( 06713 ((SECURITY_DESCRIPTOR *)ParentDescriptor)) : 06714 NULL, 06715 RtlpSaclAddrSecurityDescriptor(CurrentDescriptor), 06716 ObjectType, 06717 IsDirectoryObject, 06718 RtlpOwnerAddrSecurityDescriptor(CurrentDescriptor), 06719 RtlpGroupAddrSecurityDescriptor(CurrentDescriptor), 06720 GenericMapping, 06721 &NewSacl, 06722 &GenericControl ); 06723 06724 if ( !NT_SUCCESS(Status) ) { 06725 goto Cleanup; 06726 } 06727 06728 NewSaclAllocated = TRUE; 06729 NewSaclControl |= SE_SACL_PRESENT | SeControlGenericToSacl( GenericControl ); 06730 } 06731 06732 06733 // 06734 // Handle the DACL. 06735 // 06736 // 06737 // If the DACL isn't present, 06738 // special case it. 06739 // 06740 06741 CurrentDacl = RtlpDaclAddrSecurityDescriptor( CurrentDescriptor ); 06742 06743 if ( CurrentDacl == NULL ) { 06744 // Preserve the Dacl Present bit from the existing descriptor. 06745 NewDaclControl |= CurrentDescriptor->Control & SE_DACL_PRESENT; 06746 06747 // Always set the autoinherited bit. 06748 // Force it protected. 06749 NewDaclControl |= SE_DACL_AUTO_INHERITED | SE_DACL_PROTECTED; 06750 06751 06752 06753 // 06754 // If the DACL is already converted, 06755 // or if this object is at the root of the tree, 06756 // simply leave it alone. 06757 // 06758 // Don't force the Protect bit on at the root of the tree since it is semantically 06759 // a no-op and gets in the way if the object is ever moved. 06760 // 06761 06762 } else if ( RtlpAreControlBitsSet( CurrentDescriptor, SE_DACL_AUTO_INHERITED) || 06763 RtlpAreControlBitsSet( CurrentDescriptor, SE_DACL_PROTECTED ) || 06764 !ARGUMENT_PRESENT(ParentDescriptor) ) { 06765 06766 // Preserve the Acl Present bit and protected bit from the existing descriptor. 06767 NewDaclControl |= CurrentDescriptor->Control & (SE_DACL_PROTECTED|SE_DACL_PRESENT); 06768 06769 // Always set the autoinherited bit. 06770 NewDaclControl |= SE_DACL_AUTO_INHERITED; 06771 06772 NewDacl = CurrentDacl; 06773 06774 06775 06776 // 06777 // If the DACL is present, 06778 // compute a new DACL with appropriate ACEs marked as inherited. 06779 // 06780 06781 } else { 06782 06783 06784 Status = RtlpConvertAclToAutoInherit ( 06785 ARGUMENT_PRESENT(ParentDescriptor) ? 06786 RtlpDaclAddrSecurityDescriptor( 06787 ((SECURITY_DESCRIPTOR *)ParentDescriptor)) : 06788 NULL, 06789 RtlpDaclAddrSecurityDescriptor(CurrentDescriptor), 06790 ObjectType, 06791 IsDirectoryObject, 06792 RtlpOwnerAddrSecurityDescriptor(CurrentDescriptor), 06793 RtlpGroupAddrSecurityDescriptor(CurrentDescriptor), 06794 GenericMapping, 06795 &NewDacl, 06796 &GenericControl ); 06797 06798 if ( !NT_SUCCESS(Status) ) { 06799 goto Cleanup; 06800 } 06801 06802 NewDaclAllocated = TRUE; 06803 NewDaclControl |= SE_DACL_PRESENT | SeControlGenericToDacl( GenericControl ); 06804 } 06805 06806 06807 06808 // 06809 // Build the resultant security descriptor 06810 // 06811 // Also map the ACEs for application to the target object 06812 // type, if they haven't already been mapped. 06813 // 06814 06815 NewOwnerSize = LongAlignSize(SeLengthSid(NewOwner)); 06816 06817 if ( NewGroup != NULL ) { 06818 NewGroupSize = LongAlignSize(SeLengthSid(NewGroup)); 06819 } else { 06820 NewGroupSize = 0; 06821 } 06822 06823 if (NewSacl != NULL) { 06824 NewSaclSize = LongAlignSize(NewSacl->AclSize); 06825 } else { 06826 NewSaclSize = 0; 06827 } 06828 06829 if (NewDacl != NULL) { 06830 NewDaclSize = LongAlignSize(NewDacl->AclSize); 06831 } else { 06832 NewDaclSize = 0; 06833 } 06834 06835 AllocationSize = LongAlignSize(sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + 06836 NewOwnerSize + 06837 NewGroupSize + 06838 NewSaclSize + 06839 NewDaclSize; 06840 06841 // 06842 // Allocate and initialize the security descriptor as 06843 // self-relative form. 06844 // 06845 06846 06847 #ifdef NTOS_KERNEL_RUNTIME 06848 INewDescriptor = ExAllocatePoolWithTag( 06849 PagedPool, 06850 AllocationSize, 06851 'dSeS' ); 06852 #else // NTOS_KERNEL_RUNTIME 06853 INewDescriptor = RtlAllocateHeap( 06854 HeapHandle, 06855 MAKE_TAG(SE_TAG), 06856 AllocationSize ); 06857 #endif // NTOS_KERNEL_RUNTIME 06858 06859 if ( INewDescriptor == NULL ) { 06860 Status = STATUS_NO_MEMORY; 06861 goto Cleanup; 06862 } 06863 06864 06865 // 06866 // Initialize the security descriptor as self-relative form. 06867 // 06868 06869 RtlCreateSecurityDescriptorRelative( 06870 INewDescriptor, 06871 SECURITY_DESCRIPTOR_REVISION 06872 ); 06873 06874 RtlpSetControlBits( INewDescriptor, SE_SELF_RELATIVE ); 06875 06876 Base = (PCHAR)(INewDescriptor); 06877 Field = Base + sizeof(SECURITY_DESCRIPTOR_RELATIVE); 06878 06879 // 06880 // Copy the Sacl 06881 // 06882 06883 RtlpSetControlBits( INewDescriptor, NewSaclControl ); 06884 if (NewSacl != NULL ) { 06885 06886 RtlCopyMemory( Field, NewSacl, NewSacl->AclSize ); 06887 INewDescriptor->Sacl = RtlPointerToOffset(Base,Field); 06888 Field += NewSaclSize; 06889 06890 } else { 06891 06892 INewDescriptor->Sacl = 0; 06893 } 06894 06895 // 06896 // Copy the Dacl 06897 // 06898 06899 RtlpSetControlBits( INewDescriptor, NewDaclControl ); 06900 if (NewDacl != NULL ) { 06901 06902 RtlCopyMemory( Field, NewDacl, NewDacl->AclSize ); 06903 INewDescriptor->Dacl = RtlPointerToOffset(Base,Field); 06904 Field += NewDaclSize; 06905 06906 } else { 06907 06908 INewDescriptor->Dacl = 0; 06909 } 06910 06911 // 06912 // Assign the owner 06913 // 06914 06915 RtlCopyMemory( Field, NewOwner, SeLengthSid(NewOwner) ); 06916 INewDescriptor->Owner = RtlPointerToOffset(Base,Field); 06917 Field += NewOwnerSize; 06918 06919 if ( NewGroup != NULL ) { 06920 RtlCopyMemory( Field, NewGroup, SeLengthSid(NewGroup) ); 06921 INewDescriptor->Group = RtlPointerToOffset(Base,Field); 06922 } 06923 06924 Status = STATUS_SUCCESS; 06925 06926 06927 06928 // 06929 // Cleanup any locally used resources. 06930 // 06931 Cleanup: 06932 if (NewDaclAllocated) { 06933 #ifdef NTOS_KERNEL_RUNTIME 06934 ExFreePool( NewDacl ); 06935 #else // NTOS_KERNEL_RUNTIME 06936 RtlFreeHeap( HeapHandle, 0, NewDacl ); 06937 #endif // NTOS_KERNEL_RUNTIME 06938 } 06939 if (NewSaclAllocated) { 06940 #ifdef NTOS_KERNEL_RUNTIME 06941 ExFreePool( NewSacl ); 06942 #else // NTOS_KERNEL_RUNTIME 06943 RtlFreeHeap( HeapHandle, 0, NewSacl ); 06944 #endif // NTOS_KERNEL_RUNTIME 06945 } 06946 06947 *NewSecurityDescriptor = (PSECURITY_DESCRIPTOR) INewDescriptor; 06948 06949 return Status; 06950 06951 06952 }

NTSTATUS RtlpCopyAces IN PACL  Acl,
IN PGENERIC_MAPPING  GenericMapping,
IN ACE_TYPE_TO_COPY  AceTypeToCopy,
IN UCHAR  AceFlagsToReset,
IN BOOLEAN  MapSids,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
OUT PULONG  NewAclSizeParam,
OUT PACL  NewAcl
 

Definition at line 4371 of file sertl.c.

References CopyAllAces, CopyInheritedAces, CopyNonInheritedAces, FALSE, FirstAce, NextAce, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlFirstFreeAce(), RtlpCopyEffectiveAce(), Status, and TRUE.

Referenced by RtlpComputeMergedAcl2(), and RtlpInheritAcl2().

04387 : 04388 04389 Copy ACEs from of an ACL and perform generic mapping. Only ACEs specified 04390 by 'AceFilter' are copied. 04391 04392 Arguments: 04393 04394 Acl - Supplies the ACL to copy from. 04395 04396 GenericMapping - Specifies the generic mapping to use. 04397 04398 AceTypeToCopy - Describes which aces to copy. 04399 04400 AceFlagsToReset - Bit mask of ACE flags to reset (if set) on each ACE. 04401 04402 MapSids - TRUE if the SID in the ACE is to be mapped to the corresponding 04403 actual SID. 04404 04405 ClientOwnerSid - Specifies the owner Sid to use 04406 04407 ClientGroupSid - Specifies the new Group Sid to use 04408 04409 ServerOwnerSid - Optionally specifies the Server Sid to use in compound ACEs. 04410 04411 ServerGroupSid - Optionally specifies the Server group Sid to use in compound ACEs. 04412 04413 NewAclSizeParam - Receives the cumulatiave length of the copies ACEs 04414 04415 NewAcl - Provides a pointer to the ACL to copy to. 04416 This ACL must already be initialized. 04417 04418 04419 Return Value: 04420 04421 STATUS_SUCCESS - An inheritable ACL has been generated. 04422 04423 STATUS_BUFFER_TOO_SMALL - The ACL specified by NewAcl is too small for the 04424 copied ACEs. The required size is returned in NewAceLength. 04425 04426 04427 --*/ 04428 04429 { 04430 04431 NTSTATUS Status; 04432 ULONG i; 04433 04434 PACE_HEADER OldAce; 04435 ULONG NewAclSize, NewAceSize; 04436 BOOLEAN AclOverflowed = FALSE; 04437 BOOLEAN CopyAce; 04438 PVOID AcePosition; 04439 04440 04441 RTL_PAGED_CODE(); 04442 04443 // 04444 // Validate the ACL. 04445 // 04446 04447 if ( !ValidAclRevision(NewAcl) ) { 04448 return STATUS_UNKNOWN_REVISION; 04449 } 04450 04451 // 04452 // Find where the first ACE goes. 04453 // 04454 04455 if (!RtlFirstFreeAce( NewAcl, &AcePosition )) { 04456 return STATUS_BAD_INHERITANCE_ACL; 04457 } 04458 04459 // 04460 // Walk through the original ACL copying ACEs. 04461 // 04462 04463 NewAclSize = 0; 04464 for (i = 0, OldAce = FirstAce(Acl); 04465 i < Acl->AceCount; 04466 i += 1, OldAce = NextAce(OldAce)) { 04467 04468 // 04469 // If the ACE wasn't inherited, 04470 // copy it. 04471 // 04472 04473 switch (AceTypeToCopy) { 04474 case CopyInheritedAces: 04475 CopyAce = AceInherited(OldAce); 04476 break; 04477 case CopyNonInheritedAces: 04478 CopyAce = !AceInherited(OldAce); 04479 break; 04480 case CopyAllAces: 04481 CopyAce = TRUE; 04482 break; 04483 default: 04484 CopyAce = FALSE; 04485 break; 04486 } 04487 04488 if ( CopyAce ) { 04489 04490 04491 // 04492 // If SIDs are to be mapped, 04493 // do so (and potentially create up to two ACEs). 04494 // 04495 04496 if ( MapSids ) { 04497 PVOID TempAcePosition; 04498 ULONG EffectiveAceSize = 0; 04499 04500 BOOLEAN EffectiveAceMapped; 04501 BOOLEAN GenerateInheritAce; 04502 04503 // 04504 // Remember where the next ACE will be copied. 04505 // 04506 04507 TempAcePosition = AcePosition; 04508 NewAceSize = 0; 04509 GenerateInheritAce = 04510 (((PACE_HEADER)OldAce)->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) != 0; 04511 04512 04513 // 04514 // If the orginal ACE is an effective ACE, 04515 // create an effective ACE. 04516 // 04517 04518 if ( !(((PACE_HEADER)OldAce)->AceFlags & INHERIT_ONLY_ACE)) { 04519 BOOLEAN LocalAclOverflowed; 04520 04521 // 04522 // Copy the effective ACE into the ACL. 04523 // 04524 if ( !RtlpCopyEffectiveAce ( 04525 OldAce, 04526 FALSE, // Don't set the auto inherit bit 04527 GenerateInheritAce, 04528 ClientOwnerSid, 04529 ClientGroupSid, 04530 ServerOwnerSid, 04531 ServerGroupSid, 04532 GenericMapping, 04533 NULL, // Always copy object ACES 04534 &TempAcePosition, 04535 &EffectiveAceSize, 04536 NewAcl, 04537 NULL, // Always copy object ACES 04538 &EffectiveAceMapped, 04539 &LocalAclOverflowed ) ) { 04540 04541 return STATUS_BAD_INHERITANCE_ACL; 04542 } 04543 04544 if (LocalAclOverflowed) { 04545 AclOverflowed = TRUE; 04546 } 04547 NewAceSize += EffectiveAceSize; 04548 04549 // 04550 // Reset any undesirable AceFlags. 04551 // 04552 04553 if ( !AclOverflowed ) { 04554 ((PACE_HEADER)AcePosition)->AceFlags &= ~AceFlagsToReset; 04555 } 04556 04557 } 04558 04559 // 04560 // If the original ACE is inheritable, 04561 // create an inheritable ACE. 04562 // 04563 // ASSERT: AcePosition points to where the effective ACE was copied 04564 // ASSERT: TempAcePosition points to where the inheritable ACE should be copied 04565 // 04566 04567 if ( GenerateInheritAce ) { 04568 04569 // 04570 // If a effective ACE was created, 04571 // and it wasn't mapped, 04572 // avoid generating another ACE and simply merge the inheritance bits into 04573 // the effective ACE. 04574 // 04575 04576 if ( EffectiveAceSize != 0 && !EffectiveAceMapped ) { 04577 04578 // 04579 // Copy the inherit bits from the original ACE. 04580 // 04581 if ( !AclOverflowed ) { 04582 ((PACE_HEADER)AcePosition)->AceFlags |= 04583 ((PACE_HEADER)OldAce)->AceFlags & (VALID_INHERIT_FLAGS); 04584 ((PACE_HEADER)AcePosition)->AceFlags &= ~AceFlagsToReset; 04585 } 04586 04587 04588 // 04589 // Otherwise, generate an explicit inheritance ACE. 04590 // 04591 // But only if the access mask isn't zero. 04592 // 04593 04594 } else if ( !IsMSAceType(OldAce) || ((PKNOWN_ACE)(OldAce))->Mask != 0 ) { 04595 04596 // 04597 // Account for the new ACE being added to the ACL. 04598 // 04599 NewAceSize += (ULONG)(((PACE_HEADER)OldAce)->AceSize); 04600 04601 if (NewAceSize > 0xFFFF) { 04602 return STATUS_BAD_INHERITANCE_ACL; 04603 } 04604 04605 // 04606 // If the ACE doesn't fit, 04607 // just note the fact and don't copy the ACE. 04608 // 04609 04610 if ( ((PACE_HEADER)OldAce)->AceSize > NewAcl->AclSize - ((PUCHAR)TempAcePosition - (PUCHAR)NewAcl) ) { 04611 AclOverflowed = TRUE; 04612 } else { 04613 04614 // 04615 // copy it as is, but make sure the InheritOnly bit is set. 04616 // 04617 04618 if ( !AclOverflowed ) { 04619 RtlCopyMemory( 04620 TempAcePosition, 04621 OldAce, 04622 ((PACE_HEADER)OldAce)->AceSize 04623 ); 04624 04625 ((PACE_HEADER)TempAcePosition)->AceFlags |= INHERIT_ONLY_ACE; 04626 ((PACE_HEADER)TempAcePosition)->AceFlags &= ~AceFlagsToReset; 04627 NewAcl->AceCount += 1; 04628 } 04629 } 04630 } 04631 04632 } 04633 04634 } else { 04635 NewAceSize = (ULONG)OldAce->AceSize; 04636 04637 // 04638 // If the ACE doesn't fit, 04639 // just note the fact and don't copy the ACE. 04640 // 04641 04642 if ( AcePosition == NULL || 04643 NewAceSize > (ULONG)NewAcl->AclSize - ((PUCHAR)AcePosition - (PUCHAR)NewAcl) ) { 04644 AclOverflowed = TRUE; 04645 } else if ( !AclOverflowed ) { 04646 04647 04648 // 04649 // Copy the ACE. 04650 // 04651 04652 RtlCopyMemory( 04653 AcePosition, 04654 OldAce, 04655 NewAceSize ); 04656 04657 // 04658 // Map the generic bits. 04659 // 04660 // Is it really right to map the generic bits on an ACE 04661 // that's both effective and inheritable. Shouldn't this 04662 // be split into two ACEs in that case? Or just skip the mapping? 04663 // 04664 if (IsMSAceType( AcePosition )) { 04665 RtlApplyAceToObject( (PACE_HEADER)AcePosition, GenericMapping ); 04666 } 04667 04668 // 04669 // Reset any undesirable AceFlags. 04670 // 04671 04672 ((PACE_HEADER)AcePosition)->AceFlags &= ~AceFlagsToReset; 04673 04674 // 04675 // Account for the new ACE. 04676 // 04677 04678 NewAcl->AceCount += 1; 04679 } 04680 } 04681 04682 04683 // 04684 // Move the Ace Position to where the next ACE goes. 04685 // 04686 if ( !AclOverflowed ) { 04687 AcePosition = ((PUCHAR)AcePosition) + NewAceSize; 04688 } else { 04689 // On overflow, ensure no other ACEs are actually output to the buffer 04690 AcePosition = ((PUCHAR)NewAcl) + NewAcl->AclSize; 04691 } 04692 NewAclSize += NewAceSize; 04693 04694 } 04695 } 04696 04697 04698 // 04699 // We have the length of the new ACE, but we've calculated 04700 // it with a ULONG. It must fit into a USHORT. See if it 04701 // does. 04702 // 04703 04704 if (NewAclSize > 0xFFFF) { 04705 return STATUS_BAD_INHERITANCE_ACL; 04706 } 04707 04708 (*NewAclSizeParam) = NewAclSize; 04709 04710 return AclOverflowed ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS; 04711 04712 }

BOOLEAN RtlpCopyEffectiveAce IN PACE_HEADER  OldAce,
IN BOOLEAN  AutoInherit,
IN BOOLEAN  WillGenerateInheritAce,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN GUID *NewObjectType  OPTIONAL,
IN OUT PVOID *  AcePosition,
OUT PULONG  NewAceLength,
OUT PACL  NewAcl,
OUT PBOOLEAN ObjectAceInherited  OPTIONAL,
OUT PBOOLEAN  EffectiveAceMapped,
OUT PBOOLEAN  AclOverflowed
 

Definition at line 3880 of file sertl.c.

References ASSERT, CREATOR_SID_SIZE, CreatorSid, FALSE, KNOWN_ACE, NULL, RTL_PAGED_CODE, RtlBaseAceType, RtlEqualPrefixSid(), RtlInitializeSid(), RtlLengthRequiredSid(), SeLengthSid, TRUE, and USHORT.

Referenced by RtlpCopyAces(), and RtlpGenerateInheritedAce().

03900 : 03901 03902 This routine copy a specified ACE into an ACL as an effective ACE. 03903 The resultant ACE has all the inheritance bits turned of. 03904 The resultant ACE has the SID mapped from a generic SID to a specific SID 03905 (e.g., From "creator owner" to the passed in owner sid). 03906 03907 Arguments: 03908 03909 OldAce - Supplies the ace being inherited 03910 03911 AutoInherit - Specifies if the inheritance is an "automatic inheritance". 03912 As such, the inherited ACEs will be marked as such. 03913 03914 WillGenerateInheritAce - Specifies if the caller intends to generate an 03915 inheritable ACE the corresponds to OldAce. If TRUE, this routine will 03916 try to not map the effective ACE (increasing the likelyhood that 03917 EffectiveAceMapped will return FALSE), 03918 03919 ClientOwnerSid - Specifies the owner Sid to use 03920 03921 ClientGroupSid - Specifies the new Group Sid to use 03922 03923 ServerSid - Optionally specifies the Server Sid to use in compound ACEs. 03924 03925 ClientSid - Optionally specifies the Client Sid to use in compound ACEs. 03926 03927 GenericMapping - Specifies the generic mapping to use 03928 03929 NewObjectType - Type of object being inherited to. If not specified, 03930 the object has no object type. 03931 03932 AcePosition - On entry and exit, specifies location of the next available ACE 03933 position in NewAcl. 03934 A NULL ACE position means there is no room at all in NewAcl. 03935 03936 NewAceLength - Returns the length (in bytes) needed in NewAcl to 03937 copy the specified ACE. This might be zero to indicate that the ACE 03938 need not be copied at all. 03939 03940 NewAcl - Provides a pointer to the ACL into which the ACE is to be 03941 inherited. 03942 03943 ObjectAceInherited - Returns true if one or more object ACEs were inherited 03944 based on NewObjectType 03945 If NULL, NewObjectType is ignored and the object ACE is always inherited 03946 03947 EffectiveAceMapped - Return TRUE if the SID, guid, or access mask of Old Ace 03948 was modifed when copying the ACE. 03949 03950 AclOverflowed - Returns TRUE if NewAcl wasn't long enough to contain NewAceLength. 03951 03952 Return Value: 03953 03954 TRUE - No problem was detected. 03955 FALSE - Indicates something went wrong preventing 03956 the ACE from being compied. This generally represents a bugcheck 03957 situation when returned from this call. 03958 03959 --*/ 03960 { 03961 ULONG LengthRequired; 03962 ACCESS_MASK LocalMask; 03963 03964 PSID LocalServerOwner; 03965 PSID LocalServerGroup; 03966 03967 ULONG CreatorSid[CREATOR_SID_SIZE]; 03968 03969 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; 03970 03971 03972 RTL_PAGED_CODE(); 03973 03974 // 03975 // Allocate and initialize the universal SIDs we're going to need 03976 // to look for inheritable ACEs. 03977 // 03978 03979 ASSERT(RtlLengthRequiredSid( 1 ) == CREATOR_SID_SIZE); 03980 RtlInitializeSid( (PSID)CreatorSid, &CreatorSidAuthority, 1 ); 03981 *(RtlpSubAuthoritySid( (PSID)CreatorSid, 0 )) = SECURITY_CREATOR_OWNER_RID; 03982 03983 LocalServerOwner = ARGUMENT_PRESENT(ServerOwnerSid) ? ServerOwnerSid : ClientOwnerSid; 03984 LocalServerGroup = ARGUMENT_PRESENT(ServerGroupSid) ? ServerGroupSid : ClientGroupSid; 03985 03986 03987 // 03988 // Initialization 03989 // 03990 *EffectiveAceMapped = FALSE; 03991 if ( ARGUMENT_PRESENT(ObjectAceInherited)) { 03992 *ObjectAceInherited = FALSE; 03993 } 03994 *AclOverflowed = FALSE; 03995 LengthRequired = (ULONG)OldAce->AceSize; 03996 03997 // 03998 // Process all MS ACE types specially 03999 // 04000 04001 if ( IsMSAceType(OldAce) ) { 04002 ULONG Rid; 04003 PSID SidToCopy = NULL; 04004 ULONG AceHeaderToCopyLength; 04005 PACE_HEADER AceHeaderToCopy = OldAce; 04006 PSID ServerSidToCopy = NULL; 04007 04008 UCHAR DummyAce[sizeof(KNOWN_OBJECT_ACE)+sizeof(GUID)]; 04009 04010 // 04011 // Grab the Sid pointer and access mask as a function of the ACE type 04012 // 04013 if (IsKnownAceType( OldAce ) ) { 04014 SidToCopy = &((PKNOWN_ACE)OldAce)->SidStart; 04015 AceHeaderToCopyLength = FIELD_OFFSET(KNOWN_ACE, SidStart); 04016 04017 } else if (IsCompoundAceType(OldAce)) { 04018 04019 SidToCopy = RtlCompoundAceClientSid( OldAce ); 04020 AceHeaderToCopyLength = FIELD_OFFSET(KNOWN_COMPOUND_ACE, SidStart); 04021 ASSERT( FIELD_OFFSET(KNOWN_COMPOUND_ACE, Mask) == 04022 FIELD_OFFSET(KNOWN_ACE, Mask) ); 04023 04024 // 04025 // Compound ACEs have two SIDs (Map one now). 04026 // 04027 ServerSidToCopy = RtlCompoundAceServerSid( OldAce ); 04028 04029 if (RtlEqualPrefixSid ( ServerSidToCopy, CreatorSid )) { 04030 04031 Rid = *RtlpSubAuthoritySid( ServerSidToCopy, 0 ); 04032 switch (Rid) { 04033 case SECURITY_CREATOR_OWNER_RID: 04034 ServerSidToCopy = ClientOwnerSid; 04035 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(ClientOwnerSid); 04036 *EffectiveAceMapped = TRUE; 04037 break; 04038 case SECURITY_CREATOR_GROUP_RID: 04039 if ( ClientGroupSid != NULL ) { 04040 ServerSidToCopy = ClientGroupSid; 04041 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(ClientGroupSid); 04042 *EffectiveAceMapped = TRUE; 04043 } 04044 break; 04045 case SECURITY_CREATOR_OWNER_SERVER_RID: 04046 ServerSidToCopy = LocalServerOwner; 04047 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(LocalServerOwner); 04048 *EffectiveAceMapped = TRUE; 04049 break; 04050 case SECURITY_CREATOR_GROUP_SERVER_RID: 04051 ServerSidToCopy = LocalServerGroup; 04052 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(LocalServerGroup); 04053 *EffectiveAceMapped = TRUE; 04054 break; 04055 } 04056 04057 // 04058 // If we don't know what this SID is, just copy the original. 04059 // 04060 if ( !*EffectiveAceMapped ) { 04061 AceHeaderToCopyLength += SeLengthSid( ServerSidToCopy ); 04062 ServerSidToCopy = NULL; 04063 } 04064 04065 } else { 04066 // 04067 // We don't know what this SID is, just copy the original. 04068 // 04069 AceHeaderToCopyLength += SeLengthSid( ServerSidToCopy ); 04070 ServerSidToCopy = NULL; 04071 } 04072 04073 // 04074 // Handle Object ACEs 04075 // 04076 } else { 04077 GUID *InheritedObjectType; 04078 04079 SidToCopy = RtlObjectAceSid( OldAce ); 04080 AceHeaderToCopyLength = (ULONG) ((PUCHAR)SidToCopy - (PUCHAR)OldAce); 04081 ASSERT( FIELD_OFFSET(KNOWN_OBJECT_ACE, Mask) == 04082 FIELD_OFFSET(KNOWN_ACE, Mask) ); 04083 04084 // 04085 // Handle ACEs that are only inherited for a specific object type, 04086 // 04087 InheritedObjectType = RtlObjectAceInheritedObjectType( OldAce ); 04088 if ( ARGUMENT_PRESENT(ObjectAceInherited) && InheritedObjectType != NULL ) { 04089 04090 // 04091 // If the object type doesn't match the inherited object type, 04092 // don't inherit the ACE. 04093 // 04094 04095 if ( NewObjectType == NULL || 04096 !RtlEqualMemory( InheritedObjectType, 04097 NewObjectType, 04098 sizeof(GUID) ) ) { 04099 04100 LengthRequired = 0; 04101 04102 // 04103 // If the object type matches the inherited object type, 04104 // Inherit an ACE with no inherited object type. 04105 // 04106 04107 } else { 04108 04109 // 04110 // Tell the caller we inherited an object type specific ACE. 04111 // 04112 04113 *ObjectAceInherited = TRUE; 04114 04115 // 04116 // If the caller is not going to generate an inheritable ACE, 04117 // deleting the inherited object type GUID for the effective ACE. 04118 // 04119 // Otherwise, leave it so the caller can merge the two ACEs. 04120 // 04121 04122 if ( !WillGenerateInheritAce ) { 04123 *EffectiveAceMapped = TRUE; 04124 04125 // 04126 // If an object type GUID is present, 04127 // simply delete the inherited object type GUID. 04128 // 04129 if ( RtlObjectAceObjectTypePresent( OldAce )) { 04130 LengthRequired -= sizeof(GUID); 04131 AceHeaderToCopyLength -= sizeof(GUID); 04132 RtlCopyMemory( DummyAce, OldAce, AceHeaderToCopyLength ); 04133 04134 AceHeaderToCopy = (PACE_HEADER)DummyAce; 04135 ((PKNOWN_OBJECT_ACE)AceHeaderToCopy)->Flags &= ~ACE_INHERITED_OBJECT_TYPE_PRESENT; 04136 04137 04138 // 04139 // If an object type GUID is not present, 04140 // convert the ACE to non-object type specific. 04141 // 04142 } else { 04143 AceHeaderToCopyLength = AceHeaderToCopyLength - 04144 sizeof(GUID) + 04145 sizeof(KNOWN_ACE) - 04146 sizeof(KNOWN_OBJECT_ACE); 04147 LengthRequired = LengthRequired - 04148 sizeof(GUID) + 04149 sizeof(KNOWN_ACE) - 04150 sizeof(KNOWN_OBJECT_ACE); 04151 04152 RtlCopyMemory( DummyAce, OldAce, AceHeaderToCopyLength ); 04153 AceHeaderToCopy = (PACE_HEADER)DummyAce; 04154 04155 AceHeaderToCopy->AceType = RtlBaseAceType[ OldAce->AceType ]; 04156 04157 } 04158 } 04159 } 04160 04161 } 04162 } 04163 04164 // 04165 // Only proceed if we've not already determined to drop the ACE. 04166 // 04167 04168 if ( LengthRequired != 0 ) { 04169 04170 // 04171 // If after mapping the access mask, the access mask 04172 // is empty, then drop the ACE. 04173 // 04174 // This is incompatible with NT 4.0 which simply mapped and left 04175 // undefined access bits set. 04176 04177 LocalMask = ((PKNOWN_ACE)(OldAce))->Mask; 04178 RtlApplyGenericMask( OldAce, &LocalMask, GenericMapping); 04179 04180 if ( LocalMask != ((PKNOWN_ACE)(OldAce))->Mask ) { 04181 *EffectiveAceMapped = TRUE; 04182 } 04183 04184 // 04185 // Mask off any bits that aren't meaningful 04186 // 04187 04188 LocalMask &= ( STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL | ACCESS_SYSTEM_SECURITY ); 04189 04190 if (LocalMask == 0) { 04191 04192 LengthRequired = 0; 04193 04194 } else { 04195 04196 // 04197 // See if the SID in the ACE is one of the various CREATOR_* SIDs by 04198 // comparing identifier authorities. 04199 // 04200 04201 if (RtlEqualPrefixSid ( SidToCopy, CreatorSid )) { 04202 04203 Rid = *RtlpSubAuthoritySid( SidToCopy, 0 ); 04204 04205 switch (Rid) { 04206 case SECURITY_CREATOR_OWNER_RID: 04207 SidToCopy = ClientOwnerSid; 04208 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(ClientOwnerSid); 04209 *EffectiveAceMapped = TRUE; 04210 break; 04211 case SECURITY_CREATOR_GROUP_RID: 04212 if ( ClientGroupSid != NULL ) { 04213 SidToCopy = ClientGroupSid; 04214 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(ClientGroupSid); 04215 *EffectiveAceMapped = TRUE; 04216 } 04217 break; 04218 case SECURITY_CREATOR_OWNER_SERVER_RID: 04219 SidToCopy = LocalServerOwner; 04220 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(LocalServerOwner); 04221 *EffectiveAceMapped = TRUE; 04222 break; 04223 case SECURITY_CREATOR_GROUP_SERVER_RID: 04224 SidToCopy = LocalServerGroup; 04225 LengthRequired = LengthRequired - CREATOR_SID_SIZE + SeLengthSid(LocalServerGroup); 04226 *EffectiveAceMapped = TRUE; 04227 break; 04228 default : 04229 // 04230 // We don't know what this SID is, just copy the original. 04231 // 04232 break; 04233 } 04234 } 04235 04236 // 04237 // If the ACE doesn't fit, 04238 // just note the fact and don't copy the ACE. 04239 // 04240 04241 if ( *AcePosition == NULL || 04242 LengthRequired > (ULONG)NewAcl->AclSize - ((PUCHAR)(*AcePosition) - (PUCHAR)NewAcl) ) { 04243 *AclOverflowed = TRUE; 04244 } else { 04245 04246 PUCHAR Target; 04247 04248 // 04249 // Copy individual parts of the ACE separately. 04250 // 04251 04252 Target = (PUCHAR)*AcePosition; 04253 04254 RtlCopyMemory( 04255 Target, 04256 AceHeaderToCopy, 04257 AceHeaderToCopyLength ); 04258 04259 Target += AceHeaderToCopyLength; 04260 04261 // 04262 // Now copy the correct server SID 04263 // 04264 04265 if ( ServerSidToCopy != NULL ) { 04266 RtlCopyMemory( 04267 Target, 04268 ServerSidToCopy, 04269 SeLengthSid(ServerSidToCopy) 04270 ); 04271 Target += SeLengthSid(ServerSidToCopy); 04272 } 04273 04274 // 04275 // Now copy the correct SID 04276 // 04277 04278 RtlCopyMemory( 04279 Target, 04280 SidToCopy, 04281 SeLengthSid(SidToCopy) 04282 ); 04283 Target += SeLengthSid(SidToCopy); 04284 04285 // 04286 // Set the size of the ACE accordingly 04287 // 04288 04289 if ( LengthRequired < (ULONG)(Target - (PUCHAR)*AcePosition) ) { 04290 return FALSE; 04291 } 04292 LengthRequired = (ULONG)(Target - (PUCHAR)*AcePosition); 04293 ((PKNOWN_ACE)*AcePosition)->Header.AceSize = 04294 (USHORT)LengthRequired; 04295 04296 04297 // 04298 // Put the mapped access mask in the new ACE 04299 // 04300 04301 ((PKNOWN_ACE)*AcePosition)->Mask = LocalMask; 04302 04303 } 04304 } 04305 } 04306 04307 } else { 04308 04309 // 04310 // If the ACE doesn't fit, 04311 // just note the fact and don't copy the ACE. 04312 // 04313 04314 if ( LengthRequired > (ULONG)NewAcl->AclSize - ((PUCHAR)*AcePosition - (PUCHAR)NewAcl) ) { 04315 *AclOverflowed = TRUE; 04316 } else { 04317 04318 // 04319 // Not a known ACE type, copy ACE as is 04320 // 04321 04322 RtlCopyMemory( 04323 *AcePosition, 04324 OldAce, 04325 LengthRequired ); 04326 } 04327 } 04328 04329 // 04330 // If the ACE was actually kept, clear all the inherit flags 04331 // and update the ACE count of the ACL. 04332 // 04333 04334 if ( !*AclOverflowed && LengthRequired != 0 ) { 04335 ((PACE_HEADER)*AcePosition)->AceFlags &= ~VALID_INHERIT_FLAGS; 04336 if ( AutoInherit ) { 04337 ((PACE_HEADER)*AcePosition)->AceFlags |= INHERITED_ACE; 04338 } 04339 NewAcl->AceCount += 1; 04340 } 04341 04342 // 04343 // We have the length of the new ACE, but we've calculated 04344 // it with a ULONG. It must fit into a USHORT. See if it 04345 // does. 04346 // 04347 04348 if (LengthRequired > 0xFFFF) { 04349 return FALSE; 04350 } 04351 04352 // 04353 // Move the Ace Position to where the next ACE goes. 04354 // 04355 if ( !*AclOverflowed ) { 04356 *AcePosition = ((PUCHAR)*AcePosition) + LengthRequired; 04357 } 04358 04359 // 04360 // Now return to our caller 04361 // 04362 04363 (*NewAceLength) = LengthRequired; 04364 04365 return TRUE; 04366 }

NTSTATUS RtlpCreateServerAcl IN PACL  Acl,
IN BOOLEAN  AclUntrusted,
IN PSID  ServerSid,
OUT PACL *  ServerAcl,
OUT BOOLEAN *  ServerAclAllocated
 

Definition at line 8588 of file sertl.c.

References ASSERT, ExAllocatePoolWithTag, FALSE, FirstAce, KNOWN_ACE, MAKE_TAG, NextAce, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RTL_PAGED_CODE, RtlAllocateHeap, RtlCreateAcl(), SE_TAG, SeLengthSid, Status, TRUE, and USHORT.

Referenced by RtlpNewSecurityObject(), and RtlpSetSecurityObject().

08598 : 08599 08600 This routine takes an ACL and converts it into a server ACL. 08601 Currently, that means converting all of the GRANT ACEs into 08602 Compount Grants, and if necessary sanitizing any Compound 08603 Grants that are encountered. 08604 08605 Arguments: 08606 08607 08608 08609 Return Value: 08610 08611 08612 --*/ 08613 08614 { 08615 USHORT RequiredSize = sizeof(ACL); 08616 USHORT AceSizeAdjustment; 08617 USHORT ServerSidSize; 08618 PACE_HEADER Ace; 08619 ULONG i; 08620 PVOID Target; 08621 PVOID AcePosition; 08622 PSID UntrustedSid; 08623 PSID ClientSid; 08624 NTSTATUS Status; 08625 08626 RTL_PAGED_CODE(); 08627 08628 if (Acl == NULL) { 08629 *ServerAclAllocated = FALSE; 08630 *ServerAcl = NULL; 08631 return( STATUS_SUCCESS ); 08632 } 08633 08634 AceSizeAdjustment = sizeof( KNOWN_COMPOUND_ACE ) - sizeof( KNOWN_ACE ); 08635 ASSERT( sizeof( KNOWN_COMPOUND_ACE ) >= sizeof( KNOWN_ACE ) ); 08636 08637 ServerSidSize = (USHORT)SeLengthSid( ServerSid ); 08638 08639 // 08640 // Do this in two passes. First, determine how big the final 08641 // result is going to be, and then allocate the space and make 08642 // the changes. 08643 // 08644 08645 for (i = 0, Ace = FirstAce(Acl); 08646 i < Acl->AceCount; 08647 i += 1, Ace = NextAce(Ace)) { 08648 08649 // 08650 // If it's an ACCESS_ALLOWED_ACE_TYPE, we'll need to add in the 08651 // size of the Server SID. 08652 // 08653 08654 if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE) { 08655 08656 // 08657 // Simply add the size of the new Server SID plus whatever 08658 // adjustment needs to be made to increase the size of the ACE. 08659 // 08660 08661 RequiredSize += ( ServerSidSize + AceSizeAdjustment ); 08662 08663 } else { 08664 08665 if (AclUntrusted && Ace->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE ) { 08666 08667 // 08668 // Since the Acl is untrusted, we don't care what is in the 08669 // server SID, we're going to replace it. 08670 // 08671 08672 UntrustedSid = RtlCompoundAceServerSid( Ace ); 08673 if ((USHORT)SeLengthSid(UntrustedSid) > ServerSidSize) { 08674 RequiredSize += ((USHORT)SeLengthSid(UntrustedSid) - ServerSidSize); 08675 } else { 08676 RequiredSize += (ServerSidSize - (USHORT)SeLengthSid(UntrustedSid)); 08677 08678 } 08679 } 08680 } 08681 08682 RequiredSize += Ace->AceSize; 08683 } 08684 08685 #ifdef NTOS_KERNEL_RUNTIME 08686 (*ServerAcl) = (PACL)ExAllocatePoolWithTag( PagedPool, RequiredSize, 'cAeS' ); 08687 #else // NTOS_KERNEL_RUNTIME 08688 (*ServerAcl) = (PACL)RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( SE_TAG ), RequiredSize ); 08689 #endif // NTOS_KERNEL_RUNTIME 08690 08691 if ((*ServerAcl) == NULL) { 08692 return STATUS_INSUFFICIENT_RESOURCES; 08693 } 08694 08695 // 08696 // Mark as allocated so caller knows to free it. 08697 // 08698 08699 *ServerAclAllocated = TRUE; 08700 08701 Status = RtlCreateAcl( (*ServerAcl), RequiredSize, ACL_REVISION3 ); 08702 ASSERT( NT_SUCCESS( Status )); 08703 08704 for (i = 0, Ace = FirstAce(Acl), Target=FirstAce( *ServerAcl ); 08705 i < Acl->AceCount; 08706 i += 1, Ace = NextAce(Ace)) { 08707 08708 // 08709 // If it's an ACCESS_ALLOWED_ACE_TYPE, convert to a Server ACE. 08710 // 08711 08712 if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE || 08713 (AclUntrusted && Ace->AceType == ACCESS_ALLOWED_COMPOUND_ACE_TYPE )) { 08714 08715 AcePosition = Target; 08716 08717 if (Ace->AceType == ACCESS_ALLOWED_ACE_TYPE) { 08718 ClientSid = &((PKNOWN_ACE)Ace)->SidStart; 08719 } else { 08720 ClientSid = RtlCompoundAceClientSid( Ace ); 08721 } 08722 08723 // 08724 // Copy up to the access mask. 08725 // 08726 08727 RtlCopyMemory( 08728 Target, 08729 Ace, 08730 FIELD_OFFSET(KNOWN_ACE, SidStart) 08731 ); 08732 08733 // 08734 // Now copy the correct Server SID 08735 // 08736 08737 Target = ((PCHAR)Target + (UCHAR)(FIELD_OFFSET(KNOWN_COMPOUND_ACE, SidStart))); 08738 08739 RtlCopyMemory( 08740 Target, 08741 ServerSid, 08742 SeLengthSid(ServerSid) 08743 ); 08744 08745 Target = ((PCHAR)Target + (UCHAR)SeLengthSid(ServerSid)); 08746 08747 // 08748 // Now copy in the correct client SID. We can copy this right out of 08749 // the original ACE. 08750 // 08751 08752 RtlCopyMemory( 08753 Target, 08754 ClientSid, 08755 SeLengthSid(ClientSid) 08756 ); 08757 08758 Target = ((PCHAR)Target + SeLengthSid(ClientSid)); 08759 08760 // 08761 // Set the size of the ACE accordingly 08762 // 08763 08764 ((PKNOWN_COMPOUND_ACE)AcePosition)->Header.AceSize = 08765 (USHORT)FIELD_OFFSET(KNOWN_COMPOUND_ACE, SidStart) + 08766 (USHORT)SeLengthSid(ServerSid) + 08767 (USHORT)SeLengthSid(ClientSid); 08768 08769 // 08770 // Set the type 08771 // 08772 08773 ((PKNOWN_COMPOUND_ACE)AcePosition)->Header.AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE; 08774 ((PKNOWN_COMPOUND_ACE)AcePosition)->CompoundAceType = COMPOUND_ACE_IMPERSONATION; 08775 08776 } else { 08777 08778 // 08779 // Just copy the ACE as is. 08780 // 08781 08782 RtlCopyMemory( Target, Ace, Ace->AceSize ); 08783 08784 Target = ((PCHAR)Target + Ace->AceSize); 08785 } 08786 } 08787 08788 (*ServerAcl)->AceCount = Acl->AceCount; 08789 08790 return( STATUS_SUCCESS ); 08791 }

NTSTATUS RtlpGenerateInheritAcl IN PACL  Acl,
IN BOOLEAN  IsDirectoryObject,
IN BOOLEAN  AutoInherit,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN GUID *NewObjectType  OPTIONAL,
OUT PULONG  NewAclSizeParam,
OUT PACL  NewAcl,
OUT PBOOLEAN  ObjectAceInherited
 

Definition at line 5722 of file sertl.c.

References FALSE, FirstAce, max, NextAce, NT_SUCCESS, NTSTATUS(), RTL_PAGED_CODE, RtlpGenerateInheritedAce(), Status, and TRUE.

Referenced by RtlpInheritAcl2().

05739 : 05740 05741 This is a private routine that produces an inheritable ACL. 05742 05743 The buffer to contain the inherted ACL is passed in. If the buffer is 05744 too small, the corect size is computed and STATUS_BUFFER_TOO_SMALL is 05745 returned. 05746 05747 Arguments: 05748 05749 Acl - Supplies the acl being inherited. 05750 05751 IsDirectoryObject - Specifies if the new acl is for a directory. 05752 05753 AutoInherit - Specifies if the inheritance is an "automatic inheritance". 05754 As such, the inherited ACEs will be marked as such. 05755 05756 OwnerSid - Specifies the owner Sid to use. 05757 05758 GroupSid - Specifies the group SID to use. 05759 05760 GenericMapping - Specifies the generic mapping to use. 05761 05762 NewObjectType - Type of object being inherited to. If not specified, 05763 the object has no object type. 05764 05765 NewAclSizeParam - Receives the length of the inherited ACL. 05766 05767 NewAcl - Provides a pointer to the buffer to receive the new 05768 (inherited) acl. This ACL must already be initialized. 05769 05770 ObjectAceInherited - Returns true if one or more object ACEs were inherited 05771 based on NewObjectType 05772 05773 05774 Return Value: 05775 05776 STATUS_SUCCESS - An inheritable ACL has been generated. 05777 05778 STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL. 05779 This can becaused by a number of things. One of the more probable 05780 causes is the replacement of a CreatorId with an SID that didn't fit 05781 into the ACE or ACL. 05782 05783 STATUS_BUFFER_TOO_SMALL - The ACL specified by NewAcl is too small for the 05784 inheritance ACEs. The required size is returned in NewAceLength. 05785 05786 05787 --*/ 05788 05789 { 05790 05791 NTSTATUS Status; 05792 ULONG i; 05793 05794 PACE_HEADER OldAce; 05795 ULONG NewAclSize, NewAceSize; 05796 ULONG NewAclExtraSize, NewAceExtraSize; 05797 BOOLEAN AclOverflowed = FALSE; 05798 BOOLEAN LocalObjectAceInherited; 05799 05800 05801 RTL_PAGED_CODE(); 05802 05803 // 05804 // Walk through the original ACL generating any necessary 05805 // inheritable ACEs. 05806 // 05807 05808 NewAclSize = 0; 05809 NewAclExtraSize = 0; 05810 *ObjectAceInherited = FALSE; 05811 for (i = 0, OldAce = FirstAce(Acl); 05812 i < Acl->AceCount; 05813 i += 1, OldAce = NextAce(OldAce)) { 05814 05815 // 05816 // RtlpGenerateInheritedAce() will generate the ACE(s) necessary 05817 // to inherit a single ACE. This may be 0, 1, or more ACEs. 05818 // 05819 05820 Status = RtlpGenerateInheritedAce( 05821 OldAce, 05822 IsDirectoryObject, 05823 AutoInherit, 05824 ClientOwnerSid, 05825 ClientGroupSid, 05826 ServerOwnerSid, 05827 ServerGroupSid, 05828 GenericMapping, 05829 NewObjectType, 05830 &NewAceSize, 05831 NewAcl, 05832 &NewAceExtraSize, 05833 &LocalObjectAceInherited 05834 ); 05835 05836 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 05837 AclOverflowed = TRUE; 05838 Status = STATUS_SUCCESS; 05839 } 05840 05841 if ( !NT_SUCCESS(Status) ) { 05842 return Status; 05843 } 05844 05845 if ( LocalObjectAceInherited ) { 05846 *ObjectAceInherited = TRUE; 05847 } 05848 05849 // 05850 // Make room in the ACL for the new ACE 05851 // 05852 NewAclSize += NewAceSize; 05853 05854 // 05855 // If a previous ACE needed 'extra' space, 05856 // reduce that requirement by the size of this ACE. 05857 // 05858 // The previous ACE can use this ACE's space temporarily 05859 // 05860 if ( NewAceSize > NewAclExtraSize ) { 05861 NewAclExtraSize = 0 ; 05862 } else { 05863 NewAclExtraSize -= NewAceSize; 05864 } 05865 05866 // 05867 // The 'extra' space needed is the larger of that needed by any 05868 // previous ACE and that need by this ACE 05869 // 05870 NewAclExtraSize = max( NewAclExtraSize, NewAceExtraSize ); 05871 05872 } 05873 05874 // 05875 // We only need to include the "ExtraSize" if we've overflowed. 05876 // In those cases, the caller will allocate the size we requested and 05877 // try again. Otherwise, the caller won't call back so we don't care 05878 // if it knows about the extra size. 05879 // 05880 05881 if ( AclOverflowed ) { 05882 (*NewAclSizeParam) = NewAclSize + NewAclExtraSize; 05883 return STATUS_BUFFER_TOO_SMALL; 05884 } else { 05885 (*NewAclSizeParam) = NewAclSize; 05886 return STATUS_SUCCESS; 05887 } 05888 05889 }

NTSTATUS RtlpGenerateInheritedAce IN PACE_HEADER  OldAce,
IN BOOLEAN  IsDirectoryObject,
IN BOOLEAN  AutoInherit,
IN PSID  ClientOwnerSid,
IN PSID  ClientGroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN GUID *NewObjectType  OPTIONAL,
OUT PULONG  NewAceLength,
OUT PACL  NewAcl,
OUT PULONG  NewAceExtraLength,
OUT PBOOLEAN  ObjectAceInherited
 

Definition at line 5381 of file sertl.c.

References ASSERT, CREATOR_SID_SIZE, FALSE, max, NULL, RTL_PAGED_CODE, RtlFirstFreeAce(), RtlLengthRequiredSid(), RtlpCopyEffectiveAce(), RtlpIsDuplicateAce(), and TRUE.

Referenced by RtlpGenerateInheritAcl().

05399 : 05400 05401 This is a private routine that checks if the input ace is inheritable 05402 and produces 0, 1, or 2 inherited aces in the given buffer. 05403 05404 Arguments: 05405 05406 OldAce - Supplies the ace being inherited 05407 05408 IsDirectoryObject - Specifies if the new ACE is for a directory 05409 05410 AutoInherit - Specifies if the inheritance is an "automatic inheritance". 05411 As such, the inherited ACEs will be marked as such. 05412 05413 ClientOwnerSid - Specifies the owner Sid to use 05414 05415 ClientGroupSid - Specifies the new Group Sid to use 05416 05417 ServerSid - Optionally specifies the Server Sid to use in compound ACEs. 05418 05419 ClientSid - Optionally specifies the Client Sid to use in compound ACEs. 05420 05421 GenericMapping - Specifies the generic mapping to use 05422 05423 NewObjectType - Type of object being inherited to. If not specified, 05424 the object has no object type. 05425 05426 NewAceLength - Receives the length (number of bytes) needed to allow for 05427 the inheritance of the specified ACE. This might be zero. 05428 05429 NewAcl - Provides a pointer to the ACL into which the ACE is to be 05430 inherited. 05431 05432 NewAceExtraLength - Receives a length (number of bytes) temporarily used 05433 in the ACL for the inheritance ACE. This might be zero 05434 05435 ObjectAceInherited - Returns true if one or more object ACEs were inherited 05436 based on NewObjectType 05437 05438 Return Value: 05439 05440 STATUS_SUCCESS - The ACE was inherited successfully. 05441 05442 STATUS_BAD_INHERITANCE_ACL - Indicates something went wrong preventing 05443 the ACE from being inherited. This generally represents a bugcheck 05444 situation when returned from this call. 05445 05446 STATUS_BUFFER_TOO_SMALL - The ACL specified by NewAcl is too small for the 05447 inheritance ACEs. The required size is returned in NewAceLength. 05448 05449 05450 --*/ 05451 05452 { 05454 // // 05455 // !!!!!!!!! This is tricky !!!!!!!!!! // 05456 // // 05457 // The inheritence flags AND the sid of the ACE determine whether // 05458 // we need 0, 1, or 2 ACEs. // 05459 // // 05460 // BE CAREFUL WHEN CHANGING THIS CODE. READ THE DSA ACL ARCHITECTURE // 05461 // SECTION COVERING INHERITENCE BEFORE ASSUMING YOU KNOW WHAT THE HELL // 05462 // YOU ARE DOING!!!! // 05463 // // 05464 // The general gist of the algorithm is: // 05465 // // 05466 // if ( (container && ContainerInherit) || // 05467 // (!container && ObjectInherit) ) { // 05468 // GenerateEffectiveAce; // 05469 // } // 05470 // // 05471 // // 05472 // if (Container && Propagate) { // 05473 // Propogate copy of ACE and set InheritOnly; // 05474 // } // 05475 // // 05476 // // 05477 // A slightly more accurate description of this algorithm is: // 05478 // // 05479 // IO === InheritOnly flag // 05480 // CI === ContainerInherit flag // 05481 // OI === ObjectInherit flag // 05482 // NPI === NoPropagateInherit flag // 05483 // // 05484 // if ( (container && CI) || // 05485 // (!container && OI) ) { // 05486 // Copy Header of ACE; // 05487 // Clear IO, NPI, CI, OI; // 05488 // // 05489 // if (KnownAceType) { // 05490 // if (SID is a creator ID) { // 05491 // Copy appropriate creator SID; // 05492 // } else { // 05493 // Copy SID of original; // 05494 // } // 05495 // // 05496 // Copy AccessMask of original; // 05497 // MapGenericAccesses; // 05498 // if (AccessMask == 0) { // 05499 // discard new ACE; // 05500 // } // 05501 // // 05502 // } else { // 05503 // Copy body of ACE; // 05504 // } // 05505 // // 05506 // } // 05507 // // 05508 // if (!NPI) { // 05509 // Copy ACE as is; // 05510 // Set IO; // 05511 // } // 05512 // // 05513 // // 05514 // // 05516 05517 05518 05519 ULONG LengthRequired = 0; 05520 ULONG ExtraLengthRequired = 0; 05521 PVOID AcePosition; 05522 PVOID EffectiveAcePosition; 05523 ULONG EffectiveAceSize = 0; 05524 05525 BOOLEAN EffectiveAceMapped; 05526 BOOLEAN AclOverflowed = FALSE; 05527 BOOLEAN GenerateInheritAce; 05528 05529 RTL_PAGED_CODE(); 05530 05531 // 05532 // This is gross and ugly, but it's better than allocating 05533 // virtual memory to hold the ClientSid, because that can 05534 // fail, and propogating the error back is a tremendous pain 05535 // 05536 05537 ASSERT(RtlLengthRequiredSid( 1 ) == CREATOR_SID_SIZE); 05538 *ObjectAceInherited = FALSE; 05539 GenerateInheritAce = IsDirectoryObject && Propagate(OldAce); 05540 05541 // 05542 // Allocate and initialize the universal SIDs we're going to need 05543 // to look for inheritable ACEs. 05544 // 05545 05546 if (!RtlFirstFreeAce( NewAcl, &AcePosition ) ) { 05547 return STATUS_BAD_INHERITANCE_ACL; 05548 } 05549 05550 // 05551 // check to see if we will have a effective ACE (one mapped to 05552 // the target object type). 05553 // 05554 05555 if ( (IsDirectoryObject && ContainerInherit(OldAce)) || 05556 (!IsDirectoryObject && ObjectInherit(OldAce)) ) { 05557 05558 05559 // 05560 // Remember where the effective ACE will be copied to. 05561 // 05562 EffectiveAcePosition = AcePosition; 05563 05564 // 05565 // Copy the effective ACE into the ACL. 05566 // 05567 if ( !RtlpCopyEffectiveAce ( 05568 OldAce, 05569 AutoInherit, 05570 GenerateInheritAce, 05571 ClientOwnerSid, 05572 ClientGroupSid, 05573 ServerOwnerSid, 05574 ServerGroupSid, 05575 GenericMapping, 05576 NewObjectType, 05577 &AcePosition, 05578 &EffectiveAceSize, 05579 NewAcl, 05580 ObjectAceInherited, 05581 &EffectiveAceMapped, 05582 &AclOverflowed ) ) { 05583 05584 return STATUS_BAD_INHERITANCE_ACL; 05585 } 05586 05587 // 05588 // If the effective ACE is a duplicate of existing inherited ACEs, 05589 // Don't really generate it. 05590 // 05591 05592 if ( !AclOverflowed && 05593 EffectiveAceSize > 0 && 05594 EffectiveAcePosition != NULL && 05595 RtlpIsDuplicateAce( 05596 NewAcl, 05597 EffectiveAcePosition, 05598 NewObjectType ) ) { 05599 05600 05601 // 05602 // Truncate the ACE we just added. 05603 // 05604 05605 NewAcl->AceCount--; 05606 AcePosition = EffectiveAcePosition; 05607 ExtraLengthRequired = max( ExtraLengthRequired, EffectiveAceSize ); 05608 EffectiveAceSize = 0; 05609 } 05610 05611 LengthRequired += EffectiveAceSize; 05612 05613 } 05614 05615 // 05616 // If we are inheriting onto a container, then we may need to 05617 // propagate the inheritance as well. 05618 // 05619 05620 if ( GenerateInheritAce ) { 05621 05622 // 05623 // If a effective ACE was created, 05624 // and it wasn't mapped, 05625 // avoid generating another ACE and simply merge the inheritance bits into 05626 // the effective ACE. 05627 // 05628 05629 if ( EffectiveAceSize != 0 && !EffectiveAceMapped ) { 05630 05631 // 05632 // Copy the inherit bits from the original ACE. 05633 // 05634 if ( !AclOverflowed ) { 05635 ((PACE_HEADER)EffectiveAcePosition)->AceFlags |= 05636 ((PACE_HEADER)OldAce)->AceFlags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE); 05637 if ( AutoInherit ) { 05638 ((PACE_HEADER)EffectiveAcePosition)->AceFlags |= INHERITED_ACE; 05639 } 05640 } 05641 05642 05643 // 05644 // Otherwise, generate an explicit inheritance ACE. 05645 // 05646 // But only if the access mask isn't zero. 05647 // 05648 05649 } else if ( !IsMSAceType(OldAce) || ((PKNOWN_ACE)(OldAce))->Mask != 0 ) { 05650 05651 // 05652 // Account for the new ACE being added to the ACL. 05653 // 05654 LengthRequired += (ULONG)(((PACE_HEADER)OldAce)->AceSize); 05655 05656 if (LengthRequired > 0xFFFF) { 05657 return STATUS_BAD_INHERITANCE_ACL; 05658 } 05659 05660 // 05661 // If the ACE doesn't fit, 05662 // just note the fact and don't copy the ACE. 05663 // 05664 05665 if ( ((PACE_HEADER)OldAce)->AceSize > NewAcl->AclSize - ((PUCHAR)AcePosition - (PUCHAR)NewAcl) ) { 05666 AclOverflowed = TRUE; 05667 } else if (!AclOverflowed){ 05668 05669 // 05670 // copy it as is, but make sure the InheritOnly bit is set. 05671 // 05672 05673 RtlCopyMemory( 05674 AcePosition, 05675 OldAce, 05676 ((PACE_HEADER)OldAce)->AceSize 05677 ); 05678 05679 ((PACE_HEADER)AcePosition)->AceFlags |= INHERIT_ONLY_ACE; 05680 NewAcl->AceCount += 1; 05681 if ( AutoInherit ) { 05682 ((PACE_HEADER)AcePosition)->AceFlags |= INHERITED_ACE; 05683 05684 // 05685 // If the inheritance ACE is a duplicate of existing inherited ACEs, 05686 // Don't really generate it. 05687 // 05688 05689 if ( RtlpIsDuplicateAce( 05690 NewAcl, 05691 AcePosition, 05692 NewObjectType ) ) { 05693 05694 05695 // 05696 // Truncate the ACE we just added. 05697 // 05698 05699 NewAcl->AceCount--; 05700 ExtraLengthRequired = max( ExtraLengthRequired, 05701 ((PACE_HEADER)OldAce)->AceSize ); 05702 LengthRequired -= (ULONG)(((PACE_HEADER)OldAce)->AceSize); 05703 } 05704 } 05705 05706 } 05707 } 05708 } 05709 05710 // 05711 // Now return to our caller 05712 // 05713 05714 (*NewAceLength) = LengthRequired; 05715 (*NewAceExtraLength) = ExtraLengthRequired; 05716 05717 return AclOverflowed ? STATUS_BUFFER_TOO_SMALL : STATUS_SUCCESS; 05718 }

NTSTATUS RtlpGetDefaultsSubjectContext HANDLE  ClientToken,
OUT PTOKEN_OWNER *  OwnerInfo,
OUT PTOKEN_PRIMARY_GROUP *  GroupInfo,
OUT PTOKEN_DEFAULT_DACL *  DefaultDaclInfo,
OUT PTOKEN_OWNER *  ServerOwner,
OUT PTOKEN_PRIMARY_GROUP *  ServerGroup
 

Definition at line 8795 of file sertl.c.

References ClientToken, FALSE, HeapHandle, MAKE_TAG, NT_SUCCESS, NtClose(), NtOpenProcessToken(), NtQueryInformationToken(), NTSTATUS(), NULL, PrimaryToken, RtlAllocateHeap, RtlFreeHeap, SE_TAG, Status, and TRUE.

Referenced by RtlpNewSecurityObject().

08803 { 08804 HANDLE PrimaryToken; 08805 PVOID HeapHandle; 08806 NTSTATUS Status; 08807 ULONG ServerGroupInfoSize; 08808 ULONG ServerOwnerInfoSize; 08809 ULONG TokenDaclInfoSize; 08810 ULONG TokenGroupInfoSize; 08811 ULONG TokenOwnerInfoSize; 08812 08813 BOOLEAN ClosePrimaryToken = FALSE; 08814 08815 *OwnerInfo = NULL; 08816 *GroupInfo = NULL; 08817 *DefaultDaclInfo = NULL; 08818 *ServerOwner = NULL; 08819 *ServerGroup = NULL; 08820 08821 HeapHandle = RtlProcessHeap(); 08822 08823 // 08824 // If the caller doesn't know the client token, 08825 // simply don't return any information. 08826 // 08827 08828 if ( ClientToken != NULL ) { 08829 // 08830 // Obtain the default owner from the client. 08831 // 08832 08833 Status = NtQueryInformationToken( 08834 ClientToken, // Handle 08835 TokenOwner, // TokenInformationClass 08836 NULL, // TokenInformation 08837 0, // TokenInformationLength 08838 &TokenOwnerInfoSize // ReturnLength 08839 ); 08840 08841 if ( STATUS_BUFFER_TOO_SMALL != Status ) { 08842 goto Cleanup; 08843 } 08844 08845 *OwnerInfo = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), TokenOwnerInfoSize ); 08846 08847 if ( *OwnerInfo == NULL ) { 08848 Status = STATUS_NO_MEMORY; 08849 goto Cleanup; 08850 } 08851 08852 Status = NtQueryInformationToken( 08853 ClientToken, // Handle 08854 TokenOwner, // TokenInformationClass 08855 *OwnerInfo, // TokenInformation 08856 TokenOwnerInfoSize, // TokenInformationLength 08857 &TokenOwnerInfoSize // ReturnLength 08858 ); 08859 08860 if (!NT_SUCCESS( Status )) { 08861 goto Cleanup; 08862 } 08863 08864 // 08865 // Obtain the default group from the client token. 08866 // 08867 08868 Status = NtQueryInformationToken( 08869 ClientToken, // Handle 08870 TokenPrimaryGroup, // TokenInformationClass 08871 *GroupInfo, // TokenInformation 08872 0, // TokenInformationLength 08873 &TokenGroupInfoSize // ReturnLength 08874 ); 08875 08876 if ( STATUS_BUFFER_TOO_SMALL != Status ) { 08877 goto Cleanup; 08878 } 08879 08880 *GroupInfo = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), TokenGroupInfoSize ); 08881 08882 if ( *GroupInfo == NULL ) { 08883 08884 Status = STATUS_NO_MEMORY; 08885 goto Cleanup; 08886 } 08887 08888 Status = NtQueryInformationToken( 08889 ClientToken, // Handle 08890 TokenPrimaryGroup, // TokenInformationClass 08891 *GroupInfo, // TokenInformation 08892 TokenGroupInfoSize, // TokenInformationLength 08893 &TokenGroupInfoSize // ReturnLength 08894 ); 08895 08896 if (!NT_SUCCESS( Status )) { 08897 goto Cleanup; 08898 } 08899 08900 Status = NtQueryInformationToken( 08901 ClientToken, // Handle 08902 TokenDefaultDacl, // TokenInformationClass 08903 *DefaultDaclInfo, // TokenInformation 08904 0, // TokenInformationLength 08905 &TokenDaclInfoSize // ReturnLength 08906 ); 08907 08908 if ( STATUS_BUFFER_TOO_SMALL != Status ) { 08909 goto Cleanup; 08910 } 08911 08912 *DefaultDaclInfo = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), TokenDaclInfoSize ); 08913 08914 if ( *DefaultDaclInfo == NULL ) { 08915 08916 Status = STATUS_NO_MEMORY; 08917 goto Cleanup; 08918 } 08919 08920 Status = NtQueryInformationToken( 08921 ClientToken, // Handle 08922 TokenDefaultDacl, // TokenInformationClass 08923 *DefaultDaclInfo, // TokenInformation 08924 TokenDaclInfoSize, // TokenInformationLength 08925 &TokenDaclInfoSize // ReturnLength 08926 ); 08927 08928 if (!NT_SUCCESS( Status )) { 08929 goto Cleanup; 08930 } 08931 } 08932 08933 // 08934 // Now open the primary token to determine how to substitute for 08935 // ServerOwner and ServerGroup. 08936 // 08937 08938 Status = NtOpenProcessToken( 08939 NtCurrentProcess(), 08940 TOKEN_QUERY, 08941 &PrimaryToken 08942 ); 08943 08944 if (!NT_SUCCESS( Status )) { 08945 ClosePrimaryToken = FALSE; 08946 goto Cleanup; 08947 } else { 08948 ClosePrimaryToken = TRUE; 08949 } 08950 08951 Status = NtQueryInformationToken( 08952 PrimaryToken, // Handle 08953 TokenOwner, // TokenInformationClass 08954 NULL, // TokenInformation 08955 0, // TokenInformationLength 08956 &ServerOwnerInfoSize // ReturnLength 08957 ); 08958 08959 if ( STATUS_BUFFER_TOO_SMALL != Status ) { 08960 goto Cleanup; 08961 } 08962 08963 *ServerOwner = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), ServerOwnerInfoSize ); 08964 08965 if ( *ServerOwner == NULL ) { 08966 Status = STATUS_NO_MEMORY; 08967 goto Cleanup; 08968 } 08969 08970 Status = NtQueryInformationToken( 08971 PrimaryToken, // Handle 08972 TokenOwner, // TokenInformationClass 08973 *ServerOwner, // TokenInformation 08974 ServerOwnerInfoSize, // TokenInformationLength 08975 &ServerOwnerInfoSize // ReturnLength 08976 ); 08977 08978 if (!NT_SUCCESS( Status )) { 08979 goto Cleanup; 08980 } 08981 08982 // 08983 // Find the server group. 08984 // 08985 08986 Status = NtQueryInformationToken( 08987 PrimaryToken, // Handle 08988 TokenPrimaryGroup, // TokenInformationClass 08989 *ServerGroup, // TokenInformation 08990 0, // TokenInformationLength 08991 &ServerGroupInfoSize // ReturnLength 08992 ); 08993 08994 if ( STATUS_BUFFER_TOO_SMALL != Status ) { 08995 goto Cleanup; 08996 } 08997 08998 *ServerGroup = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), ServerGroupInfoSize ); 08999 09000 if ( *ServerGroup == NULL ) { 09001 goto Cleanup; 09002 } 09003 09004 Status = NtQueryInformationToken( 09005 PrimaryToken, // Handle 09006 TokenPrimaryGroup, // TokenInformationClass 09007 *ServerGroup, // TokenInformation 09008 ServerGroupInfoSize, // TokenInformationLength 09009 &ServerGroupInfoSize // ReturnLength 09010 ); 09011 09012 if (!NT_SUCCESS( Status )) { 09013 goto Cleanup; 09014 } 09015 09016 NtClose( PrimaryToken ); 09017 09018 return( STATUS_SUCCESS ); 09019 09020 Cleanup: 09021 09022 if (*OwnerInfo != NULL) { 09023 RtlFreeHeap( HeapHandle, 0, (PVOID)*OwnerInfo ); 09024 *OwnerInfo = NULL; 09025 } 09026 09027 if (*GroupInfo != NULL) { 09028 RtlFreeHeap( HeapHandle, 0, (PVOID)*GroupInfo ); 09029 *GroupInfo = NULL; 09030 } 09031 09032 if (*DefaultDaclInfo != NULL) { 09033 RtlFreeHeap( HeapHandle, 0, (PVOID)*DefaultDaclInfo ); 09034 *DefaultDaclInfo = NULL; 09035 } 09036 09037 if (*ServerOwner != NULL) { 09038 RtlFreeHeap( HeapHandle, 0, (PVOID)*ServerOwner ); 09039 *ServerOwner = NULL; 09040 } 09041 09042 if (*ServerGroup != NULL) { 09043 RtlFreeHeap( HeapHandle, 0, (PVOID)*ServerGroup ); 09044 *ServerGroup = NULL; 09045 } 09046 09047 if (ClosePrimaryToken == TRUE) { 09048 NtClose( PrimaryToken ); 09049 } 09050 09051 return( Status ); 09052 }

NTSTATUS RtlpInheritAcl IN PACL  DirectoryAcl,
IN PACL  ChildAcl,
IN ULONG  ChildGenericControl,
IN BOOLEAN  IsDirectoryObject,
IN BOOLEAN  AutoInherit,
IN BOOLEAN  DefaultDescriptorForObject,
IN PSID  OwnerSid,
IN PSID  GroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN BOOLEAN  IsSacl,
IN GUID *NewObjectType  OPTIONAL,
OUT PACL *  NewAcl,
OUT PBOOLEAN  NewAclExplicitlyAssigned,
OUT PULONG  NewGenericControl
 

Definition at line 5153 of file sertl.c.

References ExAllocatePoolWithTag, ExFreePool(), HeapHandle, MAKE_TAG, NT_SUCCESS, NTSTATUS(), NULL, PagedPool, RTL_PAGED_CODE, RtlAllocateHeap, RtlFreeHeap, RtlpInheritAcl2(), SE_TAG, and Status.

Referenced by RtlpConvertAclToAutoInherit(), RtlpNewSecurityObject(), and SepInheritAcl().

05174 : 05175 05176 This is a private routine that produces an inherited acl from 05177 a parent acl according to the rules of inheritance 05178 05179 Arguments: 05180 05181 DirectoryAcl - Supplies the acl being inherited. 05182 05183 ChildAcl - Supplies the acl associated with the object. This 05184 is either the current acl on the object or the acl being assigned 05185 to the object. 05186 05187 ChildGenericControl - Specifies the control flags from the SecurityDescriptor 05188 describing the ChildAcl: 05189 05190 SEP_ACL_PRESENT: Specifies that the child ACL is explictly supplied by 05191 the caller. 05192 05193 SEP_ACL_DEFAULTED: Specifies that the child ACL was supplied by some 05194 defaulting mechanism. 05195 05196 SEP_ACL_PROTECTED: Specifies that the child ACL is protected and 05197 should not inherit any ACE from the DirectoryACL 05198 05199 IsDirectoryObject - Specifies if the new acl is for a directory. 05200 05201 AutoInherit - Specifies if the inheritance is an "automatic inheritance". 05202 As such, the non-inherited ACEs from the ChildAcl will be preserved and 05203 the inherited ACEs from the DirectoryAcl will be marked as such. 05204 05205 DefaultDescriptorForObject - If set, the CreatorDescriptor 05206 is the default descriptor for ObjectType. As such, the 05207 CreatorDescriptor will be ignored if any ObjectType specific 05208 ACEs are inherited from the parent. If not such ACEs are inherited, 05209 the CreatorDescriptor is handled as though this flag were not 05210 specified. 05211 05212 OwnerSid - Specifies the owner Sid to use. 05213 05214 GroupSid - Specifies the group SID to use. 05215 05216 GenericMapping - Specifies the generic mapping to use. 05217 05218 IsSacl - True if this is the SACL. False if this is the DACL. 05219 05220 NewObjectType - Type of object being inherited to. If not specified, 05221 the object has no object type. 05222 05223 NewAcl - Receives a pointer to the new (inherited) acl. 05224 05225 NewAclExplicitlyAssigned - Returns true to indicate that some portion of 05226 "NewAcl" was derived from an the explicit ChildAcl 05227 05228 NewGenericControl - Specifies the control flags for the newly 05229 generated ACL. 05230 05231 SEP_ACL_AUTO_INHERITED: Set if the ACL was generated using the 05232 Automatic Inheritance algorithm. 05233 05234 SEP_ACL_PROTECTED: Specifies that the ACL is protected and 05235 was not inherited from the parent ACL. 05236 05237 Return Value: 05238 05239 STATUS_SUCCESS - An inheritable ACL was successfully generated. 05240 05241 STATUS_NO_INHERITANCE - An inheritable ACL was not successfully generated. 05242 This is a warning completion status. 05243 05244 STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL. 05245 This can becaused by a number of things. One of the more probable 05246 causes is the replacement of a CreatorId with an SID that didn't fit 05247 into the ACE or ACL. 05248 05249 STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that 05250 is unknown to this routine. 05251 05252 --*/ 05253 05254 { 05256 // // 05257 // The logic in the ACL inheritance code must mirror the code for // 05258 // inheritance in the executive (in seassign.c). Do not make changes // 05259 // here without also making changes in that module. // 05260 // // 05262 05263 05264 05265 NTSTATUS Status; 05266 ULONG AclBufferSize; 05267 ULONG i; 05268 05269 #ifndef NTOS_KERNEL_RUNTIME 05270 PVOID HeapHandle; 05271 #endif // NTOS_KERNEL_RUNTIME 05272 05273 RTL_PAGED_CODE(); 05274 05275 // 05276 // Get the handle to the current process heap 05277 // 05278 05279 #ifndef NTOS_KERNEL_RUNTIME 05280 HeapHandle = RtlProcessHeap(); 05281 #endif // NTOS_KERNEL_RUNTIME 05282 05283 05284 05285 // 05286 // Implement a two pass strategy. 05287 // 05288 // First try to create the ACL in a fixed length buffer. 05289 // If that is too small, 05290 // then use the buffer size determined on the first pass 05291 // 05292 05293 AclBufferSize = 1024; // Typical maximum size of an ACL 05294 for ( i=0; i<2 ; i++ ) { 05295 05296 // 05297 // Allocate heap for the new ACL. 05298 // 05299 05300 #ifdef NTOS_KERNEL_RUNTIME 05301 (*NewAcl) = ExAllocatePoolWithTag( 05302 PagedPool, 05303 AclBufferSize, 05304 'cAeS' ); 05305 #else // NTOS_KERNEL_RUNTIME 05306 (*NewAcl) = RtlAllocateHeap( 05307 HeapHandle, 05308 MAKE_TAG(SE_TAG), 05309 AclBufferSize ); 05310 #endif // NTOS_KERNEL_RUNTIME 05311 05312 if ((*NewAcl) == NULL ) { 05313 return( STATUS_NO_MEMORY ); 05314 } 05315 05316 // 05317 // Actually build the inherited ACL. 05318 // 05319 05320 Status = RtlpInheritAcl2 ( 05321 DirectoryAcl, 05322 ChildAcl, 05323 ChildGenericControl, 05324 IsDirectoryObject, 05325 AutoInherit, 05326 DefaultDescriptorForObject, 05327 OwnerSid, 05328 GroupSid, 05329 ServerOwnerSid, 05330 ServerGroupSid, 05331 GenericMapping, 05332 IsSacl, 05333 NewObjectType, 05334 &AclBufferSize, 05335 (PUCHAR) *NewAcl, 05336 NewAclExplicitlyAssigned, 05337 NewGenericControl ); 05338 05339 05340 if ( NT_SUCCESS(Status) ) { 05341 05342 // 05343 // If a NULL ACL should be used, 05344 // tell the caller. 05345 // 05346 05347 if ( AclBufferSize == 0 ) { 05348 05349 #ifdef NTOS_KERNEL_RUNTIME 05350 ExFreePool( *NewAcl ); 05351 #else // NTOS_KERNEL_RUNTIME 05352 RtlFreeHeap( HeapHandle, 0, *NewAcl ); 05353 #endif // NTOS_KERNEL_RUNTIME 05354 05355 *NewAcl = NULL; 05356 } 05357 05358 break; 05359 05360 } else { 05361 #ifdef NTOS_KERNEL_RUNTIME 05362 ExFreePool( *NewAcl ); 05363 #else // NTOS_KERNEL_RUNTIME 05364 RtlFreeHeap( HeapHandle, 0, *NewAcl ); 05365 #endif // NTOS_KERNEL_RUNTIME 05366 05367 *NewAcl = NULL; 05368 05369 if ( Status != STATUS_BUFFER_TOO_SMALL ) { 05370 break; 05371 } 05372 } 05373 } 05374 05375 05376 return Status; 05377 }

NTSTATUS RtlpInheritAcl2 IN PACL  DirectoryAcl,
IN PACL  ChildAcl,
IN ULONG  ChildGenericControl,
IN BOOLEAN  IsDirectoryObject,
IN BOOLEAN  AutoInherit,
IN BOOLEAN  DefaultDescriptorForObject,
IN PSID  OwnerSid,
IN PSID  GroupSid,
IN PSID ServerOwnerSid  OPTIONAL,
IN PSID ServerGroupSid  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping,
IN BOOLEAN  IsSacl,
IN GUID *NewObjectType  OPTIONAL,
IN PULONG  AclBufferSize,
IN OUT PUCHAR  AclBuffer,
OUT PBOOLEAN  NewAclExplicitlyAssigned,
OUT PULONG  NewGenericControl
 

Definition at line 4716 of file sertl.c.

References ACE_TYPE_TO_COPY, CopyAllAces, CopyNonInheritedAces, FALSE, FirstAce, max, NT_SUCCESS, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlCreateAcl(), RtlFirstFreeAce(), RtlpCopyAces(), RtlpGenerateInheritAcl(), Status, TRUE, and USHORT.

Referenced by RtlpInheritAcl().

04738 : 04739 04740 This is a private routine that produces an inherited acl from 04741 a parent acl according to the rules of inheritance 04742 04743 Arguments: 04744 04745 DirectoryAcl - Supplies the acl being inherited. 04746 04747 ChildAcl - Supplies the acl associated with the object. This 04748 is either the current acl on the object or the acl being assigned 04749 to the object. 04750 04751 ChildGenericControl - Specifies the control flags from the SecurityDescriptor 04752 describing the ChildAcl: 04753 04754 SEP_ACL_PRESENT: Specifies that the child ACL is explictly supplied by 04755 the caller. 04756 04757 SEP_ACL_DEFAULTED: Specifies that the child ACL was supplied by some 04758 defaulting mechanism. 04759 04760 SEP_ACL_PROTECTED: Specifies that the child ACL is protected and 04761 should not inherit any ACE from the DirectoryACL 04762 04763 IsDirectoryObject - Specifies if the new acl is for a directory. 04764 04765 AutoInherit - Specifies if the inheritance is an "automatic inheritance". 04766 As such, the non-inherited ACEs from the ChildAcl will be preserved and 04767 the inherited ACEs from the DirectoryAcl will be marked as such. 04768 04769 DefaultDescriptorForObject - If set, the CreatorDescriptor 04770 is the default descriptor for ObjectType. As such, the 04771 CreatorDescriptor will be ignored if any ObjectType specific 04772 ACEs are inherited from the parent. If not such ACEs are inherited, 04773 the CreatorDescriptor is handled as though this flag were not 04774 specified. 04775 04776 OwnerSid - Specifies the owner Sid to use. 04777 04778 GroupSid - Specifies the group SID to use. 04779 04780 GenericMapping - Specifies the generic mapping to use. 04781 04782 IsSacl - True if this is the SACL. False if this is the DACL. 04783 04784 NewObjectType - Type of object being inherited to. If not specified, 04785 the object has no object type. 04786 04787 AclBufferSize - On input, specifies the size of AclBuffer. 04788 On output, on success, returns the used size of AclBuffer. 04789 On output, if the buffer is too small, returns the required size of AclBuffer. 04790 04791 AclBuffer - Receives a pointer to the new (inherited) acl. 04792 04793 NewAclExplicitlyAssigned - Returns true to indicate that some portion of 04794 "NewAcl" was derived from an the explicit ChildAcl 04795 04796 NewGenericControl - Specifies the control flags for the newly 04797 generated ACL. 04798 04799 SEP_ACL_AUTO_INHERITED: Set if the ACL was generated using the 04800 Automatic Inheritance algorithm. 04801 04802 SEP_ACL_PROTECTED: Specifies that the ACL is protected and 04803 was not inherited from the parent ACL. 04804 04805 Return Value: 04806 04807 STATUS_SUCCESS - An inheritable ACL was successfully generated. 04808 04809 STATUS_NO_INHERITANCE - An inheritable ACL was not successfully generated. 04810 This is a warning completion status. The caller should use the default 04811 ACL. 04812 04813 STATUS_BAD_INHERITANCE_ACL - Indicates the acl built was not a valid ACL. 04814 This can becaused by a number of things. One of the more probable 04815 causes is the replacement of a CreatorId with an SID that didn't fit 04816 into the ACE or ACL. 04817 04818 STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that 04819 is unknown to this routine. 04820 04821 STATUS_BUFFER_TOO_SMALL - The ACL specified by NewAcl is too small for the 04822 inheritance ACEs. The required size is returned in AclBufferSize. 04823 04824 --*/ 04825 04826 { 04827 NTSTATUS Status; 04828 ULONG ChildNewAclSize = 0; 04829 ULONG UsedChildNewAclSize = 0; 04830 ULONG DirectoryNewAclSize = 0; 04831 ULONG AclRevision; 04832 USHORT ChildAceCount; 04833 PVOID ChildAcePosition; 04834 PVOID DirectoryAcePosition; 04835 BOOLEAN AclOverflowed = FALSE; 04836 BOOLEAN AclProtected = FALSE; 04837 BOOLEAN NullAclOk = TRUE; 04838 BOOLEAN ObjectAceInherited; 04839 04840 RTL_PAGED_CODE(); 04841 04842 04843 // 04844 // Assume the ACL revision. 04845 // 04846 04847 AclRevision = ACL_REVISION; 04848 RtlCreateAcl( (PACL)AclBuffer, *AclBufferSize, AclRevision ); 04849 *NewAclExplicitlyAssigned = FALSE; 04850 *NewGenericControl = AutoInherit ? SEP_ACL_AUTO_INHERITED : 0; 04851 04852 // 04853 // If the a current child ACL is not defaulted, 04854 // the non-inherited ACEs from the current child ACL are to be preserved. 04855 // 04856 04857 if ( (ChildGenericControl & SEP_ACL_DEFAULTED) == 0 ) { 04858 04859 // 04860 // The resultant ACL should be protected if the input ACL is 04861 // protected. 04862 // 04863 04864 if ( ChildGenericControl & SEP_ACL_PROTECTED ) { 04865 AclProtected = TRUE; 04866 *NewGenericControl |= SEP_ACL_PROTECTED; 04867 } 04868 04869 // 04870 // Only copy ACEs if the child ACL is actually present. 04871 // 04872 if ( (ChildGenericControl & (SEP_ACL_PRESENT|SEP_ACL_PROTECTED)) != 0 ) { 04873 04874 04875 if ( ChildAcl != NULL ) { 04876 ACE_TYPE_TO_COPY AceTypeToCopy; 04877 UCHAR AceFlagsToReset; 04878 BOOLEAN MapSids; 04879 04880 04881 AclRevision = max( AclRevision, ChildAcl->AclRevision ); 04882 04883 // 04884 // Since we're explicitly using the ACL specified by the caller, 04885 // we never want to return a NULL ACL. 04886 // Rather, if we have an ACL with no ACEs, 04887 // we'll return exactly that. For a DACL, that results 04888 // in a DACL that grants no access rather than a DACL 04889 // that grants all access. 04890 // 04891 04892 NullAclOk = FALSE; 04893 04894 // 04895 // If the caller doesn't understand auto inheritance, 04896 // simply preserve the specified ACL 100% intact. 04897 // 04898 if ( !AutoInherit ) { 04899 04900 AceTypeToCopy = CopyAllAces; 04901 AceFlagsToReset = 0; // Don't turn off any ACE Flags 04902 MapSids = FALSE; // For backward compatibility 04903 04904 // 04905 // If the child is protected, 04906 // keep all of the ACEs turning off the INHERITED ACE flags. 04907 // 04908 } else if ( ChildGenericControl & SEP_ACL_PROTECTED ) { 04909 04910 AceTypeToCopy = CopyAllAces; 04911 AceFlagsToReset = INHERITED_ACE; // Turn off all INHERITED_ACE flags 04912 MapSids = TRUE; 04913 04914 // 04915 // If the child is not protected, 04916 // just copy the non-inherited ACEs. 04917 // 04918 // (The inherited ACEs will be recomputed from the parent.) 04919 // 04920 } else { 04921 04922 AceTypeToCopy = CopyNonInheritedAces; 04923 AceFlagsToReset = 0; // Don't turn off any ACE Flags 04924 MapSids = TRUE; 04925 04926 } 04927 04928 // 04929 // Copy the requested ACEs. 04930 // 04931 04932 Status = RtlpCopyAces( 04933 ChildAcl, 04934 GenericMapping, 04935 AceTypeToCopy, 04936 AceFlagsToReset, 04937 MapSids, 04938 OwnerSid, 04939 GroupSid, 04940 ServerOwnerSid, 04941 ServerGroupSid, 04942 &ChildNewAclSize, 04943 (PACL)AclBuffer ); 04944 04945 UsedChildNewAclSize = ChildNewAclSize; 04946 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 04947 AclOverflowed = TRUE; 04948 Status = STATUS_SUCCESS; 04949 } 04950 04951 if ( !NT_SUCCESS(Status) ) { 04952 return Status; 04953 } 04954 04955 // 04956 // If this ACL might be ignored later, 04957 // remember the current state of the ACL. 04958 // 04959 04960 if ( DefaultDescriptorForObject && ChildNewAclSize != 0 ) { 04961 ChildAceCount = ((PACL)AclBuffer)->AceCount; 04962 04963 if (!RtlFirstFreeAce( (PACL)AclBuffer, &ChildAcePosition ) ) { 04964 return STATUS_BAD_INHERITANCE_ACL; 04965 } 04966 } 04967 04968 // 04969 // If the ACL isn't protected, 04970 // don't allow NULL ACL semantics. 04971 // (those semantics are ambiguous for auto inheritance) 04972 // 04973 } else if ( AutoInherit && 04974 !IsSacl && 04975 (ChildGenericControl & (SEP_ACL_PRESENT|SEP_ACL_PROTECTED)) == SEP_ACL_PRESENT ) { 04976 return STATUS_INVALID_ACL; 04977 04978 } 04979 04980 *NewAclExplicitlyAssigned = TRUE; 04981 04982 } 04983 04984 } 04985 04986 // 04987 // Inherit ACEs from the Directory ACL in any of the following cases: 04988 // If !AutoInheriting, 04989 // Inherit if there is no explicit child ACL (ignoring a defaulted child). 04990 // If AutoInheriting, 04991 // observe the protected flag. 04992 // 04993 04994 if ( (!AutoInherit && 04995 (ChildGenericControl & SEP_ACL_PRESENT) == 0 || 04996 (ChildGenericControl & SEP_ACL_DEFAULTED) != 0) || 04997 (AutoInherit && !AclProtected) ) { 04998 04999 // 05000 // If there is no directory ACL, 05001 // don't inherit from it. 05002 // 05003 05004 if ( DirectoryAcl != NULL ) { 05005 05006 // 05007 // If the DirectoryAcl is used, 05008 // the revision of the Directory ACL is picked up. 05009 // 05010 05011 if ( !ValidAclRevision(DirectoryAcl) ) { 05012 return STATUS_UNKNOWN_REVISION; 05013 } 05014 05015 AclRevision = max( AclRevision, DirectoryAcl->AclRevision ); 05016 05017 // 05018 // Inherit the Parent's ACL. 05019 // 05020 05021 Status = RtlpGenerateInheritAcl( 05022 DirectoryAcl, 05023 IsDirectoryObject, 05024 AutoInherit, 05025 OwnerSid, 05026 GroupSid, 05027 ServerOwnerSid, 05028 ServerGroupSid, 05029 GenericMapping, 05030 NewObjectType, 05031 &DirectoryNewAclSize, 05032 (PACL)AclBuffer, 05033 &ObjectAceInherited ); 05034 05035 if ( Status == STATUS_BUFFER_TOO_SMALL ) { 05036 AclOverflowed = TRUE; 05037 Status = STATUS_SUCCESS; 05038 } 05039 05040 if ( !NT_SUCCESS(Status) ) { 05041 return Status; 05042 } 05043 05044 // 05045 // If the default descriptor for the object should be ditched, 05046 // because object specific ACEs were inherited from the directory, 05047 // ditch them now. 05048 // 05049 05050 if ( DefaultDescriptorForObject && 05051 ChildNewAclSize != 0 && 05052 ObjectAceInherited && 05053 !AclOverflowed ) { 05054 05055 // 05056 // Compute the last used byte of the combined ACL 05057 // 05058 if (!RtlFirstFreeAce( (PACL)AclBuffer, &DirectoryAcePosition ) ) { 05059 return STATUS_BAD_INHERITANCE_ACL; 05060 } 05061 if ( DirectoryAcePosition == NULL ) { 05062 DirectoryAcePosition = AclBuffer + ((PACL)AclBuffer)->AclSize; 05063 } 05064 05065 05066 05067 // 05068 // Move all the inherited ACEs to the front of the ACL. 05069 // 05070 05071 RtlMoveMemory( FirstAce( AclBuffer ), 05072 ChildAcePosition, 05073 (ULONG)(((PUCHAR)DirectoryAcePosition) - 05074 (PUCHAR)ChildAcePosition) ); 05075 05076 // 05077 // Adjust the ACE count to remove the deleted ACEs 05078 // 05079 05080 ((PACL)AclBuffer)->AceCount -= ChildAceCount; 05081 05082 // 05083 // Save the number of bytes of the Child ACL that were 05084 // actually used. 05085 // 05086 05087 UsedChildNewAclSize = 0; 05088 05089 } 05090 } 05091 05092 } 05093 05094 // 05095 // If this routine didn't build the ACL, 05096 // tell the caller. 05097 // 05098 05099 if ( DirectoryNewAclSize + UsedChildNewAclSize == 0) { 05100 05101 // 05102 // If the ACL was not explicitly assigned, 05103 // tell the caller to default the ACL. 05104 // 05105 if ( !(*NewAclExplicitlyAssigned) ) { 05106 *AclBufferSize = 0; 05107 return STATUS_NO_INHERITANCE; 05108 05109 // 05110 // If the Acl was explictly assigned, 05111 // generate a NULL ACL based on the path taken above. 05112 // 05113 05114 } else if ( NullAclOk ) { 05115 *AclBufferSize = 0; 05116 return STATUS_SUCCESS; 05117 } 05118 05119 // DbgBreakPoint(); 05120 } 05121 05122 05123 // 05124 // And make sure we don't exceed the length limitations of an ACL (WORD) 05125 // 05126 05127 if ( DirectoryNewAclSize + UsedChildNewAclSize + sizeof(ACL) > 0xFFFF) { 05128 return(STATUS_BAD_INHERITANCE_ACL); 05129 } 05130 05131 // BUGBUG: The caller has to allocate a buffer large enough for 05132 // ChildNewAclSize rather than UsedChildNewAclSize. Due to the nature of 05133 // my algorithm above. 05134 (*AclBufferSize) = DirectoryNewAclSize + ChildNewAclSize + sizeof(ACL); 05135 05136 if ( AclOverflowed ) { 05137 return STATUS_BUFFER_TOO_SMALL; 05138 } 05139 05140 // 05141 // Patch the real ACL size and revision into the ACL 05142 // 05143 05144 ((PACL)AclBuffer)->AclSize = (USHORT) 05145 (DirectoryNewAclSize + UsedChildNewAclSize + sizeof(ACL)); 05146 ((PACL)AclBuffer)->AclRevision = (UCHAR) AclRevision; 05147 05148 return STATUS_SUCCESS; 05149 }

BOOLEAN RtlpIsDuplicateAce IN PACL  Acl,
IN PKNOWN_ACE  NewAce,
IN GUID *ObjectType  OPTIONAL
 

Definition at line 8362 of file sertl.c.

References FALSE, FirstAce, NextAce, NTSTATUS(), NULL, RTL_PAGED_CODE, RtlpCompareAces(), RtlpVerboseConvert, Status, and TRUE.

Referenced by RtlpGenerateInheritedAce().

08370 : 08371 08372 This routine determine if an ACE is a duplicate of an ACE already in an 08373 ACL. If so, the NewAce can be removed from the end of the ACL. 08374 08375 This routine currently only detects duplicate version 4 ACEs. If the 08376 ACE isn't version 4, the ACE will be declared to be a non-duplicate. 08377 08378 This routine only detects duplicate INHERTED ACEs. 08379 08380 Arguments: 08381 08382 Acl - Existing ACL 08383 08384 NewAce - Ace to determine if it is already in Acl. 08385 NewAce is expected to be the last ACE in "Acl". 08386 08387 ObjectType - GUID of the object type represented by Acl. If the object 08388 has no GUID associated with it, then this argument is 08389 specified as NULL. 08390 08391 Return Value: 08392 08393 TRUE - NewAce is a duplicate of another ACE on the Acl 08394 FALSE - NewAce is NOT a duplicate of another ACE on the Acl 08395 08396 --*/ 08397 08398 { 08399 NTSTATUS Status; 08400 BOOLEAN RetVal = FALSE; 08401 08402 LONG AceIndex; 08403 08404 ACCESS_MASK NewAceContainerInheritMask; 08405 ACCESS_MASK NewAceObjectInheritMask; 08406 ACCESS_MASK NewAceEffectiveMask; 08407 08408 ACCESS_MASK LocalMask; 08409 08410 PKNOWN_ACE AceFromAcl; 08411 08412 RTL_PAGED_CODE(); 08413 08414 08415 // 08416 // Ensure the passed in ACE is one this routine understands 08417 // 08418 08419 if ( !IsV4AceType(NewAce) || IsCompoundAceType(NewAce)) { 08420 #if DBG 08421 if ( RtlpVerboseConvert ) { 08422 KdPrint(("New Ace type (%ld) not known\n", NewAce->Header.AceType )); 08423 } 08424 #endif // DBG 08425 RetVal = FALSE; 08426 goto Cleanup; 08427 } 08428 08429 // 08430 // This routine only works for ACEs marked as INHERITED. 08431 // 08432 08433 if ( (NewAce->Header.AceFlags & INHERITED_ACE ) == 0 ) { 08434 #if DBG 08435 if ( RtlpVerboseConvert ) { 08436 KdPrint(("New Ace type isn't inherited\n" )); 08437 } 08438 #endif // DBG 08439 RetVal = FALSE; 08440 goto Cleanup; 08441 } 08442 08443 08444 // 08445 // Break the new ACE into its component parts. 08446 // 08447 // All V4 aces have an access mask in the same location. 08448 // 08449 LocalMask = ((PKNOWN_ACE)(NewAce))->Mask; 08450 08451 if ( NewAce->Header.AceFlags & CONTAINER_INHERIT_ACE ) { 08452 NewAceContainerInheritMask = LocalMask; 08453 } else { 08454 NewAceContainerInheritMask = 0; 08455 } 08456 08457 if ( NewAce->Header.AceFlags & OBJECT_INHERIT_ACE ) { 08458 NewAceObjectInheritMask = LocalMask; 08459 } else { 08460 NewAceObjectInheritMask = 0; 08461 } 08462 08463 if ( (NewAce->Header.AceFlags & INHERIT_ONLY_ACE) == 0 ) { 08464 NewAceEffectiveMask = LocalMask; 08465 } else { 08466 NewAceEffectiveMask = 0; 08467 } 08468 #if DBG 08469 if ( RtlpVerboseConvert ) { 08470 KdPrint(("Starting MASKs: %8.8lX %8.8lX %8.8lX", NewAceEffectiveMask, NewAceContainerInheritMask, NewAceObjectInheritMask )); 08471 } 08472 #endif // DBG 08473 08474 08475 08476 08477 // 08478 // Walk through the ACL one ACE at a time. 08479 // 08480 08481 for (AceIndex = 0, AceFromAcl = FirstAce(Acl); 08482 AceIndex < Acl->AceCount-1; // NewAce is the last ACE 08483 AceIndex += 1, AceFromAcl = NextAce(AceFromAcl)) { 08484 08485 08486 // 08487 // If the ACE isn't a valid version 4 ACE, 08488 // this isn't an ACE we're interested in handling. 08489 // 08490 08491 if ( !IsV4AceType(AceFromAcl) || IsCompoundAceType(AceFromAcl)) { 08492 continue; 08493 } 08494 08495 // 08496 // This routine only works for ACEs marked as INHERITED. 08497 // 08498 08499 if ( (AceFromAcl->Header.AceFlags & INHERITED_ACE ) == 0 ) { 08500 continue; 08501 } 08502 08503 08504 // 08505 // Compare the Ace from the ACL with the New ACE 08506 // 08507 // Don't stop simply because we've matched once. 08508 // Multiple ACEs in the one ACL may have been condensed into a single ACE 08509 // in the other ACL in any combination (by any of our friendly ACL editors). 08510 // 08511 #if DBG 08512 if ( RtlpVerboseConvert ) { 08513 KdPrint(("Compare Ace: %ld ", AceIndex )); 08514 } 08515 #endif // DBG 08516 08517 if ( RtlpCompareAces( AceFromAcl, 08518 NewAce, 08519 NULL, 08520 NULL ) ) { 08521 08522 08523 // 08524 // Match the bits from the current ACE with bits from the New ACE. 08525 // 08526 // All V4 aces have an access mask in the same location. 08527 // 08528 08529 LocalMask = ((PKNOWN_ACE)(AceFromAcl))->Mask; 08530 08531 if ( AceFromAcl->Header.AceFlags & CONTAINER_INHERIT_ACE ) { 08532 NewAceContainerInheritMask &= ~LocalMask; 08533 } 08534 08535 if ( AceFromAcl->Header.AceFlags & OBJECT_INHERIT_ACE ) { 08536 NewAceObjectInheritMask &= ~LocalMask; 08537 } 08538 08539 if ( (AceFromAcl->Header.AceFlags & INHERIT_ONLY_ACE) == 0 ) { 08540 NewAceEffectiveMask &= ~LocalMask; 08541 } 08542 08543 #if DBG 08544 if ( RtlpVerboseConvert ) { 08545 KdPrint(("Remaining MASKs: %8.8lX %8.8lX %8.8lX", NewAceEffectiveMask, NewAceContainerInheritMask, NewAceObjectInheritMask )); 08546 } 08547 #endif // DBG 08548 08549 // 08550 // If all bits have been matched in the New Ace, 08551 // then this is a duplicate ACE. 08552 // 08553 08554 if ( (NewAceEffectiveMask | NewAceContainerInheritMask | NewAceObjectInheritMask) == 0 ) { 08555 #if DBG 08556 if ( RtlpVerboseConvert ) { 08557 KdPrint(("\n")); 08558 } 08559 #endif // DBG 08560 RetVal = TRUE; 08561 goto Cleanup; 08562 } 08563 } 08564 #if DBG 08565 if ( RtlpVerboseConvert ) { 08566 KdPrint(("\n")); 08567 } 08568 #endif // DBG 08569 08570 08571 } 08572 08573 // 08574 // All of the ACEs of the ACL have been processed. 08575 // 08576 // We haven't matched all of the bits in the New Ace so this is not a duplicate ACE. 08577 // 08578 08579 RetVal = FALSE; 08580 Cleanup: 08581 08582 return RetVal; 08583 08584 }

NTSTATUS RtlpNewSecurityObject IN PSECURITY_DESCRIPTOR ParentDescriptor  OPTIONAL,
IN PSECURITY_DESCRIPTOR CreatorDescriptor  OPTIONAL,
OUT PSECURITY_DESCRIPTOR *  NewDescriptor,
IN GUID *ObjectType  OPTIONAL,
IN BOOLEAN  IsDirectoryObject,
IN ULONG  AutoInheritFlags,
IN HANDLE Token  OPTIONAL,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 9057 of file sertl.c.

References ExAllocatePoolWithTag, ExFreePool(), FALSE, HeapHandle, KernelMode, KPROCESSOR_MODE, MAKE_TAG, NT_SUCCESS, NtPrivilegeCheck(), NtQueryInformationToken(), NTSTATUS(), NULL, PagedPool, RtlAllocateHeap, RtlCopySid(), RtlCreateSecurityDescriptor(), RtlCreateSecurityDescriptorRelative(), RtlFreeHeap, RtlpApplyAclToObject(), RtlpCreateServerAcl(), RtlpGetDefaultsSubjectContext(), RtlpInheritAcl(), RtlpValidOwnerSubjectContext(), RtlValidSid(), SE_TAG, SeLengthSid, SeLockSubjectContext(), SepGetDefaultsSubjectContext(), SePrivilegeCheck(), SePrivilegedServiceAuditAlarm(), SepValidOwnerSubjectContext(), SeSecurityPrivilege, SeUnlockSubjectContext(), Status, Token, TRUE, and UserMode.

Referenced by RtlNewSecurityObject(), RtlNewSecurityObjectEx(), SeAssignSecurity(), and SeAssignSecurityEx().

09069 : 09070 09071 The procedure is used to allocate and initialize a self-relative 09072 Security Descriptor for a new protected server's object. It is called 09073 when a new protected server object is being created. The generated 09074 security descriptor will be in self-relative form. 09075 09076 This procedure, called only from user mode, is used to establish a 09077 security descriptor for a new protected server's object. Memory is 09078 allocated to hold each of the security descriptor's components (using 09079 NtAllocateVirtualMemory()). The final security descriptor generated by 09080 this procedure is produced according to the rules stated in ??? 09081 09082 System and Discretionary ACL Assignment 09083 --------------------------------------- 09084 09085 The assignment of system and discretionary ACLs is governed by the 09086 logic illustrated in the following table: 09087 09088 | Explicit | Explicit | 09089 | (non-default) | Default | No 09090 | Acl | Acl | Acl 09091 | Specified | Specified | Specified 09092 -------------+----------------+---------------+-------------- 09093 | | | 09094 Inheritable | Assign | Assign | Assign 09095 Acl From | Specified | Inherited | Inherited 09096 Parent | Acl(1)(2) | Acl | Acl 09097 | | | 09098 -------------+----------------+---------------+-------------- 09099 No | | | 09100 Inheritable | Assign | Assign | Assign 09101 Acl From | Specified | Default | No Acl 09102 Parent | Acl(1) | Acl | 09103 | | | 09104 -------------+----------------+---------------+-------------- 09105 09106 (1) Any ACEs with the INHERITED_ACE bit set are NOT copied to the assigned 09107 security descriptor. 09108 09109 (2) If the AutoInheritFlags is flagged to automatically inherit ACEs from 09110 parent (SEF_DACL_AUTO_INHERIT or SEF_SACL_AUTO_INHERIT), inherited 09111 ACEs from the parent will be appended after explicit ACEs from the 09112 CreatorDescriptor. 09113 09114 09115 Note that an explicitly specified ACL, whether a default ACL or 09116 not, may be empty or null. 09117 09118 If the caller is explicitly assigning a system acl, default or 09119 non-default, the caller must either be a kernel mode client or 09120 must be appropriately privileged. 09121 09122 09123 Owner and Group Assignment 09124 -------------------------- 09125 09126 The assignment of the new object's owner and group is governed 09127 by the following logic: 09128 09129 1) If the passed security descriptor includes an owner, it 09130 is assigned as the new object's owner. Otherwise, the 09131 caller's token is looked in for the owner. Within the 09132 token, if there is a default owner, it is assigned. 09133 Otherwise, the caller's user ID is assigned. 09134 09135 2) If the passed security descriptor includes a group, it 09136 is assigned as the new object's group. Otherwise, the 09137 caller's token is looked in for the group. Within the 09138 token, if there is a default group, it is assigned. 09139 Otherwise, the caller's primary group ID is assigned. 09140 09141 09142 Arguments: 09143 09144 ParentDescriptor - Supplies the Security Descriptor for the parent 09145 directory under which a new object is being created. If there is 09146 no parent directory, then this argument is specified as NULL. 09147 09148 CreatorDescriptor - (Optionally) Points to a security descriptor 09149 presented by the creator of the object. If the creator of the 09150 object did not explicitly pass security information for the new 09151 object, then a null pointer should be passed. 09152 09153 NewDescriptor - Points to a pointer that is to be made to point to the 09154 newly allocated self-relative security descriptor. 09155 09156 ObjectType - GUID of the object type being created. If the object being 09157 created has no GUID associated with it, then this argument is 09158 specified as NULL. 09159 09160 IsDirectoryObject - Specifies if the new object is going to be a 09161 directory object. A value of TRUE indicates the object is a 09162 container of other objects. 09163 09164 AutoInheritFlags - Controls automatic inheritance of ACES from the Parent 09165 Descriptor. Valid values are a bits mask of the logical OR of 09166 one or more of the following bits: 09167 09168 SEF_DACL_AUTO_INHERIT - If set, inherit ACEs from the 09169 DACL ParentDescriptor are inherited to NewDescriptor in addition 09170 to any explicit ACEs specified by the CreatorDescriptor. 09171 09172 SEF_SACL_AUTO_INHERIT - If set, inherit ACEs from the 09173 SACL ParentDescriptor are inherited to NewDescriptor in addition 09174 to any explicit ACEs specified by the CreatorDescriptor. 09175 09176 SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT - If set, the CreatorDescriptor 09177 is the default descriptor for ObjectType. As such, the 09178 CreatorDescriptor will be ignored if any ObjectType specific 09179 ACEs are inherited from the parent. If no such ACEs are inherited, 09180 the CreatorDescriptor is handled as though this flag were not 09181 specified. 09182 09183 SEF_AVOID_PRIVILEGE_CHECK - If set, no privilege checking is done by this 09184 routine. This flag is useful while implementing automatic inheritance 09185 to avoid checking privileges on each child updated. 09186 09187 SEF_AVOID_OWNER_CHECK - If set, no owner checking is done by this routine. 09188 09189 SEF_DEFAULT_OWNER_FROM_PARENT - If set, the owner of NewDescriptor will 09190 default to the owner from ParentDescriptor. If not set, the owner 09191 of NewDescriptor will default to the user specified in Token. 09192 09193 In either case, the owner of NewDescriptor is set to the owner from 09194 the CreatorDescriptor if that field is specified. 09195 09196 SEF_DEFAULT_GROUP_FROM_PARENT - If set, the group of NewDescriptor will 09197 default to the group from ParentDescriptor. If not set, the group 09198 of NewDescriptor will default to the group specified in Token. 09199 09200 In either case, the group of NewDescriptor is set to the group from 09201 the CreatorDescriptor if that field is specified. 09202 09203 Token - Supplies the token for the client on whose behalf the 09204 object is being created. If it is an impersonation token, 09205 then it must be at SecurityIdentification level or higher. If 09206 it is not an impersonation token, the operation proceeds 09207 normally. 09208 09209 A client token is used to retrieve default security 09210 information for the new object, such as default owner, primary 09211 group, and discretionary access control. The token must be 09212 open for TOKEN_QUERY access. 09213 09214 For calls from the kernel, Supplies the security context of the subject creating the 09215 object. This is used to retrieve default security information for the 09216 new object, such as default owner, primary group, and discretionary 09217 access control. 09218 09219 If not specified, the Owner and Primary group must be specified in the 09220 CreatorDescriptor. 09221 09222 GenericMapping - Supplies a pointer to a generic mapping array denoting 09223 the mapping between each generic right to specific rights. 09224 09225 Return Value: 09226 09227 STATUS_SUCCESS - The operation was successful. 09228 09229 STATUS_INVALID_OWNER - The owner SID provided as the owner of the 09230 target security descriptor is not one the subject is authorized to 09231 assign as the owner of an object. 09232 09233 STATUS_NO_CLIENT_TOKEN - Indicates a client token was not explicitly 09234 provided and the caller is not currently impersonating a client. 09235 09236 STATUS_PRIVILEGE_NOT_HELD - The caller does not have the privilege 09237 necessary to explicitly assign the specified system ACL. 09238 SeSecurityPrivilege privilege is needed to explicitly assign 09239 system ACLs to objects. 09240 09241 09242 --*/ 09243 { 09244 09245 09246 SECURITY_DESCRIPTOR *CapturedDescriptor; 09247 SECURITY_DESCRIPTOR InCaseOneNotPassed; 09248 BOOLEAN SecurityDescriptorPassed; 09249 09250 NTSTATUS Status; 09251 09252 PACL NewSacl = NULL; 09253 BOOLEAN NewSaclInherited = FALSE; 09254 09255 PACL NewDacl = NULL; 09256 PACL ServerDacl = NULL; 09257 BOOLEAN NewDaclInherited = FALSE; 09258 09259 PSID NewOwner = NULL; 09260 PSID NewGroup = NULL; 09261 09262 BOOLEAN SaclExplicitlyAssigned = FALSE; 09263 BOOLEAN OwnerExplicitlyAssigned = FALSE; 09264 BOOLEAN DaclExplicitlyAssigned = FALSE; 09265 09266 BOOLEAN ServerDaclAllocated = FALSE; 09267 09268 BOOLEAN ServerObject; 09269 BOOLEAN DaclUntrusted; 09270 09271 BOOLEAN HasPrivilege; 09272 PRIVILEGE_SET PrivilegeSet; 09273 09274 PSID SubjectContextOwner = NULL; 09275 PSID SubjectContextGroup = NULL; 09276 PSID ServerOwner = NULL; 09277 PSID ServerGroup = NULL; 09278 09279 PACL SubjectContextDacl = NULL; 09280 09281 ULONG AllocationSize; 09282 ULONG NewOwnerSize; 09283 ULONG NewGroupSize; 09284 ULONG NewSaclSize; 09285 ULONG NewDaclSize; 09286 09287 PCHAR Field; 09288 PCHAR Base; 09289 09290 09291 09292 PISECURITY_DESCRIPTOR_RELATIVE INewDescriptor = NULL; 09293 NTSTATUS PassedStatus; 09294 KPROCESSOR_MODE RequestorMode; 09295 09296 ULONG GenericControl; 09297 ULONG NewControlBits = SE_SELF_RELATIVE; 09298 09299 #ifndef NTOS_KERNEL_RUNTIME 09300 PTOKEN_OWNER TokenOwnerInfo = NULL; 09301 PTOKEN_PRIMARY_GROUP TokenPrimaryGroupInfo = NULL; 09302 PTOKEN_DEFAULT_DACL TokenDefaultDaclInfo = NULL; 09303 09304 PTOKEN_OWNER ServerOwnerInfo = NULL; 09305 PTOKEN_PRIMARY_GROUP ServerGroupInfo = NULL; 09306 PVOID HeapHandle; 09307 09308 #else 09309 09310 // 09311 // For kernel mode callers, the Token parameter is really 09312 // a pointer to a subject context structure. 09313 // 09314 09315 PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; 09316 PVOID SubjectContextInfo = NULL; 09317 09318 SubjectSecurityContext = (PSECURITY_SUBJECT_CONTEXT)Token; 09319 09320 #endif // NTOS_KERNEL_RUNTIME 09321 09322 09323 #ifdef NTOS_KERNEL_RUNTIME 09324 // 09325 // Get the previous mode of the caller 09326 // 09327 09328 RequestorMode = KeGetPreviousMode(); 09329 #else // NTOS_KERNEL_RUNTIME 09330 RequestorMode = UserMode; 09331 09332 // 09333 // Get the handle to the current process heap 09334 // 09335 09336 HeapHandle = RtlProcessHeap(); 09337 09338 // 09339 // Ensure the token is an impersonation token. 09340 // 09341 if ( Token != NULL ) { 09342 TOKEN_STATISTICS ThreadTokenStatistics; 09343 ULONG ReturnLength; 09344 09345 Status = NtQueryInformationToken( 09346 Token, // Handle 09347 TokenStatistics, // TokenInformationClass 09348 &ThreadTokenStatistics, // TokenInformation 09349 sizeof(TOKEN_STATISTICS), // TokenInformationLength 09350 &ReturnLength // ReturnLength 09351 ); 09352 09353 if (!NT_SUCCESS( Status )) { 09354 return( Status ); 09355 } 09356 09357 // 09358 // If it is an impersonation token, then make sure it is at a 09359 // high enough level. 09360 // 09361 09362 if (ThreadTokenStatistics.TokenType == TokenImpersonation) { 09363 09364 if (ThreadTokenStatistics.ImpersonationLevel < SecurityIdentification ) { 09365 09366 return( STATUS_BAD_IMPERSONATION_LEVEL ); 09367 } 09368 } 09369 09370 } 09371 #endif // NTOS_KERNEL_RUNTIME 09372 09373 09374 // 09375 // The desired end result is to build a self-relative security descriptor. 09376 // This means that a single block of memory will be allocated and all 09377 // security information copied into it. To minimize work along the way, 09378 // it is desirable to reference (rather than copy) each field as we 09379 // determine its source. This can not be done with inherited ACLs, however, 09380 // since they must be built from another ACL. So, explicitly assigned 09381 // and defaulted SIDs and ACLs are just referenced until they are copied 09382 // into the self-relative descriptor. Inherited ACLs are built in a 09383 // temporary buffer which must be deallocated after being copied to the 09384 // self-relative descriptor. 09385 // 09386 09387 09388 09389 // 09390 // If a security descriptor has been passed, capture it, otherwise 09391 // cobble up a fake one to simplify the code that follows. 09392 // 09393 09394 if (ARGUMENT_PRESENT(CreatorDescriptor)) { 09395 09396 CapturedDescriptor = CreatorDescriptor; 09397 SecurityDescriptorPassed = TRUE; 09398 09399 } else { 09400 09401 // 09402 // No descriptor passed, make a fake one 09403 // 09404 09405 SecurityDescriptorPassed = FALSE; 09406 09407 RtlCreateSecurityDescriptor(&InCaseOneNotPassed, 09408 SECURITY_DESCRIPTOR_REVISION); 09409 CapturedDescriptor = &InCaseOneNotPassed; 09410 09411 } 09412 09413 09414 if ( CapturedDescriptor->Control & SE_SERVER_SECURITY ) { 09415 ServerObject = TRUE; 09416 } else { 09417 ServerObject = FALSE; 09418 } 09419 09420 if ( CapturedDescriptor->Control & SE_DACL_UNTRUSTED ) { 09421 DaclUntrusted = TRUE; 09422 } else { 09423 DaclUntrusted = FALSE; 09424 } 09425 09426 09427 09428 // 09429 // Get the required information from the token. 09430 // 09431 // 09432 // Grab pointers to the default owner, primary group, and 09433 // discretionary ACL. 09434 // 09435 if ( Token != NULL || ServerObject ) { 09436 09437 #ifdef NTOS_KERNEL_RUNTIME 09438 09439 PSID TmpSubjectContextOwner = NULL; 09440 PSID TmpSubjectContextGroup = NULL; 09441 PSID TmpServerOwner = NULL; 09442 PSID TmpServerGroup = NULL; 09443 09444 PACL TmpSubjectContextDacl = NULL; 09445 09446 SIZE_T SubjectContextInfoSize = 0; 09447 09448 // 09449 // Lock the subject context for read access so that the pointers 09450 // we copy out of it don't disappear on us at random 09451 // 09452 09453 SeLockSubjectContext( SubjectSecurityContext ); 09454 09455 SepGetDefaultsSubjectContext( 09456 SubjectSecurityContext, 09457 &TmpSubjectContextOwner, 09458 &TmpSubjectContextGroup, 09459 &TmpServerOwner, 09460 &TmpServerGroup, 09461 &TmpSubjectContextDacl 09462 ); 09463 09464 // 09465 // We can't keep the subject context locked, because 09466 // we may have to do a privilege check later, which calls 09467 // PsLockProcessSecurityFields, which can cause a deadlock 09468 // with PsImpersonateClient, which takes them in the reverse 09469 // order. 09470 // 09471 // Since we're giving up our read lock on the token, we 09472 // need to copy all the stuff that we just got back. Since 09473 // it's not going to change, we can save some cycles and copy 09474 // it all into a single chunck of memory. 09475 // 09476 09477 SubjectContextInfoSize = SeLengthSid( TmpSubjectContextOwner ) + 09478 SeLengthSid( TmpServerOwner ) + 09479 (TmpSubjectContextGroup != NULL ? SeLengthSid( TmpSubjectContextGroup ) : 0) + 09480 (TmpServerGroup != NULL ? SeLengthSid( TmpServerGroup ) : 0) + 09481 (TmpSubjectContextDacl != NULL ? TmpSubjectContextDacl->AclSize : 0); 09482 09483 SubjectContextInfo = ExAllocatePoolWithTag( PagedPool, SubjectContextInfoSize, 'dSeS'); 09484 09485 if (SubjectContextInfo) { 09486 09487 // 09488 // Copy in the data 09489 // 09490 09491 Base = SubjectContextInfo; 09492 09493 // 09494 // There will always be an owner. 09495 // 09496 09497 SubjectContextOwner = (PSID)Base; 09498 RtlCopySid( SeLengthSid( TmpSubjectContextOwner), Base, TmpSubjectContextOwner ); 09499 Base += SeLengthSid( TmpSubjectContextOwner); 09500 09501 // 09502 // Groups may be NULL 09503 // 09504 09505 if (TmpSubjectContextGroup != NULL) { 09506 SubjectContextGroup = (PSID)Base; 09507 RtlCopySid( SeLengthSid( TmpSubjectContextGroup), Base, TmpSubjectContextGroup ); 09508 Base += SeLengthSid( TmpSubjectContextGroup ); 09509 } else { 09510 SubjectContextGroup = NULL; 09511 } 09512 09513 ServerOwner = (PSID)Base; 09514 RtlCopySid( SeLengthSid( TmpServerOwner ), Base, TmpServerOwner ); 09515 Base += SeLengthSid( TmpServerOwner ); 09516 09517 // 09518 // Groups may be NULL 09519 // 09520 09521 if (TmpServerGroup != NULL) { 09522 ServerGroup = (PSID)Base; 09523 RtlCopySid( SeLengthSid( TmpServerGroup ), Base, TmpServerGroup ); 09524 Base += SeLengthSid( TmpServerGroup ); 09525 } else { 09526 ServerGroup = NULL; 09527 } 09528 09529 if (TmpSubjectContextDacl != NULL) { 09530 SubjectContextDacl = (PACL)Base; 09531 RtlCopyMemory( Base, TmpSubjectContextDacl, TmpSubjectContextDacl->AclSize ); 09532 // Base += TmpSubjectContextDacl->AclSize; 09533 } else { 09534 SubjectContextDacl = NULL; 09535 } 09536 09537 } else { 09538 09539 SeUnlockSubjectContext( SubjectSecurityContext ); 09540 09541 return( STATUS_INSUFFICIENT_RESOURCES ); 09542 } 09543 09544 SeUnlockSubjectContext( SubjectSecurityContext ); 09545 09546 09547 #else // NTOS_KERNEL_RUNTIME 09548 Status = RtlpGetDefaultsSubjectContext( 09549 Token, 09550 &TokenOwnerInfo, 09551 &TokenPrimaryGroupInfo, 09552 &TokenDefaultDaclInfo, 09553 &ServerOwnerInfo, 09554 &ServerGroupInfo 09555 ); 09556 09557 if (!NT_SUCCESS( Status )) { 09558 return( Status ); 09559 } 09560 09561 SubjectContextOwner = TokenOwnerInfo->Owner; 09562 SubjectContextGroup = TokenPrimaryGroupInfo->PrimaryGroup; 09563 SubjectContextDacl = TokenDefaultDaclInfo->DefaultDacl; 09564 ServerOwner = ServerOwnerInfo->Owner; 09565 ServerGroup = ServerGroupInfo->PrimaryGroup; 09566 #endif // NTOS_KERNEL_RUNTIME 09567 } 09568 09569 09570 09571 // 09572 // Establish an owner SID 09573 // 09574 09575 NewOwner = RtlpOwnerAddrSecurityDescriptor(CapturedDescriptor); 09576 09577 if ((NewOwner) != NULL) { 09578 09579 // 09580 // Use the specified owner 09581 // 09582 09583 OwnerExplicitlyAssigned = TRUE; 09584 09585 } else { 09586 09587 // 09588 // If the caller said to default the owner from the parent descriptor, 09589 // grab it now. 09590 // 09591 09592 if ( AutoInheritFlags & SEF_DEFAULT_OWNER_FROM_PARENT) { 09593 if ( !ARGUMENT_PRESENT(ParentDescriptor) ) { 09594 Status = STATUS_INVALID_OWNER; 09595 goto Cleanup; 09596 } 09597 NewOwner = RtlpOwnerAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)ParentDescriptor); 09598 OwnerExplicitlyAssigned = TRUE; 09599 09600 if ( NewOwner == NULL ) { 09601 Status = STATUS_INVALID_OWNER; 09602 goto Cleanup; 09603 } 09604 } else { 09605 09606 // 09607 // Pick up the default from the subject's security context. 09608 // 09609 // This does NOT constitute explicit assignment of owner 09610 // and does not have to be checked as an ID that can be 09611 // assigned as owner. This is because a default can not 09612 // be established in a token unless the user of the token 09613 // can assign it as an owner. 09614 // 09615 09616 // 09617 // If we've been asked to create a ServerObject, we need to 09618 // make sure to pick up the new owner from the Primary token, 09619 // not the client token. If we're not impersonating, they will 09620 // end up being the same. 09621 // 09622 09623 NewOwner = ServerObject ? ServerOwner : SubjectContextOwner; 09624 09625 // 09626 // Ensure an owner is now defined. 09627 // 09628 09629 if ( NewOwner == NULL ) { 09630 Status = STATUS_NO_TOKEN; 09631 goto Cleanup; 09632 } 09633 } 09634 } 09635 09636 09637 // 09638 // Establish a Group SID 09639 // 09640 09641 NewGroup = RtlpGroupAddrSecurityDescriptor(CapturedDescriptor); 09642 09643 if (NewGroup == NULL) { 09644 09645 // 09646 // If the caller said to default the group from the parent descriptor, 09647 // grab it now. 09648 // 09649 09650 if ( AutoInheritFlags & SEF_DEFAULT_GROUP_FROM_PARENT) { 09651 if ( !ARGUMENT_PRESENT(ParentDescriptor) ) { 09652 Status = STATUS_INVALID_PRIMARY_GROUP; 09653 goto Cleanup; 09654 } 09655 NewGroup = RtlpGroupAddrSecurityDescriptor((SECURITY_DESCRIPTOR *)ParentDescriptor); 09656 } else { 09657 // 09658 // Pick up the primary group from the subject's security context 09659 // 09660 // If we're creating a Server object, use the group from the server 09661 // context. 09662 // 09663 09664 NewGroup = ServerObject ? ServerGroup : SubjectContextGroup; 09665 } 09666 09667 } 09668 09669 if (NewGroup != NULL) { 09670 if (!RtlValidSid( NewGroup )) { 09671 Status = STATUS_INVALID_PRIMARY_GROUP; 09672 goto Cleanup; 09673 } 09674 } else { 09675 Status = STATUS_INVALID_PRIMARY_GROUP; 09676 goto Cleanup; 09677 } 09678 09679 09680 09681 09682 // 09683 // Establish System Acl 09684 // 09685 09686 Status = RtlpInheritAcl ( 09687 ARGUMENT_PRESENT(ParentDescriptor) ? 09688 RtlpSaclAddrSecurityDescriptor( 09689 ((SECURITY_DESCRIPTOR *)ParentDescriptor)) : 09690 NULL, 09691 RtlpSaclAddrSecurityDescriptor(CapturedDescriptor), 09692 SeControlSaclToGeneric( CapturedDescriptor->Control ), 09693 IsDirectoryObject, 09694 (BOOLEAN)((AutoInheritFlags & SEF_SACL_AUTO_INHERIT) != 0), 09695 (BOOLEAN)((AutoInheritFlags & SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT) != 0), 09696 NewOwner, 09697 NewGroup, 09698 ServerOwner, 09699 ServerGroup, 09700 GenericMapping, 09701 TRUE, // Is a SACL 09702 ObjectType, 09703 &NewSacl, 09704 &SaclExplicitlyAssigned, 09705 &GenericControl ); 09706 09707 if ( NT_SUCCESS(Status) ) { 09708 NewSaclInherited = TRUE; 09709 NewControlBits |= SE_SACL_PRESENT | SeControlGenericToSacl( GenericControl ); 09710 09711 } else if ( Status == STATUS_NO_INHERITANCE ) { 09712 09713 // 09714 // Always set the auto inherit bit if the caller requested it. 09715 // 09716 09717 if ( AutoInheritFlags & SEF_SACL_AUTO_INHERIT) { 09718 NewControlBits |= SE_SACL_AUTO_INHERITED; 09719 } 09720 09721 // 09722 // No inheritable ACL - check for a defaulted one. 09723 // 09724 if ( RtlpAreControlBitsSet( CapturedDescriptor, 09725 SE_SACL_PRESENT | SE_SACL_DEFAULTED ) ) { 09726 09727 // 09728 // Reference the default ACL 09729 // 09730 09731 NewSacl = RtlpSaclAddrSecurityDescriptor(CapturedDescriptor); 09732 NewControlBits |= SE_SACL_PRESENT; 09733 NewControlBits |= (CapturedDescriptor->Control & SE_SACL_PROTECTED); 09734 09735 // 09736 // This counts as an explicit assignment. 09737 // 09738 SaclExplicitlyAssigned = TRUE; 09739 } 09740 09741 } else { 09742 09743 // 09744 // Some unusual error occured 09745 // 09746 09747 goto Cleanup; 09748 } 09749 09750 09751 09752 09753 // 09754 // Establish Discretionary Acl 09755 // 09756 09757 Status = RtlpInheritAcl ( 09758 ARGUMENT_PRESENT(ParentDescriptor) ? 09759 RtlpDaclAddrSecurityDescriptor( 09760 ((SECURITY_DESCRIPTOR *)ParentDescriptor)) : 09761 NULL, 09762 RtlpDaclAddrSecurityDescriptor(CapturedDescriptor), 09763 SeControlDaclToGeneric( CapturedDescriptor->Control ), 09764 IsDirectoryObject, 09765 (BOOLEAN)((AutoInheritFlags & SEF_DACL_AUTO_INHERIT) != 0), 09766 (BOOLEAN)((AutoInheritFlags & SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT) != 0), 09767 NewOwner, 09768 NewGroup, 09769 ServerOwner, 09770 ServerGroup, 09771 GenericMapping, 09772 FALSE, // Is a DACL 09773 ObjectType, 09774 &NewDacl, 09775 &DaclExplicitlyAssigned, 09776 &GenericControl ); 09777 09778 if ( NT_SUCCESS(Status) ) { 09779 NewDaclInherited = TRUE; 09780 NewControlBits |= SE_DACL_PRESENT | SeControlGenericToDacl( GenericControl ); 09781 09782 } else if ( Status == STATUS_NO_INHERITANCE ) { 09783 09784 // 09785 // Always set the auto inherit bit if the caller requested it. 09786 // 09787 09788 if ( AutoInheritFlags & SEF_DACL_AUTO_INHERIT) { 09789 NewControlBits |= SE_DACL_AUTO_INHERITED; 09790 } 09791 09792 // 09793 // No inheritable ACL - check for a defaulted one. 09794 // 09795 if ( RtlpAreControlBitsSet( CapturedDescriptor, 09796 SE_DACL_PRESENT | SE_DACL_DEFAULTED ) ) { 09797 09798 // 09799 // Reference the default ACL 09800 // 09801 09802 NewDacl = RtlpDaclAddrSecurityDescriptor(CapturedDescriptor); 09803 NewControlBits |= SE_DACL_PRESENT; 09804 NewControlBits |= (CapturedDescriptor->Control & SE_DACL_PROTECTED); 09805 09806 // 09807 // This counts as an explicit assignment. 09808 // 09809 DaclExplicitlyAssigned = TRUE; 09810 09811 // 09812 // Default to the DACL on the token. 09813 // 09814 } else if (ARGUMENT_PRESENT(SubjectContextDacl)) { 09815 09816 NewDacl = SubjectContextDacl; 09817 NewControlBits |= SE_DACL_PRESENT; 09818 09819 } 09820 09821 09822 } else { 09823 09824 // 09825 // Some unusual error occured 09826 // 09827 09828 goto Cleanup; 09829 } 09830 09831 // 09832 // If auto inheriting and the computed child DACL is NULL, 09833 // mark it as protected. 09834 // 09835 // NULL DACLs are problematic when ACEs are actually inherited from the 09836 // parent DACL. It is better to mark them as protected NOW (even if we don't 09837 // end up inheriting any ACEs) to avoid confusion later. 09838 // 09839 09840 if ( (AutoInheritFlags & SEF_DACL_AUTO_INHERIT) != 0 && 09841 NewDacl == NULL ) { 09842 NewControlBits |= SE_DACL_PROTECTED; 09843 } 09844 09845 09846 09847 // 09848 // Now make sure that the caller has the right to assign 09849 // everything in the descriptor. The requestor is subjected 09850 // to privilege and restriction tests for some assignments. 09851 // 09852 if (RequestorMode == UserMode) { 09853 09854 09855 // 09856 // Anybody can assign any Discretionary ACL or group that they want to. 09857 // 09858 09859 // 09860 // See if the system ACL was explicitly specified 09861 // 09862 09863 if ( SaclExplicitlyAssigned && 09864 (AutoInheritFlags & SEF_AVOID_PRIVILEGE_CHECK) == 0 ) { 09865 09866 // 09867 // Require a Token if we're to do the privilege check. 09868 // 09869 09870 if ( Token == NULL ) { 09871 Status = STATUS_NO_TOKEN; 09872 goto Cleanup; 09873 } 09874 09875 #ifdef NTOS_KERNEL_RUNTIME 09876 09877 // 09878 // Check for appropriate Privileges 09879 // Audit/Alarm messages need to be generated due to the attempt 09880 // to perform a privileged operation. 09881 // 09882 09883 // 09884 // Note: be sure to do the privilege check against 09885 // the passed subject context! 09886 // 09887 09888 PrivilegeSet.PrivilegeCount = 1; 09889 PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 09890 PrivilegeSet.Privilege[0].Luid = SeSecurityPrivilege; 09891 PrivilegeSet.Privilege[0].Attributes = 0; 09892 09893 HasPrivilege = SePrivilegeCheck( 09894 &PrivilegeSet, 09895 SubjectSecurityContext, 09896 RequestorMode 09897 ); 09898 09899 if ( RequestorMode != KernelMode ) { 09900 09901 SePrivilegedServiceAuditAlarm ( 09902 NULL, // BUGWARNING need service name 09903 SubjectSecurityContext, 09904 &PrivilegeSet, 09905 HasPrivilege 09906 ); 09907 } 09908 09909 #else // NTOS_KERNEL_RUNTIME 09910 // 09911 // Check for appropriate Privileges 09912 // 09913 // Audit/Alarm messages need to be generated due to the attempt 09914 // to perform a privileged operation. 09915 // 09916 09917 PrivilegeSet.PrivilegeCount = 1; 09918 PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 09919 PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE); 09920 PrivilegeSet.Privilege[0].Attributes = 0; 09921 09922 Status = NtPrivilegeCheck( 09923 Token, 09924 &PrivilegeSet, 09925 &HasPrivilege 09926 ); 09927 09928 if (!NT_SUCCESS( Status )) { 09929 goto Cleanup; 09930 } 09931 09932 #endif // NTOS_KERNEL_RUNTIME 09933 09934 if ( !HasPrivilege ) { 09935 Status = STATUS_PRIVILEGE_NOT_HELD; 09936 goto Cleanup; 09937 } 09938 09939 } 09940 09941 // 09942 // See if the owner field is one the requestor can assign 09943 // 09944 09945 if (OwnerExplicitlyAssigned && 09946 (AutoInheritFlags & SEF_AVOID_OWNER_CHECK) == 0 ) { 09947 09948 #ifdef NTOS_KERNEL_RUNTIME 09949 09950 09951 if (!SepValidOwnerSubjectContext( 09952 SubjectSecurityContext, 09953 NewOwner, 09954 ServerObject) 09955 ) { 09956 09957 Status = STATUS_INVALID_OWNER; 09958 goto Cleanup; 09959 } 09960 09961 #else // NTOS_KERNEL_RUNTIME 09962 09963 // 09964 // Require a Token if we're to do the privilege check. 09965 // 09966 09967 if ( Token == NULL ) { 09968 Status = STATUS_NO_TOKEN; 09969 goto Cleanup; 09970 } 09971 09972 if (!RtlpValidOwnerSubjectContext( 09973 Token, 09974 NewOwner, 09975 ServerObject, 09976 &PassedStatus) ) { 09977 09978 Status = PassedStatus; 09979 goto Cleanup; 09980 } 09981 #endif // NTOS_KERNEL_RUNTIME 09982 } 09983 09984 09985 // 09986 // If the DACL was explictly assigned and this is a server object, 09987 // convert the DACL to be a server DACL 09988 // 09989 09990 if (DaclExplicitlyAssigned && ServerObject) { 09991 09992 Status = RtlpCreateServerAcl( 09993 NewDacl, 09994 DaclUntrusted, 09995 ServerOwner, 09996 &ServerDacl, 09997 &ServerDaclAllocated 09998 ); 09999 10000 if (!NT_SUCCESS( Status )) { 10001 goto Cleanup; 10002 } 10003 10004 NewDacl = ServerDacl; 10005 } 10006 } 10007 10008 10009 // 10010 // Everything is assignable by the requestor. 10011 // Calculate the memory needed to house all the information in 10012 // a self-relative security descriptor. 10013 // 10014 // Also map the ACEs for application to the target object 10015 // type, if they haven't already been mapped. 10016 // 10017 10018 NewOwnerSize = LongAlignSize(SeLengthSid(NewOwner)); 10019 if (NewGroup != NULL) { 10020 NewGroupSize = LongAlignSize(SeLengthSid(NewGroup)); 10021 } 10022 10023 if ((NewControlBits & SE_SACL_PRESENT) && (NewSacl != NULL)) { 10024 NewSaclSize = LongAlignSize(NewSacl->AclSize); 10025 } else { 10026 NewSaclSize = 0; 10027 } 10028 10029 if ( (NewControlBits & SE_DACL_PRESENT) && (NewDacl != NULL)) { 10030 NewDaclSize = LongAlignSize(NewDacl->AclSize); 10031 } else { 10032 NewDaclSize = 0; 10033 } 10034 10035 AllocationSize = LongAlignSize(sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + 10036 NewOwnerSize + 10037 NewGroupSize + 10038 NewSaclSize + 10039 NewDaclSize; 10040 10041 // 10042 // Allocate and initialize the security descriptor as 10043 // self-relative form. 10044 // 10045 10046 #ifdef NTOS_KERNEL_RUNTIME 10047 INewDescriptor = (PSECURITY_DESCRIPTOR)ExAllocatePoolWithTag( PagedPool, AllocationSize, 'dSeS'); 10048 #else // NTOS_KERNEL_RUNTIME 10049 INewDescriptor = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), AllocationSize ); 10050 #endif // NTOS_KERNEL_RUNTIME 10051 10052 if ( INewDescriptor == NULL ) { 10053 #ifdef NTOS_KERNEL_RUNTIME 10054 Status = STATUS_INSUFFICIENT_RESOURCES; 10055 #else // NTOS_KERNEL_RUNTIME 10056 Status = STATUS_NO_MEMORY; 10057 #endif // NTOS_KERNEL_RUNTIME 10058 goto Cleanup; 10059 } 10060 10061 RtlCreateSecurityDescriptorRelative( 10062 INewDescriptor, 10063 SECURITY_DESCRIPTOR_REVISION 10064 ); 10065 10066 RtlpSetControlBits( INewDescriptor, NewControlBits ); 10067 10068 Base = (PCHAR)(INewDescriptor); 10069 Field = Base + sizeof(SECURITY_DESCRIPTOR_RELATIVE); 10070 10071 // 10072 // Map and Copy in the Sacl 10073 // 10074 10075 if (NewControlBits & SE_SACL_PRESENT) { 10076 10077 if (NewSacl != NULL) { 10078 10079 RtlCopyMemory( Field, NewSacl, NewSacl->AclSize ); 10080 10081 if (!NewSaclInherited) { 10082 RtlpApplyAclToObject( (PACL)Field, GenericMapping ); 10083 } 10084 10085 INewDescriptor->Sacl = RtlPointerToOffset(Base,Field); 10086 Field += NewSaclSize; 10087 10088 } else { 10089 10090 INewDescriptor->Sacl = 0; 10091 } 10092 10093 } 10094 10095 // 10096 // Map and Copy in the Dacl 10097 // 10098 10099 if (NewControlBits & SE_DACL_PRESENT) { 10100 10101 if (NewDacl != NULL) { 10102 10103 RtlCopyMemory( Field, NewDacl, NewDacl->AclSize ); 10104 10105 if (!NewDaclInherited) { 10106 RtlpApplyAclToObject( (PACL)Field, GenericMapping ); 10107 } 10108 10109 INewDescriptor->Dacl = RtlPointerToOffset(Base,Field); 10110 Field += NewDaclSize; 10111 10112 } else { 10113 10114 INewDescriptor->Dacl = 0; 10115 } 10116 10117 } 10118 10119 // 10120 // Assign the owner 10121 // 10122 10123 RtlCopyMemory( Field, NewOwner, SeLengthSid(NewOwner) ); 10124 INewDescriptor->Owner = RtlPointerToOffset(Base,Field); 10125 Field += NewOwnerSize; 10126 10127 if (NewGroup != NULL) { 10128 RtlCopyMemory( Field, NewGroup, SeLengthSid(NewGroup) ); 10129 INewDescriptor->Group = RtlPointerToOffset(Base,Field); 10130 } 10131 10132 Status = STATUS_SUCCESS; 10133 10134 10135 10136 Cleanup: 10137 // 10138 // If we allocated memory for a Server DACL, free it now. 10139 // 10140 10141 if (ServerDaclAllocated) { 10142 #ifdef NTOS_KERNEL_RUNTIME 10143 ExFreePool( ServerDacl ); 10144 #else // NTOS_KERNEL_RUNTIME 10145 RtlFreeHeap(RtlProcessHeap(), 0, ServerDacl ); 10146 #endif // NTOS_KERNEL_RUNTIME 10147 } 10148 10149 // 10150 // Either an error was encountered or the assignment has completed 10151 // successfully. In either case, we have to clean up any memory. 10152 // 10153 10154 #ifdef NTOS_KERNEL_RUNTIME 10155 // if ( SubjectSecurityContext != NULL ) { 10156 // SeUnlockSubjectContext( SubjectSecurityContext ); 10157 // } 10158 10159 if (SubjectContextInfo != NULL) { 10160 ExFreePool( SubjectContextInfo ); 10161 } 10162 10163 #else // NTOS_KERNEL_RUNTIME 10164 RtlFreeHeap( HeapHandle, 0, (PVOID)TokenOwnerInfo ); 10165 RtlFreeHeap( HeapHandle, 0, (PVOID)TokenPrimaryGroupInfo ); 10166 RtlFreeHeap( HeapHandle, 0, (PVOID)TokenDefaultDaclInfo ); 10167 RtlFreeHeap( HeapHandle, 0, (PVOID)ServerOwnerInfo ); 10168 RtlFreeHeap( HeapHandle, 0, (PVOID)ServerGroupInfo ); 10169 #endif // NTOS_KERNEL_RUNTIME 10170 10171 if (NewSaclInherited && NewSacl != NULL ) { 10172 #ifdef NTOS_KERNEL_RUNTIME 10173 ExFreePool( NewSacl ); 10174 #else // NTOS_KERNEL_RUNTIME 10175 RtlFreeHeap( HeapHandle, 0, (PVOID)NewSacl ); 10176 #endif // NTOS_KERNEL_RUNTIME 10177 } 10178 10179 if (NewDaclInherited && NewDacl != NULL ) { 10180 #ifdef NTOS_KERNEL_RUNTIME 10181 ExFreePool( NewDacl ); 10182 #else // NTOS_KERNEL_RUNTIME 10183 RtlFreeHeap( HeapHandle, 0, (PVOID)NewDacl ); 10184 #endif // NTOS_KERNEL_RUNTIME 10185 } 10186 10187 *NewDescriptor = (PSECURITY_DESCRIPTOR) INewDescriptor; 10188 10189 10190 return Status; 10191 }

NTSTATUS RtlpSetSecurityObject IN PVOID Object  OPTIONAL,
IN SECURITY_INFORMATION  SecurityInformation,
IN PSECURITY_DESCRIPTOR  ModificationDescriptor,
IN OUT PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor,
IN ULONG  AutoInheritFlags,
IN ULONG  PoolType,
IN PGENERIC_MAPPING  GenericMapping,
IN HANDLE Token  OPTIONAL
 

Definition at line 10195 of file sertl.c.

References ASSERT, ExAllocatePoolWithTag, ExFreePool(), FALSE, HeapHandle, MAKE_TAG, NT_SUCCESS, NtClose(), NtOpenProcessToken(), NtQueryInformationToken(), NTSTATUS(), NULL, ObValidateSecurityQuota(), PrimaryToken, RTL_PAGED_CODE, RtlAllocateHeap, RtlCreateSecurityDescriptorRelative(), RtlFreeHeap, RtlLengthRequiredSid(), RtlpApplyAclToObject(), RtlpComputeMergedAcl(), RtlpCreateServerAcl(), RtlpValidOwnerSubjectContext(), RtlValidSid(), SE_TAG, SeCaptureSubjectContext(), SeLengthSid, SepGetDefaultsSubjectContext(), SepValidOwnerSubjectContext(), SeReleaseSubjectContext(), Status, Token, and TRUE.

Referenced by RtlSetSecurityObject(), RtlSetSecurityObjectEx(), SeSetSecurityDescriptorInfo(), and SeSetSecurityDescriptorInfoEx().

10209 : 10210 10211 Modify an object's existing self-relative form security descriptor. 10212 10213 This procedure, called only from user mode, is used to update a 10214 security descriptor on an existing protected server's object. It 10215 applies changes requested by a new security descriptor to the existing 10216 security descriptor. If necessary, this routine will allocate 10217 additional memory to produce a larger security descriptor. All access 10218 checking is expected to be done before calling this routine. This 10219 includes checking for WRITE_OWNER, WRITE_DAC, and privilege to assign a 10220 system ACL as appropriate. 10221 10222 The caller of this routine must not be impersonating a client. 10223 10224 - - WARNING - - 10225 10226 This service is for use by protected subsystems that project their own 10227 type of object. This service is explicitly not for use by the 10228 executive for executive objects and must not be called from kernel 10229 mode. 10230 10231 Arguments: 10232 10233 Object - Optionally supplies the object whose security is 10234 being adjusted. This is used to update security quota 10235 information. 10236 10237 SecurityInformation - Indicates which security information is 10238 to be applied to the object. The value(s) to be assigned are 10239 passed in the ModificationDescriptor parameter. 10240 10241 ModificationDescriptor - Supplies the input security descriptor to be 10242 applied to the object. The caller of this routine is expected 10243 to probe and capture the passed security descriptor before calling 10244 and release it after calling. 10245 10246 ObjectsSecurityDescriptor - Supplies the address of a pointer to 10247 the objects security descriptor that is going to be altered by 10248 this procedure. This security descriptor must be in self- 10249 relative form or an error will be returned. 10250 10251 AutoInheritFlags - Controls automatic inheritance of ACES. 10252 Valid values are a bits mask of the logical OR of 10253 one or more of the following bits: 10254 10255 SEF_DACL_AUTO_INHERIT - If set, inherited ACEs from the 10256 DACL in the ObjectsSecurityDescriptor are preserved and inherited ACEs from 10257 the ModificationDescriptor are ignored. Inherited ACEs are not supposed 10258 to be modified; so preserving them across this call is appropriate. 10259 If a protected server does not itself implement auto inheritance, it should 10260 not set this bit. The caller of the protected server may implement 10261 auto inheritance and my indeed be modifying inherited ACEs. 10262 10263 SEF_SACL_AUTO_INHERIT - If set, inherited ACEs from the 10264 SACL in the ObjectsSecurityDescriptor are preserved and inherited ACEs from 10265 the ModificationDescriptor are ignored. Inherited ACEs are not supposed 10266 to be modified; so preserving them across this call is appropriate. 10267 If a protected server does not itself implement auto inheritance, it should 10268 not set this bit. The caller of the protected server may implement 10269 auto inheritance and my indeed be modifying inherited ACEs. 10270 10271 SEF_AVOID_PRIVILEGE_CHECK - If set, the Token in not used to ensure the 10272 Owner passed in ModificationDescriptor is valid. 10273 10274 PoolType - Specifies the type of pool to allocate for the objects 10275 security descriptor. 10276 10277 GenericMapping - This argument provides the mapping of generic to 10278 specific/standard access types for the object being accessed. 10279 This mapping structure is expected to be safe to access 10280 (i.e., captured if necessary) prior to be passed to this routine. 10281 10282 Token - (optionally) Supplies the token for the client on whose 10283 behalf the security is being modified. This parameter is only 10284 required to ensure that the client has provided a legitimate 10285 value for a new owner SID. The token must be open for 10286 TOKEN_QUERY access. 10287 10288 Return Value: 10289 10290 STATUS_SUCCESS - The operation was successful. 10291 10292 STATUS_INVALID_OWNER - The owner SID provided as the new owner of the 10293 target security descriptor is not one the caller is authorized to 10294 assign as the owner of an object, or the client did not pass 10295 a token at all. 10296 10297 STATUS_NO_CLIENT_TOKEN - Indicates a client token was not explicitly 10298 provided and the caller is not currently impersonating a client. 10299 10300 STATUS_BAD_DESCRIPTOR_FORMAT - Indicates the provided object's security 10301 descriptor was not in self-relative format. 10302 10303 --*/ 10304 10305 { 10306 BOOLEAN NewGroupPresent = FALSE; 10307 BOOLEAN NewOwnerPresent = FALSE; 10308 10309 BOOLEAN ServerAclAllocated = FALSE; 10310 BOOLEAN LocalDaclAllocated = FALSE; 10311 BOOLEAN LocalSaclAllocated = FALSE; 10312 BOOLEAN ServerObject; 10313 BOOLEAN DaclUntrusted; 10314 10315 PCHAR Field; 10316 PCHAR Base; 10317 10318 PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor = NULL; 10319 10320 NTSTATUS Status; 10321 10322 TOKEN_STATISTICS ThreadTokenStatistics; 10323 10324 ULONG ReturnLength; 10325 10326 PSID NewGroup; 10327 PSID NewOwner; 10328 10329 PACL NewDacl; 10330 PACL LocalDacl; 10331 PACL NewSacl; 10332 PACL LocalSacl; 10333 10334 ULONG NewDaclSize; 10335 ULONG NewSaclSize; 10336 ULONG NewOwnerSize; 10337 ULONG NewGroupSize; 10338 ULONG AllocationSize; 10339 ULONG ServerOwnerInfoSize; 10340 10341 HANDLE PrimaryToken; 10342 ULONG GenericControl; 10343 ULONG NewControlBits = SE_SELF_RELATIVE; 10344 10345 PACL ServerDacl; 10346 10347 SECURITY_SUBJECT_CONTEXT SubjectContext; 10348 10349 10350 // 10351 // Typecast to internal representation of security descriptor. 10352 // Note that the internal one is not a pointer to a pointer. 10353 // It is just a pointer to a security descriptor. 10354 // 10355 PISECURITY_DESCRIPTOR IModificationDescriptor = 10356 (PISECURITY_DESCRIPTOR)ModificationDescriptor; 10357 10358 PISECURITY_DESCRIPTOR *IObjectsSecurityDescriptor = 10359 (PISECURITY_DESCRIPTOR *)(ObjectsSecurityDescriptor); 10360 10361 #ifndef NTOS_KERNEL_RUNTIME 10362 PVOID HeapHandle; 10363 #endif // NTOS_KERNEL_RUNTIME 10364 10365 RTL_PAGED_CODE(); 10366 10367 // 10368 // Get the handle to the current process heap 10369 // 10370 10371 #ifndef NTOS_KERNEL_RUNTIME 10372 HeapHandle = RtlProcessHeap(); 10373 #endif // NTOS_KERNEL_RUNTIME 10374 10375 // 10376 // Validate that the provided SD is in self-relative form 10377 // 10378 10379 if ( !RtlpAreControlBitsSet(*IObjectsSecurityDescriptor, SE_SELF_RELATIVE) ) { 10380 Status = STATUS_BAD_DESCRIPTOR_FORMAT; 10381 goto Cleanup; 10382 } 10383 10384 // 10385 // Check to see if we need to edit the passed acl 10386 // either because we're creating a server object, or because 10387 // we were passed an untrusted ACL. 10388 // 10389 10390 if (ARGUMENT_PRESENT(ModificationDescriptor)) { 10391 10392 if ( RtlpAreControlBitsSet(IModificationDescriptor, SE_SERVER_SECURITY)) { 10393 ServerObject = TRUE; 10394 } else { 10395 ServerObject = FALSE; 10396 } 10397 10398 if ( RtlpAreControlBitsSet(IModificationDescriptor, SE_DACL_UNTRUSTED)) { 10399 DaclUntrusted = TRUE; 10400 } else { 10401 DaclUntrusted = FALSE; 10402 } 10403 10404 } else { 10405 10406 ServerObject = FALSE; 10407 DaclUntrusted = FALSE; 10408 10409 } 10410 10411 10412 // 10413 // For each item specified in the SecurityInformation, extract it 10414 // and get it to the point where it can be copied into a new 10415 // descriptor. 10416 // 10417 10418 // 10419 // if he's setting the owner field, make sure he's 10420 // allowed to set that value as an owner. 10421 // 10422 10423 if (SecurityInformation & OWNER_SECURITY_INFORMATION) { 10424 10425 NewOwner = RtlpOwnerAddrSecurityDescriptor( IModificationDescriptor ); 10426 NewOwnerPresent = TRUE; 10427 10428 if ((AutoInheritFlags & SEF_AVOID_PRIVILEGE_CHECK) == 0 ) { 10429 10430 #ifdef NTOS_KERNEL_RUNTIME 10431 10432 SeCaptureSubjectContext( &SubjectContext ); 10433 10434 if (!SepValidOwnerSubjectContext( &SubjectContext, NewOwner, ServerObject ) ) { 10435 10436 SeReleaseSubjectContext( &SubjectContext ); 10437 return( STATUS_INVALID_OWNER ); 10438 10439 } else { 10440 10441 SeReleaseSubjectContext( &SubjectContext ); 10442 } 10443 #else // NTOS_KERNEL_RUNTIME 10444 10445 if ( ARGUMENT_PRESENT( Token )) { 10446 10447 Status = NtQueryInformationToken( 10448 Token, // Handle 10449 TokenStatistics, // TokenInformationClass 10450 &ThreadTokenStatistics, // TokenInformation 10451 sizeof(TOKEN_STATISTICS), // TokenInformationLength 10452 &ReturnLength // ReturnLength 10453 ); 10454 10455 if (!NT_SUCCESS( Status )) { 10456 goto Cleanup; 10457 } 10458 10459 // 10460 // If it is an impersonation token, then make sure it is at a 10461 // high enough level. 10462 // 10463 10464 if (ThreadTokenStatistics.TokenType == TokenImpersonation) { 10465 10466 if (ThreadTokenStatistics.ImpersonationLevel < SecurityIdentification ) { 10467 Status = STATUS_BAD_IMPERSONATION_LEVEL; 10468 goto Cleanup; 10469 } 10470 } 10471 10472 } else { 10473 10474 Status = STATUS_INVALID_OWNER; 10475 goto Cleanup; 10476 } 10477 10478 if (!RtlpValidOwnerSubjectContext( 10479 Token, 10480 NewOwner, 10481 ServerObject, 10482 &Status) ) { 10483 10484 Status = STATUS_INVALID_OWNER; 10485 goto Cleanup; 10486 } 10487 #endif // NTOS_KERNEL_RUNTIME 10488 } 10489 10490 } else { 10491 10492 NewOwner = RtlpOwnerAddrSecurityDescriptor ( *IObjectsSecurityDescriptor ); 10493 if (NewOwner == NULL) { 10494 Status = STATUS_INVALID_OWNER; 10495 goto Cleanup; 10496 } 10497 10498 } 10499 ASSERT( NewOwner != NULL ); 10500 if (!RtlValidSid( NewOwner )) { 10501 Status = STATUS_INVALID_OWNER; 10502 goto Cleanup; 10503 } 10504 10505 10506 if (SecurityInformation & GROUP_SECURITY_INFORMATION) { 10507 10508 NewGroup = RtlpGroupAddrSecurityDescriptor(IModificationDescriptor); 10509 NewGroupPresent = TRUE; 10510 10511 } else { 10512 10513 NewGroup = RtlpGroupAddrSecurityDescriptor( *IObjectsSecurityDescriptor ); 10514 } 10515 10516 if (NewGroup != NULL) { 10517 if (!RtlValidSid( NewGroup )) { 10518 Status = STATUS_INVALID_PRIMARY_GROUP; 10519 goto Cleanup; 10520 } 10521 } else { 10522 Status = STATUS_INVALID_PRIMARY_GROUP; 10523 goto Cleanup; 10524 } 10525 10526 10527 if (SecurityInformation & DACL_SECURITY_INFORMATION) { 10528 10529 // 10530 // If AutoInherit is requested, 10531 // build a merged ACL. 10532 // 10533 10534 if ( AutoInheritFlags & SEF_DACL_AUTO_INHERIT ) { 10535 Status = RtlpComputeMergedAcl( 10536 RtlpDaclAddrSecurityDescriptor( *IObjectsSecurityDescriptor ), 10537 SeControlDaclToGeneric( (*IObjectsSecurityDescriptor)->Control ), 10538 RtlpDaclAddrSecurityDescriptor( IModificationDescriptor ), 10539 SeControlDaclToGeneric( IModificationDescriptor->Control ), 10540 NewOwner, 10541 NewGroup, 10542 GenericMapping, 10543 FALSE, // Not a SACL 10544 &LocalDacl, 10545 &GenericControl ); 10546 10547 if ( !NT_SUCCESS(Status)) { 10548 goto Cleanup; 10549 } 10550 10551 LocalDaclAllocated = TRUE; 10552 NewDacl = LocalDacl; 10553 NewControlBits |= SE_DACL_PRESENT; 10554 NewControlBits |= SeControlGenericToDacl( GenericControl ); 10555 10556 // 10557 // If AutoInherit isn't requested, 10558 // just grab a copy of the input DACL. 10559 // 10560 10561 } else { 10562 NewDacl = RtlpDaclAddrSecurityDescriptor( IModificationDescriptor ); 10563 NewControlBits |= SE_DACL_PRESENT; 10564 NewControlBits |= IModificationDescriptor->Control & SE_DACL_PROTECTED; 10565 10566 // 10567 // If the original caller claims he understands auto inheritance, 10568 // preserve the AutoInherited flag. 10569 // 10570 10571 if ( RtlpAreControlBitsSet(IModificationDescriptor, SE_DACL_AUTO_INHERIT_REQ|SE_DACL_AUTO_INHERITED) ) { 10572 NewControlBits |= SE_DACL_AUTO_INHERITED; 10573 } 10574 } 10575 10576 if (ServerObject) { 10577 10578 #ifdef NTOS_KERNEL_RUNTIME 10579 10580 PSID SubjectContextOwner; 10581 PSID SubjectContextGroup; 10582 PSID SubjectContextServerOwner; 10583 PSID SubjectContextServerGroup; 10584 PACL SubjectContextDacl; 10585 10586 SeCaptureSubjectContext( &SubjectContext ); 10587 10588 SepGetDefaultsSubjectContext( 10589 &SubjectContext, 10590 &SubjectContextOwner, 10591 &SubjectContextGroup, 10592 &SubjectContextServerOwner, 10593 &SubjectContextServerGroup, 10594 &SubjectContextDacl 10595 ); 10596 10597 Status = RtlpCreateServerAcl( 10598 NewDacl, 10599 DaclUntrusted, 10600 SubjectContextServerOwner, 10601 &ServerDacl, 10602 &ServerAclAllocated 10603 ); 10604 10605 SeReleaseSubjectContext( &SubjectContext ); 10606 #else // NTOS_KERNEL_RUNTIME 10607 PTOKEN_OWNER ServerSid; 10608 10609 // 10610 // Obtain the default Server SID to substitute in the 10611 // ACL if necessary. 10612 // 10613 10614 ServerOwnerInfoSize = RtlLengthRequiredSid( SID_MAX_SUB_AUTHORITIES ); 10615 10616 ServerSid = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), ServerOwnerInfoSize ); 10617 10618 if (ServerSid == NULL) { 10619 Status = STATUS_NO_MEMORY; 10620 goto Cleanup; 10621 } 10622 10623 Status = NtOpenProcessToken( 10624 NtCurrentProcess(), 10625 TOKEN_QUERY, 10626 &PrimaryToken 10627 ); 10628 10629 if (!NT_SUCCESS( Status )) { 10630 RtlFreeHeap( HeapHandle, 0, ServerSid ); 10631 goto Cleanup; 10632 } 10633 10634 Status = NtQueryInformationToken( 10635 PrimaryToken, // Handle 10636 TokenOwner, // TokenInformationClass 10637 ServerSid, // TokenInformation 10638 ServerOwnerInfoSize, // TokenInformationLength 10639 &ServerOwnerInfoSize // ReturnLength 10640 ); 10641 10642 NtClose( PrimaryToken ); 10643 10644 if (!NT_SUCCESS( Status )) { 10645 RtlFreeHeap( HeapHandle, 0, ServerSid ); 10646 goto Cleanup; 10647 } 10648 10649 Status = RtlpCreateServerAcl( 10650 NewDacl, 10651 DaclUntrusted, 10652 ServerSid->Owner, 10653 &ServerDacl, 10654 &ServerAclAllocated 10655 ); 10656 10657 RtlFreeHeap( HeapHandle, 0, ServerSid ); 10658 #endif // NTOS_KERNEL_RUNTIME 10659 10660 if (!NT_SUCCESS( Status )) { 10661 goto Cleanup; 10662 } 10663 10664 NewDacl = ServerDacl; 10665 10666 } 10667 10668 } else { 10669 10670 NewDacl = RtlpDaclAddrSecurityDescriptor( *IObjectsSecurityDescriptor ); 10671 } 10672 10673 10674 10675 if (SecurityInformation & SACL_SECURITY_INFORMATION) { 10676 10677 10678 // 10679 // If AutoInherit is requested, 10680 // build a merged ACL. 10681 // 10682 10683 if ( AutoInheritFlags & SEF_SACL_AUTO_INHERIT ) { 10684 Status = RtlpComputeMergedAcl( 10685 RtlpSaclAddrSecurityDescriptor( *IObjectsSecurityDescriptor ), 10686 SeControlSaclToGeneric( (*IObjectsSecurityDescriptor)->Control ), 10687 RtlpSaclAddrSecurityDescriptor( IModificationDescriptor ), 10688 SeControlSaclToGeneric( IModificationDescriptor->Control ), 10689 NewOwner, 10690 NewGroup, 10691 GenericMapping, 10692 TRUE, // Is a SACL 10693 &LocalSacl, 10694 &GenericControl ); 10695 10696 if ( !NT_SUCCESS(Status)) { 10697 goto Cleanup; 10698 } 10699 LocalSaclAllocated = TRUE; 10700 NewSacl = LocalSacl; 10701 NewControlBits |= SE_SACL_PRESENT; 10702 NewControlBits |= SeControlGenericToSacl( GenericControl ); 10703 } else { 10704 NewSacl = RtlpSaclAddrSecurityDescriptor( IModificationDescriptor ); 10705 NewControlBits |= SE_SACL_PRESENT; 10706 NewControlBits |= IModificationDescriptor->Control & SE_SACL_PROTECTED; 10707 10708 // 10709 // If the original caller claims he understands auto inheritance, 10710 // preserve the AutoInherited flag. 10711 // 10712 10713 if ( RtlpAreControlBitsSet(IModificationDescriptor, SE_SACL_AUTO_INHERIT_REQ|SE_SACL_AUTO_INHERITED) ) { 10714 NewControlBits |= SE_SACL_AUTO_INHERITED; 10715 } 10716 } 10717 10718 } else { 10719 10720 NewSacl = RtlpSaclAddrSecurityDescriptor( *IObjectsSecurityDescriptor ); 10721 } 10722 10723 10724 // 10725 // Everything is assignable by the requestor. 10726 // Calculate the memory needed to house all the information in 10727 // a self-relative security descriptor. 10728 // 10729 // Also map the ACEs for application to the target object 10730 // type, if they haven't already been mapped. 10731 // 10732 10733 NewOwnerSize = LongAlignSize(SeLengthSid(NewOwner)); 10734 10735 if (NewGroup != NULL) { 10736 NewGroupSize = LongAlignSize(SeLengthSid(NewGroup)); 10737 } else { 10738 NewGroupSize = 0; 10739 } 10740 10741 if (NewSacl != NULL) { 10742 NewSaclSize = LongAlignSize(NewSacl->AclSize); 10743 } else { 10744 NewSaclSize = 0; 10745 } 10746 10747 if (NewDacl !=NULL) { 10748 NewDaclSize = LongAlignSize(NewDacl->AclSize); 10749 } else { 10750 NewDaclSize = 0; 10751 } 10752 10753 AllocationSize = LongAlignSize(sizeof(SECURITY_DESCRIPTOR_RELATIVE)) + 10754 NewOwnerSize + 10755 NewGroupSize + 10756 NewSaclSize + 10757 NewDaclSize; 10758 10759 // 10760 // Allocate and initialize the security descriptor as 10761 // self-relative form. 10762 // 10763 10764 #ifdef NTOS_KERNEL_RUNTIME 10765 NewDescriptor = ExAllocatePoolWithTag(PoolType, AllocationSize, 'dSeS'); 10766 #else // NTOS_KERNEL_RUNTIME 10767 NewDescriptor = RtlAllocateHeap( HeapHandle, MAKE_TAG( SE_TAG ), AllocationSize ); 10768 #endif // NTOS_KERNEL_RUNTIME 10769 10770 if ( NewDescriptor == NULL ) { 10771 Status = STATUS_NO_MEMORY; 10772 goto Cleanup; 10773 } 10774 10775 Status = RtlCreateSecurityDescriptorRelative( 10776 NewDescriptor, 10777 SECURITY_DESCRIPTOR_REVISION 10778 ); 10779 10780 ASSERT( NT_SUCCESS( Status ) ); 10781 10782 #ifdef NTOS_KERNEL_RUNTIME 10783 // 10784 // We must check to make sure that the Group and Dacl size 10785 // do not exceed the quota preallocated for this object's 10786 // security when it was created. 10787 // 10788 // Update SeComputeSecurityQuota if this changes. 10789 // 10790 10791 10792 if (ARGUMENT_PRESENT( Object )) { 10793 10794 Status = ObValidateSecurityQuota( 10795 Object, 10796 NewGroupSize + NewDaclSize 10797 ); 10798 10799 if (!NT_SUCCESS( Status )) { 10800 10801 // 10802 // The new information is too big. 10803 // 10804 10805 ExFreePool( NewDescriptor ); 10806 goto Cleanup; 10807 } 10808 10809 } 10810 #endif // NTOS_KERNEL_RUNTIME 10811 10812 10813 Base = (PCHAR)NewDescriptor; 10814 Field = Base + sizeof(SECURITY_DESCRIPTOR_RELATIVE); 10815 10816 // 10817 // Map and Copy in the Sacl 10818 // 10819 10820 10821 // if new item { 10822 // PRESENT=TRUE 10823 // DEFAULTED=FALSE 10824 // if (NULL) { 10825 // set new pointer to NULL 10826 // } else { 10827 // copy into new SD 10828 // } 10829 // } else { 10830 // copy PRESENT bit 10831 // copy DEFAULTED bit 10832 // if (NULL) { 10833 // set new pointer to NULL 10834 // } else { 10835 // copy old one into new SD 10836 // } 10837 // } 10838 10839 RtlpSetControlBits( NewDescriptor, NewControlBits ); 10840 10841 10842 if (IModificationDescriptor->Control & SE_RM_CONTROL_VALID) { 10843 NewDescriptor->Sbz1 = IModificationDescriptor->Sbz1; 10844 NewDescriptor->Control |= SE_RM_CONTROL_VALID; 10845 } 10846 10847 if (NewSacl == NULL) { 10848 NewDescriptor->Sacl = 0; 10849 10850 } else { 10851 RtlCopyMemory( Field, NewSacl, NewSacl->AclSize ); 10852 RtlpApplyAclToObject( (PACL)Field, GenericMapping ); 10853 NewDescriptor->Sacl = RtlPointerToOffset(Base,Field); 10854 Field += NewSaclSize; 10855 } 10856 10857 10858 10859 10860 if ( (NewControlBits & SE_SACL_PRESENT) == 0 ) { 10861 10862 // 10863 // Propagate the SE_SACL_DEFAULTED and SE_SACL_PRESENT 10864 // bits from the old security descriptor into the new 10865 // one. 10866 // 10867 10868 RtlpPropagateControlBits( 10869 NewDescriptor, 10870 *IObjectsSecurityDescriptor, 10871 SE_SACL_DEFAULTED | SE_SACL_PRESENT | SE_SACL_PROTECTED 10872 ); 10873 10874 } 10875 10876 10877 10878 // 10879 // Fill in Dacl field in new SD 10880 // 10881 10882 if (NewDacl == NULL) { 10883 NewDescriptor->Dacl = 0; 10884 10885 } else { 10886 RtlCopyMemory( Field, NewDacl, NewDacl->AclSize ); 10887 RtlpApplyAclToObject( (PACL)Field, GenericMapping ); 10888 NewDescriptor->Dacl = RtlPointerToOffset(Base,Field); 10889 Field += NewDaclSize; 10890 } 10891 10892 10893 if ( (NewControlBits & SE_DACL_PRESENT) == 0 ) { 10894 10895 // 10896 // Propagate the SE_DACL_DEFAULTED and SE_DACL_PRESENT 10897 // bits from the old security descriptor into the new 10898 // one. 10899 // 10900 10901 RtlpPropagateControlBits( 10902 NewDescriptor, 10903 *IObjectsSecurityDescriptor, 10904 SE_DACL_DEFAULTED | SE_DACL_PRESENT | SE_DACL_PROTECTED 10905 ); 10906 10907 } 10908 10909 // if new item { 10910 // PRESENT=TRUE 10911 // DEFAULTED=FALSE 10912 // if (NULL) { 10913 // set new pointer to NULL 10914 // } else { 10915 // copy into new SD 10916 // } 10917 // } else { 10918 // copy PRESENT bit 10919 // copy DEFAULTED bit 10920 // if (NULL) { 10921 // set new pointer to NULL 10922 // } else { 10923 // copy old one into new SD 10924 // } 10925 // } 10926 10927 10928 // 10929 // Fill in Owner field in new SD 10930 // 10931 10932 RtlCopyMemory( Field, NewOwner, SeLengthSid(NewOwner) ); 10933 NewDescriptor->Owner = RtlPointerToOffset(Base,Field); 10934 Field += NewOwnerSize; 10935 10936 if (!NewOwnerPresent) { 10937 10938 // 10939 // Propagate the SE_OWNER_DEFAULTED bit from the old SD. 10940 // If a new owner is being assigned, we want to leave 10941 // SE_OWNER_DEFAULTED off, which means leave it alone. 10942 // 10943 10944 RtlpPropagateControlBits( 10945 NewDescriptor, 10946 *IObjectsSecurityDescriptor, 10947 SE_OWNER_DEFAULTED 10948 ); 10949 10950 } else { 10951 ASSERT( !RtlpAreControlBitsSet( NewDescriptor, SE_OWNER_DEFAULTED ) ); 10952 } 10953 10954 10955 // 10956 // Fill in Group field in new SD 10957 // 10958 10959 if ( NewGroup != NULL) { 10960 RtlCopyMemory( Field, NewGroup, SeLengthSid(NewGroup) ); 10961 NewDescriptor->Group = RtlPointerToOffset(Base,Field); 10962 } 10963 10964 if (!NewGroupPresent) { 10965 10966 // 10967 // Propagate the SE_GROUP_DEFAULTED bit from the old SD 10968 // If a new owner is being assigned, we want to leave 10969 // SE_GROUP_DEFAULTED off, which means leave it alone. 10970 // 10971 10972 RtlpPropagateControlBits( 10973 NewDescriptor, 10974 *IObjectsSecurityDescriptor, 10975 SE_GROUP_DEFAULTED 10976 ); 10977 } else { 10978 ASSERT( !RtlpAreControlBitsSet( NewDescriptor, SE_GROUP_DEFAULTED ) ); 10979 10980 } 10981 10982 // 10983 // Free old descriptor 10984 // 10985 10986 // Kernel version doesn't free the old descriptor 10987 #ifndef NTOS_KERNEL_RUNTIME 10988 RtlFreeHeap( HeapHandle, 0, (PVOID) *IObjectsSecurityDescriptor ); 10989 #endif // NTOS_KERNEL_RUNTIME 10990 10991 *ObjectsSecurityDescriptor = (PSECURITY_DESCRIPTOR)NewDescriptor; 10992 Status = STATUS_SUCCESS; 10993 10994 Cleanup: 10995 if ( LocalDaclAllocated ) { 10996 #ifdef NTOS_KERNEL_RUNTIME 10997 ExFreePool( LocalDacl ); 10998 #else // NTOS_KERNEL_RUNTIME 10999 RtlFreeHeap( HeapHandle, 0, LocalDacl ); 11000 #endif // NTOS_KERNEL_RUNTIME 11001 } 11002 if ( LocalSaclAllocated ) { 11003 #ifdef NTOS_KERNEL_RUNTIME 11004 ExFreePool( LocalSacl ); 11005 #else // NTOS_KERNEL_RUNTIME 11006 RtlFreeHeap( HeapHandle, 0, LocalSacl ); 11007 #endif // NTOS_KERNEL_RUNTIME 11008 } 11009 if (ServerAclAllocated) { 11010 #ifdef NTOS_KERNEL_RUNTIME 11011 ExFreePool( ServerDacl ); 11012 #else // NTOS_KERNEL_RUNTIME 11013 RtlFreeHeap( HeapHandle, 0, ServerDacl ); 11014 #endif // NTOS_KERNEL_RUNTIME 11015 } 11016 11017 return( Status ); 11018 }

BOOLEAN RtlpValidateSDOffsetAndSize IN ULONG  Offset,
IN ULONG  Length,
IN ULONG  MinLength,
OUT PULONG  MaxLength
 

Definition at line 11020 of file sertl.c.

References FALSE, Offset, and TRUE.

Referenced by RtlValidRelativeSecurityDescriptor().

11028 : 11029 11030 This procedure validates offsets within a SecurityDescriptor. 11031 It checks that the structure can have the minimum length, 11032 not overlap with the fixed header and returns the maximum size 11033 of the item and longword alignment. 11034 11035 Arguments: 11036 11037 Offset - Offset from start of SD of structure to validate 11038 Length - Total size of SD 11039 MinLength - Minimum size this structure can be 11040 MaxLength - Retuns the maximum length this item can be given by 11041 the enclosing structure. 11042 11043 Return Value: 11044 11045 BOOLEAN - TRUE if the item is valid 11046 11047 11048 --*/ 11049 11050 { 11051 ULONG Left; 11052 11053 *MaxLength = 0; 11054 // 11055 // Don't allow overlap with header just in case caller modifies control bits etc 11056 // 11057 if (Offset < sizeof (SECURITY_DESCRIPTOR_RELATIVE)) { 11058 return FALSE; 11059 } 11060 11061 // 11062 // Don't allow offsets beyond the end of the buffer 11063 // 11064 if (Offset >= Length) { 11065 return FALSE; 11066 } 11067 11068 // 11069 // Calculate maximim size of segment and check its limits 11070 // 11071 Left = Length - Offset; 11072 11073 if (Left < MinLength) { 11074 return FALSE; 11075 } 11076 11077 // 11078 // Reject unaligned offsets 11079 // 11080 if (Offset & (sizeof (ULONG) - 1)) { 11081 return FALSE; 11082 } 11083 *MaxLength = Left; 11084 return TRUE; 11085 }

BOOLEAN RtlpValidOwnerSubjectContext IN HANDLE  Token,
IN PSID  Owner,
IN BOOLEAN  ServerObject,
OUT PNTSTATUS  ReturnStatus
 

Definition at line 3544 of file sertl.c.

References FALSE, HeapHandle, Index, NT_SUCCESS, NtClose(), NtOpenProcessToken(), NtPrivilegeCheck(), NtQueryInformationToken(), NTSTATUS(), NULL, Owner, RTL_PAGED_CODE, RtlAllocateHeap, RtlEqualSid(), RtlFreeHeap, Status, Token, and TRUE.

Referenced by RtlpNewSecurityObject(), and RtlpSetSecurityObject().

03552 : 03553 03554 This routine checks to see whether the provided SID is one the subject 03555 is authorized to assign as the owner of objects. 03556 03557 Arguments: 03558 03559 Token - Points to the subject's effective token 03560 03561 Owner - Points to the SID to be checked. 03562 03563 ServerObject - Boolean indicating whether or not this is a server 03564 object, meaning it is protected by a primary-client combination. 03565 03566 ReturnStatus - Status to be passed back to the caller on failure. 03567 03568 Return Value: 03569 03570 FALSE on failure. 03571 03572 --*/ 03573 03574 { 03575 NTSTATUS Status; 03576 03577 ULONG Index; 03578 BOOLEAN Found; 03579 ULONG ReturnLength; 03580 PTOKEN_GROUPS GroupIds = NULL; 03581 PTOKEN_USER UserId = NULL; 03582 PVOID HeapHandle; 03583 HANDLE TokenToUse; 03584 03585 BOOLEAN HasPrivilege; 03586 PRIVILEGE_SET PrivilegeSet; 03587 03588 RTL_PAGED_CODE(); 03589 03590 // 03591 // Get the handle to the current process heap 03592 // 03593 03594 if ( Owner == NULL ) { 03595 *ReturnStatus = STATUS_INVALID_OWNER; 03596 return(FALSE); 03597 } 03598 03599 // 03600 // If it's not a server object, check the owner against the contents of the 03601 // client token. If it is a server object, the owner must be valid in the 03602 // primary token. 03603 // 03604 03605 if (!ServerObject) { 03606 03607 TokenToUse = Token; 03608 03609 } else { 03610 03611 *ReturnStatus = NtOpenProcessToken( 03612 NtCurrentProcess(), 03613 TOKEN_QUERY, 03614 &TokenToUse 03615 ); 03616 03617 if (!NT_SUCCESS( *ReturnStatus )) { 03618 return( FALSE ); 03619 } 03620 } 03621 03622 HeapHandle = RtlProcessHeap(); 03623 03624 // 03625 // Get the User from the Token 03626 // 03627 03628 *ReturnStatus = NtQueryInformationToken( 03629 TokenToUse, 03630 TokenUser, 03631 UserId, 03632 0, 03633 &ReturnLength 03634 ); 03635 03636 if (!NT_SUCCESS( *ReturnStatus ) && (STATUS_BUFFER_TOO_SMALL != *ReturnStatus)) { 03637 if (ServerObject) { 03638 NtClose( TokenToUse ); 03639 } 03640 return( FALSE ); 03641 03642 } 03643 03644 UserId = RtlAllocateHeap( HeapHandle, 0, ReturnLength ); 03645 03646 if (UserId == NULL) { 03647 03648 *ReturnStatus = STATUS_NO_MEMORY; 03649 if (ServerObject) { 03650 NtClose( TokenToUse ); 03651 } 03652 03653 return( FALSE ); 03654 } 03655 03656 *ReturnStatus = NtQueryInformationToken( 03657 TokenToUse, 03658 TokenUser, 03659 UserId, 03660 ReturnLength, 03661 &ReturnLength 03662 ); 03663 03664 if (!NT_SUCCESS( *ReturnStatus )) { 03665 RtlFreeHeap( HeapHandle, 0, (PVOID)UserId ); 03666 if (ServerObject) { 03667 NtClose( TokenToUse ); 03668 } 03669 return( FALSE ); 03670 } 03671 03672 if ( RtlEqualSid( Owner, UserId->User.Sid ) ) { 03673 03674 RtlFreeHeap( HeapHandle, 0, (PVOID)UserId ); 03675 if (ServerObject) { 03676 NtClose( TokenToUse ); 03677 } 03678 return( TRUE ); 03679 } 03680 03681 RtlFreeHeap( HeapHandle, 0, (PVOID)UserId ); 03682 03683 // 03684 // Get the groups from the Token 03685 // 03686 03687 *ReturnStatus = NtQueryInformationToken( 03688 TokenToUse, 03689 TokenGroups, 03690 GroupIds, 03691 0, 03692 &ReturnLength 03693 ); 03694 03695 if (!NT_SUCCESS( *ReturnStatus ) && (STATUS_BUFFER_TOO_SMALL != *ReturnStatus)) { 03696 03697 if (ServerObject) { 03698 NtClose( TokenToUse ); 03699 } 03700 return( FALSE ); 03701 } 03702 03703 GroupIds = RtlAllocateHeap( HeapHandle, 0, ReturnLength ); 03704 03705 if (GroupIds == NULL) { 03706 03707 *ReturnStatus = STATUS_NO_MEMORY; 03708 if (ServerObject) { 03709 NtClose( TokenToUse ); 03710 } 03711 return( FALSE ); 03712 } 03713 03714 *ReturnStatus = NtQueryInformationToken( 03715 TokenToUse, 03716 TokenGroups, 03717 GroupIds, 03718 ReturnLength, 03719 &ReturnLength 03720 ); 03721 03722 if (ServerObject) { 03723 NtClose( TokenToUse ); 03724 } 03725 03726 if (!NT_SUCCESS( *ReturnStatus )) { 03727 RtlFreeHeap( HeapHandle, 0, GroupIds ); 03728 return( FALSE ); 03729 } 03730 03731 // 03732 // Walk through the list of group IDs looking for a match to 03733 // the specified SID. If one is found, make sure it may be 03734 // assigned as an owner. 03735 // 03736 // This code is similar to that performed to set the default 03737 // owner of a token (NtSetInformationToken). 03738 // 03739 03740 Index = 0; 03741 while (Index < GroupIds->GroupCount) { 03742 03743 Found = RtlEqualSid( 03744 Owner, 03745 GroupIds->Groups[Index].Sid 03746 ); 03747 03748 if ( Found ) { 03749 03750 if ( RtlpIdAssignableAsOwner(GroupIds->Groups[Index])) { 03751 03752 RtlFreeHeap( HeapHandle, 0, GroupIds ); 03753 return TRUE; 03754 03755 } else { 03756 03757 break; 03758 03759 } //endif assignable 03760 03761 } //endif Found 03762 03763 Index++; 03764 03765 } //endwhile 03766 03767 RtlFreeHeap( HeapHandle, 0, GroupIds ); 03768 03769 // 03770 // If we are going to fail this call, check for Restore privilege, 03771 // and succeed if he has it. 03772 // 03773 03774 // 03775 // Check for appropriate Privileges 03776 // 03777 // Audit/Alarm messages need to be generated due to the attempt 03778 // to perform a privileged operation. 03779 // 03780 03781 PrivilegeSet.PrivilegeCount = 1; 03782 PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY; 03783 PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid(SE_RESTORE_PRIVILEGE); 03784 PrivilegeSet.Privilege[0].Attributes = 0; 03785 03786 Status = NtPrivilegeCheck( 03787 Token, 03788 &PrivilegeSet, 03789 &HasPrivilege 03790 ); 03791 03792 if (!NT_SUCCESS( Status )) { 03793 HasPrivilege = FALSE; 03794 } 03795 03796 if ( HasPrivilege ) { 03797 return TRUE; 03798 } else { 03799 *ReturnStatus = STATUS_INVALID_OWNER; 03800 return FALSE; 03801 } 03802 } #endif // NTOS_KERNEL_RUNTIME

VOID RtlRunDecodeUnicodeString UCHAR  Seed,
PUNICODE_STRING  String
 

Definition at line 520 of file sertl.c.

References RTL_PAGED_CODE, Seed, and String.

Referenced by ECLock().

00526 : 00527 00528 This function performs the inverse of the function performed 00529 by RtlRunEncodeUnicodeString(). Please see RtlRunEncodeUnicodeString() 00530 for details. 00531 00532 00533 Arguments: 00534 00535 Seed - The seed value to use in RtlRunEncodeUnicodeString(). 00536 00537 String - The string to reveal. 00538 00539 00540 Return Value: 00541 00542 None - Nothing can really go wrong unless the caller passes bogus 00543 parameters. In this case, the caller can catch the access 00544 violation. 00545 00546 00547 --*/ 00548 00549 { 00550 00551 ULONG 00552 i; 00553 00554 PSTRING 00555 S; 00556 00557 RTL_PAGED_CODE(); 00558 00559 // 00560 // Typecast so we can work on bytes rather than WCHARs 00561 // 00562 00563 S = (PSTRING)((PVOID)String); 00564 00565 00566 // 00567 // Transform the end of the string 00568 // 00569 00570 for (i=S->Length; i>1; i--) { 00571 00572 // 00573 // a simple running XOR with the previous byte and the 00574 // seed value. 00575 // 00576 00577 S->Buffer[i-1] ^= (S->Buffer[i-2]^Seed); 00578 00579 } 00580 00581 // 00582 // Finally, transform the initial byte 00583 // 00584 00585 if (S->Length >= 1) { 00586 S->Buffer[0] ^= (Seed | 0X43); 00587 } 00588 00589 00590 return; 00591 }

VOID RtlRunEncodeUnicodeString PUCHAR Seed  OPTIONAL,
PUNICODE_STRING  String
 

Definition at line 388 of file sertl.c.

References ASSERT, NT_SUCCESS, NTSTATUS(), RTL_PAGED_CODE, Status, String, and Time.

Referenced by ECUnlock().

00395 : 00396 00397 This function performs a trivial XOR run-encoding of a string. 00398 The purpose of this run-encoding is to change the character values 00399 to appear somewhat random and typically not printable. This is 00400 useful for transforming passwords that you don't want to be easily 00401 distinguishable by visually scanning a paging file or memory dump. 00402 00403 00404 Arguments: 00405 00406 Seed - Points to a seed value to use in the encoding. If the 00407 pointed to value is zero, then this routine will assign 00408 a value. 00409 00410 String - The string to encode. This string may be decode 00411 by passing it and the seed value to RtlRunDecodeUnicodeString(). 00412 00413 00414 Return Value: 00415 00416 None - Nothing can really go wrong unless the caller passes bogus 00417 parameters. In this case, the caller can catch the access 00418 violation. 00419 00420 00421 --*/ 00422 { 00423 00424 LARGE_INTEGER Time; 00425 PUCHAR LocalSeed; 00426 NTSTATUS Status; 00427 ULONG i; 00428 PSTRING S; 00429 00430 00431 RTL_PAGED_CODE(); 00432 00433 // 00434 // Typecast so we can work on bytes rather than WCHARs 00435 // 00436 00437 S = (PSTRING)((PVOID)String); 00438 00439 // 00440 // If a seed wasn't passed, use the 2nd byte of current time. 00441 // This byte seems to be sufficiently random (by observation). 00442 // 00443 00444 if ((*Seed) == 0) { 00445 Status = NtQuerySystemTime ( &Time ); 00446 ASSERT(NT_SUCCESS(Status)); 00447 00448 LocalSeed = (PUCHAR)((PVOID)&Time); 00449 00450 i = 1; 00451 00452 (*Seed) = LocalSeed[ i ]; 00453 00454 // 00455 // Occasionally, this byte could be zero. That would cause the 00456 // string to become un-decodable, since 0 is the magic value that 00457 // causes us to re-gen the seed. This loop makes sure that we 00458 // never end up with a zero byte (unless time is zero, as well). 00459 // 00460 00461 while ( ((*Seed) == 0) && ( i < sizeof( Time ) ) ) 00462 { 00463 (*Seed) |= LocalSeed[ i++ ] ; 00464 } 00465 00466 if ( (*Seed) == 0 ) 00467 { 00468 (*Seed) = 1; 00469 } 00470 } 00471 00472 // 00473 // Transform the initial byte. 00474 // The funny constant just keeps the first byte from propagating 00475 // into the second byte in the next step. Without a funny constant 00476 // this would happen for many languages (which typically have every 00477 // other byte zero. 00478 // 00479 // 00480 00481 if (S->Length >= 1) { 00482 S->Buffer[0] ^= ((*Seed) | 0X43); 00483 } 00484 00485 00486 // 00487 // Now transform the rest of the string 00488 // 00489 00490 for (i=1; i<S->Length; i++) { 00491 00492 // 00493 // There are export issues that cause us to want to 00494 // keep this algorithm simple. Please don't change it 00495 // without checking with JimK first. Thanks. 00496 // 00497 00498 // 00499 // In order to be compatible with zero terminated unicode strings, 00500 // this algorithm is designed to not produce a wide character of 00501 // zero as long a the seed is not zero. 00502 // 00503 00504 // 00505 // Simple running XOR with the previous byte and the 00506 // seed value. 00507 // 00508 00509 S->Buffer[i] ^= (S->Buffer[i-1]^(*Seed)); 00510 00511 } 00512 00513 00514 return; 00515 00516 }

NTSTATUS RtlSetAttributesSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL  Control,
OUT PULONG  Revision
 

Definition at line 2386 of file sertl.c.

References RTL_PAGED_CODE, RtlSetControlSecurityDescriptor(), and SE_VALID_CONTROL_BITS.

02391 { 02392 RTL_PAGED_CODE(); 02393 02394 // 02395 // Always return the revision value - even if this isn't a valid 02396 // security descriptor 02397 // 02398 02399 *Revision = ((SECURITY_DESCRIPTOR *)SecurityDescriptor)->Revision; 02400 02401 if ( ((SECURITY_DESCRIPTOR *)SecurityDescriptor)->Revision 02402 != SECURITY_DESCRIPTOR_REVISION ) { 02403 return STATUS_UNKNOWN_REVISION; 02404 } 02405 02406 // BUGBUG: This is a worthless API. There is no way to turn any of the bits off. 02407 // Use the newer RtlSetControlSecurityDescriptor. 02408 Control &= SE_VALID_CONTROL_BITS; 02409 return RtlSetControlSecurityDescriptor ( SecurityDescriptor, Control, Control ); 02410 }

NTSTATUS RtlSetControlSecurityDescriptor IN PSECURITY_DESCRIPTOR  pSecurityDescriptor,
IN SECURITY_DESCRIPTOR_CONTROL  ControlBitsOfInterest,
IN SECURITY_DESCRIPTOR_CONTROL  ControlBitsToSet
 

Definition at line 2472 of file sertl.c.

References SE_VALID_CONTROL_BITS.

Referenced by RtlSetAttributesSecurityDescriptor().

02479 : 02480 02481 This procedure sets the control information in a security descriptor. 02482 02483 02484 For instance, 02485 02486 SetSecurityDescriptorControl( &SecDesc, 02487 SE_DACL_PROTECTED, 02488 SE_DACL_PROTECTED ); 02489 02490 marks the DACL on the security descriptor as protected. And 02491 02492 SetSecurityDescriptorControl( &SecDesc, 02493 SE_DACL_PROTECTED, 02494 0 ); 02495 02496 02497 marks the DACL as not protected. 02498 02499 Arguments: 02500 02501 pSecurityDescriptor - Supplies the security descriptor. 02502 02503 ControlBitsOfInterest - A mask of the control bits being changed, set, 02504 or reset by this call. The mask is the logical OR of one or more of 02505 the following flags: 02506 02507 SE_DACL_UNTRUSTED 02508 SE_SERVER_SECURITY 02509 SE_DACL_AUTO_INHERIT_REQ 02510 SE_SACL_AUTO_INHERIT_REQ 02511 SE_DACL_AUTO_INHERITED 02512 SE_SACL_AUTO_INHERITED 02513 SE_DACL_PROTECTED 02514 SE_SACL_PROTECTED 02515 02516 ControlBitsToSet - A mask indicating what the bits specified by ControlBitsOfInterest 02517 should be set to. 02518 02519 Return Value: 02520 02521 Returns TRUE for success, FALSE for failure. Extended error status 02522 is available using GetLastError. 02523 02524 --*/ 02525 { 02526 // 02527 // Ensure the caller passed valid bits. 02528 // 02529 02530 if ( (ControlBitsOfInterest & ~SE_VALID_CONTROL_BITS) != 0 || 02531 (ControlBitsToSet & ~ControlBitsOfInterest) != 0 ) { 02532 return STATUS_INVALID_PARAMETER; 02533 } 02534 02535 ((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control &= ~ControlBitsOfInterest; 02536 ((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control |= ControlBitsToSet; 02537 02538 return STATUS_SUCCESS; 02539 }

NTSTATUS RtlSetDaclSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN BOOLEAN  DaclPresent,
IN PACL Dacl  OPTIONAL,
IN BOOLEAN DaclDefaulted  OPTIONAL
 

Definition at line 2543 of file sertl.c.

References Dacl, NULL, RTL_PAGED_CODE, and TRUE.

Referenced by CmpHiveRootSecurityDescriptor(), CreateBSMEventSD(), CreateDAclToken(), CreateSecurityDescriptor(), GenerateDescriptor(), InternalCreateCallbackThread(), IoCreateUnprotectedSymbolicLink(), IopApplySystemPartitionProt(), IopCreateDefaultDeviceSecurityDescriptor(), IopInitializePlugPlayServices(), IopOpenDeviceParametersSubkey(), NtOpenThreadToken(), ObInitSystem(), ObpGetDosDevicesProtection(), RtlCreateAndSetSD(), SeMakeAnonymousLogonToken(), SeMakeSystemToken(), SepInitializationPhase1(), SepInitSystemDacls(), SmbTraceStart(), TestSeNamedCreate(), TestSeSecurityDescriptor(), and TestTokenInitialize().

02552 : 02553 02554 This procedure sets the discretionary ACL information of an absolute 02555 format security descriptor. If there is already a discretionary ACL 02556 present in the security descriptor, it is superseded. 02557 02558 Arguments: 02559 02560 SecurityDescriptor - Supplies the security descriptor to be which 02561 the discretionary ACL is to be added. 02562 02563 DaclPresent - If FALSE, indicates the DaclPresent flag in the 02564 security descriptor should be set to FALSE. In this case, 02565 the remaining optional parameters are ignored. Otherwise, 02566 the DaclPresent control flag in the security descriptor is 02567 set to TRUE and the remaining optional parameters are not 02568 ignored. 02569 02570 Dacl - Supplies the discretionary ACL for the security 02571 descriptor. If this optional parameter is not passed, then a 02572 null ACL is assigned to the security descriptor. A null 02573 discretionary ACL unconditionally grants access. The ACL is 02574 referenced by, not copied into, by the security descriptor. 02575 02576 DaclDefaulted - When set, indicates the discretionary ACL was 02577 picked up from some default mechanism (rather than explicitly 02578 specified by a user). This value is set in the DaclDefaulted 02579 control flag in the security descriptor. If this optional 02580 parameter is not passed, then the DaclDefaulted flag will be 02581 cleared. 02582 02583 Return Value: 02584 02585 STATUS_SUCCESS - Indicates the call completed successfully. 02586 02587 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 02588 descriptor is not known to the routine. It may be a newer 02589 revision than the routine knows about. 02590 02591 STATUS_INVALID_SECURITY_DESCR - Indicates the security descriptor 02592 is not an absolute format security descriptor. 02593 02594 02595 --*/ 02596 02597 { 02598 02599 // 02600 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02601 // 02602 02603 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 02604 02605 RTL_PAGED_CODE(); 02606 02607 // 02608 // Check the revision 02609 // 02610 02611 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 02612 return STATUS_UNKNOWN_REVISION; 02613 } 02614 02615 // 02616 // Make sure the descriptor is absolute format 02617 // 02618 02619 if (ISecurityDescriptor->Control & SE_SELF_RELATIVE) { 02620 return STATUS_INVALID_SECURITY_DESCR; 02621 } 02622 02623 // 02624 // Assign the DaclPresent flag value passed 02625 // 02626 02627 02628 if (DaclPresent) { 02629 02630 ISecurityDescriptor->Control |= SE_DACL_PRESENT; 02631 02632 // 02633 // Assign the ACL address if passed, otherwise set to null. 02634 // 02635 02636 ISecurityDescriptor->Dacl = NULL; 02637 if (ARGUMENT_PRESENT(Dacl)) { 02638 ISecurityDescriptor->Dacl = Dacl; 02639 } 02640 02641 02642 02643 02644 // 02645 // Assign DaclDefaulted flag if passed, otherwise clear it. 02646 // 02647 02648 ISecurityDescriptor->Control &= ~SE_DACL_DEFAULTED; 02649 if (DaclDefaulted == TRUE) { 02650 ISecurityDescriptor->Control |= SE_DACL_DEFAULTED; 02651 } 02652 } else { 02653 02654 ISecurityDescriptor->Control &= ~SE_DACL_PRESENT; 02655 02656 } 02657 02658 02659 return STATUS_SUCCESS; 02660 02661 }

NTSTATUS RtlSetGroupSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID Group  OPTIONAL,
IN BOOLEAN GroupDefaulted  OPTIONAL
 

Definition at line 3135 of file sertl.c.

References Group, NULL, and RTL_PAGED_CODE.

Referenced by CreateDAclToken(), CreateSecurityDescriptor(), RtlCreateAndSetSD(), SeMakeAnonymousLogonToken(), SeMakeSystemToken(), and TestSeSecurityDescriptor().

03143 : 03144 03145 This procedure sets the primary group information of an absolute security 03146 descriptor. If there is already an primary group present in the 03147 security descriptor, it is superseded. 03148 03149 Arguments: 03150 03151 SecurityDescriptor - Supplies the security descriptor in which 03152 the primary group is to be set. If the security descriptor 03153 already includes a primary group, it will be superseded by 03154 the new group. 03155 03156 Group - Supplies the primary group SID for the security 03157 descriptor. If this optional parameter is not passed, then 03158 the primary group is cleared (indicating the security 03159 descriptor has no primary group). The SID is referenced by, 03160 not copied into, the security descriptor. 03161 03162 GroupDefaulted - When set, indicates the owner was picked up from 03163 some default mechanism (rather than explicitly specified by a 03164 user). This value is set in the OwnerDefaulted control flag 03165 in the security descriptor. If this optional parameter is 03166 not passed, then the SaclDefaulted flag will be cleared. 03167 03168 Return Value: 03169 03170 STATUS_SUCCESS - Indicates the call completed successfully. 03171 03172 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 03173 descriptor is not known to the routine. It may be a newer 03174 revision than the routine knows about. 03175 03176 STATUS_INVALID_SECURITY_DESCR - Indicates the security descriptor 03177 is not an absolute format security descriptor. 03178 03179 03180 --*/ 03181 03182 { 03183 03184 // 03185 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 03186 // 03187 03188 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 03189 03190 RTL_PAGED_CODE(); 03191 03192 // 03193 // Check the revision 03194 // 03195 03196 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 03197 return STATUS_UNKNOWN_REVISION; 03198 } 03199 03200 // 03201 // Make sure the descriptor is absolute format 03202 // 03203 03204 if (ISecurityDescriptor->Control & SE_SELF_RELATIVE) { 03205 return STATUS_INVALID_SECURITY_DESCR; 03206 } 03207 03208 // 03209 // Assign the Group field if passed, otherwise clear it. 03210 // 03211 03212 ISecurityDescriptor->Group = NULL; 03213 if (ARGUMENT_PRESENT(Group)) { 03214 ISecurityDescriptor->Group = Group; 03215 } 03216 03217 // 03218 // Assign the GroupDefaulted flag if passed, otherwise clear it. 03219 // 03220 03221 ISecurityDescriptor->Control &= ~SE_GROUP_DEFAULTED; 03222 if (ARGUMENT_PRESENT(GroupDefaulted)) { 03223 ISecurityDescriptor->Control |= SE_GROUP_DEFAULTED; 03224 } 03225 03226 return STATUS_SUCCESS; 03227 03228 }

NTSTATUS RtlSetOwnerSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PSID Owner  OPTIONAL,
IN BOOLEAN OwnerDefaulted  OPTIONAL
 

Definition at line 2963 of file sertl.c.

References NULL, Owner, RTL_PAGED_CODE, and TRUE.

Referenced by CreateDAclToken(), CreateSecurityDescriptor(), RtlCreateAndSetSD(), SeMakeAnonymousLogonToken(), SeMakeSystemToken(), and TestSeSecurityDescriptor().

02971 : 02972 02973 This procedure sets the owner information of an absolute security 02974 descriptor. If there is already an owner present in the security 02975 descriptor, it is superseded. 02976 02977 Arguments: 02978 02979 SecurityDescriptor - Supplies the security descriptor in which 02980 the owner is to be set. If the security descriptor already 02981 includes an owner, it will be superseded by the new owner. 02982 02983 Owner - Supplies the owner SID for the security descriptor. If 02984 this optional parameter is not passed, then the owner is 02985 cleared (indicating the security descriptor has no owner). 02986 The SID is referenced by, not copied into, the security 02987 descriptor. 02988 02989 OwnerDefaulted - When set, indicates the owner was picked up from 02990 some default mechanism (rather than explicitly specified by a 02991 user). This value is set in the OwnerDefaulted control flag 02992 in the security descriptor. If this optional parameter is 02993 not passed, then the SaclDefaulted flag will be cleared. 02994 02995 Return Value: 02996 02997 STATUS_SUCCESS - Indicates the call completed successfully. 02998 02999 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 03000 descriptor is not known to the routine. It may be a newer 03001 revision than the routine knows about. 03002 03003 STATUS_INVALID_SECURITY_DESCR - Indicates the security descriptor 03004 is not an absolute format security descriptor. 03005 03006 03007 --*/ 03008 03009 { 03010 03011 // 03012 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 03013 // 03014 03015 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 03016 03017 RTL_PAGED_CODE(); 03018 03019 // 03020 // Check the revision 03021 // 03022 03023 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 03024 return STATUS_UNKNOWN_REVISION; 03025 } 03026 03027 // 03028 // Make sure the descriptor is absolute format 03029 // 03030 03031 if (ISecurityDescriptor->Control & SE_SELF_RELATIVE) { 03032 return STATUS_INVALID_SECURITY_DESCR; 03033 } 03034 03035 // 03036 // Assign the Owner field if passed, otherwise clear it. 03037 // 03038 03039 ISecurityDescriptor->Owner = NULL; 03040 if (ARGUMENT_PRESENT(Owner)) { 03041 ISecurityDescriptor->Owner = Owner; 03042 } 03043 03044 // 03045 // Assign the OwnerDefaulted flag if passed, otherwise clear it. 03046 // 03047 03048 ISecurityDescriptor->Control &= ~SE_OWNER_DEFAULTED; 03049 if (OwnerDefaulted == TRUE) { 03050 ISecurityDescriptor->Control |= SE_OWNER_DEFAULTED; 03051 } 03052 03053 return STATUS_SUCCESS; 03054 03055 }

NTSTATUS RtlSetSaclSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN BOOLEAN  SaclPresent,
IN PACL Sacl  OPTIONAL,
IN BOOLEAN SaclDefaulted  OPTIONAL
 

Definition at line 2756 of file sertl.c.

References NULL, and RTL_PAGED_CODE.

Referenced by CreateDAclToken(), CreateSecurityDescriptor(), ObInitSystem(), RtlCreateAndSetSD(), and TestSeSecurityDescriptor().

02765 : 02766 02767 This procedure sets the system ACL information of an absolute security 02768 descriptor. If there is already a system ACL present in the 02769 security descriptor, it is superseded. 02770 02771 Arguments: 02772 02773 SecurityDescriptor - Supplies the security descriptor to be which 02774 the system ACL is to be added. 02775 02776 SaclPresent - If FALSE, indicates the SaclPresent flag in the 02777 security descriptor should be set to FALSE. In this case, 02778 the remaining optional parameters are ignored. Otherwise, 02779 the SaclPresent control flag in the security descriptor is 02780 set to TRUE and the remaining optional parameters are not 02781 ignored. 02782 02783 Sacl - Supplies the system ACL for the security descriptor. If 02784 this optional parameter is not passed, then a null ACL is 02785 assigned to the security descriptor. The ACL is referenced 02786 by, not copied into, by the security descriptor. 02787 02788 SaclDefaulted - When set, indicates the system ACL was picked up 02789 from some default mechanism (rather than explicitly specified 02790 by a user). This value is set in the SaclDefaulted control 02791 flag in the security descriptor. If this optional parameter 02792 is not passed, then the SaclDefaulted flag will be cleared. 02793 02794 Return Value: 02795 02796 STATUS_SUCCESS - Indicates the call completed successfully. 02797 02798 STATUS_UNKNOWN_REVISION - Indicates the revision of the security 02799 descriptor is not known to the routine. It may be a newer 02800 revision than the routine knows about. 02801 02802 STATUS_INVALID_SECURITY_DESCR - Indicates the security descriptor 02803 is not an absolute format security descriptor. 02804 02805 02806 --*/ 02807 02808 { 02809 02810 // 02811 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02812 // 02813 02814 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 02815 02816 RTL_PAGED_CODE(); 02817 02818 // 02819 // Check the revision 02820 // 02821 02822 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 02823 return STATUS_UNKNOWN_REVISION; 02824 } 02825 02826 // 02827 // Make sure the descriptor is absolute format 02828 // 02829 02830 if (ISecurityDescriptor->Control & SE_SELF_RELATIVE) { 02831 return STATUS_INVALID_SECURITY_DESCR; 02832 } 02833 02834 // 02835 // Assign the SaclPresent flag value passed 02836 // 02837 02838 02839 if (SaclPresent) { 02840 02841 ISecurityDescriptor->Control |= SE_SACL_PRESENT; 02842 02843 // 02844 // Assign the ACL address if passed, otherwise set to null. 02845 // 02846 02847 ISecurityDescriptor->Sacl = NULL; 02848 if (ARGUMENT_PRESENT(Sacl)) { 02849 ISecurityDescriptor->Sacl = Sacl; 02850 } 02851 02852 // 02853 // Assign SaclDefaulted flag if passed, otherwise clear it. 02854 // 02855 02856 ISecurityDescriptor->Control &= ~ SE_SACL_DEFAULTED; 02857 if (ARGUMENT_PRESENT(SaclDefaulted)) { 02858 ISecurityDescriptor->Control |= SE_SACL_DEFAULTED; 02859 } 02860 } else { 02861 02862 ISecurityDescriptor->Control &= ~SE_SACL_PRESENT; 02863 } 02864 02865 return STATUS_SUCCESS; 02866 02867 }

VOID RtlSetSecurityDescriptorRMControl IN OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN PUCHAR RMControl  OPTIONAL
 

Definition at line 11370 of file sertl.c.

11377 : 11378 11379 This procedure sets the RM Control flag in the control field of 11380 SecurityDescriptor and sets Sbz1 to the the byte to which RMContol points. 11381 If RMControl is NULL then the bits are cleared. 11382 11383 Arguments: 11384 11385 SecurityDescriptor - Pointer to the SECURITY_DESCRIPTOR structure 11386 RMControl - Pointer to the flags to set. If NULL then the bits 11387 are cleared. 11388 11389 Note: 11390 Parameter validation has already been done in Advapi. 11391 11392 11393 --*/ 11394 11395 { 11396 PISECURITY_DESCRIPTOR ISecurityDescriptor = (PISECURITY_DESCRIPTOR) SecurityDescriptor; 11397 11398 if (ARGUMENT_PRESENT(RMControl)) { 11399 ISecurityDescriptor->Control |= SE_RM_CONTROL_VALID; 11400 ISecurityDescriptor->Sbz1 = *RMControl; 11401 } else { 11402 ISecurityDescriptor->Control &= ~SE_RM_CONTROL_VALID; 11403 ISecurityDescriptor->Sbz1 = 0; 11404 } 11405 } }

PUCHAR RtlSubAuthorityCountSid IN PSID  Sid  ) 
 

Definition at line 1316 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by DisplayAccountSid(), GetMangledSiteSid(), RtlEqualSid(), TestSeAclRtl(), and TSeVariableInitialization().

01321 : 01322 01323 This function returns the address of the sub-authority count field of 01324 an SID. 01325 01326 Arguments: 01327 01328 Sid - Pointer to the SID data structure. 01329 01330 Return Value: 01331 01332 01333 --*/ 01334 { 01335 PISID ISid; 01336 01337 RTL_PAGED_CODE(); 01338 01339 // 01340 // Typecast to the opaque SID 01341 // 01342 01343 ISid = (PISID)Sid; 01344 01345 return &(ISid->SubAuthorityCount); 01346 01347 }

PULONG RtlSubAuthoritySid IN PSID  Sid,
IN ULONG  SubAuthority
 

Definition at line 1286 of file sertl.c.

References RTL_PAGED_CODE.

Referenced by CmpHiveRootSecurityDescriptor(), DisplayAccountSid(), GenerateDescriptor(), GetMangledSiteSid(), InitVars(), RtlDefaultNpAcl(), SepVariableInitialization(), TestSeAclRtl(), and TSeVariableInitialization().

01292 : 01293 01294 This function returns the address of a sub-authority array element of 01295 an SID. 01296 01297 Arguments: 01298 01299 Sid - Pointer to the SID data structure. 01300 01301 SubAuthority - An index indicating which sub-authority is being specified. 01302 This value is not compared against the number of sub-authorities in the 01303 SID for validity. 01304 01305 Return Value: 01306 01307 01308 --*/ 01309 { 01310 RTL_PAGED_CODE(); 01311 01312 return RtlpSubAuthoritySid( Sid, SubAuthority ); 01313 }

BOOLEAN RtlValidRelativeSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptorInput,
IN ULONG  SecurityDescriptorLength,
IN SECURITY_INFORMATION  RequiredInformation
 

Definition at line 11089 of file sertl.c.

References Dacl, FALSE, RtlpValidateSDOffsetAndSize(), RtlValidAcl(), SeLengthSid, and TRUE.

11097 : 11098 11099 This procedure validates a SecurityDescriptor's structure 11100 contained within a flat buffer. This involves validating 11101 the revision levels of each component of the security 11102 descriptor. 11103 11104 Arguments: 11105 11106 SecurityDescriptor - Pointer to the SECURITY_DESCRIPTOR structure 11107 to validate. 11108 SecurityDescriptorLength - Size of flat buffer containing the security 11109 descriptor. 11110 RequiredInformation - Which SD components must be present to be valid. 11111 OWNER_SECURITY_INFORMATION etc as a bit mask. 11112 OWNER_SECURITY_INFORMATION - There must be a valid owner SID 11113 GROUP_SECURITY_INFORMATION - There must be a valid group SID 11114 DACL_SECURITY_INFORMATION - Ignored 11115 SACL_SECURITY_INFORMATION - Ignored 11116 11117 Return Value: 11118 11119 BOOLEAN - TRUE if the structure of SecurityDescriptor is valid. 11120 11121 11122 --*/ 11123 11124 { 11125 PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor; 11126 PISID OwnerSid; 11127 PISID GroupSid; 11128 PACE_HEADER Ace; 11129 PACL Dacl; 11130 PACL Sacl; 11131 ULONG MaxOwnerSidLength; 11132 ULONG MaxGroupSidLength; 11133 ULONG MaxDaclLength; 11134 ULONG MaxSaclLength; 11135 11136 if (SecurityDescriptorLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) { 11137 return FALSE; 11138 } 11139 11140 // 11141 // Check the revision information. 11142 // 11143 11144 if (((PISECURITY_DESCRIPTOR) SecurityDescriptorInput)->Revision != 11145 SECURITY_DESCRIPTOR_REVISION) { 11146 return FALSE; 11147 } 11148 11149 // 11150 // Make sure the passed SecurityDescriptor is in self-relative form 11151 // 11152 11153 if (!(((PISECURITY_DESCRIPTOR) SecurityDescriptorInput)->Control & SE_SELF_RELATIVE)) { 11154 return FALSE; 11155 } 11156 11157 SecurityDescriptor = (PISECURITY_DESCRIPTOR_RELATIVE) SecurityDescriptorInput; 11158 11159 // 11160 // Validate the owner if it's there and see if its allowed to be missing 11161 // 11162 if (SecurityDescriptor->Owner == 0) { 11163 if (RequiredInformation & OWNER_SECURITY_INFORMATION) { 11164 return FALSE; 11165 } 11166 } else { 11167 if (!RtlpValidateSDOffsetAndSize (SecurityDescriptor->Owner, 11168 SecurityDescriptorLength, 11169 sizeof (SID), 11170 &MaxOwnerSidLength)) { 11171 return FALSE; 11172 } 11173 // 11174 // It is safe to reference the owner's SubAuthorityCount, compute the 11175 // expected length of the SID 11176 // 11177 11178 OwnerSid = (PSID)RtlOffsetToPointer (SecurityDescriptor, 11179 SecurityDescriptor->Owner); 11180 11181 if (OwnerSid->Revision != SID_REVISION) { 11182 return FALSE; 11183 } 11184 11185 if (OwnerSid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { 11186 return FALSE; 11187 } 11188 11189 if (MaxOwnerSidLength < (ULONG) SeLengthSid (OwnerSid)) { 11190 return FALSE; 11191 } 11192 11193 } 11194 11195 // 11196 // The owner appears to be a structurally valid SID that lies within 11197 // the bounds of the security descriptor. Do the same for the Group 11198 // if there is one. 11199 // 11200 // 11201 // Validate the group if it's there and see if its allowed to be missing 11202 // 11203 if (SecurityDescriptor->Group == 0) { 11204 if (RequiredInformation & GROUP_SECURITY_INFORMATION) { 11205 return FALSE; 11206 } 11207 } else { 11208 if (!RtlpValidateSDOffsetAndSize (SecurityDescriptor->Group, 11209 SecurityDescriptorLength, 11210 sizeof (SID), 11211 &MaxGroupSidLength)) { 11212 return FALSE; 11213 } 11214 // 11215 // It is safe to reference the group's SubAuthorityCount, compute the 11216 // expected length of the SID 11217 // 11218 11219 GroupSid = (PSID)RtlOffsetToPointer (SecurityDescriptor, 11220 SecurityDescriptor->Group); 11221 11222 if (GroupSid->Revision != SID_REVISION) { 11223 return FALSE; 11224 } 11225 11226 if (GroupSid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) { 11227 return FALSE; 11228 } 11229 11230 if (MaxGroupSidLength < (ULONG) SeLengthSid (GroupSid)) { 11231 return FALSE; 11232 } 11233 11234 } 11235 11236 // 11237 // Validate the DACL if it's there and check if its allowed to be missing. 11238 // 11239 11240 if (!RtlpAreControlBitsSet (SecurityDescriptor, SE_DACL_PRESENT)) { 11241 // 11242 // Some code does this kind of thing: 11243 // 11244 // InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); 11245 // RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, &sd) ) 11246 // 11247 // With the current system this works the same as passing in a NULL DACL but it looks 11248 // almost by accident 11249 // 11250 // if (RequiredInformation & DACL_SECURITY_INFORMATION) { 11251 // return FALSE; 11252 // } 11253 } else if (SecurityDescriptor->Dacl) { 11254 if (!RtlpValidateSDOffsetAndSize (SecurityDescriptor->Dacl, 11255 SecurityDescriptorLength, 11256 sizeof (ACL), 11257 &MaxDaclLength)) { 11258 return FALSE; 11259 } 11260 11261 Dacl = (PACL) RtlOffsetToPointer (SecurityDescriptor, 11262 SecurityDescriptor->Dacl); 11263 11264 // 11265 // Make sure the DACL length fits within the bounds of the security descriptor. 11266 // 11267 if (MaxDaclLength < Dacl->AclSize) { 11268 return FALSE; 11269 } 11270 11271 // 11272 // Make sure the ACL is structurally valid. 11273 // 11274 if (!RtlValidAcl (Dacl)) { 11275 return FALSE; 11276 } 11277 } 11278 11279 // 11280 // Validate the SACL if it's there and check if its allowed to be missing. 11281 // 11282 11283 if (!RtlpAreControlBitsSet (SecurityDescriptor, SE_SACL_PRESENT)) { 11284 // if (RequiredInformation & SACL_SECURITY_INFORMATION) { 11285 // return FALSE; 11286 // } 11287 } else if (SecurityDescriptor->Sacl) { 11288 if (!RtlpValidateSDOffsetAndSize (SecurityDescriptor->Sacl, 11289 SecurityDescriptorLength, 11290 sizeof (ACL), 11291 &MaxSaclLength)) { 11292 return FALSE; 11293 } 11294 11295 Sacl = (PACL) RtlOffsetToPointer (SecurityDescriptor, 11296 SecurityDescriptor->Sacl); 11297 11298 // 11299 // Make sure the SACL length fits within the bounds of the security descriptor. 11300 // 11301 11302 if (MaxSaclLength < Sacl->AclSize) { 11303 return FALSE; 11304 } 11305 11306 // 11307 // Make sure the ACL is structurally valid. 11308 // 11309 11310 if (!RtlValidAcl (Sacl)) { 11311 return FALSE; 11312 } 11313 } 11314 11315 return TRUE; 11316 }

BOOLEAN RtlValidSecurityDescriptor IN PSECURITY_DESCRIPTOR  SecurityDescriptor  ) 
 

Definition at line 2066 of file sertl.c.

References Dacl, EXCEPTION_EXECUTE_HANDLER, FALSE, Group, NULL, Owner, RTL_PAGED_CODE, RtlValidAcl(), RtlValidSid(), and TRUE.

Referenced by IopInitializePlugPlayServices(), IopOpenDeviceParametersSubkey(), ObpReferenceSecurityDescriptor(), RtlpConvertToAutoInheritSecurityObject(), and TestSeSecurityDescriptor().

02072 : 02073 02074 This procedure validates a SecurityDescriptor's structure. This 02075 involves validating the revision levels of each component of the 02076 security descriptor. 02077 02078 Arguments: 02079 02080 SecurityDescriptor - Pointer to the SECURITY_DESCRIPTOR structure 02081 to validate. 02082 02083 Return Value: 02084 02085 BOOLEAN - TRUE if the structure of SecurityDescriptor is valid. 02086 02087 02088 --*/ 02089 02090 { 02091 PSID Owner; 02092 PSID Group; 02093 PACL Dacl; 02094 PACL Sacl; 02095 02096 // 02097 // Typecast to the opaque SECURITY_DESCRIPTOR structure. 02098 // 02099 02100 SECURITY_DESCRIPTOR *ISecurityDescriptor = SecurityDescriptor; 02101 02102 RTL_PAGED_CODE(); 02103 02104 try { 02105 02106 // 02107 // known revision ? 02108 // 02109 02110 if (ISecurityDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION) { 02111 return FALSE; 02112 } 02113 02114 02115 // 02116 // Validate each element contained in the security descriptor 02117 // 02118 02119 Owner = RtlpOwnerAddrSecurityDescriptor( ISecurityDescriptor ); 02120 02121 if (Owner != NULL) { 02122 if (!RtlValidSid( Owner )) { 02123 return FALSE; 02124 } 02125 } 02126 02127 Group = RtlpGroupAddrSecurityDescriptor( ISecurityDescriptor ); 02128 02129 if (Group != NULL) { 02130 if (!RtlValidSid( Group )) { 02131 return FALSE; 02132 } 02133 } 02134 02135 Dacl = RtlpDaclAddrSecurityDescriptor( ISecurityDescriptor ); 02136 if (Dacl != NULL ) { 02137 02138 if (!RtlValidAcl( Dacl )) { 02139 return FALSE; 02140 } 02141 } 02142 02143 Sacl = RtlpSaclAddrSecurityDescriptor( ISecurityDescriptor ); 02144 if ( Sacl != NULL ) { 02145 if (!RtlValidAcl( Sacl )) { 02146 return FALSE; 02147 } 02148 } 02149 02150 } except(EXCEPTION_EXECUTE_HANDLER) { 02151 return FALSE; 02152 } 02153 02154 // 02155 // All components are valid 02156 // 02157 02158 return TRUE; 02159 02160 02161 }

BOOLEAN RtlValidSid IN PSID  Sid  ) 
 

Definition at line 810 of file sertl.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, NULL, ProbeAndReadUlongUM, RTL_PAGED_CODE, and TRUE.

Referenced by CmpHiveRootSecurityDescriptor(), GenerateDescriptor(), IoCheckQuotaBufferValidity(), IopCheckGetQuotaBufferValidity(), NtQueryQuotaInformationFile(), RtlAddCompoundAce(), RtlConvertSidToUnicodeString(), RtlLengthSidAsUnicodeString(), RtlpAddKnownAce(), RtlpAddKnownObjectAce(), RtlpNewSecurityObject(), RtlpSetSecurityObject(), RtlValidSecurityDescriptor(), SeCaptureSecurityDescriptor(), SeCaptureSid(), SeCaptureSidAndAttributesArray(), and TestSeSid().

00816 : 00817 00818 This procedure validates an SID's structure. 00819 00820 Arguments: 00821 00822 Sid - Pointer to the SID structure to validate. 00823 00824 Return Value: 00825 00826 BOOLEAN - TRUE if the structure of Sid is valid. 00827 00828 --*/ 00829 00830 { 00831 PISID Isid = (PISID) Sid; 00832 RTL_PAGED_CODE(); 00833 // 00834 // Make sure revision is SID_REVISION and sub authority count is not 00835 // greater than maximum number of allowed sub-authorities. 00836 // 00837 00838 try { 00839 00840 if ( Isid != NULL && (Isid->Revision & 0x0f) == SID_REVISION) { 00841 if (Isid->SubAuthorityCount <= SID_MAX_SUB_AUTHORITIES) { 00842 00843 // 00844 // Verify the memory actually contains the last subauthority 00845 // 00846 #ifndef NTOS_KERNEL_RUNTIME 00847 #define ProbeAndReadUlongUM(Address) \ 00848 (*(volatile ULONG *)(Address)) 00849 00850 if (Isid->SubAuthorityCount > 0) { 00851 ProbeAndReadUlongUM( 00852 &Isid->SubAuthority[Isid->SubAuthorityCount-1] 00853 ); 00854 } 00855 #endif // !NTOS_KERNEL_RUNTIME 00856 return TRUE; 00857 } 00858 } 00859 00860 } except(EXCEPTION_EXECUTE_HANDLER) { 00861 return FALSE; 00862 } 00863 00864 return FALSE; 00865 00866 }


Variable Documentation

UCHAR RtlBaseAceType[]
 

Initial value:

{ ACCESS_ALLOWED_ACE_TYPE, ACCESS_DENIED_ACE_TYPE, SYSTEM_AUDIT_ACE_TYPE, SYSTEM_ALARM_ACE_TYPE, ACCESS_ALLOWED_ACE_TYPE, ACCESS_ALLOWED_ACE_TYPE, ACCESS_DENIED_ACE_TYPE, SYSTEM_AUDIT_ACE_TYPE, SYSTEM_ALARM_ACE_TYPE }

Definition at line 340 of file sertl.c.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpConvertAclToAutoInherit(), and RtlpCopyEffectiveAce().

UCHAR RtlIsSystemAceType[]
 

Initial value:

Definition at line 356 of file sertl.c.

Referenced by RtlpCompareKnownAces(), and RtlpCompareKnownObjectAces().

BOOLEAN RtlpVerboseConvert = FALSE
 

Definition at line 368 of file sertl.c.

Referenced by RtlpCompareKnownAces(), RtlpCompareKnownObjectAces(), RtlpConvertAclToAutoInherit(), and RtlpIsDuplicateAce().


Generated on Sat May 15 19:45:37 2004 for test by doxygen 1.3.7