static NTSTATUS BuildTokenDefaultDacl(PTOKEN_DEFAULT_DACL DefaultDacl, PSID OwnerSid) { SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY}; PSID LocalSystemSid = NULL; PACL Dacl = NULL; NTSTATUS Status = STATUS_SUCCESS; RtlAllocateAndInitializeSid(&SystemAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, &LocalSystemSid); Dacl = DispatchTable.AllocateLsaHeap(1024); if (Dacl == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } Status = RtlCreateAcl(Dacl, 1024, ACL_REVISION); if (!NT_SUCCESS(Status)) goto done; RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, OwnerSid); /* SID: S-1-5-18 */ RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, LocalSystemSid); DefaultDacl->DefaultDacl = Dacl; done: if (!NT_SUCCESS(Status)) { if (Dacl != NULL) DispatchTable.FreeLsaHeap(Dacl); } if (LocalSystemSid != NULL) RtlFreeSid(LocalSystemSid); return Status; }
/*++ * @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; }
// 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; }
/*++ * @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; }
/* * @implemented */ NTSTATUS NTAPI RtlCreateSystemVolumeInformationFolder(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; }
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 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 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; }
/* * @implemented */ BOOL WINAPI LogonUserExW( _In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken, _Out_opt_ PSID *ppLogonSid, _Out_opt_ PVOID *ppProfileBuffer, _Out_opt_ LPDWORD pdwProfileLength, _Out_opt_ PQUOTA_LIMITS pQuotaLimits) { SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY}; PSID LogonSid = NULL; PSID LocalSid = NULL; LSA_STRING OriginName; UNICODE_STRING DomainName; UNICODE_STRING UserName; UNICODE_STRING Password; PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL; ULONG AuthInfoLength; ULONG_PTR Ptr; TOKEN_SOURCE TokenSource; PTOKEN_GROUPS TokenGroups = NULL; PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL; ULONG ProfileBufferLength = 0; LUID Luid = {0, 0}; LUID LogonId = {0, 0}; HANDLE TokenHandle = NULL; QUOTA_LIMITS QuotaLimits; SECURITY_LOGON_TYPE LogonType; NTSTATUS SubStatus = STATUS_SUCCESS; NTSTATUS Status; *phToken = NULL; switch (dwLogonType) { case LOGON32_LOGON_INTERACTIVE: LogonType = Interactive; break; case LOGON32_LOGON_NETWORK: LogonType = Network; break; case LOGON32_LOGON_BATCH: LogonType = Batch; break; case LOGON32_LOGON_SERVICE: LogonType = Service; break; default: ERR("Invalid logon type: %ul\n", dwLogonType); Status = STATUS_INVALID_PARAMETER; goto done; } if (LsaHandle == NULL) { Status = OpenLogonLsaHandle(); if (!NT_SUCCESS(Status)) goto done; } RtlInitAnsiString((PANSI_STRING)&OriginName, "Advapi32 Logon"); RtlInitUnicodeString(&DomainName, lpszDomain); RtlInitUnicodeString(&UserName, lpszUsername); RtlInitUnicodeString(&Password, lpszPassword); AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+ DomainName.MaximumLength + UserName.MaximumLength + Password.MaximumLength; AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, AuthInfoLength); if (AuthInfo == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } AuthInfo->MessageType = MsV1_0InteractiveLogon; Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON); AuthInfo->LogonDomainName.Length = DomainName.Length; AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength; AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr; if (DomainName.MaximumLength > 0) { RtlCopyMemory(AuthInfo->LogonDomainName.Buffer, DomainName.Buffer, DomainName.MaximumLength); Ptr += DomainName.MaximumLength; } AuthInfo->UserName.Length = UserName.Length; AuthInfo->UserName.MaximumLength = UserName.MaximumLength; AuthInfo->UserName.Buffer = (PWCHAR)Ptr; if (UserName.MaximumLength > 0) RtlCopyMemory(AuthInfo->UserName.Buffer, UserName.Buffer, UserName.MaximumLength); Ptr += UserName.MaximumLength; AuthInfo->Password.Length = Password.Length; AuthInfo->Password.MaximumLength = Password.MaximumLength; AuthInfo->Password.Buffer = (PWCHAR)Ptr; if (Password.MaximumLength > 0) RtlCopyMemory(AuthInfo->Password.Buffer, Password.Buffer, Password.MaximumLength); /* Create the Logon SID*/ AllocateLocallyUniqueId(&LogonId); Status = RtlAllocateAndInitializeSid(&SystemAuthority, SECURITY_LOGON_IDS_RID_COUNT, SECURITY_LOGON_IDS_RID, LogonId.HighPart, LogonId.LowPart, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, &LogonSid); if (!NT_SUCCESS(Status)) goto done; /* Create the Local SID*/ Status = RtlAllocateAndInitializeSid(&LocalAuthority, 1, SECURITY_LOCAL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, SECURITY_NULL_RID, &LocalSid); if (!NT_SUCCESS(Status)) goto done; /* Allocate and set the token groups */ TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES))); if (TokenGroups == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto done; } TokenGroups->GroupCount = 2; TokenGroups->Groups[0].Sid = LogonSid; TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID; TokenGroups->Groups[1].Sid = LocalSid; TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT; /* Set the token source */ strncpy(TokenSource.SourceName, "Advapi ", sizeof(TokenSource.SourceName)); AllocateLocallyUniqueId(&TokenSource.SourceIdentifier); Status = LsaLogonUser(LsaHandle, &OriginName, LogonType, AuthenticationPackage, (PVOID)AuthInfo, AuthInfoLength, TokenGroups, &TokenSource, (PVOID*)&ProfileBuffer, &ProfileBufferLength, &Luid, &TokenHandle, &QuotaLimits, &SubStatus); if (!NT_SUCCESS(Status)) { ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status); goto done; } if (ProfileBuffer != NULL) { TRACE("ProfileBuffer: %p\n", ProfileBuffer); TRACE("MessageType: %u\n", ProfileBuffer->MessageType); TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer); TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer); TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer); TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer); } TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart); if (TokenHandle != NULL) { TRACE("TokenHandle: %p\n", TokenHandle); } *phToken = TokenHandle; /* FIXME: return ppLogonSid, ppProfileBuffer, pdwProfileLength and pQuotaLimits */ done: if (ProfileBuffer != NULL) LsaFreeReturnBuffer(ProfileBuffer); if (!NT_SUCCESS(Status)) { if (TokenHandle != NULL) CloseHandle(TokenHandle); } if (TokenGroups != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups); if (LocalSid != NULL) RtlFreeSid(LocalSid); if (LogonSid != NULL) RtlFreeSid(LogonSid); if (AuthInfo != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
NTSTATUS NlCloseChangeLog( VOID ) /*++ Routine Description: Frees any resources consumed by NlInitChangeLog. Arguments: NONE Return Value: NT Status code --*/ { if ( (NlGlobalChangeLogDesc.FileHandle == INVALID_HANDLE_VALUE) && (NlGlobalChangeLogRole == ChangeLogPrimary) ) { // // try to save change log cache one last time. // (VOID)NlCreateChangeLogFile( &NlGlobalChangeLogDesc ); } if ( NlGlobalChangeLogDesc.FileHandle != INVALID_HANDLE_VALUE ) { CloseHandle( NlGlobalChangeLogDesc.FileHandle ); NlGlobalChangeLogDesc.FileHandle = INVALID_HANDLE_VALUE; } NlGlobalChangeLogFilePrefix[0] = L'\0'; if ( NlGlobalChangeLogDesc.Buffer != NULL ) { NetpMemoryFree( NlGlobalChangeLogDesc.Buffer ); NlGlobalChangeLogDesc.Buffer = NULL; } if ( NlGlobalChWorkerBuiltinDomainSid != NULL ) { RtlFreeSid( NlGlobalChWorkerBuiltinDomainSid ); NlGlobalChWorkerBuiltinDomainSid = NULL; } if ( NlGlobalChWorkerSamDomainSid != NULL ) { NetpMemoryFree( NlGlobalChWorkerSamDomainSid ); NlGlobalChWorkerSamDomainSid = NULL; } if ( NlGlobalChangeLogEvent != NULL ) { (VOID) CloseHandle(NlGlobalChangeLogEvent); NlGlobalChangeLogEvent = NULL; } if ( NlGlobalChangeLogWorkerQueueEvent != NULL ) { (VOID) CloseHandle(NlGlobalChangeLogWorkerQueueEvent); NlGlobalChangeLogWorkerQueueEvent = NULL; } // // if worker thread running, stop it. // NlStopChangeLogWorker(); LOCK_CHANGELOG(); NlAssert( IsListEmpty( &NlGlobalChangeLogNotifications ) ); NlAssert( IsListEmpty( &NlGlobalChangeLogWorkerQueue ) ); UNLOCK_CHANGELOG(); NlGlobalChangeLogWorkInit = FALSE; // // close all handles // if ( NlGlobalChWorkerSamServerHandle != NULL ) { (VOID)SamrCloseHandle( &NlGlobalChWorkerSamServerHandle); } if ( NlGlobalChWorkerPolicyHandle != NULL ) { (VOID)LsarClose( &NlGlobalChWorkerPolicyHandle); } if ( NlGlobalChWorkerSamDBHandle != NULL ) { (VOID)SamrCloseHandle( &NlGlobalChWorkerSamDBHandle); } if ( NlGlobalChWorkerBuiltinDBHandle != NULL ) { (VOID)SamrCloseHandle( &NlGlobalChWorkerBuiltinDBHandle); } DeleteCriticalSection( &NlGlobalChangeLogCritSect ); #if DBG DeleteCriticalSection( &NlGlobalLogFileCritSect ); #endif // DBG return STATUS_SUCCESS; }
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; }
/****************************************************************************** * FreeSid [ADVAPI32.@] * * PARAMS * pSid [] */ PVOID WINAPI FreeSid( PSID pSid ) { RtlFreeSid(pSid); return NULL; /* is documented like this */ }
NTSTATUS NTAPI CreateBaseAcls(OUT PACL* Dacl, OUT PACL* RestrictedDacl) { PSID SystemSid, WorldSid, RestrictedSid; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY}; NTSTATUS Status; #if 0 // Unused code UCHAR KeyValueBuffer[0x40]; PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; UNICODE_STRING KeyName; ULONG ProtectionMode = 0; #endif ULONG AclLength; #if 0 // Unused code ULONG ResultLength; HANDLE hKey; OBJECT_ATTRIBUTES ObjectAttributes; /* 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); } #endif /* Allocate the System SID */ Status = RtlAllocateAndInitializeSid(&NtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemSid); ASSERT(NT_SUCCESS(Status)); /* Allocate the World SID */ Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &WorldSid); ASSERT(NT_SUCCESS(Status)); /* Allocate the restricted SID */ Status = RtlAllocateAndInitializeSid(&NtAuthority, 1, SECURITY_RESTRICTED_CODE_RID, 0, 0, 0, 0, 0, 0, 0, &RestrictedSid); ASSERT(NT_SUCCESS(Status)); /* Allocate one ACL with 3 ACEs each for one SID */ AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(SystemSid) + RtlLengthSid(WorldSid) + RtlLengthSid(RestrictedSid); *Dacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength); ASSERT(*Dacl != NULL); /* Set the correct header fields */ Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); /* Give the appropriate rights to each SID */ /* FIXME: Should check SessionId/ProtectionMode */ Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid); ASSERT(NT_SUCCESS(Status)); /* Now allocate the restricted DACL */ *RestrictedDacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength); ASSERT(*RestrictedDacl != NULL); /* Initialize it */ Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2); ASSERT(NT_SUCCESS(Status)); /* And add the same ACEs as before */ /* FIXME: Not really fully correct */ Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid); ASSERT(NT_SUCCESS(Status)); Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid); ASSERT(NT_SUCCESS(Status)); /* The SIDs are captured, can free them now */ RtlFreeSid(RestrictedSid); RtlFreeSid(WorldSid); RtlFreeSid(SystemSid); return Status; }
BOOLEAN OpenDotNetPublicControlBlock_V4( _In_ BOOLEAN IsImmersive, _In_ HANDLE ProcessHandle, _In_ HANDLE ProcessId, _Out_ HANDLE* BlockTableHandle, _Out_ PVOID* BlockTableAddress ) { BOOLEAN result = FALSE; PVOID boundaryDescriptorHandle = NULL; HANDLE privateNamespaceHandle = NULL; HANDLE blockTableHandle = NULL; HANDLE tokenHandle = NULL; PSID everyoneSIDHandle = NULL; PVOID blockTableAddress = NULL; LARGE_INTEGER sectionOffset = { 0 }; SIZE_T viewSize = 0; UNICODE_STRING prefixNameUs; UNICODE_STRING sectionNameUs; UNICODE_STRING boundaryNameUs; OBJECT_ATTRIBUTES namespaceObjectAttributes; OBJECT_ATTRIBUTES sectionObjectAttributes; PTOKEN_APPCONTAINER_INFORMATION appContainerInfo = NULL; SID_IDENTIFIER_AUTHORITY SIDWorldAuth = SECURITY_WORLD_SID_AUTHORITY; if (!PhStringRefToUnicodeString(&GenerateBoundaryDescriptorName(ProcessId)->sr, &boundaryNameUs)) goto CleanupExit; if (!(boundaryDescriptorHandle = RtlCreateBoundaryDescriptor(&boundaryNameUs, 0))) goto CleanupExit; if (!NT_SUCCESS(RtlAllocateAndInitializeSid(&SIDWorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSIDHandle))) goto CleanupExit; if (!NT_SUCCESS(RtlAddSIDToBoundaryDescriptor(&boundaryDescriptorHandle, everyoneSIDHandle))) goto CleanupExit; if (WINDOWS_HAS_IMMERSIVE && IsImmersive) { if (NT_SUCCESS(NtOpenProcessToken(&tokenHandle, TOKEN_QUERY, ProcessHandle))) { ULONG returnLength = 0; if (NtQueryInformationToken( tokenHandle, TokenAppContainerSid, NULL, 0, &returnLength ) != STATUS_BUFFER_TOO_SMALL) { goto CleanupExit; } appContainerInfo = PhAllocate(returnLength); if (!NT_SUCCESS(NtQueryInformationToken( tokenHandle, TokenAppContainerSid, appContainerInfo, returnLength, &returnLength ))) { goto CleanupExit; } if (!NT_SUCCESS(RtlAddSIDToBoundaryDescriptor(&boundaryDescriptorHandle, appContainerInfo->TokenAppContainer))) goto CleanupExit; } } RtlInitUnicodeString(&prefixNameUs, CorSxSReaderPrivateNamespacePrefix); InitializeObjectAttributes( &namespaceObjectAttributes, &prefixNameUs, OBJ_CASE_INSENSITIVE, boundaryDescriptorHandle, NULL ); if (!NT_SUCCESS(NtOpenPrivateNamespace( &privateNamespaceHandle, MAXIMUM_ALLOWED, &namespaceObjectAttributes, boundaryDescriptorHandle ))) { goto CleanupExit; } RtlInitUnicodeString(§ionNameUs, CorSxSVistaPublicIPCBlock); InitializeObjectAttributes( §ionObjectAttributes, §ionNameUs, OBJ_CASE_INSENSITIVE, privateNamespaceHandle, NULL ); if (!NT_SUCCESS(NtOpenSection( &blockTableHandle, SECTION_MAP_READ, §ionObjectAttributes ))) { goto CleanupExit; } if (!NT_SUCCESS(NtMapViewOfSection( blockTableHandle, NtCurrentProcess(), &blockTableAddress, 0, viewSize, §ionOffset, &viewSize, ViewShare, 0, PAGE_READONLY ))) { goto CleanupExit; } *BlockTableHandle = blockTableHandle; *BlockTableAddress = blockTableAddress; result = TRUE; CleanupExit: if (!result) { if (blockTableHandle) { NtClose(blockTableHandle); } if (blockTableAddress) { NtUnmapViewOfSection(NtCurrentProcess(), blockTableAddress); } *BlockTableHandle = NULL; *BlockTableAddress = NULL; } if (tokenHandle) { NtClose(tokenHandle); } if (appContainerInfo) { PhFree(appContainerInfo); } if (privateNamespaceHandle) { NtClose(privateNamespaceHandle); } if (everyoneSIDHandle) { RtlFreeSid(everyoneSIDHandle); } if (boundaryDescriptorHandle) { RtlDeleteBoundaryDescriptor(boundaryDescriptorHandle); } return result; }
static NTSTATUS LsapCreateDatabaseObjects(VOID) { PLSAP_POLICY_AUDIT_EVENTS_DATA AuditEventsInfo = NULL; POLICY_DEFAULT_QUOTA_INFO QuotaInfo; POLICY_MODIFICATION_INFO ModificationInfo; POLICY_AUDIT_FULL_QUERY_INFO AuditFullInfo = {FALSE, FALSE}; POLICY_AUDIT_LOG_INFO AuditLogInfo; GUID DnsDomainGuid; PLSA_DB_OBJECT PolicyObject = NULL; PSID AccountDomainSid = NULL; PSECURITY_DESCRIPTOR PolicySd = NULL; ULONG PolicySdSize = 0; ULONG AuditEventsCount; ULONG AuditEventsSize; ULONG i; NTSTATUS Status; /* Initialize the default quota limits */ QuotaInfo.QuotaLimits.PagedPoolLimit = 0x2000000; QuotaInfo.QuotaLimits.NonPagedPoolLimit = 0x100000; QuotaInfo.QuotaLimits.MinimumWorkingSetSize = 0x10000; QuotaInfo.QuotaLimits.MaximumWorkingSetSize = 0xF000000; QuotaInfo.QuotaLimits.PagefileLimit = 0; QuotaInfo.QuotaLimits.TimeLimit.QuadPart = 0; /* Initialize the audit log attribute */ AuditLogInfo.AuditLogPercentFull = 0; AuditLogInfo.MaximumLogSize = 0; // DWORD AuditLogInfo.AuditRetentionPeriod.QuadPart = 0; // LARGE_INTEGER AuditLogInfo.AuditLogFullShutdownInProgress = 0; // BYTE AuditLogInfo.TimeToShutdown.QuadPart = 0; // LARGE_INTEGER AuditLogInfo.NextAuditRecordId = 0; // DWORD /* Initialize the Audit Events attribute */ AuditEventsCount = AuditCategoryAccountLogon - AuditCategorySystem + 1; AuditEventsSize = sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA) + AuditEventsCount * sizeof(DWORD); AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, AuditEventsSize); if (AuditEventsInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES; AuditEventsInfo->AuditingMode = FALSE; AuditEventsInfo->MaximumAuditEventCount = AuditEventsCount; for (i = 0; i < AuditEventsCount; i++) AuditEventsInfo->AuditEvents[i] = 0; /* Initialize the DNS Domain GUID attribute */ memset(&DnsDomainGuid, 0, sizeof(GUID)); /* Initialize the modification attribute */ ModificationInfo.ModifiedId.QuadPart = 0; NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime); /* Create a random domain SID */ Status = LsapCreateRandomDomainSid(&AccountDomainSid); if (!NT_SUCCESS(Status)) goto done; Status = LsapCreatePolicySd(&PolicySd, &PolicySdSize); if (!NT_SUCCESS(Status)) goto done; /* Open the 'Policy' object */ Status = LsapOpenDbObject(NULL, NULL, L"Policy", LsaDbPolicyObject, 0, TRUE, &PolicyObject); if (!NT_SUCCESS(Status)) goto done; LsapSetObjectAttribute(PolicyObject, L"PolPrDmN", NULL, 0); LsapSetObjectAttribute(PolicyObject, L"PolPrDmS", NULL, 0); LsapSetObjectAttribute(PolicyObject, L"PolAcDmN", NULL, 0); LsapSetObjectAttribute(PolicyObject, L"PolAcDmS", AccountDomainSid, RtlLengthSid(AccountDomainSid)); /* Set the default quota limits attribute */ LsapSetObjectAttribute(PolicyObject, L"DefQuota", &QuotaInfo, sizeof(POLICY_DEFAULT_QUOTA_INFO)); /* Set the modification attribute */ LsapSetObjectAttribute(PolicyObject, L"PolMod", &ModificationInfo, sizeof(POLICY_MODIFICATION_INFO)); /* Set the audit full attribute */ LsapSetObjectAttribute(PolicyObject, L"PolAdtFl", &AuditFullInfo, sizeof(POLICY_AUDIT_FULL_QUERY_INFO)); /* Set the audit log attribute */ LsapSetObjectAttribute(PolicyObject, L"PolAdtLg", &AuditLogInfo, sizeof(POLICY_AUDIT_LOG_INFO)); /* Set the audit events attribute */ LsapSetObjectAttribute(PolicyObject, L"PolAdtEv", AuditEventsInfo, AuditEventsSize); /* Set the DNS Domain Name attribute */ LsapSetObjectAttribute(PolicyObject, L"PolDnDDN", NULL, 0); /* Set the DNS Forest Name attribute */ LsapSetObjectAttribute(PolicyObject, L"PolDnTrN", NULL, 0); /* Set the DNS Domain GUID attribute */ LsapSetObjectAttribute(PolicyObject, L"PolDnDmG", &DnsDomainGuid, sizeof(GUID)); /* Set the Sceurity Descriptor */ LsapSetObjectAttribute(PolicyObject, L"SecDesc", PolicySd, PolicySdSize); done: if (AuditEventsInfo != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo); if (PolicyObject != NULL) LsapCloseDbObject(PolicyObject); if (AccountDomainSid != NULL) RtlFreeSid(AccountDomainSid); if (PolicySd != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, PolicySd); return Status; }