mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
1089 lines
31 KiB
C
1089 lines
31 KiB
C
/*
|
|
* PROJECT: Local Security Authority Server DLL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/win32/lsasrv/database.c
|
|
* PURPOSE: LSA object database
|
|
* COPYRIGHT: Copyright 2011 Eric Kohl
|
|
*/
|
|
|
|
#include "lsasrv.h"
|
|
|
|
#include <pseh/pseh2.h>
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
static HANDLE SecurityKeyHandle = NULL;
|
|
|
|
SID_IDENTIFIER_AUTHORITY NullSidAuthority = {SECURITY_NULL_SID_AUTHORITY};
|
|
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
|
SID_IDENTIFIER_AUTHORITY LocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
|
|
SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
|
|
|
PSID BuiltinDomainSid = NULL;
|
|
PSID AccountDomainSid = NULL;
|
|
UNICODE_STRING BuiltinDomainName = {0, 0, NULL};
|
|
UNICODE_STRING AccountDomainName = {0, 0, NULL};
|
|
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
static NTSTATUS
|
|
LsapOpenServiceKey(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"\\Registry\\Machine\\SECURITY");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = RtlpNtOpenKey(&SecurityKeyHandle,
|
|
KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
|
|
&ObjectAttributes,
|
|
0);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static BOOLEAN
|
|
LsapIsDatabaseInstalled(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE KeyHandle;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"Policy");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
SecurityKeyHandle,
|
|
NULL);
|
|
|
|
Status = RtlpNtOpenKey(&KeyHandle,
|
|
KEY_READ,
|
|
&ObjectAttributes,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
NtClose(KeyHandle);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
LsapCreateDatabaseKeys(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE PolicyKeyHandle = NULL;
|
|
HANDLE AccountsKeyHandle = NULL;
|
|
HANDLE DomainsKeyHandle = NULL;
|
|
HANDLE SecretsKeyHandle = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
TRACE("LsapInstallDatabase()\n");
|
|
|
|
/* Create the 'Policy' key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"Policy");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
SecurityKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&PolicyKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
/* Create the 'Accounts' key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"Accounts");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
PolicyKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&AccountsKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
/* Create the 'Domains' key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"Domains");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
PolicyKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&DomainsKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
/* Create the 'Secrets' key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
L"Secrets");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
PolicyKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&SecretsKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
|
|
goto Done;
|
|
}
|
|
|
|
Done:
|
|
if (SecretsKeyHandle != NULL)
|
|
NtClose(SecretsKeyHandle);
|
|
|
|
if (DomainsKeyHandle != NULL)
|
|
NtClose(DomainsKeyHandle);
|
|
|
|
if (AccountsKeyHandle != NULL)
|
|
NtClose(AccountsKeyHandle);
|
|
|
|
if (PolicyKeyHandle != NULL)
|
|
NtClose(PolicyKeyHandle);
|
|
|
|
TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
LsapCreateRandomDomainSid(OUT PSID *Sid)
|
|
{
|
|
LARGE_INTEGER SystemTime;
|
|
PULONG Seed;
|
|
|
|
NtQuerySystemTime(&SystemTime);
|
|
Seed = &SystemTime.u.LowPart;
|
|
|
|
return RtlAllocateAndInitializeSid(&NtAuthority,
|
|
4,
|
|
SECURITY_NT_NON_UNIQUE,
|
|
RtlUniform(Seed),
|
|
RtlUniform(Seed),
|
|
RtlUniform(Seed),
|
|
SECURITY_NULL_RID,
|
|
SECURITY_NULL_RID,
|
|
SECURITY_NULL_RID,
|
|
SECURITY_NULL_RID,
|
|
Sid);
|
|
}
|
|
|
|
|
|
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 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 */
|
|
AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA));
|
|
if (AuditEventsInfo == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
AuditEventsInfo->AuditingMode = FALSE;
|
|
AuditEventsInfo->MaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
|
|
for (i = 0; i < POLICY_AUDIT_EVENT_TYPE_COUNT; i++)
|
|
AuditEventsInfo->AuditEvents[i] = 0;
|
|
|
|
/* Initialize the DNS Domain GUID attribute */
|
|
RtlZeroMemory(&DnsDomainGuid, sizeof(DnsDomainGuid));
|
|
|
|
/* 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;
|
|
|
|
/* Set the Primary Domain Name attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolPrDmN",
|
|
NULL,
|
|
0);
|
|
|
|
/* Set the Primary Domain SID attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolPrDmS",
|
|
NULL,
|
|
0);
|
|
|
|
/* Set the Account Domain Name attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolAcDmN",
|
|
NULL,
|
|
0);
|
|
|
|
/* Set the Account Domain SID attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolAcDmS",
|
|
AccountDomainSid,
|
|
RtlLengthSid(AccountDomainSid));
|
|
|
|
/* Set the default quota limits attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"DefQuota",
|
|
&QuotaInfo,
|
|
sizeof(QuotaInfo));
|
|
|
|
/* Set the modification attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolMod",
|
|
&ModificationInfo,
|
|
sizeof(ModificationInfo));
|
|
|
|
/* Set the audit full attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolAdtFl",
|
|
&AuditFullInfo,
|
|
sizeof(AuditFullInfo));
|
|
|
|
/* Set the audit log attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolAdtLg",
|
|
&AuditLogInfo,
|
|
sizeof(AuditLogInfo));
|
|
|
|
/* Set the audit events attribute */
|
|
LsapSetObjectAttribute(PolicyObject,
|
|
L"PolAdtEv",
|
|
AuditEventsInfo,
|
|
sizeof(*AuditEventsInfo));
|
|
|
|
/* 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(DnsDomainGuid));
|
|
|
|
/* Set the Security 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;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
LsapUpdateDatabase(VOID)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static NTSTATUS
|
|
LsapGetDomainInfo(VOID)
|
|
{
|
|
PLSA_DB_OBJECT PolicyObject = NULL;
|
|
PUNICODE_STRING DomainName = NULL;
|
|
ULONG AttributeSize;
|
|
LPWSTR SidString = NULL;
|
|
NTSTATUS Status;
|
|
|
|
/* Get the built-in domain SID and name */
|
|
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
|
1,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&BuiltinDomainSid);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
/**/
|
|
RtlInitUnicodeString(&BuiltinDomainName,
|
|
L"BUILTIN");
|
|
|
|
/* Open the 'Policy' object */
|
|
Status = LsapOpenDbObject(NULL,
|
|
NULL,
|
|
L"Policy",
|
|
LsaDbPolicyObject,
|
|
0,
|
|
TRUE,
|
|
&PolicyObject);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* Get the account domain SID */
|
|
AttributeSize = 0;
|
|
Status = LsapGetObjectAttribute(PolicyObject,
|
|
L"PolAcDmS",
|
|
NULL,
|
|
&AttributeSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
if (AttributeSize > 0)
|
|
{
|
|
AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
AttributeSize);
|
|
if (AccountDomainSid == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapGetObjectAttribute(PolicyObject,
|
|
L"PolAcDmS",
|
|
AccountDomainSid,
|
|
&AttributeSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
}
|
|
|
|
/* Get the account domain name */
|
|
AttributeSize = 0;
|
|
Status = LsapGetObjectAttribute(PolicyObject,
|
|
L"PolAcDmN",
|
|
NULL,
|
|
&AttributeSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
if (AttributeSize > 0)
|
|
{
|
|
DomainName = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
AttributeSize);
|
|
if (DomainName == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapGetObjectAttribute(PolicyObject,
|
|
L"PolAcDmN",
|
|
DomainName,
|
|
&AttributeSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer);
|
|
|
|
AccountDomainName.Length = DomainName->Length;
|
|
AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR);
|
|
AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
AccountDomainName.MaximumLength);
|
|
if (AccountDomainName.Buffer == NULL)
|
|
{
|
|
ERR("Failed to allocate the account domain name buffer\n");
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
RtlCopyMemory(AccountDomainName.Buffer,
|
|
DomainName->Buffer,
|
|
DomainName->Length);
|
|
}
|
|
|
|
ConvertSidToStringSidW(BuiltinDomainSid, &SidString);
|
|
TRACE("Builtin Domain SID: %S\n", SidString);
|
|
LocalFree(SidString);
|
|
SidString = NULL;
|
|
|
|
TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName);
|
|
|
|
ConvertSidToStringSidW(AccountDomainSid, &SidString);
|
|
TRACE("Account Domain SID: %S\n", SidString);
|
|
LocalFree(SidString);
|
|
SidString = NULL;
|
|
|
|
TRACE("Account Domain Name: %wZ\n", &AccountDomainName);
|
|
|
|
done:
|
|
if (DomainName != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName);
|
|
|
|
if (PolicyObject != NULL)
|
|
LsapCloseDbObject(PolicyObject);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapInitDatabase(VOID)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
TRACE("LsapInitDatabase()\n");
|
|
|
|
Status = LsapOpenServiceKey();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
if (!LsapIsDatabaseInstalled())
|
|
{
|
|
Status = LsapCreateDatabaseKeys();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = LsapCreateDatabaseObjects();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = LsapUpdateDatabase();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Status = LsapGetDomainInfo();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
TRACE("LsapInitDatabase() done\n");
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
|
|
IN LPWSTR ContainerName,
|
|
IN LPWSTR ObjectName,
|
|
IN LSA_DB_OBJECT_TYPE ObjectType,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Trusted,
|
|
OUT PLSA_DB_OBJECT *DbObject)
|
|
{
|
|
PLSA_DB_OBJECT NewObject;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE ParentKeyHandle;
|
|
HANDLE ContainerKeyHandle = NULL;
|
|
HANDLE ObjectKeyHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
if (DbObject == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
if (ParentObject == NULL)
|
|
ParentKeyHandle = SecurityKeyHandle;
|
|
else
|
|
ParentKeyHandle = ParentObject->KeyHandle;
|
|
|
|
if (ContainerName != NULL)
|
|
{
|
|
/* Open the container key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
ContainerName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&ContainerKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Open the object key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
ObjectName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ContainerKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&ObjectKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
|
|
NtClose(ContainerKeyHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&KeyName,
|
|
ObjectName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&ObjectKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
sizeof(LSA_DB_OBJECT));
|
|
if (NewObject == NULL)
|
|
{
|
|
NtClose(ObjectKeyHandle);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
NewObject->Signature = LSAP_DB_SIGNATURE;
|
|
NewObject->RefCount = 1;
|
|
NewObject->ObjectType = ObjectType;
|
|
NewObject->Access = DesiredAccess;
|
|
NewObject->KeyHandle = ObjectKeyHandle;
|
|
NewObject->ParentObject = ParentObject;
|
|
NewObject->Trusted = Trusted;
|
|
|
|
if (ParentObject != NULL)
|
|
ParentObject->RefCount++;
|
|
|
|
*DbObject = NewObject;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
|
|
IN LPWSTR ContainerName,
|
|
IN LPWSTR ObjectName,
|
|
IN LSA_DB_OBJECT_TYPE ObjectType,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Trusted,
|
|
OUT PLSA_DB_OBJECT *DbObject)
|
|
{
|
|
PLSA_DB_OBJECT NewObject;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE ParentKeyHandle;
|
|
HANDLE ContainerKeyHandle = NULL;
|
|
HANDLE ObjectKeyHandle = NULL;
|
|
NTSTATUS Status;
|
|
|
|
if (DbObject == NULL)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
if (ParentObject == NULL)
|
|
ParentKeyHandle = SecurityKeyHandle;
|
|
else
|
|
ParentKeyHandle = ParentObject->KeyHandle;
|
|
|
|
if (ContainerName != NULL)
|
|
{
|
|
/* Open the container key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
ContainerName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&ContainerKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* Open the object key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
ObjectName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ContainerKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&ObjectKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
|
|
NtClose(ContainerKeyHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Open the object key */
|
|
RtlInitUnicodeString(&KeyName,
|
|
ObjectName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentKeyHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&ObjectKeyHandle,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
sizeof(LSA_DB_OBJECT));
|
|
if (NewObject == NULL)
|
|
{
|
|
NtClose(ObjectKeyHandle);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
NewObject->Signature = LSAP_DB_SIGNATURE;
|
|
NewObject->RefCount = 1;
|
|
NewObject->ObjectType = ObjectType;
|
|
NewObject->Access = DesiredAccess;
|
|
NewObject->KeyHandle = ObjectKeyHandle;
|
|
NewObject->ParentObject = ParentObject;
|
|
NewObject->Trusted = Trusted;
|
|
|
|
if (ParentObject != NULL)
|
|
ParentObject->RefCount++;
|
|
|
|
*DbObject = NewObject;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapValidateDbObject(LSAPR_HANDLE Handle,
|
|
LSA_DB_OBJECT_TYPE ObjectType,
|
|
ACCESS_MASK DesiredAccess,
|
|
PLSA_DB_OBJECT *DbObject)
|
|
{
|
|
PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
|
|
BOOLEAN bValid = FALSE;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
if (LocalObject->Signature == LSAP_DB_SIGNATURE)
|
|
{
|
|
if ((ObjectType == LsaDbIgnoreObject) ||
|
|
(LocalObject->ObjectType == ObjectType))
|
|
bValid = TRUE;
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
bValid = FALSE;
|
|
}
|
|
_SEH2_END;
|
|
|
|
if (bValid == FALSE)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
if (DesiredAccess != 0)
|
|
{
|
|
/* Check for granted access rights */
|
|
if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
|
|
{
|
|
ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
|
|
LocalObject->Access, DesiredAccess);
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
if (DbObject != NULL)
|
|
*DbObject = LocalObject;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
|
|
{
|
|
PLSA_DB_OBJECT ParentObject = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DbObject->RefCount--;
|
|
|
|
if (DbObject->RefCount > 0)
|
|
return STATUS_SUCCESS;
|
|
|
|
if (DbObject->KeyHandle != NULL)
|
|
NtClose(DbObject->KeyHandle);
|
|
|
|
if (DbObject->ParentObject != NULL)
|
|
ParentObject = DbObject->ParentObject;
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
|
|
|
|
if (ParentObject != NULL)
|
|
{
|
|
ParentObject->RefCount--;
|
|
|
|
if (ParentObject->RefCount == 0)
|
|
Status = LsapCloseDbObject(ParentObject);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject)
|
|
{
|
|
PLSA_DB_OBJECT ParentObject = NULL;
|
|
WCHAR KeyName[64];
|
|
ULONG Index;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DbObject->RefCount--;
|
|
|
|
if (DbObject->RefCount > 0)
|
|
return STATUS_SUCCESS;
|
|
|
|
if (DbObject->KeyHandle != NULL)
|
|
{
|
|
Index = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
Status = LsapRegEnumerateSubKey(DbObject->KeyHandle,
|
|
Index,
|
|
sizeof(KeyName),
|
|
KeyName);
|
|
if (!NT_SUCCESS(Status))
|
|
break;
|
|
|
|
TRACE("Index: %lu\n", Index);
|
|
TRACE("Key name: %S\n", KeyName);
|
|
|
|
Status = LsapRegDeleteSubKey(DbObject->KeyHandle,
|
|
KeyName);
|
|
if (!NT_SUCCESS(Status))
|
|
break;
|
|
}
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
Status = STATUS_SUCCESS;
|
|
|
|
LsapRegDeleteKey(DbObject->KeyHandle);
|
|
|
|
NtClose(DbObject->KeyHandle);
|
|
}
|
|
|
|
if (DbObject->ParentObject != NULL)
|
|
ParentObject = DbObject->ParentObject;
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
|
|
|
|
if (ParentObject != NULL)
|
|
{
|
|
ParentObject->RefCount--;
|
|
|
|
if (ParentObject->RefCount == 0)
|
|
Status = LsapCloseDbObject(ParentObject);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
|
|
LPWSTR AttributeName,
|
|
LPVOID AttributeData,
|
|
ULONG AttributeSize)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE AttributeKey;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
AttributeName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
DbObject->KeyHandle,
|
|
NULL);
|
|
|
|
Status = NtCreateKey(&AttributeKey,
|
|
KEY_SET_VALUE,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtCreateKey failed for '%S' with status 0x%lx\n",
|
|
AttributeName, Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = RtlpNtSetValueKey(AttributeKey,
|
|
REG_NONE,
|
|
AttributeData,
|
|
AttributeSize);
|
|
|
|
NtClose(AttributeKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("RtlpNtSetValueKey failed for '%S' with status 0x%lx\n",
|
|
AttributeName, Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
|
|
LPWSTR AttributeName,
|
|
LPVOID AttributeData,
|
|
PULONG AttributeSize)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING KeyName;
|
|
HANDLE AttributeKey;
|
|
ULONG ValueSize;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&KeyName,
|
|
AttributeName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
DbObject->KeyHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&AttributeKey,
|
|
KEY_QUERY_VALUE,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
ValueSize = *AttributeSize;
|
|
Status = RtlpNtQueryValueKey(AttributeKey,
|
|
NULL,
|
|
NULL,
|
|
&ValueSize,
|
|
0);
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if (AttributeData == NULL || *AttributeSize == 0)
|
|
{
|
|
*AttributeSize = ValueSize;
|
|
Status = STATUS_SUCCESS;
|
|
goto Done;
|
|
}
|
|
else if (*AttributeSize < ValueSize)
|
|
{
|
|
*AttributeSize = ValueSize;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
goto Done;
|
|
}
|
|
|
|
Status = RtlpNtQueryValueKey(AttributeKey,
|
|
NULL,
|
|
AttributeData,
|
|
&ValueSize,
|
|
0);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*AttributeSize = ValueSize;
|
|
}
|
|
|
|
Done:
|
|
NtClose(AttributeKey);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapDeleteObjectAttribute(PLSA_DB_OBJECT DbObject,
|
|
LPWSTR AttributeName)
|
|
{
|
|
return LsapRegDeleteSubKey(DbObject->KeyHandle,
|
|
AttributeName);
|
|
}
|
|
|
|
/* EOF */
|