/* * @implemented */ BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted) { NTSTATUS Status; Status = RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(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; }
// Takes ownership on handle (file or registry key). // The handle must be open for WRITE_OWNER access static NTSTATUS NtTakeOwnershipObject(HANDLE ObjectHandle) { SECURITY_DESCRIPTOR sd; PTOKEN_USER pTokenUser = NULL; NTSTATUS Status; HANDLE TokenHandle = NULL; ULONG cbTokenUser = 0; // Open the token of the current process Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle); if(NT_SUCCESS(Status)) { NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); if(cbTokenUser == 0) { NtClose(TokenHandle); return STATUS_UNSUCCESSFUL; } pTokenUser = (PTOKEN_USER)RtlAllocateHeap(RtlProcessHeap(), 0, cbTokenUser); if(pTokenUser != NULL) { Status = NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); } else { Status = STATUS_NO_MEMORY; } } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the owner to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetOwnerSecurityDescriptor(&sd, pTokenUser->User.Sid, FALSE); } // Apply the owner to the object handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, OWNER_SECURITY_INFORMATION, &sd); } // Free buffers if(pTokenUser != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pTokenUser); if(TokenHandle != NULL) NtClose(TokenHandle); return Status; }
static NTSTATUS RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath, IN PSECURITY_DESCRIPTOR SecurityDescriptor) { TOKEN_PRIVILEGES TokenPrivileges; OBJECT_ATTRIBUTES ObjectAttributes; SECURITY_DESCRIPTOR AbsSD; PSID AdminSid = NULL; IO_STATUS_BLOCK IoStatusBlock; BOOLEAN TokenEnabled = FALSE; HANDLE hToken = NULL; HANDLE hDirectory = NULL; NTSTATUS Status; ULONG ReturnLength; Status = ZwOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */ TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; TokenPrivileges.Privileges[0].Luid.HighPart = 0; TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Status = ZwAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, sizeof(TokenPrivileges), &TokenPrivileges, &ReturnLength); if (!NT_SUCCESS(Status)) { goto Cleanup; } TokenEnabled = (TokenPrivileges.PrivilegeCount != 0); /* open the directory */ InitializeObjectAttributes(&ObjectAttributes, DirectoryPath, 0, NULL, SecurityDescriptor); Status = ZwOpenFile(&hDirectory, SYNCHRONIZE | WRITE_OWNER, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 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 security descriptor */ Status = RtlCreateSecurityDescriptor(&AbsSD, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlSetOwnerSecurityDescriptor(&AbsSD, AdminSid, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* attempt to take ownership */ Status = ZwSetSecurityObject(hDirectory, OWNER_SECURITY_INFORMATION, &AbsSD); Cleanup: if (TokenEnabled) { ZwAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, 0, NULL, NULL); } if (AdminSid != NULL) { RtlFreeSid(AdminSid); } if (hDirectory != NULL) { ZwClose(hDirectory); } if (hToken != NULL) { ZwClose(hToken); } return Status; }
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; }
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; }
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; }
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 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 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; }
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 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; }
/****************************************************************************** * SetSecurityDescriptorOwner [ADVAPI32.@] * * PARAMS */ BOOL WINAPI SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted) { CallWin32ToNt (RtlSetOwnerSecurityDescriptor(pSecurityDescriptor, pOwner, bOwnerDefaulted)); }
DWORD LocalDirCreateNewAccountSecurityDescriptor( PSID pDomainSid, DWORD dwRid, DWORD dwObjectClass, PSECURITY_DESCRIPTOR_ABSOLUTE *ppSecDesc ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; PSECURITY_DESCRIPTOR_ABSOLUTE pSecDesc = NULL; PSID pAdminSid = NULL; DWORD dwAdminSidSize = 0; PSID pBuiltinAdminsSid = NULL; DWORD dwBuiltinAdminsSidSize = 0; PACL pDacl = NULL; BAIL_ON_INVALID_POINTER(pDomainSid); BAIL_ON_INVALID_POINTER(ppSecDesc); if (dwRid <= DOMAIN_USER_RID_MAX) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } if (dwObjectClass != DIR_OBJECT_CLASS_USER && dwObjectClass != DIR_OBJECT_CLASS_LOCAL_GROUP) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } dwError = LwAllocateMemory(SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pSecDesc)); BAIL_ON_LSA_ERROR(dwError); ntStatus = RtlCreateSecurityDescriptorAbsolute( pSecDesc, SECURITY_DESCRIPTOR_REVISION); BAIL_ON_NT_STATUS(ntStatus); /* * Set owner (Administrator) */ dwError = LwAllocateWellKnownSid(WinAccountAdministratorSid, pDomainSid, &pAdminSid, &dwAdminSidSize); BAIL_ON_LSA_ERROR(dwError); ntStatus = RtlSetOwnerSecurityDescriptor(pSecDesc, pAdminSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* * Set group (BUILTIN\Administrators) */ dwError = LwAllocateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &pBuiltinAdminsSid, &dwBuiltinAdminsSidSize); BAIL_ON_LSA_ERROR(dwError); ntStatus = RtlSetGroupSecurityDescriptor(pSecDesc, pBuiltinAdminsSid, FALSE); BAIL_ON_NT_STATUS(ntStatus); /* * Create default DACL */ if (dwObjectClass == DIR_OBJECT_CLASS_USER) { ntStatus = LocalDirCreateLocalUserDacl(pDomainSid, dwRid, &pDacl); } else if (dwObjectClass == DIR_OBJECT_CLASS_LOCAL_GROUP) { ntStatus = LocalDirCreateLocalGroupDacl(pDomainSid, dwRid, &pDacl); } BAIL_ON_NT_STATUS(ntStatus); ntStatus = RtlSetDaclSecurityDescriptor( pSecDesc, TRUE, pDacl, FALSE); BAIL_ON_NT_STATUS(ntStatus); *ppSecDesc = pSecDesc; cleanup: if (dwError == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { dwError = LwNtStatusToWin32Error(ntStatus); } return dwError; error: LocalDirFreeSecurityDescriptor(&pSecDesc); goto cleanup; }
BOOL EditDefaultDacl( HWND hwndOwner, HANDLE Instance, HANDLE MyToken ) { NTSTATUS Status; BOOL Success = FALSE; DWORD EditResult; HANDLE Token = NULL; PTOKEN_DEFAULT_DACL DefaultDacl = NULL; PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; PTOKEN_OWNER Owner = NULL; PTOKEN_PRIMARY_GROUP PrimaryGroup = NULL; WCHAR string[MAX_STRING_LENGTH]; // // Get the window text so we can use it as the token name // GetWindowTextW(((PMYTOKEN)MyToken)->hwnd, string, sizeof(string)/sizeof(*string)); // // Get a handle to the token // Token = OpenToken(MyToken, TOKEN_QUERY); if (Token == NULL) { DbgPrint("SECEDIT : Failed to open the token with TOKEN_QUERY access\n"); goto CleanupAndExit; } // // Read the default DACL from the token // if (!GetTokenInfo(Token, TokenDefaultDacl, (PPVOID)&DefaultDacl)) { DbgPrint("SECEDIT : Failed to read default DACL from token\n"); goto CleanupAndExit; } // // Get the owner and group of the token // if (!GetTokenInfo(Token, TokenOwner, (PPVOID)&Owner)) { DbgPrint("SECEDIT : Failed to read owner from token\n"); goto CleanupAndExit; } if (!GetTokenInfo(Token, TokenPrimaryGroup, (PPVOID)&PrimaryGroup)) { DbgPrint("SECEDIT : Failed to read primary group from token\n"); goto CleanupAndExit; } // // Create a security descriptor // SecurityDescriptor = Alloc(SECURITY_DESCRIPTOR_MIN_LENGTH); if (SecurityDescriptor == NULL) { DbgPrint("SECEDIT : Failed to allocate security descriptor\n"); goto CleanupAndExit; } Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); ASSERT(NT_SUCCESS(Status)); // // Set the DACL on the security descriptor // Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor, TRUE, // DACL present DefaultDacl->DefaultDacl, FALSE // DACL defaulted ); ASSERT(NT_SUCCESS(Status)); // // Put the owner and group in the security descriptor to keep the // ACL editor happy // Status = RtlSetOwnerSecurityDescriptor( SecurityDescriptor, Owner->Owner, FALSE // Owner defaulted ); ASSERT(NT_SUCCESS(Status)); Status = RtlSetGroupSecurityDescriptor( SecurityDescriptor, PrimaryGroup->PrimaryGroup, FALSE // Owner defaulted ); ASSERT(NT_SUCCESS(Status)); ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor)); // // Call the ACL editor, it will call our ApplySecurity function // to store any ACL changes in the token. // Success = EditTokenDefaultAcl( hwndOwner, Instance, string, MyToken, SecurityDescriptor, &EditResult ); if (!Success) { DbgPrint("SECEDIT: Failed to edit token DACL\n"); } CleanupAndExit: if (DefaultDacl != NULL) { FreeTokenInfo(DefaultDacl); } if (SecurityDescriptor != NULL) { FreeTokenInfo(SecurityDescriptor); } if (PrimaryGroup != NULL) { FreeTokenInfo(PrimaryGroup); } if (Owner != NULL) { FreeTokenInfo(Owner); } if (Token != NULL) { CloseToken(Token); } return(Success); }