/****************************************************************************** * SetSecurityDescriptorDacl [ADVAPI32.@] */ BOOL WINAPI SetSecurityDescriptorDacl ( PSECURITY_DESCRIPTOR lpsd, BOOL daclpresent, PACL dacl, BOOL dacldefaulted ) { CallWin32ToNt (RtlSetDaclSecurityDescriptor (lpsd, daclpresent, dacl, dacldefaulted )); }
/*++ * @name CsrCreateLocalSystemSD * * The CsrCreateLocalSystemSD routine creates a Security Descriptor for * the local account with PORT_ALL_ACCESS. * * @param LocalSystemSd * Pointer to a pointer to the security descriptor to create. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd) { SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; PSID SystemSid; ULONG Length; PSECURITY_DESCRIPTOR SystemSd; PACL Dacl; NTSTATUS Status; /* Initialize the System SID */ RtlAllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemSid); /* Get the length of the SID */ Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) goto Quit; /* Create the DACL for it */ RtlCreateAcl(Dacl, Length, ACL_REVISION2); /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid); if (!NT_SUCCESS(Status)) goto Quit; /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) goto Quit; Quit: if (!NT_SUCCESS(Status)) { RtlFreeHeap(CsrHeap, 0, SystemSd); SystemSd = NULL; } /* Free the SID and return*/ RtlFreeSid(SystemSid); *LocalSystemSd = SystemSd; return Status; }
VOID StripPermissions( WCHAR* KeyName ) { HANDLE keyHandle; unsigned char p[9000]; PSECURITY_DESCRIPTOR psecdesc = (PSECURITY_DESCRIPTOR)p; VOID* selfSecurityDescriptor; ULONG bufferLength = 20; keyHandle = Registry::OpenKey(KeyName, WRITE_DAC); RtlCreateSecurityDescriptor(psecdesc, SECURITY_DESCRIPTOR_REVISION); RtlSetDaclSecurityDescriptor(psecdesc, TRUE, NULL, TRUE); selfSecurityDescriptor = RtlAllocateHeap(PushHeapHandle, 0, 20); RtlMakeSelfRelativeSD(psecdesc, selfSecurityDescriptor, &bufferLength); NtSetSecurityObject(keyHandle, DACL_SECURITY_INFORMATION, selfSecurityDescriptor); NtClose(keyHandle); }
/* * @implemented */ BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted) { NTSTATUS Status; Status = RtlSetDaclSecurityDescriptor(pSecurityDescriptor, bDaclPresent, pDacl, bDaclDefaulted); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
NTSTATUS SrvShareSetDefaultSecurity( PSRV_SHARE_INFO pShareInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL; ULONG ulRelSecDescLen = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL; DWORD dwAceCount = 0; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; DWORD dwSizeDacl = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } administratorsSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } powerUsersSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } everyoneSid; ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer); ULONG ulPowerUsersSidSize = sizeof(powerUsersSid.buffer); ULONG ulEveryoneSidSize = sizeof(everyoneSid.buffer); ACCESS_MASK worldAccessMask = 0; /* Clear out any existing SecDesc's. This is not a normal use case, but be paranoid */ if (pShareInfo->ulSecDescLen) { SrvShareFreeSecurity(pShareInfo); } /* Build the new Absolute Security Descriptor */ ntStatus = RTL_ALLOCATE( &pAbsSecDesc, VOID, SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateSecurityDescriptorAbsolute( pAbsSecDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); /* Create some SIDs */ ntStatus = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, (PSID)administratorsSid.buffer, &ulAdministratorsSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinPowerUsersSid, NULL, (PSID)powerUsersSid.buffer, &ulPowerUsersSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinWorldSid, NULL, (PSID)everyoneSid.buffer, &ulEveryoneSidSize); BAIL_ON_NT_STATUS(ntStatus); /* Owner: Administrators */ ntStatus = RtlDuplicateSid(&pOwnerSid, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pAbsSecDesc, pOwnerSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Group: Power Users */ ntStatus = RtlDuplicateSid(&pGroupSid, &powerUsersSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pAbsSecDesc, pGroupSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* DACL: Administrators - (Full Control) Everyone - (Read) for disk shares, (Read/Write) to IPC shares */ dwAceCount = 2; dwSizeDacl = ACL_HEADER_SIZE + dwAceCount * sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&administratorsSid.sid) + RtlLengthSid(&everyoneSid.sid) - dwAceCount * sizeof(ULONG); ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, FILE_ALL_ACCESS, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); worldAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; if (pShareInfo->service == SHARE_SERVICE_NAMED_PIPE) { worldAccessMask |= FILE_GENERIC_WRITE; } ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, worldAccessMask, &everyoneSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetDaclSecurityDescriptor( pAbsSecDesc, TRUE, pDacl, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Create the SelfRelative SD and assign them to the Share */ ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, NULL, &ulRelSecDescLen); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, pRelSecDesc, &ulRelSecDescLen); } BAIL_ON_NT_STATUS(ntStatus); pShareInfo->pSecDesc = pRelSecDesc; pShareInfo->ulSecDescLen = ulRelSecDescLen; pShareInfo->pAbsSecDesc = pAbsSecDesc; ntStatus = STATUS_SUCCESS; cleanup: return ntStatus; error: RTL_FREE(&pAbsSecDesc); RTL_FREE(&pOwnerSid); RTL_FREE(&pGroupSid); RTL_FREE(&pDacl); if (pRelSecDesc) { SrvFreeMemory(pRelSecDesc); } goto cleanup; }
BOOLEAN ObInitSystem( VOID ) /*++ Routine Description: This function performs the system initialization for the object manager. The object manager data structures are self describing with the exception of the root directory, the type object type and the directory object type. The initialization code then constructs these objects by hand to get the ball rolling. Arguments: None. Return Value: TRUE if successful and FALSE if an error occurred. The following errors can occur: - insufficient memory --*/ { USHORT CreateInfoMaxDepth; USHORT NameBufferMaxDepth; ULONG RegionSegmentSize; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; UNICODE_STRING TypeTypeName; UNICODE_STRING SymbolicLinkTypeName; UNICODE_STRING DosDevicesDirectoryName; UNICODE_STRING DirectoryTypeName; UNICODE_STRING RootDirectoryName; UNICODE_STRING TypeDirectoryName; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE RootDirectoryHandle; HANDLE TypeDirectoryHandle; PLIST_ENTRY Next, Head; POBJECT_HEADER ObjectTypeHeader; POBJECT_HEADER_CREATOR_INFO CreatorInfo; POBJECT_HEADER_NAME_INFO NameInfo; MM_SYSTEMSIZE SystemSize; SECURITY_DESCRIPTOR AuditSd; PSECURITY_DESCRIPTOR EffectiveSd; PACL AuditAllAcl; UCHAR AuditAllBuffer[250]; // Ample room for the ACL ULONG AuditAllLength; PACE_HEADER Ace; // // PHASE 0 Initialization // if (InitializationPhase == 0) { // // Determine the the size of the object creation and the name buffer // lookaside lists. // SystemSize = MmQuerySystemSize(); if (SystemSize == MmLargeSystem) { if (MmIsThisAnNtAsSystem()) { CreateInfoMaxDepth = 64; NameBufferMaxDepth = 32; } else { CreateInfoMaxDepth = 32; NameBufferMaxDepth = 16; } } else { CreateInfoMaxDepth = 3; NameBufferMaxDepth = 3; } // // Initialize the object creation lookaside list. // ExInitializeNPagedLookasideList(&ObpCreateInfoLookasideList, NULL, NULL, 0, sizeof(OBJECT_CREATE_INFORMATION), 'iCbO', CreateInfoMaxDepth); // // Initialize the name buffer lookaside list. // ExInitializeNPagedLookasideList(&ObpNameBufferLookasideList, NULL, NULL, 0, OBJECT_NAME_BUFFER_SIZE, 'mNbO', NameBufferMaxDepth); InitializeListHead( &ObpRemoveObjectQueue ); // // Initialize security descriptor cache // ObpInitSecurityDescriptorCache(); KeInitializeMutant( &ObpInitKillMutant, FALSE ); KeInitializeEvent( &ObpDefaultObject, NotificationEvent, TRUE ); KeInitializeSpinLock( &ObpLock ); PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS; PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS; // // Initialize the quota block // KeInitializeSpinLock(&PspDefaultQuotaBlock.QuotaLock); PspDefaultQuotaBlock.ReferenceCount = 1; PspDefaultQuotaBlock.QuotaPoolLimit[PagedPool] = (ULONG)-1; PspDefaultQuotaBlock.QuotaPoolLimit[NonPagedPool] = (ULONG)-1; PspDefaultQuotaBlock.PagefileLimit = (ULONG)-1; PsGetCurrentProcess()->QuotaBlock = &PspDefaultQuotaBlock; PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable( NULL, 0, 0 ); RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.PoolType = NonPagedPool; RtlInitUnicodeString( &TypeTypeName, L"Type" ); ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = ObpTypeMapping; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_TYPE ); ObjectTypeInitializer.MaintainTypeList = TRUE; ObjectTypeInitializer.UseDefaultObject = TRUE; ObCreateObjectType( &TypeTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpTypeObjectType ); RtlInitUnicodeString( &DirectoryTypeName, L"Directory" ); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_DIRECTORY ); ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping; ObjectTypeInitializer.MaintainTypeList = FALSE; ObCreateObjectType( &DirectoryTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpDirectoryObjectType ); RtlInitUnicodeString( &SymbolicLinkTypeName, L"SymbolicLink" ); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_SYMBOLIC_LINK ); ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS; ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping; ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink; ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink; ObCreateObjectType( &SymbolicLinkTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObpSymbolicLinkObjectType ); ExInitializeResourceLite( &ObpRootDirectoryMutex ); #if i386 && !FPO ObpCurCachedGrantedAccessIndex = 0; ObpMaxCachedGrantedAccessIndex = PAGE_SIZE / sizeof( ACCESS_MASK ); ObpCachedGrantedAccesses = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, 'gAbO' ); #endif // i386 && !FPO #if DBG ObpCreateObjectEventId = RtlCreateEventId( NULL, 0, "CreateObject", 6, RTL_EVENT_ULONG_PARAM, "Object", 0, RTL_EVENT_PUNICODE_STRING_PARAM, "Type", 0, RTL_EVENT_ULONG_PARAM, "PagedPool", 0, RTL_EVENT_ULONG_PARAM, "NonPagedPool", 0, RTL_EVENT_PUNICODE_STRING_PARAM, "Name", 0, RTL_EVENT_FLAGS_PARAM, "", 5, OBJ_INHERIT, "Inherit", OBJ_PERMANENT, "Permanent", OBJ_OPENIF, "OpenIf", OBJ_CASE_INSENSITIVE, "CaseInsenitive", OBJ_EXCLUSIVE, "Exclusive" ); ObpFreeObjectEventId = RtlCreateEventId( NULL, 0, "FreeObject", 3, RTL_EVENT_ULONG_PARAM, "Object", 0, RTL_EVENT_ULONG_PARAM, "Type", 0, RTL_EVENT_PUNICODE_STRING_PARAM, "Name", 0 ); #endif // DBG } // End of Phase 0 Initializtion // // PHASE 1 Initialization // if (InitializationPhase == 1) { EffectiveSd = SePublicDefaultSd; // // This code is only executed if base auditing is turned on. // if ((ObpAuditBaseDirectories != 0) || (ObpAuditBaseObjects != 0)) { // // build an SACL to audit // AuditAllAcl = (PACL)AuditAllBuffer; AuditAllLength = (ULONG)sizeof(ACL) + ((ULONG)sizeof(SYSTEM_AUDIT_ACE)) + SeLengthSid(SeWorldSid); ASSERT( sizeof(AuditAllBuffer) > AuditAllLength ); Status = RtlCreateAcl( AuditAllAcl, AuditAllLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAuditAccessAce ( AuditAllAcl, ACL_REVISION2, GENERIC_ALL, SeWorldSid, TRUE, TRUE //Audit success and failure ); ASSERT( NT_SUCCESS(Status) ); Status = RtlGetAce( AuditAllAcl, 0, (PVOID)&Ace ); ASSERT( NT_SUCCESS(Status) ); if (ObpAuditBaseDirectories != 0) { Ace->AceFlags |= (CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); } if (ObpAuditBaseObjects != 0) { Ace->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); } // // Now create a security descriptor that looks just like // the public default, but has auditing in it as well. EffectiveSd = (PSECURITY_DESCRIPTOR)&AuditSd; Status = RtlCreateSecurityDescriptor( EffectiveSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( EffectiveSd, TRUE, // DaclPresent SePublicDefaultDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetSaclSecurityDescriptor( EffectiveSd, TRUE, // DaclPresent AuditAllAcl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); } // // We only need to use the EffectiveSd on the root. The SACL // will be inherited by all other objects. // RtlInitUnicodeString( &RootDirectoryName, L"\\" ); InitializeObjectAttributes( &ObjectAttributes, &RootDirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, EffectiveSd ); Status = NtCreateDirectoryObject( &RootDirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { return( FALSE ); } Status = ObReferenceObjectByHandle( RootDirectoryHandle, 0, ObpDirectoryObjectType, KernelMode, (PVOID *)&ObpRootDirectoryObject, NULL ); if (!NT_SUCCESS( Status )) { return( FALSE ); } Status = NtClose( RootDirectoryHandle ); if (!NT_SUCCESS( Status )) { return( FALSE ); } RtlInitUnicodeString( &TypeDirectoryName, L"\\ObjectTypes" ); InitializeObjectAttributes( &ObjectAttributes, &TypeDirectoryName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL ); Status = NtCreateDirectoryObject( &TypeDirectoryHandle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS( Status )) { return( FALSE ); } Status = ObReferenceObjectByHandle( TypeDirectoryHandle, 0, ObpDirectoryObjectType, KernelMode, (PVOID *)&ObpTypeDirectoryObject, NULL ); if (!NT_SUCCESS( Status )) { return( FALSE ); } Status = NtClose( TypeDirectoryHandle ); if (!NT_SUCCESS( Status )) { return( FALSE ); } ObpEnterRootDirectoryMutex(); Head = &ObpTypeObjectType->TypeList; Next = Head->Flink; while (Next != Head) { CreatorInfo = CONTAINING_RECORD( Next, OBJECT_HEADER_CREATOR_INFO, TypeList ); ObjectTypeHeader = (POBJECT_HEADER)(CreatorInfo+1); NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectTypeHeader ); if (NameInfo != NULL && NameInfo->Directory == NULL) { if (!ObpLookupDirectoryEntry( ObpTypeDirectoryObject, &NameInfo->Name, OBJ_CASE_INSENSITIVE ) ) { ObpInsertDirectoryEntry( ObpTypeDirectoryObject, &ObjectTypeHeader->Body ); } } Next = Next->Flink; } ObpLeaveRootDirectoryMutex(); // // Create \DosDevices object directory for drive letters and Win32 device names // Status = ObpCreateDosDevicesDirectory(); if (!NT_SUCCESS( Status )) { return FALSE; } } return TRUE; }
//---------------------------------------------------------------------- // // NTIMakeAbsoluteSD // // Takes a self-relative security descriptor and returns an allocated // absolute version. Caller is responsibile for freeing the allocated // buffer on success. // //---------------------------------------------------------------------- NTSTATUS NTIMakeAbsoluteSD( PSECURITY_DESCRIPTOR RelSecurityDescriptor, PSECURITY_DESCRIPTOR *pAbsSecurityDescriptor ) { NTSTATUS status; BOOLEAN DaclPresent, DaclDefaulted, OwnerDefaulted, GroupDefaulted; PACL Dacl; PSID Owner, Group; PSECURITY_DESCRIPTOR absSecurityDescriptor; // // Initialize buffer pointers // absSecurityDescriptor = (PSECURITY_DESCRIPTOR) ExAllocatePool( NonPagedPool, 1024 ); *pAbsSecurityDescriptor = absSecurityDescriptor; // // Create an absolute-form security descriptor for manipulation. // The one on the security descriptor is in self-relative form. // status = RtlCreateSecurityDescriptor( absSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); if( !NT_SUCCESS( status ) ) { DbgPrint(("Secsys: Unable to initialize security descriptor\n")); goto cleanup; } // // Locate the descriptor's DACL and apply the DACL to the new // descriptor we're going to modify // status = RtlGetDaclSecurityDescriptor( RelSecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted ); if( !NT_SUCCESS( status ) || !DaclPresent ) { if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Error obtaining security descriptor's DACL: %x\n", status )); } else { DbgPrint(("Secsys: Security descriptor does not have a DACL\n" )); } goto cleanup; } status = RtlSetDaclSecurityDescriptor( absSecurityDescriptor, DaclPresent, Dacl, DaclDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Coult not set new security descriptor DACL: %x\n", status )); goto cleanup; } // // We would get and apply the SACL at this point, but NT does not export // the appropriate function, RtlGetSaclSecurityDescriptor :-( // // // Get and apply the owner // status = RtlGetOwnerSecurityDescriptor( RelSecurityDescriptor, &Owner, &OwnerDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not security descriptor owner: %x\n", Owner )); goto cleanup; } status = RtlSetOwnerSecurityDescriptor( absSecurityDescriptor, Owner, OwnerDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not set owner: %x\n", status )); goto cleanup; } // // Get and apply group // status = RtlGetGroupSecurityDescriptor( RelSecurityDescriptor, &Group, &GroupDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not security descriptor group: %x\n", Owner )); goto cleanup; } status = RtlSetGroupSecurityDescriptor( absSecurityDescriptor, Group, GroupDefaulted ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not set group: %x\n", status )); goto cleanup; } // // Finally, make sure that what we made is valid // if( !RtlValidSecurityDescriptor( absSecurityDescriptor )) { DbgPrint(("Secsys: absolute descriptor not valid!\n")); status = STATUS_UNSUCCESSFUL; } // // Done! Return. // cleanup: if( !NT_SUCCESS( status ) ) { ExFreePool( absSecurityDescriptor ); } return status; }
/*++ * @name CsrSetProcessSecurity * * The CsrSetProcessSecurity routine protects access to the CSRSS process * from unauthorized tampering. * * @param None. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrSetProcessSecurity(VOID) { NTSTATUS Status; HANDLE hToken, hProcess = NtCurrentProcess(); ULONG Length; PTOKEN_USER TokenInfo = NULL; PSECURITY_DESCRIPTOR ProcSd = NULL; PACL Dacl; PSID UserSid; /* Open our token */ Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Get the Token User Length */ NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length); /* Allocate space for it */ TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length); if (!TokenInfo) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Now query the data */ Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length); NtClose(hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Now check the SID Length */ UserSid = TokenInfo->User.Sid; Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); if (!ProcSd) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status); goto Quickie; } /* Create the DACL for it*/ Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status); goto Quickie; } /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | READ_CONTROL, UserSid); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status); goto Quickie; } /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status); goto Quickie; } /* Write the SD into the Process */ Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status); goto Quickie; } /* Free the memory and return */ Quickie: if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd); RtlFreeHeap(CsrHeap, 0, TokenInfo); return Status; }
NTSTATUS NtOpenThreadToken( IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle ) /*++ Routine Description: Open a token object associated with a thread and return a handle that may be used to access that token. Arguments: ThreadHandle - Specifies the thread whose token is to be opened. DesiredAccess - Is an access mask indicating which access types are desired to the token. These access types are reconciled with the Discretionary Access Control list of the token to determine whether the accesses will be granted or denied. OpenAsSelf - Is a boolean value indicating whether the access should be made using the calling thread's current security context, which may be that of a client if impersonating, or using the caller's process-level security context. A value of FALSE indicates the caller's current context should be used un-modified. A value of TRUE indicates the request should be fulfilled using the process level security context. This parameter is necessary to allow a server process to open a client's token when the client specified IDENTIFICATION level impersonation. In this case, the caller would not be able to open the client's token using the client's context (because you can't create executive level objects using IDENTIFICATION level impersonation). TokenHandle - Receives the handle of the newly opened token. Return Value: STATUS_SUCCESS - Indicates the operation was successful. STATUS_NO_TOKEN - Indicates an attempt has been made to open a token associated with a thread that is not currently impersonating a client. STATUS_CANT_OPEN_ANONYMOUS - Indicates the client requested anonymous impersonation level. An anonymous token can not be openned. --*/ { KPROCESSOR_MODE PreviousMode; NTSTATUS Status; PVOID Token; PTOKEN NewToken = NULL; BOOLEAN CopyOnOpen; BOOLEAN EffectiveOnly; SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; SE_IMPERSONATION_STATE DisabledImpersonationState; BOOLEAN RestoreImpersonationState = FALSE; HANDLE LocalHandle; SECURITY_DESCRIPTOR SecurityDescriptor; OBJECT_ATTRIBUTES ObjectAttributes; PACL NewAcl = NULL; PETHREAD Thread; PETHREAD OriginalThread = NULL; PACCESS_TOKEN PrimaryToken; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; PAGED_CODE(); PreviousMode = KeGetPreviousMode(); // // Probe parameters // if (PreviousMode != KernelMode) { try { ProbeForWriteHandle(TokenHandle); } except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } // end_try } //end_if // // Valdiate access to the thread and obtain a pointer to the // thread's token (if there is one). If successful, this will // cause the token's reference count to be incremented. // // This routine disabled impersonation as necessary to properly // honor the OpenAsSelf flag. // Status = SepOpenTokenOfThread( ThreadHandle, OpenAsSelf, ((PACCESS_TOKEN *)&Token), &OriginalThread, &CopyOnOpen, &EffectiveOnly, &ImpersonationLevel ); if (!NT_SUCCESS(Status)) { return Status; } // // The token was successfully referenced. // // // We need to create and/or open a token object, so disable impersonation // if necessary. // if (OpenAsSelf) { RestoreImpersonationState = PsDisableImpersonation( PsGetCurrentThread(), &DisabledImpersonationState ); } // // If the CopyOnOpen flag is not set, then the token can be // opened directly. Otherwise, the token must be duplicated, // and a handle to the duplicate returned. // if (CopyOnOpen) { // // Create the new security descriptor for the token. // // We must obtain the correct SID to put into the Dacl. Do this // by finding the process associated with the passed thread // and grabbing the User SID out of that process's token. // If we just use the current SubjectContext, we'll get the // SID of whoever is calling us, which isn't what we want. // Status = ObReferenceObjectByHandle( ThreadHandle, THREAD_ALL_ACCESS, PsThreadType, KernelMode, (PVOID)&Thread, NULL ); // // Verify that the handle is still pointer to the same thread\ // BUGBUG: wrong error code. // if (NT_SUCCESS(Status) && (Thread != OriginalThread)) { Status = STATUS_OBJECT_TYPE_MISMATCH; } if (NT_SUCCESS(Status)) { PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess); Status = SepCreateImpersonationTokenDacl( (PTOKEN)Token, PrimaryToken, &NewAcl ); PsDereferencePrimaryToken( PrimaryToken ); if (NT_SUCCESS( Status )) { if (NewAcl != NULL) { // // There exist tokens that either do not have security descriptors at all, // or have security descriptors, but do not have DACLs. In either case, do // nothing. // Status = RtlCreateSecurityDescriptor ( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); ASSERT( NT_SUCCESS( Status )); Status = RtlSetDaclSecurityDescriptor ( &SecurityDescriptor, TRUE, NewAcl, FALSE ); ASSERT( NT_SUCCESS( Status )); } InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NewAcl == NULL ? NULL : &SecurityDescriptor ); // // Open a copy of the token // Status = SepDuplicateToken( (PTOKEN)Token, // ExistingToken &ObjectAttributes, // ObjectAttributes EffectiveOnly, // EffectiveOnly TokenImpersonation, // TokenType ImpersonationLevel, // ImpersonationLevel KernelMode, // RequestorMode must be kernel mode &NewToken ); if (NT_SUCCESS( Status )) { // // Reference the token so it doesn't go away // ObReferenceObject(NewToken); // // Insert the new token // Status = ObInsertObject( NewToken, NULL, DesiredAccess, 0, (PVOID *)NULL, &LocalHandle ); } } } } else { // // We do not have to modify the security on the token in the static case, // because in all the places in the system where impersonation takes place // over a secure transport (e.g., LPC), CopyOnOpen is set. The only reason // we'be be here is if the impersonation is taking place because someone did // an NtSetInformationThread and passed in a token. // // In that case, we absolutely do not want to give the caller guaranteed // access, because that would allow anyone who has access to a thread to // impersonate any of that thread's clients for any access. // // // Open the existing token // Status = ObOpenObjectByPointer( (PVOID)Token, // Object 0, // HandleAttributes NULL, // AccessState DesiredAccess, // DesiredAccess SepTokenObjectType, // ObjectType PreviousMode, // AccessMode &LocalHandle // Handle ); } if (NewAcl != NULL) { ExFreePool( NewAcl ); } if (RestoreImpersonationState) { PsRestoreImpersonation( PsGetCurrentThread(), &DisabledImpersonationState ); } // // And decrement the reference count of the existing token to counter // the action performed by PsOpenTokenOfThread. If the open // was successful, the handle will have caused the token's // reference count to have been incremented. // ObDereferenceObject( Token ); if (NT_SUCCESS( Status ) && CopyOnOpen) { // // Assign the newly duplicated token to the thread. // PsImpersonateClient( Thread, NewToken, FALSE, // turn off CopyOnOpen flag EffectiveOnly, ImpersonationLevel ); } // // We've impersonated the token so let go of oure reference // if (NewToken != NULL) { ObDereferenceObject( NewToken ); } if (CopyOnOpen && (Thread != NULL)) { ObDereferenceObject( Thread ); } if (OriginalThread != NULL) { ObDereferenceObject(OriginalThread); } // // Return the new handle // if (NT_SUCCESS(Status)) { try { *TokenHandle = LocalHandle; } except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } } return Status; }
static DWORD LwpsLegacyCreateSecurityDescriptor( IN BOOLEAN bIsWorldReadable, IN OUT PSECURITY_DESCRIPTOR_ABSOLUTE *ppSecurityDescriptor ) { NTSTATUS status = STATUS_SUCCESS; int EE = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; PACL pDacl = NULL; PSID pRootSid = NULL; PSID pAdminsSid = NULL; PSID pEveryoneSid = NULL; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; DWORD dwError = 0; status = RtlAllocateWellKnownSid(WinLocalSystemSid, NULL, &pRootSid); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = RtlAllocateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &pAdminsSid); GOTO_CLEANUP_ON_STATUS_EE(status, EE); if (bIsWorldReadable) { status = RtlAllocateWellKnownSid(WinWorldSid, NULL, &pEveryoneSid); GOTO_CLEANUP_ON_STATUS_EE(status, EE); } status = LW_RTL_ALLOCATE( &pSecDesc, VOID, SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = RtlCreateSecurityDescriptorAbsolute( pSecDesc, SECURITY_DESCRIPTOR_REVISION); GOTO_CLEANUP_ON_STATUS_EE(status, EE); // Owner: Root status = RtlDuplicateSid(&pOwnerSid, pRootSid); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = RtlSetOwnerSecurityDescriptor( pSecDesc, pOwnerSid, FALSE); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pOwnerSid = NULL; // Group: Administrators status = RtlDuplicateSid(&pGroupSid, pAdminsSid); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = RtlSetGroupSecurityDescriptor( pSecDesc, pGroupSid, FALSE); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pGroupSid = NULL; // Do not set Sacl currently // DACL status = LwpsLegacyBuildRestrictedDaclForKey( pRootSid, pEveryoneSid, &pDacl); GOTO_CLEANUP_ON_STATUS_EE(status, EE); status = RtlSetDaclSecurityDescriptor( pSecDesc, TRUE, pDacl, FALSE); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pDacl = NULL; if (!RtlValidSecurityDescriptor(pSecDesc)) { status = STATUS_INVALID_SECURITY_DESCR; GOTO_CLEANUP_ON_STATUS_EE(status, EE); } cleanup: if (status) { if (pSecDesc) { LwpsLegacyFreeSecurityDescriptor(&pSecDesc); } } LW_RTL_FREE(&pDacl); LW_RTL_FREE(&pRootSid); LW_RTL_FREE(&pAdminsSid); LW_RTL_FREE(&pEveryoneSid); LW_RTL_FREE(&pOwnerSid); LW_RTL_FREE(&pGroupSid); *ppSecurityDescriptor = pSecDesc; dwError = LwNtStatusToWin32Error(status); LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
static NTSTATUS RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor, OUT PSID *SystemSid) { PSECURITY_DESCRIPTOR AbsSD = NULL; PSID LocalSystemSid = NULL; PACL Dacl = NULL; ULONG DaclSize; NTSTATUS Status; /* create the local SYSTEM SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid); if (!NT_SUCCESS(Status)) { return Status; } /* allocate and initialize the security descriptor */ AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR), 'dSeS'); if (AbsSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } Status = RtlCreateSecurityDescriptor(AbsSD, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* allocate and create the DACL */ DaclSize = sizeof(ACL) + sizeof(ACE) + RtlLengthSid(LocalSystemSid); Dacl = RtlpAllocateMemory(DaclSize, 'cAeS'); if (Dacl == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } Status = RtlCreateAcl(Dacl, DaclSize, ACL_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlAddAccessAllowedAceEx(Dacl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, LocalSystemSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the DACL in the security descriptor */ Status = RtlSetDaclSecurityDescriptor(AbsSD, TRUE, Dacl, FALSE); /* all done */ if (NT_SUCCESS(Status)) { *SecurityDescriptor = AbsSD; *SystemSid = LocalSystemSid; } else { Cleanup: if (LocalSystemSid != NULL) { RtlFreeSid(LocalSystemSid); } if (Dacl != NULL) { RtlpFreeMemory(Dacl, 'cAeS'); } if (AbsSD != NULL) { RtlpFreeMemory(AbsSD, 'dSeS'); } } return Status; }
static NTSTATUS LsaSrvQueryPolicySecurity( PPOLICY_CONTEXT pAccountContext, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR_RELATIVE *ppSecurityDescRelative, PDWORD pSecurityDescRelativeSize ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD err = ERROR_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = gpLsaSecDesc; PSECURITY_DESCRIPTOR_ABSOLUTE pSecurityDesc = NULL; PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescRelative = NULL; DWORD securityDescRelativeSize = 0; err = LwAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pSecurityDesc)); BAIL_ON_LSA_ERROR(err); ntStatus = RtlCreateSecurityDescriptorAbsolute( pSecurityDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); if (SecurityInformation & OWNER_SECURITY_INFORMATION) { PSID owner = NULL; BOOLEAN defaulted = FALSE; ntStatus = RtlGetOwnerSecurityDescriptor( pSecDesc, &owner, &defaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDesc, owner, defaulted); BAIL_ON_NT_STATUS(ntStatus); } if (SecurityInformation & GROUP_SECURITY_INFORMATION) { PSID group = NULL; BOOLEAN defaulted = FALSE; ntStatus = RtlGetGroupSecurityDescriptor( pSecDesc, &group, &defaulted); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pSecurityDesc, group, defaulted); BAIL_ON_NT_STATUS(ntStatus); } if (SecurityInformation & DACL_SECURITY_INFORMATION) { PACL pDacl = NULL; BOOLEAN daclPresent = FALSE; BOOLEAN defaulted = FALSE; ntStatus = RtlGetDaclSecurityDescriptor( pSecDesc, &daclPresent, &pDacl, &defaulted); BAIL_ON_NT_STATUS(ntStatus); if (daclPresent) { ntStatus = RtlSetDaclSecurityDescriptor( pSecurityDesc, daclPresent, pDacl, defaulted); BAIL_ON_NT_STATUS(ntStatus); } } if (SecurityInformation & SACL_SECURITY_INFORMATION) { PACL pSacl = NULL; BOOLEAN saclPresent = FALSE; BOOLEAN defaulted = FALSE; ntStatus = RtlGetSaclSecurityDescriptor( pSecDesc, &saclPresent, &pSacl, &defaulted); BAIL_ON_NT_STATUS(ntStatus); if (saclPresent) { ntStatus = RtlSetSaclSecurityDescriptor( pSecurityDesc, saclPresent, pSacl, defaulted); BAIL_ON_NT_STATUS(ntStatus); } } ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDesc, pSecurityDescRelative, &securityDescRelativeSize); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = STATUS_SUCCESS; } else if (ntStatus != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LsaSrvAllocateMemory( OUT_PPVOID(&pSecurityDescRelative), securityDescRelativeSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDesc, pSecurityDescRelative, &securityDescRelativeSize); BAIL_ON_NT_STATUS(ntStatus); *ppSecurityDescRelative = pSecurityDescRelative; *pSecurityDescRelativeSize = securityDescRelativeSize; error: if (err || ntStatus) { if (pSecurityDescRelative) { LsaSrvFreeMemory(pSecurityDescRelative); } *ppSecurityDescRelative = NULL; *pSecurityDescRelativeSize = 0; } LW_SAFE_FREE_MEMORY(pSecurityDesc); if (ntStatus == STATUS_SUCCESS && err != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(err); } return ntStatus; }
/** * Sets the access control lists of the current window station * and desktop to allow all access. */ VOID PhSetDesktopWinStaAccess( VOID ) { static SID_IDENTIFIER_AUTHORITY appPackageAuthority = SECURITY_APP_PACKAGE_AUTHORITY; HWINSTA wsHandle; HDESK desktopHandle; ULONG allocationLength; PSECURITY_DESCRIPTOR securityDescriptor; PACL dacl; CHAR allAppPackagesSidBuffer[FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * 2]; PSID allAppPackagesSid; // TODO: Set security on the correct window station and desktop. allAppPackagesSid = (PISID)allAppPackagesSidBuffer; RtlInitializeSid(allAppPackagesSid, &appPackageAuthority, SECURITY_BUILTIN_APP_PACKAGE_RID_COUNT); *RtlSubAuthoritySid(allAppPackagesSid, 0) = SECURITY_APP_PACKAGE_BASE_RID; *RtlSubAuthoritySid(allAppPackagesSid, 1) = SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE; // We create a DACL that allows everyone to access everything. allocationLength = SECURITY_DESCRIPTOR_MIN_LENGTH + (ULONG)sizeof(ACL) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&PhSeEveryoneSid) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(allAppPackagesSid); securityDescriptor = PhAllocate(allocationLength); dacl = (PACL)((PCHAR)securityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH); RtlCreateSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION); RtlCreateAcl(dacl, allocationLength - SECURITY_DESCRIPTOR_MIN_LENGTH, ACL_REVISION); RtlAddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, &PhSeEveryoneSid); if (WindowsVersion >= WINDOWS_8) { RtlAddAccessAllowedAce(dacl, ACL_REVISION, GENERIC_ALL, allAppPackagesSid); } RtlSetDaclSecurityDescriptor(securityDescriptor, TRUE, dacl, FALSE); if (wsHandle = OpenWindowStation( L"WinSta0", FALSE, WRITE_DAC )) { PhSetObjectSecurity(wsHandle, DACL_SECURITY_INFORMATION, securityDescriptor); CloseWindowStation(wsHandle); } if (desktopHandle = OpenDesktop( L"Default", 0, FALSE, WRITE_DAC | DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS )) { PhSetObjectSecurity(desktopHandle, DACL_SECURITY_INFORMATION, securityDescriptor); CloseDesktop(desktopHandle); } PhFree(securityDescriptor); }
static DWORD ConstructSecurityDescriptor( DWORD dwAllowUserCount, PWSTR* ppwszAllowUsers, DWORD dwDenyUserCount, PWSTR* ppwszDenyUsers, BOOLEAN bReadOnly, PSECURITY_DESCRIPTOR_RELATIVE* ppRelative, PDWORD pdwRelativeSize ) { DWORD dwError = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL; PSECURITY_DESCRIPTOR_RELATIVE pRelative = NULL; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Owner; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Group; ULONG OwnerSidSize = sizeof(Owner.buffer); ULONG GroupSidSize = sizeof(Group.buffer); DWORD dwDaclSize = 0; PACL pDacl = NULL; DWORD dwIndex = 0; PSID pSid = NULL; ULONG ulRelativeSize = 0; HANDLE hLsa = NULL; ACCESS_MASK mask = bReadOnly ? (FILE_GENERIC_READ|FILE_GENERIC_EXECUTE) : FILE_ALL_ACCESS; dwError = LsaOpenServer(&hLsa); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &Owner.sid, &OwnerSidSize)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinPowerUsersSid, NULL, &Group.sid, &GroupSidSize)); BAIL_ON_LTNET_ERROR(dwError); dwDaclSize = ACL_HEADER_SIZE + dwAllowUserCount * (sizeof(ACCESS_ALLOWED_ACE) + SID_MAX_SIZE) + dwDenyUserCount * (sizeof(ACCESS_DENIED_ACE) + SID_MAX_SIZE) + RtlLengthSid(&Owner.sid) + RtlLengthSid(&Group.sid); dwError = LwNetAllocateMemory( dwDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION)); BAIL_ON_LTNET_ERROR(dwError); for (dwIndex = 0; dwIndex < dwDenyUserCount; dwIndex++) { dwError = MapNameToSid(hLsa, ppwszDenyUsers[dwIndex], &pSid); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinNameToSid(&pSid, ppwszDenyUsers[dwIndex]); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessDeniedAceEx( pDacl, ACL_REVISION, 0, FILE_ALL_ACCESS, pSid)); BAIL_ON_LTNET_ERROR(dwError); RTL_FREE(&pSid); } for (dwIndex = 0; dwIndex < dwAllowUserCount; dwIndex++) { dwError = MapNameToSid(hLsa, ppwszAllowUsers[dwIndex], &pSid); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinNameToSid(&pSid, ppwszAllowUsers[dwIndex]); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, mask, pSid)); BAIL_ON_LTNET_ERROR(dwError); RTL_FREE(&pSid); } dwError = LwNetAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pAbsolute)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateSecurityDescriptorAbsolute( pAbsolute, SECURITY_DESCRIPTOR_REVISION)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetOwnerSecurityDescriptor( pAbsolute, &Owner.sid, FALSE)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetGroupSecurityDescriptor( pAbsolute, &Group.sid, FALSE)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetDaclSecurityDescriptor( pAbsolute, TRUE, pDacl, FALSE)); BAIL_ON_LTNET_ERROR(dwError); RtlAbsoluteToSelfRelativeSD( pAbsolute, NULL, &ulRelativeSize); dwError = LwNetAllocateMemory(ulRelativeSize, OUT_PPVOID(&pRelative)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAbsoluteToSelfRelativeSD( pAbsolute, pRelative, &ulRelativeSize)); BAIL_ON_LTNET_ERROR(dwError); *ppRelative = pRelative; *pdwRelativeSize = ulRelativeSize; cleanup: if (hLsa) { LsaCloseServer(hLsa); } LTNET_SAFE_FREE_MEMORY(pSid); LTNET_SAFE_FREE_MEMORY(pDacl); LTNET_SAFE_FREE_MEMORY(pAbsolute); return dwError; error: *ppRelative = NULL; *pdwRelativeSize = 0; LTNET_SAFE_FREE_MEMORY(pRelative); goto cleanup; }
/* * @implemented */ BOOL WINAPI CheckTokenMembership(IN HANDLE ExistingTokenHandle, IN PSID SidToCheck, OUT PBOOL IsMember) { PISECURITY_DESCRIPTOR SecurityDescriptor = NULL; ACCESS_MASK GrantedAccess; struct { PRIVILEGE_SET PrivilegeSet; LUID_AND_ATTRIBUTES Privileges[4]; } PrivBuffer; ULONG PrivBufferSize = sizeof(PrivBuffer); GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE, STANDARD_RIGHTS_ALL }; PACL Dacl; ULONG SidLen; HANDLE hToken = NULL; NTSTATUS Status, AccessStatus; /* doesn't return gracefully if IsMember is NULL! */ *IsMember = FALSE; SidLen = RtlLengthSid(SidToCheck); if (ExistingTokenHandle == NULL) { Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, &hToken); if (Status == STATUS_NO_TOKEN) { /* we're not impersonating, open the primary token */ Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken); if (NT_SUCCESS(Status)) { HANDLE hNewToken = FALSE; BOOL DupRet; /* duplicate the primary token to create an impersonation token */ DupRet = DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_IMPERSONATE, NULL, SecurityImpersonation, TokenImpersonation, &hNewToken); NtClose(hToken); if (!DupRet) { WARN("Failed to duplicate the primary token!\n"); return FALSE; } hToken = hNewToken; } } if (!NT_SUCCESS(Status)) { goto Cleanup; } } else { hToken = ExistingTokenHandle; } /* create a security descriptor */ SecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(SECURITY_DESCRIPTOR) + sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE)); if (SecurityDescriptor == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the owner and group */ Status = RtlSetOwnerSecurityDescriptor(SecurityDescriptor, SidToCheck, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlSetGroupSecurityDescriptor(SecurityDescriptor, SidToCheck, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the DACL */ Dacl = (PACL)(SecurityDescriptor + 1); Status = RtlCreateAcl(Dacl, sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE), ACL_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, 0x1, SidToCheck); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* assign the DACL to the security descriptor */ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* it's time to perform the access check. Just use _some_ desired access right (same as for the ACE) and see if we're getting it granted. This indicates our SID is a member of the token. We however can't use a generic access right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */ Status = NtAccessCheck(SecurityDescriptor, hToken, 0x1, &GenericMapping, &PrivBuffer.PrivilegeSet, &PrivBufferSize, &GrantedAccess, &AccessStatus); if (NT_SUCCESS(Status) && NT_SUCCESS(AccessStatus) && (GrantedAccess == 0x1)) { *IsMember = TRUE; } Cleanup: if (hToken != NULL && hToken != ExistingTokenHandle) { NtClose(hToken); } if (SecurityDescriptor != NULL) { RtlFreeHeap(RtlGetProcessHeap(), 0, SecurityDescriptor); } if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
static HANDLE K32CreateDBMonMutex(void) { static SID_IDENTIFIER_AUTHORITY siaNTAuth = {SECURITY_NT_AUTHORITY}; static SID_IDENTIFIER_AUTHORITY siaWorldAuth = {SECURITY_WORLD_SID_AUTHORITY}; HANDLE hMutex; /* SIDs to be used in the DACL */ PSID psidSystem = NULL; PSID psidAdministrators = NULL; PSID psidEveryone = NULL; /* buffer for the DACL */ PVOID pDaclBuf = NULL; /* minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE headers. We'll add the size of SIDs when we'll know it */ SIZE_T nDaclBufSize = sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)0)->SidStart)) * 3; /* security descriptor of the mutex */ SECURITY_DESCRIPTOR sdMutexSecurity; /* attributes of the mutex object we'll create */ SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs), &sdMutexSecurity, TRUE}; NTSTATUS nErrCode; /* first, try to open the mutex */ hMutex = OpenMutexW (SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, TRUE, L"DBWinMutex"); if(hMutex != NULL) { /* success */ return hMutex; } /* error other than the mutex not being found */ else if(GetLastError() != ERROR_FILE_NOT_FOUND) { /* failure */ return NULL; } /* if the mutex doesn't exist, create it */ /* first, set up the mutex security */ /* allocate the NT AUTHORITY\SYSTEM SID */ nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* allocate the BUILTIN\Administrators SID */ nErrCode = RtlAllocateAndInitializeSid(&siaNTAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* allocate the Everyone SID */ nErrCode = RtlAllocateAndInitializeSid(&siaWorldAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, &psidEveryone); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* allocate space for the SIDs too */ nDaclBufSize += RtlLengthSid(psidSystem); nDaclBufSize += RtlLengthSid(psidAdministrators); nDaclBufSize += RtlLengthSid(psidEveryone); /* allocate the buffer for the DACL */ pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize); /* failure */ if(pDaclBuf == NULL) goto l_Cleanup; /* create the DACL */ nErrCode = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* grant the minimum required access to Everyone */ nErrCode = RtlAddAccessAllowedAce(pDaclBuf, ACL_REVISION, SYNCHRONIZE | READ_CONTROL | MUTANT_QUERY_STATE, psidEveryone); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* grant full access to BUILTIN\Administrators */ nErrCode = RtlAddAccessAllowedAce(pDaclBuf, ACL_REVISION, MUTANT_ALL_ACCESS, psidAdministrators); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* grant full access to NT AUTHORITY\SYSTEM */ nErrCode = RtlAddAccessAllowedAce(pDaclBuf, ACL_REVISION, MUTANT_ALL_ACCESS, psidSystem); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* create the security descriptor */ nErrCode = RtlCreateSecurityDescriptor(&sdMutexSecurity, SECURITY_DESCRIPTOR_REVISION); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* set the descriptor's DACL to the ACL we created */ nErrCode = RtlSetDaclSecurityDescriptor(&sdMutexSecurity, TRUE, pDaclBuf, FALSE); /* failure */ if(!NT_SUCCESS(nErrCode)) goto l_Cleanup; /* create the mutex */ hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex"); l_Cleanup: /* free the buffers */ if(pDaclBuf) GlobalFree(pDaclBuf); if(psidEveryone) RtlFreeSid(psidEveryone); if(psidAdministrators) RtlFreeSid(psidAdministrators); if(psidSystem) RtlFreeSid(psidSystem); return hMutex; }
NTSTATUS LsapCreateSecretSd(PSECURITY_DESCRIPTOR *SecretSd, PULONG SecretSdSize) { SECURITY_DESCRIPTOR AbsoluteSd; PSECURITY_DESCRIPTOR RelativeSd = NULL; ULONG RelativeSdSize = 0; PSID AdministratorsSid = NULL; PSID EveryoneSid = NULL; PSID LocalSystemSid = NULL; PACL Dacl = NULL; ULONG DaclSize; NTSTATUS Status; if (SecretSd == NULL || SecretSdSize == NULL) return STATUS_INVALID_PARAMETER; *SecretSd = NULL; *SecretSdSize = 0; /* Initialize the SD */ Status = RtlCreateSecurityDescriptor(&AbsoluteSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) return Status; Status = RtlAllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsSid); if (!NT_SUCCESS(Status)) goto done; Status = RtlAllocateAndInitializeSid(&WorldSidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); if (!NT_SUCCESS(Status)) goto done; Status = RtlAllocateAndInitializeSid(&NtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid); if (!NT_SUCCESS(Status)) goto done; /* Allocate and initialize the DACL */ DaclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(AdministratorsSid) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + RtlLengthSid(EveryoneSid); Dacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize); if (Dacl == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } Status = RtlCreateAcl(Dacl, DaclSize, ACL_REVISION); if (!NT_SUCCESS(Status)) goto done; Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, SECRET_ALL_ACCESS, AdministratorsSid); if (!NT_SUCCESS(Status)) goto done; Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, SECRET_EXECUTE, EveryoneSid); if (!NT_SUCCESS(Status)) goto done; Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) goto done; Status = RtlSetGroupSecurityDescriptor(&AbsoluteSd, LocalSystemSid, FALSE); if (!NT_SUCCESS(Status)) goto done; Status = RtlSetOwnerSecurityDescriptor(&AbsoluteSd, AdministratorsSid, FALSE); if (!NT_SUCCESS(Status)) goto done; Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd, RelativeSd, &RelativeSdSize); if (Status != STATUS_BUFFER_TOO_SMALL) goto done; RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, RelativeSdSize); if (RelativeSd == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd, RelativeSd, &RelativeSdSize); if (!NT_SUCCESS(Status)) goto done; *SecretSd = RelativeSd; *SecretSdSize = RelativeSdSize; done: if (Dacl != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl); if (AdministratorsSid != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AdministratorsSid); if (EveryoneSid != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, EveryoneSid); if (LocalSystemSid != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid); if (!NT_SUCCESS(Status)) { if (RelativeSd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd); } return Status; }
static DWORD EVTCreateAccessDescriptor( PCSTR pszAllowReadTo, PCSTR pszAllowWriteTo, PCSTR pszAllowDeleteTo, PSECURITY_DESCRIPTOR_ABSOLUTE* ppDescriptor, PBOOLEAN pbFullyResolved ) { PSECURITY_DESCRIPTOR_ABSOLUTE pDescriptor = NULL; DWORD dwCount = 0; PSTR* ppszArray = NULL; DWORD dwReadCount = 0; DWORD dwWriteCount = 0; DWORD dwDeleteCount = 0; PSID* ppReadList = NULL; PSID* ppWriteList = NULL; PSID* ppDeleteList = NULL; PACL pDacl = NULL; DWORD dwDaclSize = 0; PLW_MAP_SECURITY_CONTEXT pContext = NULL; DWORD dwError = 0; PSID pLocalSystem = NULL; PSID pAdministrators = NULL; BOOLEAN bFullyResolved = TRUE; dwError = LwAllocateWellKnownSid( WinLocalSystemSid, NULL, &pLocalSystem, NULL); BAIL_ON_EVT_ERROR(dwError); dwError = LwAllocateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &pAdministrators, NULL); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( LwMapSecurityCreateContext( &pContext)); BAIL_ON_EVT_ERROR(dwError); dwError = LwAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, (PVOID*)&pDescriptor); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateSecurityDescriptorAbsolute( pDescriptor, SECURITY_DESCRIPTOR_REVISION)); BAIL_ON_EVT_ERROR(dwError); dwError = EVTStringSplit( pszAllowReadTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwReadCount, &ppReadList); BAIL_ON_EVT_ERROR(dwError); if (dwReadCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwError = EVTStringSplit( pszAllowWriteTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwWriteCount, &ppWriteList); BAIL_ON_EVT_ERROR(dwError); if (dwWriteCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwError = EVTStringSplit( pszAllowDeleteTo, &dwCount, &ppszArray); BAIL_ON_EVT_ERROR(dwError); dwError = EVTNamesToSids( pContext, dwCount, ppszArray, &dwDeleteCount, &ppDeleteList); BAIL_ON_EVT_ERROR(dwError); if (dwDeleteCount < dwCount) { bFullyResolved = FALSE; } LwFreeStringArray( ppszArray, dwCount); ppszArray = NULL; dwDaclSize = ACL_HEADER_SIZE + EVTGetAllowAcesSize(dwReadCount, ppReadList) + EVTGetAllowAcesSize(dwWriteCount, ppWriteList) + EVTGetAllowAcesSize(dwDeleteCount, ppDeleteList); dwError = LwAllocateMemory( dwDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION)); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwReadCount, ppReadList, EVENTLOG_READ_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwWriteCount, ppWriteList, EVENTLOG_WRITE_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = EVTAddAllowAces( pDacl, dwWriteCount, ppWriteList, EVENTLOG_DELETE_RECORD); BAIL_ON_EVT_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetDaclSecurityDescriptor( pDescriptor, TRUE, pDacl, FALSE)); BAIL_ON_EVT_ERROR(dwError); pDacl = NULL; dwError = LwNtStatusToWin32Error( RtlSetOwnerSecurityDescriptor( pDescriptor, pLocalSystem, FALSE)); BAIL_ON_EVT_ERROR(dwError); pLocalSystem = NULL; dwError = LwNtStatusToWin32Error( RtlSetGroupSecurityDescriptor( pDescriptor, pAdministrators, FALSE)); BAIL_ON_EVT_ERROR(dwError); pAdministrators = NULL; *ppDescriptor = pDescriptor; if (pbFullyResolved) { *pbFullyResolved = bFullyResolved; } cleanup: if (ppszArray) { LwFreeStringArray( ppszArray, dwCount); } EVTFreeSidArray( pContext, dwReadCount, ppReadList); EVTFreeSidArray( pContext, dwWriteCount, ppWriteList); EVTFreeSidArray( pContext, dwDeleteCount, ppDeleteList); LwMapSecurityFreeContext(&pContext); return dwError; error: EVTFreeSecurityDescriptor(pDescriptor); *ppDescriptor = NULL; if (pbFullyResolved) { *pbFullyResolved = FALSE; } LW_SAFE_FREE_MEMORY(pDacl); LW_SAFE_FREE_MEMORY(pLocalSystem); LW_SAFE_FREE_MEMORY(pAdministrators); goto cleanup; }
static NTSTATUS RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle, IN PISECURITY_DESCRIPTOR SecurityDescriptor) { PSECURITY_DESCRIPTOR RelSD = NULL; PSECURITY_DESCRIPTOR NewRelSD = NULL; PSECURITY_DESCRIPTOR AbsSD = NULL; #ifdef _WIN64 BOOLEAN AbsSDAllocated = FALSE; #endif PSID AdminSid = NULL; PSID LocalSystemSid = NULL; ULONG DescriptorSize; ULONG AbsSDSize, RelSDSize = 0; PACL Dacl; BOOLEAN DaclPresent, DaclDefaulted; PSID OwnerSid; BOOLEAN OwnerDefaulted; ULONG AceIndex; PACE Ace = NULL; NTSTATUS Status; /* find out how much memory we need to allocate for the self-relative descriptor we're querying */ Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &DescriptorSize); if (Status != STATUS_BUFFER_TOO_SMALL) { /* looks like the FS doesn't support security... return success */ Status = STATUS_SUCCESS; goto Cleanup; } /* allocate enough memory for the security descriptor */ RelSD = RtlpAllocateMemory(DescriptorSize, 'dSeS'); if (RelSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } /* query the self-relative security descriptor */ Status = ZwQuerySecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, RelSD, DescriptorSize, &DescriptorSize); if (!NT_SUCCESS(Status)) { /* FIXME - handle the case where someone else modified the owner and/or DACL while we allocated memory. But that should be *very* unlikely.... */ goto Cleanup; } /* query the owner and DACL from the descriptor */ Status = RtlGetOwnerSecurityDescriptor(RelSD, &OwnerSid, &OwnerDefaulted); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlGetDaclSecurityDescriptor(RelSD, &DaclPresent, &Dacl, &DaclDefaulted); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the Administrators SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the local SYSTEM SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* check if the Administrators are the owner and at least a not-NULL DACL is present */ if (OwnerSid != NULL && RtlEqualSid(OwnerSid, AdminSid) && DaclPresent && Dacl != NULL) { /* check the DACL for an Allowed ACE for the SYSTEM account */ AceIndex = 0; do { Status = RtlGetAce(Dacl, AceIndex++, (PVOID*)&Ace); if (!NT_SUCCESS(Status)) { Ace = NULL; } else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) { /* check if the the ACE is a set of allowed permissions for the local SYSTEM account */ if (RtlEqualSid((PSID)(Ace + 1), LocalSystemSid)) { /* check if the ACE is inherited by noncontainer and container objects, if not attempt to change that */ if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) || !(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE)) { Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = ZwSetSecurityObject(DirectoryHandle, DACL_SECURITY_INFORMATION, RelSD); } else { /* all done, we have access */ Status = STATUS_SUCCESS; } goto Cleanup; } } } while (Ace != NULL); } AbsSDSize = DescriptorSize; /* because we need to change any existing data we need to convert it to an absolute security descriptor first */ Status = RtlSelfRelativeToAbsoluteSD2(RelSD, &AbsSDSize); #ifdef _WIN64 if (Status == STATUS_BUFFER_TOO_SMALL) { /* this error code can only be returned on 64 bit builds because the size of an absolute security descriptor is greater than the size of a self-relative security descriptor */ ASSERT(AbsSDSize > DescriptorSize); AbsSD = RtlpAllocateMemory(DescriptorSize, 'dSeS'); if (AbsSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } AbsSDAllocated = TRUE; /* make a raw copy of the self-relative descriptor */ RtlCopyMemory(AbsSD, RelSD, DescriptorSize); /* finally convert it */ Status = RtlSelfRelativeToAbsoluteSD2(AbsSD, &AbsSDSize); } else #endif { AbsSD = RelSD; } if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the owner SID */ Status = RtlSetOwnerSecurityDescriptor(AbsSD, AdminSid, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the DACL in the security descriptor */ Status = RtlSetDaclSecurityDescriptor(AbsSD, TRUE, SecurityDescriptor->Dacl, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* convert it back to a self-relative descriptor, find out how much memory we need */ Status = RtlAbsoluteToSelfRelativeSD(AbsSD, NULL, &RelSDSize); if (Status != STATUS_BUFFER_TOO_SMALL) { goto Cleanup; } /* allocate enough memory for the new self-relative descriptor */ NewRelSD = RtlpAllocateMemory(RelSDSize, 'dSeS'); if (NewRelSD == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } /* convert the security descriptor to self-relative format */ Status = RtlAbsoluteToSelfRelativeSD(AbsSD, NewRelSD, &RelSDSize); if (Status == STATUS_BUFFER_TOO_SMALL) { goto Cleanup; } /* finally attempt to change the security information */ Status = ZwSetSecurityObject(DirectoryHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NewRelSD); Cleanup: if (AdminSid != NULL) { RtlFreeSid(AdminSid); } if (LocalSystemSid != NULL) { RtlFreeSid(LocalSystemSid); } if (RelSD != NULL) { RtlpFreeMemory(RelSD, 'dSeS'); } if (NewRelSD != NULL) { RtlpFreeMemory(NewRelSD, 'dSeS'); } #ifdef _WIN64 if (AbsSDAllocated) { RtlpFreeMemory(AbsSD, 'dSeS'); } #endif return Status; }
VOID NtfsInitializeNtfsData ( IN PDRIVER_OBJECT DriverObject ) /*++ Routine Description: This routine initializes the global ntfs data record Arguments: DriverObject - Supplies the driver object for NTFS Return Value: None. --*/ { USHORT FileLockMaxDepth; USHORT IoContextMaxDepth; USHORT IrpContextMaxDepth; USHORT KeventMaxDepth; USHORT ScbNonpagedMaxDepth; USHORT ScbSnapshotMaxDepth; USHORT CcbDataMaxDepth; USHORT CcbMaxDepth; USHORT DeallocatedRecordsMaxDepth; USHORT FcbDataMaxDepth; USHORT FcbIndexMaxDepth; USHORT IndexContextMaxDepth; USHORT LcbMaxDepth; USHORT NukemMaxDepth; USHORT ScbDataMaxDepth; PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; BOOLEAN CapturedSubjectContext = FALSE; PACL SystemDacl = NULL; ULONG SystemDaclLength; PSID AdminSid = NULL; PSID SystemSid = NULL; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsInitializeNtfsData\n") ); // // Zero the record and set its node type code and size // RtlZeroMemory( &NtfsData, sizeof(NTFS_DATA)); NtfsData.NodeTypeCode = NTFS_NTC_DATA_HEADER; NtfsData.NodeByteSize = sizeof(NTFS_DATA); // // Initialize the queue of mounted Vcbs // InitializeListHead(&NtfsData.VcbQueue); // // This list head keeps track of closes yet to be done. // InitializeListHead( &NtfsData.AsyncCloseList ); InitializeListHead( &NtfsData.DelayedCloseList ); ExInitializeWorkItem( &NtfsData.NtfsCloseItem, (PWORKER_THREAD_ROUTINE)NtfsFspClose, NULL ); // // Set the driver object, device object, and initialize the global // resource protecting the file system // NtfsData.DriverObject = DriverObject; ExInitializeResource( &NtfsData.Resource ); // // Now allocate and initialize the s-list structures used as our pool // of IRP context records. The size of the zone is based on the // system memory size. We also initialize the spin lock used to protect // the zone. // KeInitializeSpinLock( &NtfsData.StrucSupSpinLock ); { switch ( MmQuerySystemSize() ) { case MmSmallSystem: NtfsData.FreeEresourceTotal = 14; // // Nonpaged Lookaside list maximum depths // FileLockMaxDepth = 8; IoContextMaxDepth = 8; IrpContextMaxDepth = 4; KeventMaxDepth = 8; ScbNonpagedMaxDepth = 8; ScbSnapshotMaxDepth = 8; // // Paged Lookaside list maximum depths // CcbDataMaxDepth = 4; CcbMaxDepth = 4; DeallocatedRecordsMaxDepth = 8; FcbDataMaxDepth = 8; FcbIndexMaxDepth = 4; IndexContextMaxDepth = 8; LcbMaxDepth = 4; NukemMaxDepth = 8; ScbDataMaxDepth = 4; SetFlag( NtfsData.Flags, NTFS_FLAGS_SMALL_SYSTEM ); NtfsMaxDelayedCloseCount = MAX_DELAYED_CLOSE_COUNT; break; case MmMediumSystem: NtfsData.FreeEresourceTotal = 30; // // Nonpaged Lookaside list maximum depths // FileLockMaxDepth = 8; IoContextMaxDepth = 8; IrpContextMaxDepth = 8; KeventMaxDepth = 8; ScbNonpagedMaxDepth = 30; ScbSnapshotMaxDepth = 8; // // Paged Lookaside list maximum depths // CcbDataMaxDepth = 12; CcbMaxDepth = 6; DeallocatedRecordsMaxDepth = 8; FcbDataMaxDepth = 30; FcbIndexMaxDepth = 12; IndexContextMaxDepth = 8; LcbMaxDepth = 12; NukemMaxDepth = 8; ScbDataMaxDepth = 12; SetFlag( NtfsData.Flags, NTFS_FLAGS_MEDIUM_SYSTEM ); NtfsMaxDelayedCloseCount = 4 * MAX_DELAYED_CLOSE_COUNT; break; case MmLargeSystem: SetFlag( NtfsData.Flags, NTFS_FLAGS_LARGE_SYSTEM ); NtfsMaxDelayedCloseCount = 16 * MAX_DELAYED_CLOSE_COUNT; if (MmIsThisAnNtAsSystem()) { NtfsData.FreeEresourceTotal = 256; // // Nonpaged Lookaside list maximum depths // FileLockMaxDepth = 8; IoContextMaxDepth = 8; IrpContextMaxDepth = 256; KeventMaxDepth = 8; ScbNonpagedMaxDepth = 128; ScbSnapshotMaxDepth = 8; // // Paged Lookaside list maximum depths // CcbDataMaxDepth = 40; CcbMaxDepth = 20; DeallocatedRecordsMaxDepth = 8; FcbDataMaxDepth = 128; FcbIndexMaxDepth = 40; IndexContextMaxDepth = 8; LcbMaxDepth = 40; NukemMaxDepth = 8; ScbDataMaxDepth = 40; } else { NtfsData.FreeEresourceTotal = 128; // // Nonpaged Lookaside list maximum depths // FileLockMaxDepth = 8; IoContextMaxDepth = 8; IrpContextMaxDepth = 64; KeventMaxDepth = 8; ScbNonpagedMaxDepth = 64; ScbSnapshotMaxDepth = 8; // // Paged Lookaside list maximum depths // CcbDataMaxDepth = 20; CcbMaxDepth = 10; DeallocatedRecordsMaxDepth = 8; FcbDataMaxDepth = 64; FcbIndexMaxDepth = 20; IndexContextMaxDepth = 8; LcbMaxDepth = 20; NukemMaxDepth = 8; ScbDataMaxDepth = 20; } break; } NtfsMinDelayedCloseCount = NtfsMaxDelayedCloseCount * 4 / 5; } // // Initialize our various lookaside lists. To make it a bit more readable we'll // define two quick macros to do the initialization // #if DBG && i386 && defined (NTFSPOOLCHECK) #define NPagedInit(L,S,T,D) { ExInitializeNPagedLookasideList( (L), NtfsDebugAllocatePoolWithTag, NtfsDebugFreePool, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); } #define PagedInit(L,S,T,D) { ExInitializePagedLookasideList( (L), NtfsDebugAllocatePoolWithTag, NtfsDebugFreePool, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); } #else // DBG && i386 #define NPagedInit(L,S,T,D) { ExInitializeNPagedLookasideList( (L), NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); } #define PagedInit(L,S,T,D) { ExInitializePagedLookasideList( (L), NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); } #endif // DBG && i386 NPagedInit( &NtfsFileLockLookasideList, sizeof(FILE_LOCK), 'kftN', FileLockMaxDepth ); NPagedInit( &NtfsIoContextLookasideList, sizeof(NTFS_IO_CONTEXT), 'IftN', IoContextMaxDepth ); NPagedInit( &NtfsIrpContextLookasideList, sizeof(IRP_CONTEXT), 'iftN', IrpContextMaxDepth ); NPagedInit( &NtfsKeventLookasideList, sizeof(KEVENT), 'KftN', KeventMaxDepth ); NPagedInit( &NtfsScbNonpagedLookasideList, sizeof(SCB_NONPAGED), 'nftN', ScbNonpagedMaxDepth ); NPagedInit( &NtfsScbSnapshotLookasideList, sizeof(SCB_SNAPSHOT), 'TftN', ScbSnapshotMaxDepth ); PagedInit( &NtfsCcbLookasideList, sizeof(CCB), 'CftN', CcbMaxDepth ); PagedInit( &NtfsCcbDataLookasideList, sizeof(CCB_DATA), 'cftN', CcbDataMaxDepth ); PagedInit( &NtfsDeallocatedRecordsLookasideList, sizeof(DEALLOCATED_RECORDS), 'DftN', DeallocatedRecordsMaxDepth ); PagedInit( &NtfsFcbDataLookasideList, sizeof(FCB_DATA), 'fftN', FcbDataMaxDepth ); PagedInit( &NtfsFcbIndexLookasideList, sizeof(FCB_INDEX), 'FftN', FcbIndexMaxDepth ); PagedInit( &NtfsIndexContextLookasideList, sizeof(INDEX_CONTEXT), 'EftN', IndexContextMaxDepth ); PagedInit( &NtfsLcbLookasideList, sizeof(LCB), 'lftN', LcbMaxDepth ); PagedInit( &NtfsNukemLookasideList, sizeof(NUKEM), 'NftN', NukemMaxDepth ); PagedInit( &NtfsScbDataLookasideList, SIZEOF_SCB_DATA, 'sftN', ScbDataMaxDepth ); // // Initialize the cache manager callback routines, First are the routines // for normal file manipulations, followed by the routines for // volume manipulations. // { PCACHE_MANAGER_CALLBACKS Callbacks = &NtfsData.CacheManagerCallbacks; Callbacks->AcquireForLazyWrite = &NtfsAcquireScbForLazyWrite; Callbacks->ReleaseFromLazyWrite = &NtfsReleaseScbFromLazyWrite; Callbacks->AcquireForReadAhead = &NtfsAcquireScbForReadAhead; Callbacks->ReleaseFromReadAhead = &NtfsReleaseScbFromReadAhead; } { PCACHE_MANAGER_CALLBACKS Callbacks = &NtfsData.CacheManagerVolumeCallbacks; Callbacks->AcquireForLazyWrite = &NtfsAcquireVolumeFileForLazyWrite; Callbacks->ReleaseFromLazyWrite = &NtfsReleaseVolumeFileFromLazyWrite; Callbacks->AcquireForReadAhead = NULL; Callbacks->ReleaseFromReadAhead = NULL; } // // Initialize the queue of read ahead threads // InitializeListHead(&NtfsData.ReadAheadThreads); // // Set up global pointer to our process. // NtfsData.OurProcess = PsGetCurrentProcess(); // // Use a try-finally to cleanup on errors. // try { SECURITY_DESCRIPTOR NewDescriptor; SID_IDENTIFIER_AUTHORITY Authority = SECURITY_NT_AUTHORITY; SubjectContext = NtfsAllocatePool( PagedPool, sizeof( SECURITY_SUBJECT_CONTEXT )); SeCaptureSubjectContext( SubjectContext ); CapturedSubjectContext = TRUE; // // Build the default security descriptor which gives full access to // system and administrator. // AdminSid = (PSID) NtfsAllocatePool( PagedPool, RtlLengthRequiredSid( 2 )); RtlInitializeSid( AdminSid, &Authority, 2 ); *(RtlSubAuthoritySid( AdminSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID; *(RtlSubAuthoritySid( AdminSid, 1 )) = DOMAIN_ALIAS_RID_ADMINS; SystemSid = (PSID) NtfsAllocatePool( PagedPool, RtlLengthRequiredSid( 1 )); RtlInitializeSid( SystemSid, &Authority, 1 ); *(RtlSubAuthoritySid( SystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID; SystemDaclLength = sizeof( ACL ) + (2 * sizeof( ACCESS_ALLOWED_ACE )) + SeLengthSid( AdminSid ) + SeLengthSid( SystemSid ) + 8; // The 8 is just for good measure SystemDacl = NtfsAllocatePool( PagedPool, SystemDaclLength ); Status = RtlCreateAcl( SystemDacl, SystemDaclLength, ACL_REVISION2 ); if (!NT_SUCCESS( Status )) { leave; } Status = RtlAddAccessAllowedAce( SystemDacl, ACL_REVISION2, GENERIC_ALL, SystemSid ); if (!NT_SUCCESS( Status )) { leave; } Status = RtlAddAccessAllowedAce( SystemDacl, ACL_REVISION2, GENERIC_ALL, AdminSid ); if (!NT_SUCCESS( Status )) { leave; } Status = RtlCreateSecurityDescriptor( &NewDescriptor, SECURITY_DESCRIPTOR_REVISION1 ); if (!NT_SUCCESS( Status )) { leave; } Status = RtlSetDaclSecurityDescriptor( &NewDescriptor, TRUE, SystemDacl, FALSE ); if (!NT_SUCCESS( Status )) { leave; } Status = SeAssignSecurity( NULL, &NewDescriptor, &NtfsData.DefaultDescriptor, FALSE, SubjectContext, IoGetFileObjectGenericMapping(), PagedPool ); if (!NT_SUCCESS( Status )) { leave; } NtfsData.DefaultDescriptorLength = RtlLengthSecurityDescriptor( NtfsData.DefaultDescriptor ); ASSERT( SeValidSecurityDescriptor( NtfsData.DefaultDescriptorLength, NtfsData.DefaultDescriptor )); } finally { if (CapturedSubjectContext) { SeReleaseSubjectContext( SubjectContext ); } if (SubjectContext != NULL) { NtfsFreePool( SubjectContext ); } if (SystemDacl != NULL) { NtfsFreePool( SystemDacl ); } if (AdminSid != NULL) { NtfsFreePool( AdminSid ); } if (SystemSid != NULL) { NtfsFreePool( SystemSid ); } } // // Raise if we hit an error building the security descriptor. // if (!NT_SUCCESS( Status )) { ExRaiseStatus( Status ); } // // And return to our caller // DebugTrace( -1, Dbg, ("NtfsInitializeNtfsData -> VOID\n") ); return; }
/*++ * @name GetDosDevicesProtection * * The GetDosDevicesProtection creates a security descriptor for the DOS Devices * Object Directory. * * @param DosDevicesSd * Pointer to the Security Descriptor to return. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks Depending on the DOS Devices Protection Mode (set in the registry), * regular users may or may not have full access to the directory. * *--*/ NTSTATUS NTAPI GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd) { SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; PSID WorldSid, CreatorSid, AdminSid, SystemSid; UCHAR KeyValueBuffer[0x40]; PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; UNICODE_STRING KeyName; ULONG ProtectionMode = 0; OBJECT_ATTRIBUTES ObjectAttributes; PACL Dacl; PACCESS_ALLOWED_ACE Ace; HANDLE hKey; NTSTATUS Status; ULONG ResultLength, SidLength, AclLength; /* Create the SD */ Status = RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION); ASSERT(NT_SUCCESS(Status)); /* Initialize the System SID */ Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the World SID */ Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &WorldSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the Admin SID */ Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); ASSERT(NT_SUCCESS(Status)); /* Initialize the Creator SID */ Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1, SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0, &CreatorSid); ASSERT(NT_SUCCESS(Status)); /* Open the Session Manager Key */ RtlInitUnicodeString(&KeyName, SM_REG_KEY); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* Read the key value */ RtlInitUnicodeString(&KeyName, L"ProtectionMode"); Status = NtQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, KeyValueBuffer, sizeof(KeyValueBuffer), &ResultLength); /* Make sure it's what we expect it to be */ KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer; if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) && (*(PULONG)KeyValuePartialInfo->Data)) { /* Save the Protection Mode */ ProtectionMode = *(PULONG)KeyValuePartialInfo->Data; } /* Close the handle */ NtClose(hKey); } /* Check the Protection Mode */ if (ProtectionMode & 3) { /* Calculate SID Lengths */ SidLength = RtlLengthSid(CreatorSid) + RtlLengthSid(SystemSid) + RtlLengthSid(AdminSid); AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; /* Allocate memory for the DACL */ Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength); ASSERT(Dacl != NULL); /* Build the ACL and add 3 ACEs */ Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, AdminSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, CreatorSid); ASSERT(NT_SUCCESS(Status)); /* Edit the ACEs to make them inheritable */ Status = RtlGetAce(Dacl, 0, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = RtlGetAce(Dacl, 1, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; /* Set this DACL with the SD */ Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE); ASSERT(NT_SUCCESS(Status)); goto Quickie; } else { /* Calculate SID Lengths */ SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid); AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength; /* Allocate memory for the DACL */ Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength); ASSERT(Dacl != NULL); /* Build the ACL and add 3 ACEs */ Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, WorldSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, WorldSid); ASSERT(NT_SUCCESS(Status)); /* Edit the last ACE to make it inheritable */ Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace); ASSERT(NT_SUCCESS(Status)); Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE; /* Set this DACL with the SD */ Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE); ASSERT(NT_SUCCESS(Status)); goto Quickie; } /* FIXME: failure cases! Fail: */ /* Free the memory */ RtlFreeHeap(CsrHeap, 0, Dacl); /* FIXME: semi-failure cases! Quickie: */ Quickie: /* Free the SIDs */ RtlFreeSid(CreatorSid); RtlFreeSid(AdminSid); RtlFreeSid(WorldSid); RtlFreeSid(SystemSid); /* Return */ return Status; }
// Sets the access-control list for a handle to "Everyone:AccessMask" // The handle must be open for WRITE_DAC access static NTSTATUS NtSetObjectAccessForEveryone( IN HANDLE ObjectHandle, IN ACCESS_MASK AccessMask) { SID_IDENTIFIER_AUTHORITY SiaEveryone = SECURITY_WORLD_SID_AUTHORITY; SECURITY_DESCRIPTOR sd; NTSTATUS Status; ULONG cbAclLength = 0; PSID pSidEveryone = NULL; PACL pAcl = NULL; // Get the SID of Everyone Status = RtlAllocateAndInitializeSid(&SiaEveryone, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone); // Allocate space for ACL if(NT_SUCCESS(Status)) { ULONG dwSidLength = RtlLengthSid(pSidEveryone); // Create ACL for full access to the file cbAclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + dwSidLength - sizeof(DWORD); pAcl = (PACL)RtlAllocateHeap(RtlProcessHeap(), 0, cbAclLength); if(pAcl == NULL) Status = STATUS_INSUFFICIENT_RESOURCES; } // Create the Access control list with one ACE if(NT_SUCCESS(Status)) { Status = RtlCreateAcl(pAcl, cbAclLength, ACL_REVISION); } // Add the ACE to the ACL if(NT_SUCCESS(Status)) { Status = RtlAddAccessAllowedAce(pAcl, ACL_REVISION, AccessMask, pSidEveryone); } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the ACL to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetDaclSecurityDescriptor(&sd, TRUE, pAcl, FALSE); } // Apply the security information to the handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, DACL_SECURITY_INFORMATION, &sd); } // Free buffers if(pAcl != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pAcl); if(pSidEveryone != NULL) RtlFreeSid(pSidEveryone); return Status; }
PSECURITY_DESCRIPTOR NTAPI INIT_FUNCTION CmpHiveRootSecurityDescriptor(VOID) { NTSTATUS Status; PSECURITY_DESCRIPTOR SecurityDescriptor; PACL Acl, AclCopy; PSID Sid[4]; SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; ULONG AceLength, AclLength, SidLength; PACE_HEADER AceHeader; ULONG i; PAGED_CODE(); /* Phase 1: Allocate SIDs */ SidLength = RtlLengthRequiredSid(1); Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); SidLength = RtlLengthRequiredSid(2); Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM); /* Make sure all SIDs were allocated */ if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3])) { /* Bugcheck */ KeBugCheckEx(REGISTRY_ERROR, 11, 1, 0, 0); } /* Phase 2: Initialize all SIDs */ Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1); Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1); Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1); Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2); if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 2, 0, 0); /* Phase 2: Setup SID Sub Authorities */ *RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID; *RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID; *RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID; *RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID; *RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS; /* Make sure all SIDs are valid */ ASSERT(RtlValidSid(Sid[0])); ASSERT(RtlValidSid(Sid[1])); ASSERT(RtlValidSid(Sid[2])); ASSERT(RtlValidSid(Sid[3])); /* Phase 3: Calculate ACL Length */ AclLength = sizeof(ACL); for (i = 0; i < 4; i++) { /* This is what MSDN says to do */ AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart); AceLength += SeLengthSid(Sid[i]); AclLength += AceLength; } /* Phase 3: Allocate the ACL */ Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM); if (!Acl) KeBugCheckEx(REGISTRY_ERROR, 11, 3, 0, 0); /* Phase 4: Create the ACL */ Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION); if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 4, Status, 0); /* Phase 5: Build the ACL */ Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]); Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]); Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]); Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]); if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 5, Status, 0); /* Phase 5: Make the ACEs inheritable */ Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader); ASSERT(NT_SUCCESS(Status)); AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader); ASSERT(NT_SUCCESS(Status)); AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader); ASSERT(NT_SUCCESS(Status)); AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader); ASSERT(NT_SUCCESS(Status)); AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; /* Phase 6: Allocate the security descriptor and make space for the ACL */ SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, sizeof(SECURITY_DESCRIPTOR) + AclLength, TAG_CM); if (!SecurityDescriptor) KeBugCheckEx(REGISTRY_ERROR, 11, 6, 0, 0); /* Phase 6: Make a copy of the ACL */ AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1); RtlCopyMemory(AclCopy, Acl, AclLength); /* Phase 7: Create the security descriptor */ Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 7, Status, 0); /* Phase 8: Set the ACL as a DACL */ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, AclCopy, FALSE); if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 8, Status, 0); /* Free the SIDs and original ACL */ for (i = 0; i < 4; i++) ExFreePoolWithTag(Sid[i], TAG_CM); ExFreePoolWithTag(Acl, TAG_CM); /* Return the security descriptor */ return SecurityDescriptor; }
static NTSTATUS SrvBuildDefaultShareSID( PSECURITY_DESCRIPTOR_RELATIVE* ppSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_RELATIVE pRelSecDesc = NULL; ULONG ulRelSecDescLen = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsSecDesc = NULL; DWORD dwAceCount = 0; PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; DWORD dwSizeDacl = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } localSystemSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } administratorsSid; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } builtinUsersSid; ULONG ulLocalSystemSidSize = sizeof(localSystemSid.buffer); ULONG ulAdministratorsSidSize = sizeof(administratorsSid.buffer); ULONG ulBuiltinUsersSidSize = sizeof(builtinUsersSid.buffer); ACCESS_MASK builtinUsersAccessMask = 0; ULONG ulAceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; /* Build the new Absolute Security Descriptor */ ntStatus = RTL_ALLOCATE( &pAbsSecDesc, VOID, SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateSecurityDescriptorAbsolute( pAbsSecDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); /* Create some SIDs */ ntStatus = RtlCreateWellKnownSid( WinLocalSystemSid, NULL, (PSID)localSystemSid.buffer, &ulLocalSystemSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, (PSID)administratorsSid.buffer, &ulAdministratorsSidSize); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateWellKnownSid( WinBuiltinUsersSid, NULL, (PSID)builtinUsersSid.buffer, &ulBuiltinUsersSidSize); BAIL_ON_NT_STATUS(ntStatus); /* Owner: Local System */ ntStatus = RtlDuplicateSid(&pOwnerSid, &localSystemSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetOwnerSecurityDescriptor( pAbsSecDesc, pOwnerSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Group: Administrators */ ntStatus = RtlDuplicateSid(&pGroupSid, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetGroupSecurityDescriptor( pAbsSecDesc, pGroupSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* DACL: Administrators - (Full Control) LocalSystem - (Full Control) Builtin Users - (Read && Execute && List Directory Contents) */ dwAceCount = 3; dwSizeDacl = ACL_HEADER_SIZE + dwAceCount * sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&localSystemSid.sid) + RtlLengthSid(&administratorsSid.sid) + RtlLengthSid(&builtinUsersSid.sid) - dwAceCount * sizeof(ULONG); ntStatus= RTL_ALLOCATE(&pDacl, VOID, dwSizeDacl); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlCreateAcl(pDacl, dwSizeDacl, ACL_REVISION); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, FILE_ALL_ACCESS, &localSystemSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, FILE_ALL_ACCESS, &administratorsSid.sid); BAIL_ON_NT_STATUS(ntStatus); builtinUsersAccessMask = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE; ntStatus = RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, ulAceFlags, builtinUsersAccessMask, &builtinUsersSid.sid); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetDaclSecurityDescriptor( pAbsSecDesc, TRUE, pDacl, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* Create the SelfRelative SD */ ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, NULL, &ulRelSecDescLen); if (ntStatus == STATUS_BUFFER_TOO_SMALL) { ntStatus = SrvAllocateMemory(ulRelSecDescLen, (PVOID*)&pRelSecDesc); BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlAbsoluteToSelfRelativeSD( pAbsSecDesc, pRelSecDesc, &ulRelSecDescLen); } BAIL_ON_NT_STATUS(ntStatus); *ppSecDesc = pRelSecDesc; cleanup: RTL_FREE(&pAbsSecDesc); RTL_FREE(&pOwnerSid); RTL_FREE(&pGroupSid); RTL_FREE(&pDacl); return ntStatus; error: *ppSecDesc = NULL; if (pRelSecDesc) { SrvFreeMemory(pRelSecDesc); } goto cleanup; }
void ApfInitDll () { NTSTATUS Status; DWORD ulInitElapsedTime; SHORT sInitTimerHandle; DWORD ARGS64; #ifdef CALIBDBG SHORT sTimerHandle; ULONG ulElapsedTime; #endif #ifdef ERRORDBG DWORD Error; #endif int i; STRING DataSemName; UNICODE_STRING DataSemUnicodeName; OBJECT_ATTRIBUTES DataSemAttributes; // Create public share security descriptor for all the named objects // Status = RtlCreateSecurityDescriptor ( &SecDescriptor, SECURITY_DESCRIPTOR_REVISION1 ); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: RtlCreateSecurityDescriptor falied - 0x%lx\n", Status)); } #endif Status = RtlSetDaclSecurityDescriptor ( &SecDescriptor, // SecurityDescriptor TRUE, // DaclPresent NULL, // Dacl FALSE // DaclDefaulted ); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: RtlSetDaclSecurityDescriptor falied - 0x%lx\n", Status)); } #endif // Create sections for data and api arrays // if ( NT_SUCCESS(ApfCreateDataSection(&ApfControl)) ) { // Leave room for control flag // ApfData = (PAPFDATA)(ApfControl+1); // Initialization for semaphore creation // RtlInitString(&DataSemName, DATA_SEM_NAME); Status = RtlAnsiStringToUnicodeString( &DataSemUnicodeName, &DataSemName, TRUE); if (NT_SUCCESS(Status)) { InitializeObjectAttributes( &DataSemAttributes, &DataSemUnicodeName, OBJ_OPENIF | OBJ_CASE_INSENSITIVE, NULL, &SecDescriptor); } // Create semaphores // Status = NtCreateSemaphore( &hDataSem, SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, &DataSemAttributes, 1L, 1L); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Data semaphore creation falied %lx\n", Status)); } #endif // Get semaphores // Status = NtWaitForSingleObject(hDataSem,FALSE,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n", Status)); } #endif // // Do timer calibration if not already done. // if (!ApfControl->fCalibrate) { ApfControl->fCalibrate = TRUE; // // Calibrate time overheads: // we get the minimum time here, to avoid extra time from // interrupts etc. // the tedious approach has two benefits // - duplicate generated code as accurately as possible // - pick up timer overhead, that isn't handled correctly // in timer // NOTE: ApfData[I_CALIBRATE].ulMinTime contains the // timer overhead, while ApfData[I_CALIBRATE].cCalls // contains the number of processess accessing this // DLL. // ApfData[I_CALIBRATE].cCalls = 0L; ApfData[I_CALIBRATE].cTimingErrors = 0L; ApfData[I_CALIBRATE].ulTotalTime = 0L; ApfData[I_CALIBRATE].ulFirstTime = MAX_LONG; ApfData[I_CALIBRATE].ulMaxTime = MAX_LONG; ApfData[I_CALIBRATE].ulMinTime = MAX_LONG; ApfClearData(); TimerOpen(&sInitTimerHandle, MICROSECONDS); #ifdef CALIBDBG // Release semaphore // Status = NtReleaseSemaphore(hDataSem,1,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n", Status)); } #endif // // Overhead for all the API wrapper code // Stored in ApfData[I_CALIBRATE].ulMaxTime // Used for debugging - for WOW profiling overhead. // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); if (fInitDone == FALSE) { } TimerOpen(&sTimerHandle, MICROSECONDS); TimerInit(sTimerHandle); // // Get the elapsed time // ulElapsedTime = TimerRead(sTimerHandle); ApfRecordInfo(1, ulElapsedTime); TimerClose(sTimerHandle); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMaxTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulMaxTime = ulInitElapsedTime; } } // Get semaphores // Status = NtWaitForSingleObject(hDataSem,FALSE,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Could not wait for Dsemaphore in ApfInitDll, %lx\n", Status)); } #endif #endif // // Excess overhead for TimerInit() followed by TimerREad() calls // Stored in ApfData[I_CALIBRATE].ulMinTime // Used by all APIs // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulMinTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulMinTime = ulInitElapsedTime; } } // // Oerhead for calling cdecl APIs with 64 DWORD arguments // Stored in ApfData[I_CALIBRATE].ulFirstTime // Used by all variable argument cdecl APIs such as wsprintf() // for (i=0; i<NUM_ITRATIONS; i++) { TimerInit(sInitTimerHandle); CalibCdeclApi (ARGS64); ulInitElapsedTime = TimerRead(sInitTimerHandle); if ((ulInitElapsedTime < ApfData[I_CALIBRATE].ulFirstTime) && (ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD)) { ApfData[I_CALIBRATE].ulFirstTime = ulInitElapsedTime; } } ApfData[I_CALIBRATE].ulFirstTime -= ApfData[I_CALIBRATE].ulMinTime; TimerClose(sInitTimerHandle); } // Increment the number of active processes on this DLL // ApfData[I_CALIBRATE].cCalls++; // Load the module being profiled // hModule=GetModuleHandle(MODULE_NAME); #ifdef ERRORDBG if (hModule==NULL) { Error=GetLastError(); KdPrint (("WAP: Module Handle is null - %lx\n",Error)); } #endif // Release semaphore // Status = NtReleaseSemaphore(hDataSem,1,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: DSemaphore Not Released in ApfInitDll!! %lx\n", Status)); } #endif fInitDone = TRUE; } #ifdef ERRORDBG else { KdPrint (("WAP: Couldn't create DATA section in ApfInitDll\n")); } #endif } /* ApfInitDll () */
VOID SepInitProcessAuditSd( VOID ) /*++ Routine Description: This function initializes SepProcessAuditSd -- a security descriptor that is used by SepAddSaclToProcess to add SACL to the existing security descriptor on a system process. A system process is defined as the one whose token has at least one of the following sids. -- SeLocalSystemSid -- SeLocalServiceSid -- SeNetworkServiceSid Arguments: None. Return Value: None. --*/ { #define PROCESS_ACCESSES_TO_AUDIT ( PROCESS_CREATE_THREAD |\ PROCESS_SET_INFORMATION |\ PROCESS_SET_PORT |\ PROCESS_SUSPEND_RESUME ) NTSTATUS Status = STATUS_SUCCESS; ULONG AclLength, TotalSdLength; PISECURITY_DESCRIPTOR Sd = NULL; PISECURITY_DESCRIPTOR Sd2 = NULL; PACL Acl = NULL; // // free earlier instance if present // if ( SepProcessAuditSd != NULL ) { ExFreePool( SepProcessAuditSd ); SepProcessAuditSd = NULL; } // // Don't initialize SeProcessAuditSd if SepProcessAccessesToAudit is 0 // This effectively disables process access auditing // if ( SepProcessAccessesToAudit == 0 ) { goto Cleanup; } AclLength = (ULONG)sizeof(ACL) + ((ULONG)sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG)) + SeLengthSid( SeWorldSid ); TotalSdLength = sizeof(SECURITY_DESCRIPTOR) + AclLength; Sd = (PSECURITY_DESCRIPTOR) ExAllocatePoolWithTag( NonPagedPool, TotalSdLength, 'cAeS'); if ( Sd == NULL ) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Acl = (PACL) (Sd + 1); Status = RtlCreateAcl( Acl, AclLength, ACL_REVISION2 ); if ( NT_SUCCESS( Status )) { Status = RtlAddAuditAccessAce( Acl, ACL_REVISION2, SepProcessAccessesToAudit, SeWorldSid, TRUE, TRUE ); if ( NT_SUCCESS( Status )) { Status = RtlCreateSecurityDescriptor( Sd, SECURITY_DESCRIPTOR_REVISION1 ); if ( NT_SUCCESS( Status )) { Status = RtlSetSaclSecurityDescriptor( Sd, TRUE, Acl, FALSE ); if ( NT_SUCCESS( Status )) { SepProcessAuditSd = Sd; } } } } ASSERT( NT_SUCCESS(Status) ); if ( !NT_SUCCESS( Status )) { goto Cleanup; } // // create and initialize SepImportantProcessSd // AclLength = (ULONG)sizeof(ACL) + (3*((ULONG)sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) + SeLengthSid( SeLocalSystemSid ) + SeLengthSid( SeLocalServiceSid ) + SeLengthSid( SeNetworkServiceSid ); TotalSdLength = sizeof(SECURITY_DESCRIPTOR) + AclLength; Sd2 = (PSECURITY_DESCRIPTOR) ExAllocatePoolWithTag( NonPagedPool, TotalSdLength, 'cAeS'); if ( Sd2 == NULL ) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Acl = (PACL) (Sd2 + 1); Status = RtlCreateAcl( Acl, AclLength, ACL_REVISION2 ); if ( NT_SUCCESS( Status )) { Status = RtlAddAccessAllowedAce( Acl, ACL_REVISION2, SEP_QUERY_MEMBERSHIP, SeLocalSystemSid ); if ( !NT_SUCCESS( Status )) { goto Cleanup; } Status = RtlAddAccessAllowedAce( Acl, ACL_REVISION2, SEP_QUERY_MEMBERSHIP, SeLocalServiceSid ); if ( !NT_SUCCESS( Status )) { goto Cleanup; } Status = RtlAddAccessAllowedAce( Acl, ACL_REVISION2, SEP_QUERY_MEMBERSHIP, SeNetworkServiceSid ); if ( !NT_SUCCESS( Status )) { goto Cleanup; } Status = RtlCreateSecurityDescriptor( Sd2, SECURITY_DESCRIPTOR_REVISION1 ); if ( NT_SUCCESS( Status )) { Status = RtlSetDaclSecurityDescriptor( Sd2, TRUE, Acl, FALSE ); if ( NT_SUCCESS( Status )) { SepImportantProcessSd = Sd2; } } } Cleanup: if ( !NT_SUCCESS( Status )) { ASSERT( FALSE && L"SepInitProcessAuditSd failed" ); // // this will bugcheck if SepCrashOnAuditFail is TRUE // SepAuditFailed( Status ); if ( Sd ) { ExFreePool( Sd ); Sd = NULL; SepProcessAuditSd = NULL; } if ( Sd2 ) { ExFreePool( Sd2 ); Sd2 = NULL; SepImportantProcessSd = NULL; } } }
NTSTATUS PhSvcApiPortInitialization( _In_ PUNICODE_STRING PortName ) { static SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; PSECURITY_DESCRIPTOR securityDescriptor; ULONG sdAllocationLength; UCHAR administratorsSidBuffer[FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * 2]; PSID administratorsSid; PACL dacl; ULONG i; // Create the API port. administratorsSid = (PSID)administratorsSidBuffer; RtlInitializeSid(administratorsSid, &ntAuthority, 2); *RtlSubAuthoritySid(administratorsSid, 0) = SECURITY_BUILTIN_DOMAIN_RID; *RtlSubAuthoritySid(administratorsSid, 1) = DOMAIN_ALIAS_RID_ADMINS; sdAllocationLength = SECURITY_DESCRIPTOR_MIN_LENGTH + (ULONG)sizeof(ACL) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(administratorsSid) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&PhSeEveryoneSid); securityDescriptor = PhAllocate(sdAllocationLength); dacl = (PACL)PTR_ADD_OFFSET(securityDescriptor, SECURITY_DESCRIPTOR_MIN_LENGTH); RtlCreateSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION); RtlCreateAcl(dacl, sdAllocationLength - SECURITY_DESCRIPTOR_MIN_LENGTH, ACL_REVISION); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_ALL_ACCESS, administratorsSid); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_CONNECT, &PhSeEveryoneSid); RtlSetDaclSecurityDescriptor(securityDescriptor, TRUE, dacl, FALSE); InitializeObjectAttributes( &objectAttributes, PortName, OBJ_CASE_INSENSITIVE, NULL, securityDescriptor ); status = NtCreatePort( &PhSvcApiPortHandle, &objectAttributes, sizeof(PHSVC_API_CONNECTINFO), PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG), 0 ); PhFree(securityDescriptor); if (!NT_SUCCESS(status)) return status; // Start the API threads. PhSvcApiThreadContextTlsIndex = TlsAlloc(); for (i = 0; i < 2; i++) { PhCreateThread2(PhSvcApiRequestThreadStart, NULL); } return status; }
VOID SepInitSystemDacls( VOID ) /*++ Routine Description: This function initializes the system's default dacls & security descriptors. Arguments: None. Return Value: None. --*/ { NTSTATUS Status; ULONG PublicLength, PublicUnrestrictedLength, SystemLength, PublicOpenLength, LocalServiceLength; PAGED_CODE(); // // Set up a default ACLs // // Public: WORLD:execute, SYSTEM:all, ADMINS:all // PublicUnrestricted: WORLD:execute, SYSTEM:all, ADMINS:all, Restricted:execute // Public Open: WORLD:(Read|Write|Execute), ADMINS:(all), SYSTEM:all // System: SYSTEM:all, ADMINS:(read|execute|read_control) // Unrestricted: WORLD:(all), Restricted:(all) SystemLength = (ULONG)sizeof(ACL) + (2*((ULONG)sizeof(ACCESS_ALLOWED_ACE))) + SeLengthSid( SeLocalSystemSid ) + SeLengthSid( SeAliasAdminsSid ); PublicLength = SystemLength + ((ULONG)sizeof(ACCESS_ALLOWED_ACE)) + SeLengthSid( SeWorldSid ); PublicUnrestrictedLength = PublicLength + ((ULONG)sizeof(ACCESS_ALLOWED_ACE)) + SeLengthSid( SeRestrictedSid ); PublicOpenLength = PublicLength; LocalServiceLength = (ULONG)sizeof(ACL) + 4 * (ULONG)sizeof(ACCESS_ALLOWED_ACE) + SeLengthSid(SeWorldSid) + SeLengthSid(SeLocalSystemSid) + SeLengthSid(SeLocalServiceSid) + SeLengthSid(SeAliasAdminsSid); SePublicDefaultDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicLength, 'cAeS'); SePublicDefaultUnrestrictedDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicUnrestrictedLength, 'cAeS'); SePublicOpenDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicOpenLength, 'cAeS'); SePublicOpenUnrestrictedDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicUnrestrictedLength, 'cAeS'); SeSystemDefaultDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, SystemLength, 'cAeS'); SeLocalServicePublicDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, LocalServiceLength, 'cAeS'); ASSERT(SePublicDefaultDacl != NULL); ASSERT(SePublicDefaultUnrestrictedDacl != NULL); ASSERT(SePublicOpenDacl != NULL); ASSERT(SePublicOpenUnrestrictedDacl != NULL); ASSERT(SeSystemDefaultDacl != NULL); ASSERT(SeLocalServicePublicDacl != NULL); Status = RtlCreateAcl( SePublicDefaultDacl, PublicLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlCreateAcl( SePublicDefaultUnrestrictedDacl, PublicUnrestrictedLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlCreateAcl( SePublicOpenDacl, PublicOpenLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlCreateAcl( SePublicOpenUnrestrictedDacl, PublicUnrestrictedLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlCreateAcl( SeSystemDefaultDacl, SystemLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); Status = RtlCreateAcl( SeLocalServicePublicDacl, LocalServiceLength, ACL_REVISION2); ASSERT( NT_SUCCESS(Status) ); // // WORLD access (Public DACLs and OpenUnrestricted only) // Status = RtlAddAccessAllowedAce ( SePublicDefaultDacl, ACL_REVISION2, GENERIC_EXECUTE, SeWorldSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicDefaultUnrestrictedDacl, ACL_REVISION2, GENERIC_EXECUTE, SeWorldSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenDacl, ACL_REVISION2, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE), SeWorldSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenUnrestrictedDacl, ACL_REVISION2, (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE), SeWorldSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SeLocalServicePublicDacl, ACL_REVISION2, GENERIC_EXECUTE, SeWorldSid ); ASSERT( NT_SUCCESS(Status) ); // // SYSTEM access (PublicDefault, PublicOpen, and SystemDefault) // Status = RtlAddAccessAllowedAce ( SePublicDefaultDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicDefaultUnrestrictedDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenUnrestrictedDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SeSystemDefaultDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SeLocalServicePublicDacl, ACL_REVISION2, GENERIC_ALL, SeLocalSystemSid ); ASSERT( NT_SUCCESS(Status) ); // // ADMINISTRATORS access (PublicDefault, PublicOpen, and SystemDefault) // Status = RtlAddAccessAllowedAce ( SePublicDefaultDacl, ACL_REVISION2, GENERIC_ALL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicDefaultUnrestrictedDacl, ACL_REVISION2, GENERIC_ALL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenDacl, ACL_REVISION2, GENERIC_ALL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenUnrestrictedDacl, ACL_REVISION2, GENERIC_ALL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SeSystemDefaultDacl, ACL_REVISION2, GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SeLocalServicePublicDacl, ACL_REVISION2, GENERIC_ALL, SeAliasAdminsSid ); ASSERT( NT_SUCCESS(Status) ); // // RESTRICTED access (PublicDefaultUnrestricted and OpenUnrestricted) // Status = RtlAddAccessAllowedAce ( SePublicDefaultUnrestrictedDacl, ACL_REVISION2, GENERIC_EXECUTE, SeRestrictedSid ); ASSERT( NT_SUCCESS(Status) ); Status = RtlAddAccessAllowedAce ( SePublicOpenUnrestrictedDacl, ACL_REVISION2, GENERIC_EXECUTE | GENERIC_READ, SeRestrictedSid ); ASSERT( NT_SUCCESS(Status) ); // // Local Service // Status = RtlAddAccessAllowedAce ( SeLocalServicePublicDacl, ACL_REVISION2, GENERIC_ALL, SeLocalServiceSid ); ASSERT( NT_SUCCESS(Status) ); // // Now initialize security descriptors // that export this protection // SePublicDefaultSd = (PSECURITY_DESCRIPTOR)&SepPublicDefaultSd; Status = RtlCreateSecurityDescriptor( SePublicDefaultSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SePublicDefaultSd, TRUE, // DaclPresent SePublicDefaultDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); SePublicDefaultUnrestrictedSd = (PSECURITY_DESCRIPTOR)&SepPublicDefaultUnrestrictedSd; Status = RtlCreateSecurityDescriptor( SePublicDefaultUnrestrictedSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SePublicDefaultUnrestrictedSd, TRUE, // DaclPresent SePublicDefaultUnrestrictedDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); SePublicOpenSd = (PSECURITY_DESCRIPTOR)&SepPublicOpenSd; Status = RtlCreateSecurityDescriptor( SePublicOpenSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SePublicOpenSd, TRUE, // DaclPresent SePublicOpenDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); SePublicOpenUnrestrictedSd = (PSECURITY_DESCRIPTOR)&SepPublicOpenUnrestrictedSd; Status = RtlCreateSecurityDescriptor( SePublicOpenUnrestrictedSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SePublicOpenUnrestrictedSd, TRUE, // DaclPresent SePublicOpenUnrestrictedDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); SeSystemDefaultSd = (PSECURITY_DESCRIPTOR)&SepSystemDefaultSd; Status = RtlCreateSecurityDescriptor( SeSystemDefaultSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SeSystemDefaultSd, TRUE, // DaclPresent SeSystemDefaultDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); SeLocalServicePublicSd = (PSECURITY_DESCRIPTOR)&SepLocalServicePublicSd; Status = RtlCreateSecurityDescriptor( SeLocalServicePublicSd, SECURITY_DESCRIPTOR_REVISION1 ); ASSERT( NT_SUCCESS(Status) ); Status = RtlSetDaclSecurityDescriptor( SeLocalServicePublicSd, TRUE, // DaclPresent SeLocalServicePublicDacl, FALSE // DaclDefaulted ); ASSERT( NT_SUCCESS(Status) ); return; }
//---------------------------------------------------------------------- // // NTIRemoveWorldAce // // Scans the passed security descriptor's DACL, looking for // the World SID's ACE (its first because the of the way device object // security descriptors are created) and removes it. // // If successful, the original security descriptor is deallocated // and a new one is returned. // //---------------------------------------------------------------------- NTSTATUS NTIRemoveWorldAce( PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR *NewSecurityDescriptor ) { PSECURITY_DESCRIPTOR absSecurityDescriptor; PSECURITY_DESCRIPTOR relSecurityDescriptor; PACE_HEADER aceHeader; NTSTATUS status; PACL Dacl; BOOLEAN DaclPresent, DaclDefaulted; USHORT aceIndex; ULONG worldSidLength; SID_IDENTIFIER_AUTHORITY worldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; PULONG worldSidSubAuthority; ULONG relLength; PSID worldSid; PSID aceSid; // // First, get an absolute version of the self-relative descriptor // relLength = RtlLengthSecurityDescriptor( SecurityDescriptor ); status = NTIMakeAbsoluteSD( SecurityDescriptor, &absSecurityDescriptor ); if( !NT_SUCCESS( status )) { return status; } // // Pull the DACL out so that we can scan it // status = RtlGetDaclSecurityDescriptor( absSecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted ); if( !NT_SUCCESS( status ) || !DaclPresent ) { DbgPrint(("Secsys: strange - couldn't get DACL from our absolute SD: %x\n", status )); ExFreePool( absSecurityDescriptor ); return status; } // // Initialize a SID that identifies the world-authority so // that we can recognize it in the ACL // worldSidLength = RtlLengthRequiredSid( 1 ); worldSid = (PSID) ExAllocatePool( PagedPool, worldSidLength ); RtlInitializeSid( worldSid, &worldSidAuthority, 1 ); worldSidSubAuthority = RtlSubAuthoritySid( worldSid, 0 ); *worldSidSubAuthority = SECURITY_WORLD_RID; // // Now march through the ACEs looking for the World ace. We could // do one of two things: // // - remove the ACE // - convert it into a grant-nothing ACE // // For demonstration purposes I'll remove the ACE. In addition, // this requires that I implement kernel-mode GetAce and DeleteAce functions, // since they are not implemented by the NT kernel. // DbgPrint(("Secsys: %d ACEs in DACL\n", Dacl->AceCount )); for( aceIndex = 0; aceIndex < Dacl->AceCount; aceIndex++ ) { aceHeader = NTIGetAce( Dacl, aceIndex ); DbgPrint((" ACE: type: %s mask: %x\n", (aceHeader->AceType & ACCESS_DENIED_ACE_TYPE ? "Deny" : "Allow"), *(PULONG) ((PUCHAR) aceHeader + sizeof(ACE_HEADER)))); // // Get the SID in this ACE and see if its the WORLD (Everyone) SID // aceSid = (PSID) ((PUCHAR) aceHeader + sizeof(ACE_HEADER) + sizeof(ULONG)); if( RtlEqualSid( worldSid, aceSid )) { // // We found it: remove it. // DbgPrint(("Secsys: Deleting ace %d\n", aceIndex )); NTIDeleteAce( Dacl, aceIndex ); break; } } // // Write new DACL back to security descriptor // status = RtlSetDaclSecurityDescriptor( absSecurityDescriptor, TRUE, Dacl, FALSE ); if( !NT_SUCCESS( status )) { DbgPrint(("Secsys: Could not update SD Dacl: %x\n", status )); goto cleanup; } // // Make sure its valid // if( !RtlValidSecurityDescriptor( absSecurityDescriptor )) { DbgPrint(("Secsys: SD after remove is invalid!\n")); status = STATUS_UNSUCCESSFUL; goto cleanup; } // // Now convert the security descriptor back to // self-relative // relSecurityDescriptor = ExAllocatePool( PagedPool, relLength ); status = RtlAbsoluteToSelfRelativeSD( absSecurityDescriptor, relSecurityDescriptor, &relLength ); if( !NT_SUCCESS( status )) { DbgPrint(("Could not convert absolute SD to relative: %x\n", status )); } // // Final step, free the original security descriptor and return the new one // ExFreePool( SecurityDescriptor ); *NewSecurityDescriptor = relSecurityDescriptor; cleanup: ExFreePool( worldSid ); ExFreePool( absSecurityDescriptor ); return status; }
NTSTATUS ObpGetDosDevicesProtection( PSECURITY_DESCRIPTOR SecurityDescriptor ) /*++ Routine Description: This routine builds a security descriptor for use in creating the \DosDevices object directory. The protection of \DosDevices must establish inheritable protection which will dictate how dos devices created via the DefineDosDevice() and IoCreateUnprotectedSymbolicLink() apis can be managed. The protection assigned is dependent upon an administrable registry key: Key: \hkey_local_machine\System\CurrentControlSet\Control\Session Manager Value: [REG_DWORD] ProtectionMode If this value is 0x1, then Administrators may control all Dos devices, Anyone may create new Dos devices (such as net drives or additional printers), Anyone may use any Dos device, The creator of a Dos device may delete it. Note that this protects system-defined LPTs and COMs so that only administrators may redirect them. However, anyone may add additional printers and direct them to wherever they would like. This is achieved with the following protection for the DosDevices Directory object: Grant: World: Execute | Read | Write (No Inherit) Grant: System: All Access (No Inherit) Grant: World: Execute (Inherit Only) Grant: Admins: All Access (Inherit Only) Grant: System: All Access (Inherit Only) Grant: Owner: All Access (Inherit Only) If this value is 0x0, or not present, then Administrators may control all Dos devices, Anyone may create new Dos devices (such as net drives or additional printers), Anyone may use any Dos device, Anyone may delete Dos devices created with either DefineDosDevice() or IoCreateUnprotectedSymbolicLink(). This is how network drives and LPTs are created (but not COMs). This is achieved with the following protection for the DosDevices Directory object: Grant: World: Execute | Read | Write (No Inherit) Grant: System: All Access (No Inherit) Grant: World: All Access (Inherit Only) Arguments: SecurityDescriptor - The address of a security descriptor to be initialized and filled in. When this security descriptor is no longer needed, you should call ObpFreeDosDevicesProtection() to free the protection information. Return Value: Returns one of the following status codes: STATUS_SUCCESS - normal, successful completion. STATUS_NO_MEMORY - not enough memory --*/ { NTSTATUS Status; ULONG aceIndex, aclLength; PACL dacl; PACE_HEADER ace; ACCESS_MASK accessMask; UCHAR inheritOnlyFlags = (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE ); // // NOTE: This routine expects the value of ObpProtectionMode to have been set // Status = RtlCreateSecurityDescriptor( SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); ASSERT( NT_SUCCESS( Status ) ); if (ObpProtectionMode & 0x00000001) { // // Dacl: // Grant: World: Execute | Read | Write (No Inherit) // Grant: System: All Access (No Inherit) // Grant: World: Execute (Inherit Only) // Grant: Admins: All Access (Inherit Only) // Grant: System: All Access (Inherit Only) // Grant: Owner: All Access (Inherit Only) // aclLength = sizeof( ACL ) + 6 * sizeof( ACCESS_ALLOWED_ACE ) + (2*RtlLengthSid( SeWorldSid )) + (2*RtlLengthSid( SeLocalSystemSid )) + RtlLengthSid( SeAliasAdminsSid ) + RtlLengthSid( SeCreatorOwnerSid ); dacl = (PACL)ExAllocatePool(PagedPool, aclLength ); if (dacl == NULL) { return STATUS_NO_MEMORY; } Status = RtlCreateAcl( dacl, aclLength, ACL_REVISION2); ASSERT( NT_SUCCESS( Status ) ); // // Non-inheritable ACEs first // World // System // aceIndex = 0; accessMask = (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeWorldSid ); ASSERT( NT_SUCCESS( Status ) ); aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeLocalSystemSid ); ASSERT( NT_SUCCESS( Status ) ); // // Inheritable ACEs at the end of the ACL // World // Admins // System // Owner // aceIndex++; accessMask = (GENERIC_EXECUTE); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeWorldSid ); ASSERT( NT_SUCCESS( Status ) ); Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace ); ASSERT( NT_SUCCESS( Status ) ); ace->AceFlags |= inheritOnlyFlags; aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeAliasAdminsSid ); ASSERT( NT_SUCCESS( Status ) ); Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace ); ASSERT( NT_SUCCESS( Status ) ); ace->AceFlags |= inheritOnlyFlags; aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeLocalSystemSid ); ASSERT( NT_SUCCESS( Status ) ); Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace ); ASSERT( NT_SUCCESS( Status ) ); ace->AceFlags |= inheritOnlyFlags; aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeCreatorOwnerSid ); ASSERT( NT_SUCCESS( Status ) ); Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace ); ASSERT( NT_SUCCESS( Status ) ); ace->AceFlags |= inheritOnlyFlags; Status = RtlSetDaclSecurityDescriptor ( SecurityDescriptor, TRUE, //DaclPresent, dacl, //Dacl FALSE //!DaclDefaulted ); ASSERT( NT_SUCCESS( Status ) ); } else { // // DACL: // Grant: World: Execute | Read | Write (No Inherit) // Grant: System: All Access (No Inherit) // Grant: World: All Access (Inherit Only) // aclLength = sizeof( ACL ) + 3 * sizeof( ACCESS_ALLOWED_ACE ) + (2*RtlLengthSid( SeWorldSid )) + RtlLengthSid( SeLocalSystemSid ); dacl = (PACL)ExAllocatePool(PagedPool, aclLength ); if (dacl == NULL) { return STATUS_NO_MEMORY; } Status = RtlCreateAcl( dacl, aclLength, ACL_REVISION2); ASSERT( NT_SUCCESS( Status ) ); // // Non-inheritable ACEs first // World // System // aceIndex = 0; accessMask = (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeWorldSid ); ASSERT( NT_SUCCESS( Status ) ); aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeLocalSystemSid ); ASSERT( NT_SUCCESS( Status ) ); // // Inheritable ACEs at the end of the ACL // World // aceIndex++; accessMask = (GENERIC_ALL); Status = RtlAddAccessAllowedAce ( dacl, ACL_REVISION2, accessMask, SeWorldSid ); ASSERT( NT_SUCCESS( Status ) ); Status = RtlGetAce( dacl, aceIndex, (PVOID)&ace ); ASSERT( NT_SUCCESS( Status ) ); ace->AceFlags |= inheritOnlyFlags; Status = RtlSetDaclSecurityDescriptor ( SecurityDescriptor, TRUE, //DaclPresent, dacl, //Dacl FALSE //!DaclDefaulted ); ASSERT( NT_SUCCESS( Status ) ); } return STATUS_SUCCESS; }