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
;
20 SID_IDENTIFIER_AUTHORITY NullSidAuthority
= {SECURITY_NULL_SID_AUTHORITY
};
21 SID_IDENTIFIER_AUTHORITY WorldSidAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
22 SID_IDENTIFIER_AUTHORITY LocalSidAuthority
= {SECURITY_LOCAL_SID_AUTHORITY
};
23 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority
= {SECURITY_CREATOR_SID_AUTHORITY
};
24 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
26 PSID BuiltinDomainSid
= NULL
;
27 PSID AccountDomainSid
= NULL
;
28 UNICODE_STRING BuiltinDomainName
= {0, 0, NULL
};
29 UNICODE_STRING AccountDomainName
= {0, 0, NULL
};
32 /* FUNCTIONS ***************************************************************/
35 LsapOpenServiceKey(VOID
)
37 OBJECT_ATTRIBUTES ObjectAttributes
;
38 UNICODE_STRING KeyName
;
41 RtlInitUnicodeString(&KeyName
,
42 L
"\\Registry\\Machine\\SECURITY");
44 InitializeObjectAttributes(&ObjectAttributes
,
50 Status
= RtlpNtOpenKey(&SecurityKeyHandle
,
51 KEY_READ
| KEY_CREATE_SUB_KEY
| KEY_ENUMERATE_SUB_KEYS
,
60 LsapIsDatabaseInstalled(VOID
)
62 OBJECT_ATTRIBUTES ObjectAttributes
;
63 UNICODE_STRING KeyName
;
67 RtlInitUnicodeString(&KeyName
,
70 InitializeObjectAttributes(&ObjectAttributes
,
76 Status
= RtlpNtOpenKey(&KeyHandle
,
80 if (!NT_SUCCESS(Status
))
90 LsapCreateDatabaseKeys(VOID
)
92 OBJECT_ATTRIBUTES ObjectAttributes
;
93 UNICODE_STRING KeyName
;
94 HANDLE PolicyKeyHandle
= NULL
;
95 HANDLE AccountsKeyHandle
= NULL
;
96 HANDLE DomainsKeyHandle
= NULL
;
97 HANDLE SecretsKeyHandle
= NULL
;
98 NTSTATUS Status
= STATUS_SUCCESS
;
100 TRACE("LsapInstallDatabase()\n");
102 /* Create the 'Policy' key */
103 RtlInitUnicodeString(&KeyName
,
106 InitializeObjectAttributes(&ObjectAttributes
,
108 OBJ_CASE_INSENSITIVE
,
112 Status
= NtCreateKey(&PolicyKeyHandle
,
119 if (!NT_SUCCESS(Status
))
121 ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status
);
125 /* Create the 'Accounts' key */
126 RtlInitUnicodeString(&KeyName
,
129 InitializeObjectAttributes(&ObjectAttributes
,
131 OBJ_CASE_INSENSITIVE
,
135 Status
= NtCreateKey(&AccountsKeyHandle
,
142 if (!NT_SUCCESS(Status
))
144 ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status
);
148 /* Create the 'Domains' key */
149 RtlInitUnicodeString(&KeyName
,
152 InitializeObjectAttributes(&ObjectAttributes
,
154 OBJ_CASE_INSENSITIVE
,
158 Status
= NtCreateKey(&DomainsKeyHandle
,
165 if (!NT_SUCCESS(Status
))
167 ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status
);
171 /* Create the 'Secrets' key */
172 RtlInitUnicodeString(&KeyName
,
175 InitializeObjectAttributes(&ObjectAttributes
,
177 OBJ_CASE_INSENSITIVE
,
181 Status
= NtCreateKey(&SecretsKeyHandle
,
188 if (!NT_SUCCESS(Status
))
190 ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status
);
195 if (SecretsKeyHandle
!= NULL
)
196 NtClose(SecretsKeyHandle
);
198 if (DomainsKeyHandle
!= NULL
)
199 NtClose(DomainsKeyHandle
);
201 if (AccountsKeyHandle
!= NULL
)
202 NtClose(AccountsKeyHandle
);
204 if (PolicyKeyHandle
!= NULL
)
205 NtClose(PolicyKeyHandle
);
207 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status
);
214 LsapCreateRandomDomainSid(OUT PSID
*Sid
)
216 LARGE_INTEGER SystemTime
;
219 NtQuerySystemTime(&SystemTime
);
220 Seed
= &SystemTime
.u
.LowPart
;
222 return RtlAllocateAndInitializeSid(&NtAuthority
,
224 SECURITY_NT_NON_UNIQUE
,
237 LsapCreateDatabaseObjects(VOID
)
239 PLSAP_POLICY_AUDIT_EVENTS_DATA AuditEventsInfo
= NULL
;
240 POLICY_DEFAULT_QUOTA_INFO QuotaInfo
;
241 POLICY_MODIFICATION_INFO ModificationInfo
;
242 POLICY_AUDIT_FULL_QUERY_INFO AuditFullInfo
= {FALSE
, FALSE
};
243 POLICY_AUDIT_LOG_INFO AuditLogInfo
;
245 PLSA_DB_OBJECT PolicyObject
= NULL
;
246 PSID AccountDomainSid
= NULL
;
247 ULONG AuditEventsCount
;
248 ULONG AuditEventsSize
;
252 /* Initialize the default quota limits */
253 QuotaInfo
.QuotaLimits
.PagedPoolLimit
= 0x2000000;
254 QuotaInfo
.QuotaLimits
.NonPagedPoolLimit
= 0x100000;
255 QuotaInfo
.QuotaLimits
.MinimumWorkingSetSize
= 0x10000;
256 QuotaInfo
.QuotaLimits
.MaximumWorkingSetSize
= 0xF000000;
257 QuotaInfo
.QuotaLimits
.PagefileLimit
= 0;
258 QuotaInfo
.QuotaLimits
.TimeLimit
.QuadPart
= 0;
260 /* Initialize the audit log attribute */
261 AuditLogInfo
.AuditLogPercentFull
= 0;
262 AuditLogInfo
.MaximumLogSize
= 0; // DWORD
263 AuditLogInfo
.AuditRetentionPeriod
.QuadPart
= 0; // LARGE_INTEGER
264 AuditLogInfo
.AuditLogFullShutdownInProgress
= 0; // BYTE
265 AuditLogInfo
.TimeToShutdown
.QuadPart
= 0; // LARGE_INTEGER
266 AuditLogInfo
.NextAuditRecordId
= 0; // DWORD
268 /* Initialize the Audit Events attribute */
269 AuditEventsCount
= AuditCategoryAccountLogon
- AuditCategorySystem
+ 1;
270 AuditEventsSize
= sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA
) + AuditEventsCount
* sizeof(DWORD
);
271 AuditEventsInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
274 if (AuditEventsInfo
== NULL
)
275 return STATUS_INSUFFICIENT_RESOURCES
;
277 AuditEventsInfo
->AuditingMode
= FALSE
;
278 AuditEventsInfo
->MaximumAuditEventCount
= AuditEventsCount
;
279 for (i
= 0; i
< AuditEventsCount
; i
++)
280 AuditEventsInfo
->AuditEvents
[i
] = 0;
282 /* Initialize the DNS Domain GUID attribute */
283 memset(&DnsDomainGuid
, 0, sizeof(GUID
));
285 /* Initialize the modification attribute */
286 ModificationInfo
.ModifiedId
.QuadPart
= 0;
287 NtQuerySystemTime(&ModificationInfo
.DatabaseCreationTime
);
289 /* Create a random domain SID */
290 Status
= LsapCreateRandomDomainSid(&AccountDomainSid
);
291 if (!NT_SUCCESS(Status
))
294 /* Open the 'Policy' object */
295 Status
= LsapOpenDbObject(NULL
,
301 if (!NT_SUCCESS(Status
))
304 LsapSetObjectAttribute(PolicyObject
,
309 LsapSetObjectAttribute(PolicyObject
,
314 LsapSetObjectAttribute(PolicyObject
,
319 LsapSetObjectAttribute(PolicyObject
,
322 RtlLengthSid(AccountDomainSid
));
324 /* Set the default quota limits attribute */
325 LsapSetObjectAttribute(PolicyObject
,
328 sizeof(POLICY_DEFAULT_QUOTA_INFO
));
330 /* Set the modification attribute */
331 LsapSetObjectAttribute(PolicyObject
,
334 sizeof(POLICY_MODIFICATION_INFO
));
336 /* Set the audit full attribute */
337 LsapSetObjectAttribute(PolicyObject
,
340 sizeof(POLICY_AUDIT_FULL_QUERY_INFO
));
342 /* Set the audit log attribute */
343 LsapSetObjectAttribute(PolicyObject
,
346 sizeof(POLICY_AUDIT_LOG_INFO
));
348 /* Set the audit events attribute */
349 LsapSetObjectAttribute(PolicyObject
,
354 /* Set the DNS Domain Name attribute */
355 LsapSetObjectAttribute(PolicyObject
,
360 /* Set the DNS Forest Name attribute */
361 LsapSetObjectAttribute(PolicyObject
,
366 /* Set the DNS Domain GUID attribute */
367 LsapSetObjectAttribute(PolicyObject
,
373 if (AuditEventsInfo
!= NULL
)
374 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo
);
376 if (PolicyObject
!= NULL
)
377 LsapCloseDbObject(PolicyObject
);
379 if (AccountDomainSid
!= NULL
)
380 RtlFreeSid(AccountDomainSid
);
387 LsapUpdateDatabase(VOID
)
389 return STATUS_SUCCESS
;
394 LsapGetDomainInfo(VOID
)
396 PLSA_DB_OBJECT PolicyObject
= NULL
;
397 PUNICODE_STRING DomainName
= NULL
;
399 LPWSTR SidString
= NULL
;
402 /* Get the built-in domain SID and name */
403 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
405 SECURITY_BUILTIN_DOMAIN_RID
,
408 if (!NT_SUCCESS(Status
))
412 RtlInitUnicodeString(&BuiltinDomainName
,
415 /* Open the 'Policy' object */
416 Status
= LsapOpenDbObject(NULL
,
422 if (!NT_SUCCESS(Status
))
425 /* Get the account domain SID */
427 Status
= LsapGetObjectAttribute(PolicyObject
,
431 if (!NT_SUCCESS(Status
))
434 if (AttributeSize
> 0)
436 AccountDomainSid
= RtlAllocateHeap(RtlGetProcessHeap(),
439 if (AccountDomainSid
== NULL
)
441 Status
= STATUS_INSUFFICIENT_RESOURCES
;
445 Status
= LsapGetObjectAttribute(PolicyObject
,
449 if (!NT_SUCCESS(Status
))
453 /* Get the account domain name */
455 Status
= LsapGetObjectAttribute(PolicyObject
,
459 if (!NT_SUCCESS(Status
))
462 if (AttributeSize
> 0)
464 DomainName
= RtlAllocateHeap(RtlGetProcessHeap(),
467 if (DomainName
== NULL
)
469 Status
= STATUS_INSUFFICIENT_RESOURCES
;
473 Status
= LsapGetObjectAttribute(PolicyObject
,
477 if (!NT_SUCCESS(Status
))
480 DomainName
->Buffer
= (LPWSTR
)((ULONG_PTR
)DomainName
+ (ULONG_PTR
)DomainName
->Buffer
);
482 AccountDomainName
.Length
= DomainName
->Length
;
483 AccountDomainName
.MaximumLength
= DomainName
->Length
+ sizeof(WCHAR
);
484 AccountDomainName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
486 AccountDomainName
.MaximumLength
);
487 if (AccountDomainName
.Buffer
== NULL
)
489 ERR("Failed to allocate the account domain name buffer\n");
490 Status
= STATUS_INSUFFICIENT_RESOURCES
;
494 RtlCopyMemory(AccountDomainName
.Buffer
,
499 ConvertSidToStringSidW(BuiltinDomainSid
, &SidString
);
500 TRACE("Builtin Domain SID: %S\n", SidString
);
501 LocalFree(SidString
);
504 TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName
);
506 ConvertSidToStringSidW(AccountDomainSid
, &SidString
);
507 TRACE("Account Domain SID: %S\n", SidString
);
508 LocalFree(SidString
);
511 TRACE("Account Domain Name: %wZ\n", &AccountDomainName
);
514 if (DomainName
!= NULL
)
515 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName
);
517 if (PolicyObject
!= NULL
)
518 LsapCloseDbObject(PolicyObject
);
525 LsapInitDatabase(VOID
)
529 TRACE("LsapInitDatabase()\n");
531 Status
= LsapOpenServiceKey();
532 if (!NT_SUCCESS(Status
))
534 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status
);
538 if (!LsapIsDatabaseInstalled())
540 Status
= LsapCreateDatabaseKeys();
541 if (!NT_SUCCESS(Status
))
543 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status
);
547 Status
= LsapCreateDatabaseObjects();
548 if (!NT_SUCCESS(Status
))
550 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status
);
556 Status
= LsapUpdateDatabase();
557 if (!NT_SUCCESS(Status
))
559 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status
);
564 Status
= LsapGetDomainInfo();
565 if (!NT_SUCCESS(Status
))
567 ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status
);
571 TRACE("LsapInitDatabase() done\n");
573 return STATUS_SUCCESS
;
578 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject
,
579 IN LPWSTR ContainerName
,
580 IN LPWSTR ObjectName
,
581 IN LSA_DB_OBJECT_TYPE ObjectType
,
582 IN ACCESS_MASK DesiredAccess
,
583 OUT PLSA_DB_OBJECT
*DbObject
)
585 PLSA_DB_OBJECT NewObject
;
586 OBJECT_ATTRIBUTES ObjectAttributes
;
587 UNICODE_STRING KeyName
;
588 HANDLE ParentKeyHandle
;
589 HANDLE ContainerKeyHandle
= NULL
;
590 HANDLE ObjectKeyHandle
= NULL
;
593 if (DbObject
== NULL
)
594 return STATUS_INVALID_PARAMETER
;
596 if (ParentObject
== NULL
)
597 ParentKeyHandle
= SecurityKeyHandle
;
599 ParentKeyHandle
= ParentObject
->KeyHandle
;
601 if (ContainerName
!= NULL
)
603 /* Open the container key */
604 RtlInitUnicodeString(&KeyName
,
607 InitializeObjectAttributes(&ObjectAttributes
,
609 OBJ_CASE_INSENSITIVE
,
613 Status
= NtOpenKey(&ContainerKeyHandle
,
616 if (!NT_SUCCESS(Status
))
621 /* Open the object key */
622 RtlInitUnicodeString(&KeyName
,
625 InitializeObjectAttributes(&ObjectAttributes
,
627 OBJ_CASE_INSENSITIVE
,
631 Status
= NtCreateKey(&ObjectKeyHandle
,
639 NtClose(ContainerKeyHandle
);
641 if (!NT_SUCCESS(Status
))
648 RtlInitUnicodeString(&KeyName
,
651 InitializeObjectAttributes(&ObjectAttributes
,
653 OBJ_CASE_INSENSITIVE
,
657 Status
= NtCreateKey(&ObjectKeyHandle
,
664 if (!NT_SUCCESS(Status
))
670 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
672 sizeof(LSA_DB_OBJECT
));
673 if (NewObject
== NULL
)
675 NtClose(ObjectKeyHandle
);
676 return STATUS_NO_MEMORY
;
679 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
680 NewObject
->RefCount
= 1;
681 NewObject
->ObjectType
= ObjectType
;
682 NewObject
->Access
= DesiredAccess
;
683 NewObject
->KeyHandle
= ObjectKeyHandle
;
684 NewObject
->ParentObject
= ParentObject
;
686 if (ParentObject
!= NULL
)
687 ParentObject
->RefCount
++;
689 *DbObject
= NewObject
;
691 return STATUS_SUCCESS
;
696 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject
,
697 IN LPWSTR ContainerName
,
698 IN LPWSTR ObjectName
,
699 IN LSA_DB_OBJECT_TYPE ObjectType
,
700 IN ACCESS_MASK DesiredAccess
,
701 OUT PLSA_DB_OBJECT
*DbObject
)
703 PLSA_DB_OBJECT NewObject
;
704 OBJECT_ATTRIBUTES ObjectAttributes
;
705 UNICODE_STRING KeyName
;
706 HANDLE ParentKeyHandle
;
707 HANDLE ContainerKeyHandle
= NULL
;
708 HANDLE ObjectKeyHandle
= NULL
;
711 if (DbObject
== NULL
)
712 return STATUS_INVALID_PARAMETER
;
714 if (ParentObject
== NULL
)
715 ParentKeyHandle
= SecurityKeyHandle
;
717 ParentKeyHandle
= ParentObject
->KeyHandle
;
719 if (ContainerName
!= NULL
)
721 /* Open the container key */
722 RtlInitUnicodeString(&KeyName
,
725 InitializeObjectAttributes(&ObjectAttributes
,
727 OBJ_CASE_INSENSITIVE
,
731 Status
= NtOpenKey(&ContainerKeyHandle
,
734 if (!NT_SUCCESS(Status
))
739 /* Open the object key */
740 RtlInitUnicodeString(&KeyName
,
743 InitializeObjectAttributes(&ObjectAttributes
,
745 OBJ_CASE_INSENSITIVE
,
749 Status
= NtOpenKey(&ObjectKeyHandle
,
753 NtClose(ContainerKeyHandle
);
755 if (!NT_SUCCESS(Status
))
762 /* Open the object key */
763 RtlInitUnicodeString(&KeyName
,
766 InitializeObjectAttributes(&ObjectAttributes
,
768 OBJ_CASE_INSENSITIVE
,
772 Status
= NtOpenKey(&ObjectKeyHandle
,
775 if (!NT_SUCCESS(Status
))
781 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
783 sizeof(LSA_DB_OBJECT
));
784 if (NewObject
== NULL
)
786 NtClose(ObjectKeyHandle
);
787 return STATUS_NO_MEMORY
;
790 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
791 NewObject
->RefCount
= 1;
792 NewObject
->ObjectType
= ObjectType
;
793 NewObject
->Access
= DesiredAccess
;
794 NewObject
->KeyHandle
= ObjectKeyHandle
;
795 NewObject
->ParentObject
= ParentObject
;
797 if (ParentObject
!= NULL
)
798 ParentObject
->RefCount
++;
800 *DbObject
= NewObject
;
802 return STATUS_SUCCESS
;
807 LsapValidateDbObject(LSAPR_HANDLE Handle
,
808 LSA_DB_OBJECT_TYPE ObjectType
,
809 ACCESS_MASK DesiredAccess
,
810 PLSA_DB_OBJECT
*DbObject
)
812 PLSA_DB_OBJECT LocalObject
= (PLSA_DB_OBJECT
)Handle
;
813 BOOLEAN bValid
= FALSE
;
817 if (LocalObject
->Signature
== LSAP_DB_SIGNATURE
)
819 if ((ObjectType
== LsaDbIgnoreObject
) ||
820 (LocalObject
->ObjectType
== ObjectType
))
824 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
831 return STATUS_INVALID_HANDLE
;
833 if (DesiredAccess
!= 0)
835 /* Check for granted access rights */
836 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
838 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
839 LocalObject
->Access
, DesiredAccess
);
840 return STATUS_ACCESS_DENIED
;
844 if (DbObject
!= NULL
)
845 *DbObject
= LocalObject
;
847 return STATUS_SUCCESS
;
852 LsapCloseDbObject(PLSA_DB_OBJECT DbObject
)
854 PLSA_DB_OBJECT ParentObject
= NULL
;
855 NTSTATUS Status
= STATUS_SUCCESS
;
857 DbObject
->RefCount
--;
859 if (DbObject
->RefCount
> 0)
860 return STATUS_SUCCESS
;
862 if (DbObject
->KeyHandle
!= NULL
)
863 NtClose(DbObject
->KeyHandle
);
865 if (DbObject
->ParentObject
!= NULL
)
866 ParentObject
= DbObject
->ParentObject
;
868 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
870 if (ParentObject
!= NULL
)
872 ParentObject
->RefCount
--;
874 if (ParentObject
->RefCount
== 0)
875 Status
= LsapCloseDbObject(ParentObject
);
883 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject
,
884 LPWSTR AttributeName
,
885 LPVOID AttributeData
,
888 OBJECT_ATTRIBUTES ObjectAttributes
;
889 UNICODE_STRING KeyName
;
893 RtlInitUnicodeString(&KeyName
,
896 InitializeObjectAttributes(&ObjectAttributes
,
898 OBJ_CASE_INSENSITIVE
,
902 Status
= NtCreateKey(&AttributeKey
,
907 REG_OPTION_NON_VOLATILE
,
909 if (!NT_SUCCESS(Status
))
915 Status
= RtlpNtSetValueKey(AttributeKey
,
920 NtClose(AttributeKey
);
927 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject
,
928 LPWSTR AttributeName
,
929 LPVOID AttributeData
,
930 PULONG AttributeSize
)
932 OBJECT_ATTRIBUTES ObjectAttributes
;
933 UNICODE_STRING KeyName
;
938 RtlInitUnicodeString(&KeyName
,
941 InitializeObjectAttributes(&ObjectAttributes
,
943 OBJ_CASE_INSENSITIVE
,
947 Status
= NtOpenKey(&AttributeKey
,
950 if (!NT_SUCCESS(Status
))
955 ValueSize
= *AttributeSize
;
956 Status
= RtlpNtQueryValueKey(AttributeKey
,
961 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
966 if (AttributeData
== NULL
|| *AttributeSize
== 0)
968 *AttributeSize
= ValueSize
;
969 Status
= STATUS_SUCCESS
;
972 else if (*AttributeSize
< ValueSize
)
974 *AttributeSize
= ValueSize
;
975 Status
= STATUS_BUFFER_OVERFLOW
;
979 Status
= RtlpNtQueryValueKey(AttributeKey
,
984 if (NT_SUCCESS(Status
))
986 *AttributeSize
= ValueSize
;
990 NtClose(AttributeKey
);