2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/lsasrv/database.c
5 * PURPOSE: LSA object database
6 * COPYRIGHT: Copyright 2011 Eric Kohl
9 /* INCLUDES ****************************************************************/
13 WINE_DEFAULT_DEBUG_CHANNEL(lsasrv
);
16 /* GLOBALS *****************************************************************/
18 static HANDLE SecurityKeyHandle
= NULL
;
21 /* FUNCTIONS ***************************************************************/
24 LsapOpenServiceKey(VOID
)
26 OBJECT_ATTRIBUTES ObjectAttributes
;
27 UNICODE_STRING KeyName
;
30 RtlInitUnicodeString(&KeyName
,
31 L
"\\Registry\\Machine\\SECURITY");
33 InitializeObjectAttributes(&ObjectAttributes
,
39 Status
= RtlpNtOpenKey(&SecurityKeyHandle
,
40 KEY_READ
| KEY_CREATE_SUB_KEY
| KEY_ENUMERATE_SUB_KEYS
,
49 LsapIsDatabaseInstalled(VOID
)
51 OBJECT_ATTRIBUTES ObjectAttributes
;
52 UNICODE_STRING KeyName
;
56 RtlInitUnicodeString(&KeyName
,
59 InitializeObjectAttributes(&ObjectAttributes
,
65 Status
= RtlpNtOpenKey(&KeyHandle
,
69 if (!NT_SUCCESS(Status
))
79 LsapCreateDatabaseKeys(VOID
)
81 OBJECT_ATTRIBUTES ObjectAttributes
;
82 UNICODE_STRING KeyName
;
83 HANDLE PolicyKeyHandle
= NULL
;
84 HANDLE AccountsKeyHandle
= NULL
;
85 HANDLE DomainsKeyHandle
= NULL
;
86 HANDLE SecretsKeyHandle
= NULL
;
87 NTSTATUS Status
= STATUS_SUCCESS
;
89 TRACE("LsapInstallDatabase()\n");
91 /* Create the 'Policy' key */
92 RtlInitUnicodeString(&KeyName
,
95 InitializeObjectAttributes(&ObjectAttributes
,
101 Status
= NtCreateKey(&PolicyKeyHandle
,
108 if (!NT_SUCCESS(Status
))
110 ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status
);
114 /* Create the 'Accounts' key */
115 RtlInitUnicodeString(&KeyName
,
118 InitializeObjectAttributes(&ObjectAttributes
,
120 OBJ_CASE_INSENSITIVE
,
124 Status
= NtCreateKey(&AccountsKeyHandle
,
131 if (!NT_SUCCESS(Status
))
133 ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status
);
137 /* Create the 'Domains' key */
138 RtlInitUnicodeString(&KeyName
,
141 InitializeObjectAttributes(&ObjectAttributes
,
143 OBJ_CASE_INSENSITIVE
,
147 Status
= NtCreateKey(&DomainsKeyHandle
,
154 if (!NT_SUCCESS(Status
))
156 ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status
);
160 /* Create the 'Secrets' key */
161 RtlInitUnicodeString(&KeyName
,
164 InitializeObjectAttributes(&ObjectAttributes
,
166 OBJ_CASE_INSENSITIVE
,
170 Status
= NtCreateKey(&SecretsKeyHandle
,
177 if (!NT_SUCCESS(Status
))
179 ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status
);
184 if (SecretsKeyHandle
!= NULL
)
185 NtClose(SecretsKeyHandle
);
187 if (DomainsKeyHandle
!= NULL
)
188 NtClose(DomainsKeyHandle
);
190 if (AccountsKeyHandle
!= NULL
)
191 NtClose(AccountsKeyHandle
);
193 if (PolicyKeyHandle
!= NULL
)
194 NtClose(PolicyKeyHandle
);
196 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status
);
203 LsapCreateRandomDomainSid(OUT PSID
*Sid
)
205 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
206 LARGE_INTEGER SystemTime
;
209 NtQuerySystemTime(&SystemTime
);
210 Seed
= &SystemTime
.u
.LowPart
;
212 return RtlAllocateAndInitializeSid(&SystemAuthority
,
214 SECURITY_NT_NON_UNIQUE
,
227 LsapCreateDatabaseObjects(VOID
)
229 PLSAP_POLICY_AUDIT_EVENTS_DATA AuditEventsInfo
= NULL
;
230 POLICY_DEFAULT_QUOTA_INFO QuotaInfo
;
231 POLICY_MODIFICATION_INFO ModificationInfo
;
232 POLICY_AUDIT_FULL_QUERY_INFO AuditFullInfo
= {FALSE
, FALSE
};
233 POLICY_AUDIT_LOG_INFO AuditLogInfo
;
235 PLSA_DB_OBJECT PolicyObject
= NULL
;
236 PSID AccountDomainSid
= NULL
;
237 ULONG AuditEventsCount
;
238 ULONG AuditEventsSize
;
242 /* Initialize the default quota limits */
243 QuotaInfo
.QuotaLimits
.PagedPoolLimit
= 0x2000000;
244 QuotaInfo
.QuotaLimits
.NonPagedPoolLimit
= 0x100000;
245 QuotaInfo
.QuotaLimits
.MinimumWorkingSetSize
= 0x10000;
246 QuotaInfo
.QuotaLimits
.MaximumWorkingSetSize
= 0xF000000;
247 QuotaInfo
.QuotaLimits
.PagefileLimit
= 0;
248 QuotaInfo
.QuotaLimits
.TimeLimit
.QuadPart
= 0;
250 /* Initialize the audit log attribute */
251 AuditLogInfo
.AuditLogPercentFull
= 0;
252 AuditLogInfo
.MaximumLogSize
= 0; // DWORD
253 AuditLogInfo
.AuditRetentionPeriod
.QuadPart
= 0; // LARGE_INTEGER
254 AuditLogInfo
.AuditLogFullShutdownInProgress
= 0; // BYTE
255 AuditLogInfo
.TimeToShutdown
.QuadPart
= 0; // LARGE_INTEGER
256 AuditLogInfo
.NextAuditRecordId
= 0; // DWORD
258 /* Initialize the Audit Events attribute */
259 AuditEventsCount
= AuditCategoryAccountLogon
- AuditCategorySystem
+ 1;
260 AuditEventsSize
= sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA
) + AuditEventsCount
* sizeof(DWORD
);
261 AuditEventsInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
264 if (AuditEventsInfo
== NULL
)
265 return STATUS_INSUFFICIENT_RESOURCES
;
267 AuditEventsInfo
->AuditingMode
= FALSE
;
268 AuditEventsInfo
->MaximumAuditEventCount
= AuditEventsCount
;
269 for (i
= 0; i
< AuditEventsCount
; i
++)
270 AuditEventsInfo
->AuditEvents
[i
] = 0;
272 /* Initialize the DNS Domain GUID attribute */
273 memset(&DnsDomainGuid
, 0, sizeof(GUID
));
275 /* Initialize the modification attribute */
276 ModificationInfo
.ModifiedId
.QuadPart
= 0;
277 NtQuerySystemTime(&ModificationInfo
.DatabaseCreationTime
);
279 /* Create a random domain SID */
280 Status
= LsapCreateRandomDomainSid(&AccountDomainSid
);
281 if (!NT_SUCCESS(Status
))
284 /* Open the 'Policy' object */
285 Status
= LsapOpenDbObject(NULL
,
291 if (!NT_SUCCESS(Status
))
294 LsapSetObjectAttribute(PolicyObject
,
299 LsapSetObjectAttribute(PolicyObject
,
304 LsapSetObjectAttribute(PolicyObject
,
309 LsapSetObjectAttribute(PolicyObject
,
312 RtlLengthSid(AccountDomainSid
));
314 /* Set the default quota limits attribute */
315 LsapSetObjectAttribute(PolicyObject
,
318 sizeof(POLICY_DEFAULT_QUOTA_INFO
));
320 /* Set the modification attribute */
321 LsapSetObjectAttribute(PolicyObject
,
324 sizeof(POLICY_MODIFICATION_INFO
));
326 /* Set the audit full attribute */
327 LsapSetObjectAttribute(PolicyObject
,
330 sizeof(POLICY_AUDIT_FULL_QUERY_INFO
));
332 /* Set the audit log attribute */
333 LsapSetObjectAttribute(PolicyObject
,
336 sizeof(POLICY_AUDIT_LOG_INFO
));
338 /* Set the audit events attribute */
339 LsapSetObjectAttribute(PolicyObject
,
344 /* Set the DNS Domain Name attribute */
345 LsapSetObjectAttribute(PolicyObject
,
350 /* Set the DNS Forest Name attribute */
351 LsapSetObjectAttribute(PolicyObject
,
356 /* Set the DNS Domain GUID attribute */
357 LsapSetObjectAttribute(PolicyObject
,
363 if (AuditEventsInfo
!= NULL
)
364 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo
);
366 if (PolicyObject
!= NULL
)
367 LsapCloseDbObject(PolicyObject
);
369 if (AccountDomainSid
!= NULL
)
370 RtlFreeSid(AccountDomainSid
);
377 LsapUpdateDatabase(VOID
)
379 return STATUS_SUCCESS
;
384 LsapInitDatabase(VOID
)
388 TRACE("LsapInitDatabase()\n");
390 Status
= LsapOpenServiceKey();
391 if (!NT_SUCCESS(Status
))
393 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status
);
397 if (!LsapIsDatabaseInstalled())
399 Status
= LsapCreateDatabaseKeys();
400 if (!NT_SUCCESS(Status
))
402 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status
);
406 Status
= LsapCreateDatabaseObjects();
407 if (!NT_SUCCESS(Status
))
409 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status
);
415 Status
= LsapUpdateDatabase();
416 if (!NT_SUCCESS(Status
))
418 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status
);
423 TRACE("LsapInitDatabase() done\n");
425 return STATUS_SUCCESS
;
430 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject
,
431 IN LPWSTR ContainerName
,
432 IN LPWSTR ObjectName
,
433 IN LSA_DB_OBJECT_TYPE ObjectType
,
434 IN ACCESS_MASK DesiredAccess
,
435 OUT PLSA_DB_OBJECT
*DbObject
)
437 PLSA_DB_OBJECT NewObject
;
438 OBJECT_ATTRIBUTES ObjectAttributes
;
439 UNICODE_STRING KeyName
;
440 HANDLE ParentKeyHandle
;
441 HANDLE ContainerKeyHandle
= NULL
;
442 HANDLE ObjectKeyHandle
= NULL
;
445 if (DbObject
== NULL
)
446 return STATUS_INVALID_PARAMETER
;
448 if (ParentObject
== NULL
)
449 ParentKeyHandle
= SecurityKeyHandle
;
451 ParentKeyHandle
= ParentObject
->KeyHandle
;
453 if (ContainerName
!= NULL
)
455 /* Open the container key */
456 RtlInitUnicodeString(&KeyName
,
459 InitializeObjectAttributes(&ObjectAttributes
,
461 OBJ_CASE_INSENSITIVE
,
465 Status
= NtOpenKey(&ContainerKeyHandle
,
468 if (!NT_SUCCESS(Status
))
473 /* Open the object key */
474 RtlInitUnicodeString(&KeyName
,
477 InitializeObjectAttributes(&ObjectAttributes
,
479 OBJ_CASE_INSENSITIVE
,
483 Status
= NtCreateKey(&ObjectKeyHandle
,
491 NtClose(ContainerKeyHandle
);
493 if (!NT_SUCCESS(Status
))
500 RtlInitUnicodeString(&KeyName
,
503 InitializeObjectAttributes(&ObjectAttributes
,
505 OBJ_CASE_INSENSITIVE
,
509 Status
= NtCreateKey(&ObjectKeyHandle
,
516 if (!NT_SUCCESS(Status
))
522 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
524 sizeof(LSA_DB_OBJECT
));
525 if (NewObject
== NULL
)
527 NtClose(ObjectKeyHandle
);
528 return STATUS_NO_MEMORY
;
531 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
532 NewObject
->RefCount
= 1;
533 NewObject
->ObjectType
= ObjectType
;
534 NewObject
->Access
= DesiredAccess
;
535 NewObject
->KeyHandle
= ObjectKeyHandle
;
536 NewObject
->ParentObject
= ParentObject
;
538 if (ParentObject
!= NULL
)
539 ParentObject
->RefCount
++;
541 *DbObject
= NewObject
;
543 return STATUS_SUCCESS
;
548 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject
,
549 IN LPWSTR ContainerName
,
550 IN LPWSTR ObjectName
,
551 IN LSA_DB_OBJECT_TYPE ObjectType
,
552 IN ACCESS_MASK DesiredAccess
,
553 OUT PLSA_DB_OBJECT
*DbObject
)
555 PLSA_DB_OBJECT NewObject
;
556 OBJECT_ATTRIBUTES ObjectAttributes
;
557 UNICODE_STRING KeyName
;
558 HANDLE ParentKeyHandle
;
559 HANDLE ContainerKeyHandle
= NULL
;
560 HANDLE ObjectKeyHandle
= NULL
;
563 if (DbObject
== NULL
)
564 return STATUS_INVALID_PARAMETER
;
566 if (ParentObject
== NULL
)
567 ParentKeyHandle
= SecurityKeyHandle
;
569 ParentKeyHandle
= ParentObject
->KeyHandle
;
571 if (ContainerName
!= NULL
)
573 /* Open the container key */
574 RtlInitUnicodeString(&KeyName
,
577 InitializeObjectAttributes(&ObjectAttributes
,
579 OBJ_CASE_INSENSITIVE
,
583 Status
= NtOpenKey(&ContainerKeyHandle
,
586 if (!NT_SUCCESS(Status
))
591 /* Open the object key */
592 RtlInitUnicodeString(&KeyName
,
595 InitializeObjectAttributes(&ObjectAttributes
,
597 OBJ_CASE_INSENSITIVE
,
601 Status
= NtOpenKey(&ObjectKeyHandle
,
605 NtClose(ContainerKeyHandle
);
607 if (!NT_SUCCESS(Status
))
614 /* Open the object key */
615 RtlInitUnicodeString(&KeyName
,
618 InitializeObjectAttributes(&ObjectAttributes
,
620 OBJ_CASE_INSENSITIVE
,
624 Status
= NtOpenKey(&ObjectKeyHandle
,
627 if (!NT_SUCCESS(Status
))
633 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
635 sizeof(LSA_DB_OBJECT
));
636 if (NewObject
== NULL
)
638 NtClose(ObjectKeyHandle
);
639 return STATUS_NO_MEMORY
;
642 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
643 NewObject
->RefCount
= 1;
644 NewObject
->ObjectType
= ObjectType
;
645 NewObject
->Access
= DesiredAccess
;
646 NewObject
->KeyHandle
= ObjectKeyHandle
;
647 NewObject
->ParentObject
= ParentObject
;
649 if (ParentObject
!= NULL
)
650 ParentObject
->RefCount
++;
652 *DbObject
= NewObject
;
654 return STATUS_SUCCESS
;
659 LsapValidateDbObject(LSAPR_HANDLE Handle
,
660 LSA_DB_OBJECT_TYPE ObjectType
,
661 ACCESS_MASK DesiredAccess
,
662 PLSA_DB_OBJECT
*DbObject
)
664 PLSA_DB_OBJECT LocalObject
= (PLSA_DB_OBJECT
)Handle
;
665 BOOLEAN bValid
= FALSE
;
669 if (LocalObject
->Signature
== LSAP_DB_SIGNATURE
)
671 if ((ObjectType
== LsaDbIgnoreObject
) ||
672 (LocalObject
->ObjectType
== ObjectType
))
676 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
683 return STATUS_INVALID_HANDLE
;
685 if (DesiredAccess
!= 0)
687 /* Check for granted access rights */
688 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
690 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
691 LocalObject
->Access
, DesiredAccess
);
692 return STATUS_ACCESS_DENIED
;
696 if (DbObject
!= NULL
)
697 *DbObject
= LocalObject
;
699 return STATUS_SUCCESS
;
704 LsapCloseDbObject(PLSA_DB_OBJECT DbObject
)
706 PLSA_DB_OBJECT ParentObject
= NULL
;
707 NTSTATUS Status
= STATUS_SUCCESS
;
709 DbObject
->RefCount
--;
711 if (DbObject
->RefCount
> 0)
712 return STATUS_SUCCESS
;
714 if (DbObject
->KeyHandle
!= NULL
)
715 NtClose(DbObject
->KeyHandle
);
717 if (DbObject
->ParentObject
!= NULL
)
718 ParentObject
= DbObject
->ParentObject
;
720 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
722 if (ParentObject
!= NULL
)
724 ParentObject
->RefCount
--;
726 if (ParentObject
->RefCount
== 0)
727 Status
= LsapCloseDbObject(ParentObject
);
735 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject
,
736 LPWSTR AttributeName
,
737 LPVOID AttributeData
,
740 OBJECT_ATTRIBUTES ObjectAttributes
;
741 UNICODE_STRING KeyName
;
745 RtlInitUnicodeString(&KeyName
,
748 InitializeObjectAttributes(&ObjectAttributes
,
750 OBJ_CASE_INSENSITIVE
,
754 Status
= NtCreateKey(&AttributeKey
,
759 REG_OPTION_NON_VOLATILE
,
761 if (!NT_SUCCESS(Status
))
767 Status
= RtlpNtSetValueKey(AttributeKey
,
772 NtClose(AttributeKey
);
779 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject
,
780 LPWSTR AttributeName
,
781 LPVOID AttributeData
,
782 PULONG AttributeSize
)
784 OBJECT_ATTRIBUTES ObjectAttributes
;
785 UNICODE_STRING KeyName
;
790 RtlInitUnicodeString(&KeyName
,
793 InitializeObjectAttributes(&ObjectAttributes
,
795 OBJ_CASE_INSENSITIVE
,
799 Status
= NtOpenKey(&AttributeKey
,
802 if (!NT_SUCCESS(Status
))
807 ValueSize
= *AttributeSize
;
808 Status
= RtlpNtQueryValueKey(AttributeKey
,
813 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
818 if (AttributeData
== NULL
|| *AttributeSize
== 0)
820 *AttributeSize
= ValueSize
;
821 Status
= STATUS_SUCCESS
;
824 else if (*AttributeSize
< ValueSize
)
826 *AttributeSize
= ValueSize
;
827 Status
= STATUS_BUFFER_OVERFLOW
;
831 Status
= RtlpNtQueryValueKey(AttributeKey
,
836 if (NT_SUCCESS(Status
))
838 *AttributeSize
= ValueSize
;
842 NtClose(AttributeKey
);