static NTSTATUS
-LsapInstallDatabase(VOID)
+LsapCreateDatabaseKeys(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
goto Done;
}
-
Done:
if (SecretsKeyHandle != NULL)
NtClose(SecretsKeyHandle);
}
+static NTSTATUS
+LsapCreateRandomDomainSid(OUT PSID *Sid)
+{
+ SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
+ LARGE_INTEGER SystemTime;
+ PULONG Seed;
+
+ NtQuerySystemTime(&SystemTime);
+ Seed = &SystemTime.u.LowPart;
+
+ return RtlAllocateAndInitializeSid(&SystemAuthority,
+ 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;
+
+ PLSA_DB_OBJECT PolicyObject = NULL;
+ PSID AccountDomainSid = NULL;
+ 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
+
+ AuditEventsCount = AuditCategoryAccountLogon - AuditCategorySystem + 1;
+ AuditEventsSize = sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA) + AuditEventsCount * sizeof(DWORD);
+ AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ 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 modification attribute */
+ ModificationInfo.ModifiedId.QuadPart = 0;
+ NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime);
+
+ /* Create a random domain SID */
+ Status = LsapCreateRandomDomainSid(&AccountDomainSid);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Open the 'Policy' object */
+ Status = LsapOpenDbObject(NULL,
+ L"Policy",
+ LsaDbPolicyObject,
+ 0,
+ &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);
+
+done:
+ if (AuditEventsInfo != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo);
+
+ if (PolicyObject != NULL)
+ LsapCloseDbObject(PolicyObject);
+
+ if (AccountDomainSid != NULL)
+ RtlFreeSid(AccountDomainSid);
+
+ return Status;
+}
+
+
+static NTSTATUS
+LsapUpdateDatabase(VOID)
+{
+ return STATUS_SUCCESS;
+}
+
+
NTSTATUS
LsapInitDatabase(VOID)
{
if (!LsapIsDatabaseInstalled())
{
- Status = LsapInstallDatabase();
+ 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 install the LSA database (Status: 0x%08lx)\n", Status);
+ ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
return Status;
}
}
}
-LSAPR_HANDLE
-LsapCreateDbObject(LSAPR_HANDLE ParentHandle,
- LPWSTR ObjectName,
- BOOLEAN Open,
- LSA_DB_OBJECT_TYPE ObjectType,
- ACCESS_MASK DesiredAccess)
+NTSTATUS
+LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
+ IN LPWSTR ObjectName,
+ IN LSA_DB_OBJECT_TYPE ObjectType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PLSA_DB_OBJECT *DbObject)
{
- PLSA_DB_OBJECT ParentObject = (PLSA_DB_OBJECT)ParentHandle;
- PLSA_DB_OBJECT DbObject;
+ PLSA_DB_OBJECT NewObject;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE ParentKeyHandle;
HANDLE ObjectKeyHandle;
NTSTATUS Status;
- if (ParentHandle != NULL)
- ParentKeyHandle = ParentObject->KeyHandle;
- else
+ if (DbObject == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (ParentObject == NULL)
ParentKeyHandle = SecurityKeyHandle;
+ else
+ ParentKeyHandle = ParentObject->KeyHandle;
RtlInitUnicodeString(&KeyName,
ObjectName);
ParentKeyHandle,
NULL);
- if (Open == TRUE)
+ Status = NtCreateKey(&ObjectKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ 0,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- Status = NtOpenKey(&ObjectKeyHandle,
- KEY_ALL_ACCESS,
- &ObjectAttributes);
+ return Status;
}
- else
+
+ NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(LSA_DB_OBJECT));
+ if (NewObject == NULL)
{
- Status = NtCreateKey(&ObjectKeyHandle,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- 0,
- 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;
+
+ if (ParentObject != NULL)
+ ParentObject->RefCount++;
+
+ *DbObject = NewObject;
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
+ IN LPWSTR ObjectName,
+ IN LSA_DB_OBJECT_TYPE ObjectType,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PLSA_DB_OBJECT *DbObject)
+{
+ PLSA_DB_OBJECT NewObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE ParentKeyHandle;
+ HANDLE ObjectKeyHandle;
+ NTSTATUS Status;
+
+ if (DbObject == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ if (ParentObject == NULL)
+ ParentKeyHandle = SecurityKeyHandle;
+ else
+ ParentKeyHandle = ParentObject->KeyHandle;
+
+ RtlInitUnicodeString(&KeyName,
+ ObjectName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ ParentKeyHandle,
+ NULL);
+
+ Status = NtOpenKey(&ObjectKeyHandle,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
- return NULL;
+ return Status;
}
- DbObject = (PLSA_DB_OBJECT)RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(LSA_DB_OBJECT));
- if (DbObject == NULL)
+ NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(LSA_DB_OBJECT));
+ if (NewObject == NULL)
{
NtClose(ObjectKeyHandle);
- return NULL;
+ return STATUS_NO_MEMORY;
}
- DbObject->Signature = LSAP_DB_SIGNATURE;
- DbObject->RefCount = 0;
- DbObject->ObjectType = ObjectType;
- DbObject->Access = DesiredAccess;
- DbObject->KeyHandle = ObjectKeyHandle;
- DbObject->ParentObject = ParentObject;
+ NewObject->Signature = LSAP_DB_SIGNATURE;
+ NewObject->RefCount = 1;
+ NewObject->ObjectType = ObjectType;
+ NewObject->Access = DesiredAccess;
+ NewObject->KeyHandle = ObjectKeyHandle;
+ NewObject->ParentObject = ParentObject;
if (ParentObject != NULL)
ParentObject->RefCount++;
- return (LSAPR_HANDLE)DbObject;
+ *DbObject = NewObject;
+
+ return STATUS_SUCCESS;
}
NTSTATUS
LsapValidateDbObject(LSAPR_HANDLE Handle,
LSA_DB_OBJECT_TYPE ObjectType,
- ACCESS_MASK GrantedAccess)
+ ACCESS_MASK DesiredAccess,
+ PLSA_DB_OBJECT *DbObject)
{
- PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
+ PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
BOOLEAN bValid = FALSE;
_SEH2_TRY
{
- if (DbObject->Signature == LSAP_DB_SIGNATURE)
+ if (LocalObject->Signature == LSAP_DB_SIGNATURE)
{
if ((ObjectType == LsaDbIgnoreObject) ||
- (DbObject->ObjectType == ObjectType))
+ (LocalObject->ObjectType == ObjectType))
bValid = TRUE;
}
}
if (bValid == FALSE)
return STATUS_INVALID_HANDLE;
- if (GrantedAccess != 0)
+ if (DesiredAccess != 0)
{
- /* FIXME: Check for granted access rights */
+ /* 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(LSAPR_HANDLE Handle)
+LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
{
- PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
+ PLSA_DB_OBJECT ParentObject = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
- if (DbObject->RefCount != 0)
- return STATUS_UNSUCCESSFUL;
+ DbObject->RefCount--;
- if (DbObject->ParentObject != NULL)
- DbObject->ParentObject->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);
- return STATUS_SUCCESS;
+ if (ParentObject != NULL)
+ {
+ ParentObject->RefCount--;
+
+ if (ParentObject->RefCount == 0)
+ Status = LsapCloseDbObject(ParentObject);
+ }
+
+ return Status;
}
if (AttributeData == NULL || *AttributeSize == 0)
{
*AttributeSize = ValueSize;
- Status == STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
goto Done;
}
else if (*AttributeSize < ValueSize)
{
*AttributeSize = ValueSize;
- Status == STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_OVERFLOW;
goto Done;
}