Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * PURPOSE: Boot Data implementation * FILE: lib/rtl/bootdata.c * PROGRAMMERS: */
/* INCLUDES *****************************************************************/
#include <rtl.h>#define NDEBUG#include <debug.h>
/* FUNCTIONS *****************************************************************/
static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY};
static NTSTATUSRtlpSysVolCreateSecurityDescriptor(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 NTSTATUSRtlpSysVolCheckOwnerAndSecurity(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;}
_Must_inspect_result_staticNTSTATUSRtlpSysVolTakeOwnership(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) { /* Disable privileges that we had to enable, whetever the result was. */ NTSTATUS Status2 = ZwAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, 0, NULL, NULL); /* This must succeed */ ASSERT(NT_SUCCESS(Status2)); (void)Status2; }
if (AdminSid != NULL) { RtlFreeSid(AdminSid); }
if (hDirectory != NULL) { ZwClose(hDirectory); }
if (hToken != NULL) { ZwClose(hToken); }
return Status;}
/** @implemented*/NTSTATUSNTAPIRtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath){ OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; HANDLE hDirectory; UNICODE_STRING DirectoryName, NewPath; ULONG PathLen; PISECURITY_DESCRIPTOR SecurityDescriptor = NULL; PSID SystemSid = NULL; BOOLEAN AddSep = FALSE; NTSTATUS Status;
PAGED_CODE_RTL();
RtlInitUnicodeString(&DirectoryName, L"System Volume Information");
PathLen = VolumeRootPath->Length + DirectoryName.Length;
/* make sure we don't overflow while appending the strings */ if (PathLen > 0xFFFC) { return STATUS_INVALID_PARAMETER; }
if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\') { AddSep = TRUE; PathLen += sizeof(WCHAR); }
/* allocate the new string */ NewPath.MaximumLength = (USHORT)PathLen + sizeof(WCHAR); NewPath.Buffer = RtlpAllocateStringMemory(NewPath.MaximumLength, TAG_USTR); if (NewPath.Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
/* create the new path string */ NewPath.Length = VolumeRootPath->Length; RtlCopyMemory(NewPath.Buffer, VolumeRootPath->Buffer, NewPath.Length); if (AddSep) { NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\\'; NewPath.Length += sizeof(WCHAR); } RtlCopyMemory(NewPath.Buffer + (NewPath.Length / sizeof(WCHAR)), DirectoryName.Buffer, DirectoryName.Length); NewPath.Length += DirectoryName.Length; NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\0';
ASSERT(NewPath.Length == PathLen); ASSERT(NewPath.Length == NewPath.MaximumLength - sizeof(WCHAR));
/* create the security descriptor for the new directory */ Status = RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor, &SystemSid); if (NT_SUCCESS(Status)) { /* create or open the directory */ InitializeObjectAttributes(&ObjectAttributes, &NewPath, 0, NULL, SecurityDescriptor);
Status = ZwCreateFile(&hDirectory, SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { Status = RtlpSysVolTakeOwnership(&NewPath, SecurityDescriptor);
if (NT_SUCCESS(Status)) { /* successfully took ownership, attempt to open it */ Status = ZwCreateFile(&hDirectory, SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); } }
if (NT_SUCCESS(Status)) { /* check security now and adjust it if neccessary */ Status = RtlpSysVolCheckOwnerAndSecurity(hDirectory, SecurityDescriptor); ZwClose(hDirectory); }
/* free allocated memory */ ASSERT(SecurityDescriptor != NULL); ASSERT(SecurityDescriptor->Dacl != NULL);
RtlpFreeMemory(SecurityDescriptor->Dacl, 'cAeS'); RtlpFreeMemory(SecurityDescriptor, 'dSeS');
RtlFreeSid(SystemSid); }
RtlpFreeStringMemory(NewPath.Buffer, TAG_USTR); return Status;}
/* EOF */