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 AuditEventsCount
= AuditCategoryAccountLogon
- AuditCategorySystem
+ 1;
259 AuditEventsSize
= sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA
) + AuditEventsCount
* sizeof(DWORD
);
260 AuditEventsInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
263 if (AuditEventsInfo
== NULL
)
264 return STATUS_INSUFFICIENT_RESOURCES
;
266 AuditEventsInfo
->AuditingMode
= FALSE
;
267 AuditEventsInfo
->MaximumAuditEventCount
= AuditEventsCount
;
268 for (i
= 0; i
< AuditEventsCount
; i
++)
269 AuditEventsInfo
->AuditEvents
[i
] = 0;
271 /* Initialize the modification attribute */
272 ModificationInfo
.ModifiedId
.QuadPart
= 0;
273 NtQuerySystemTime(&ModificationInfo
.DatabaseCreationTime
);
275 /* Create a random domain SID */
276 Status
= LsapCreateRandomDomainSid(&AccountDomainSid
);
277 if (!NT_SUCCESS(Status
))
280 /* Open the 'Policy' object */
281 Status
= LsapOpenDbObject(NULL
,
286 if (!NT_SUCCESS(Status
))
289 LsapSetObjectAttribute(PolicyObject
,
294 LsapSetObjectAttribute(PolicyObject
,
299 LsapSetObjectAttribute(PolicyObject
,
304 LsapSetObjectAttribute(PolicyObject
,
307 RtlLengthSid(AccountDomainSid
));
309 /* Set the default quota limits attribute */
310 LsapSetObjectAttribute(PolicyObject
,
313 sizeof(POLICY_DEFAULT_QUOTA_INFO
));
315 /* Set the modification attribute */
316 LsapSetObjectAttribute(PolicyObject
,
319 sizeof(POLICY_MODIFICATION_INFO
));
321 /* Set the audit full attribute */
322 LsapSetObjectAttribute(PolicyObject
,
325 sizeof(POLICY_AUDIT_FULL_QUERY_INFO
));
327 /* Set the audit log attribute */
328 LsapSetObjectAttribute(PolicyObject
,
331 sizeof(POLICY_AUDIT_LOG_INFO
));
333 /* Set the audit events attribute */
334 LsapSetObjectAttribute(PolicyObject
,
340 if (AuditEventsInfo
!= NULL
)
341 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo
);
343 if (PolicyObject
!= NULL
)
344 LsapCloseDbObject(PolicyObject
);
346 if (AccountDomainSid
!= NULL
)
347 RtlFreeSid(AccountDomainSid
);
354 LsapUpdateDatabase(VOID
)
356 return STATUS_SUCCESS
;
361 LsapInitDatabase(VOID
)
365 TRACE("LsapInitDatabase()\n");
367 Status
= LsapOpenServiceKey();
368 if (!NT_SUCCESS(Status
))
370 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status
);
374 if (!LsapIsDatabaseInstalled())
376 Status
= LsapCreateDatabaseKeys();
377 if (!NT_SUCCESS(Status
))
379 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status
);
383 Status
= LsapCreateDatabaseObjects();
384 if (!NT_SUCCESS(Status
))
386 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status
);
392 Status
= LsapUpdateDatabase();
393 if (!NT_SUCCESS(Status
))
395 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status
);
400 TRACE("LsapInitDatabase() done\n");
402 return STATUS_SUCCESS
;
407 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject
,
408 IN LPWSTR ObjectName
,
409 IN LSA_DB_OBJECT_TYPE ObjectType
,
410 IN ACCESS_MASK DesiredAccess
,
411 OUT PLSA_DB_OBJECT
*DbObject
)
413 PLSA_DB_OBJECT NewObject
;
414 OBJECT_ATTRIBUTES ObjectAttributes
;
415 UNICODE_STRING KeyName
;
416 HANDLE ParentKeyHandle
;
417 HANDLE ObjectKeyHandle
;
420 if (DbObject
== NULL
)
421 return STATUS_INVALID_PARAMETER
;
423 if (ParentObject
== NULL
)
424 ParentKeyHandle
= SecurityKeyHandle
;
426 ParentKeyHandle
= ParentObject
->KeyHandle
;
428 RtlInitUnicodeString(&KeyName
,
431 InitializeObjectAttributes(&ObjectAttributes
,
433 OBJ_CASE_INSENSITIVE
,
437 Status
= NtCreateKey(&ObjectKeyHandle
,
444 if (!NT_SUCCESS(Status
))
449 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
451 sizeof(LSA_DB_OBJECT
));
452 if (NewObject
== NULL
)
454 NtClose(ObjectKeyHandle
);
455 return STATUS_NO_MEMORY
;
458 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
459 NewObject
->RefCount
= 1;
460 NewObject
->ObjectType
= ObjectType
;
461 NewObject
->Access
= DesiredAccess
;
462 NewObject
->KeyHandle
= ObjectKeyHandle
;
463 NewObject
->ParentObject
= ParentObject
;
465 if (ParentObject
!= NULL
)
466 ParentObject
->RefCount
++;
468 *DbObject
= NewObject
;
470 return STATUS_SUCCESS
;
475 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject
,
476 IN LPWSTR ObjectName
,
477 IN LSA_DB_OBJECT_TYPE ObjectType
,
478 IN ACCESS_MASK DesiredAccess
,
479 OUT PLSA_DB_OBJECT
*DbObject
)
481 PLSA_DB_OBJECT NewObject
;
482 OBJECT_ATTRIBUTES ObjectAttributes
;
483 UNICODE_STRING KeyName
;
484 HANDLE ParentKeyHandle
;
485 HANDLE ObjectKeyHandle
;
488 if (DbObject
== NULL
)
489 return STATUS_INVALID_PARAMETER
;
491 if (ParentObject
== NULL
)
492 ParentKeyHandle
= SecurityKeyHandle
;
494 ParentKeyHandle
= ParentObject
->KeyHandle
;
496 RtlInitUnicodeString(&KeyName
,
499 InitializeObjectAttributes(&ObjectAttributes
,
501 OBJ_CASE_INSENSITIVE
,
505 Status
= NtOpenKey(&ObjectKeyHandle
,
508 if (!NT_SUCCESS(Status
))
513 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
515 sizeof(LSA_DB_OBJECT
));
516 if (NewObject
== NULL
)
518 NtClose(ObjectKeyHandle
);
519 return STATUS_NO_MEMORY
;
522 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
523 NewObject
->RefCount
= 1;
524 NewObject
->ObjectType
= ObjectType
;
525 NewObject
->Access
= DesiredAccess
;
526 NewObject
->KeyHandle
= ObjectKeyHandle
;
527 NewObject
->ParentObject
= ParentObject
;
529 if (ParentObject
!= NULL
)
530 ParentObject
->RefCount
++;
532 *DbObject
= NewObject
;
534 return STATUS_SUCCESS
;
539 LsapValidateDbObject(LSAPR_HANDLE Handle
,
540 LSA_DB_OBJECT_TYPE ObjectType
,
541 ACCESS_MASK DesiredAccess
,
542 PLSA_DB_OBJECT
*DbObject
)
544 PLSA_DB_OBJECT LocalObject
= (PLSA_DB_OBJECT
)Handle
;
545 BOOLEAN bValid
= FALSE
;
549 if (LocalObject
->Signature
== LSAP_DB_SIGNATURE
)
551 if ((ObjectType
== LsaDbIgnoreObject
) ||
552 (LocalObject
->ObjectType
== ObjectType
))
556 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
563 return STATUS_INVALID_HANDLE
;
565 if (DesiredAccess
!= 0)
567 /* Check for granted access rights */
568 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
570 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
571 LocalObject
->Access
, DesiredAccess
);
572 return STATUS_ACCESS_DENIED
;
576 if (DbObject
!= NULL
)
577 *DbObject
= LocalObject
;
579 return STATUS_SUCCESS
;
584 LsapCloseDbObject(PLSA_DB_OBJECT DbObject
)
586 PLSA_DB_OBJECT ParentObject
= NULL
;
587 NTSTATUS Status
= STATUS_SUCCESS
;
589 DbObject
->RefCount
--;
591 if (DbObject
->RefCount
> 0)
592 return STATUS_SUCCESS
;
594 if (DbObject
->KeyHandle
!= NULL
)
595 NtClose(DbObject
->KeyHandle
);
597 if (DbObject
->ParentObject
!= NULL
)
598 ParentObject
= DbObject
->ParentObject
;
600 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
602 if (ParentObject
!= NULL
)
604 ParentObject
->RefCount
--;
606 if (ParentObject
->RefCount
== 0)
607 Status
= LsapCloseDbObject(ParentObject
);
615 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject
,
616 LPWSTR AttributeName
,
617 LPVOID AttributeData
,
620 OBJECT_ATTRIBUTES ObjectAttributes
;
621 UNICODE_STRING KeyName
;
625 RtlInitUnicodeString(&KeyName
,
628 InitializeObjectAttributes(&ObjectAttributes
,
630 OBJ_CASE_INSENSITIVE
,
634 Status
= NtCreateKey(&AttributeKey
,
639 REG_OPTION_NON_VOLATILE
,
641 if (!NT_SUCCESS(Status
))
647 Status
= RtlpNtSetValueKey(AttributeKey
,
652 NtClose(AttributeKey
);
659 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject
,
660 LPWSTR AttributeName
,
661 LPVOID AttributeData
,
662 PULONG AttributeSize
)
664 OBJECT_ATTRIBUTES ObjectAttributes
;
665 UNICODE_STRING KeyName
;
670 RtlInitUnicodeString(&KeyName
,
673 InitializeObjectAttributes(&ObjectAttributes
,
675 OBJ_CASE_INSENSITIVE
,
679 Status
= NtOpenKey(&AttributeKey
,
682 if (!NT_SUCCESS(Status
))
687 ValueSize
= *AttributeSize
;
688 Status
= RtlpNtQueryValueKey(AttributeKey
,
693 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
698 if (AttributeData
== NULL
|| *AttributeSize
== 0)
700 *AttributeSize
= ValueSize
;
701 Status
= STATUS_SUCCESS
;
704 else if (*AttributeSize
< ValueSize
)
706 *AttributeSize
= ValueSize
;
707 Status
= STATUS_BUFFER_OVERFLOW
;
711 Status
= RtlpNtQueryValueKey(AttributeKey
,
716 if (NT_SUCCESS(Status
))
718 *AttributeSize
= ValueSize
;
722 NtClose(AttributeKey
);