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 POLICY_DEFAULT_QUOTA_INFO QuotaInfo
;
230 PLSA_DB_OBJECT PolicyObject
= NULL
;
231 PSID AccountDomainSid
= NULL
;
234 /* Initialize the default quota limits */
235 QuotaInfo
.QuotaLimits
.PagedPoolLimit
= 0x2000000;
236 QuotaInfo
.QuotaLimits
.NonPagedPoolLimit
= 0x100000;
237 QuotaInfo
.QuotaLimits
.MinimumWorkingSetSize
= 0x10000;
238 QuotaInfo
.QuotaLimits
.MaximumWorkingSetSize
= 0xF000000;
239 QuotaInfo
.QuotaLimits
.PagefileLimit
= 0;
240 QuotaInfo
.QuotaLimits
.TimeLimit
.QuadPart
= 0;
242 /* Create a random domain SID */
243 Status
= LsapCreateRandomDomainSid(&AccountDomainSid
);
244 if (!NT_SUCCESS(Status
))
247 /* Open the 'Policy' object */
248 Status
= LsapOpenDbObject(NULL
,
253 if (!NT_SUCCESS(Status
))
256 LsapSetObjectAttribute(PolicyObject
,
261 LsapSetObjectAttribute(PolicyObject
,
266 LsapSetObjectAttribute(PolicyObject
,
271 LsapSetObjectAttribute(PolicyObject
,
274 RtlLengthSid(AccountDomainSid
));
276 /* Set the default quota limits attribute */
277 LsapSetObjectAttribute(PolicyObject
,
280 sizeof(POLICY_DEFAULT_QUOTA_INFO
));
283 if (PolicyObject
!= NULL
)
284 LsapCloseDbObject(PolicyObject
);
286 if (AccountDomainSid
!= NULL
)
287 RtlFreeSid(AccountDomainSid
);
294 LsapUpdateDatabase(VOID
)
296 return STATUS_SUCCESS
;
301 LsapInitDatabase(VOID
)
305 TRACE("LsapInitDatabase()\n");
307 Status
= LsapOpenServiceKey();
308 if (!NT_SUCCESS(Status
))
310 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status
);
314 if (!LsapIsDatabaseInstalled())
316 Status
= LsapCreateDatabaseKeys();
317 if (!NT_SUCCESS(Status
))
319 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status
);
323 Status
= LsapCreateDatabaseObjects();
324 if (!NT_SUCCESS(Status
))
326 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status
);
332 Status
= LsapUpdateDatabase();
333 if (!NT_SUCCESS(Status
))
335 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status
);
340 TRACE("LsapInitDatabase() done\n");
342 return STATUS_SUCCESS
;
347 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject
,
348 IN LPWSTR ObjectName
,
349 IN LSA_DB_OBJECT_TYPE ObjectType
,
350 IN ACCESS_MASK DesiredAccess
,
351 OUT PLSA_DB_OBJECT
*DbObject
)
353 PLSA_DB_OBJECT NewObject
;
354 OBJECT_ATTRIBUTES ObjectAttributes
;
355 UNICODE_STRING KeyName
;
356 HANDLE ParentKeyHandle
;
357 HANDLE ObjectKeyHandle
;
360 if (DbObject
== NULL
)
361 return STATUS_INVALID_PARAMETER
;
363 if (ParentObject
== NULL
)
364 ParentKeyHandle
= SecurityKeyHandle
;
366 ParentKeyHandle
= ParentObject
->KeyHandle
;
368 RtlInitUnicodeString(&KeyName
,
371 InitializeObjectAttributes(&ObjectAttributes
,
373 OBJ_CASE_INSENSITIVE
,
377 Status
= NtCreateKey(&ObjectKeyHandle
,
384 if (!NT_SUCCESS(Status
))
389 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
391 sizeof(LSA_DB_OBJECT
));
392 if (NewObject
== NULL
)
394 NtClose(ObjectKeyHandle
);
395 return STATUS_NO_MEMORY
;
398 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
399 NewObject
->RefCount
= 1;
400 NewObject
->ObjectType
= ObjectType
;
401 NewObject
->Access
= DesiredAccess
;
402 NewObject
->KeyHandle
= ObjectKeyHandle
;
403 NewObject
->ParentObject
= ParentObject
;
405 if (ParentObject
!= NULL
)
406 ParentObject
->RefCount
++;
408 *DbObject
= NewObject
;
410 return STATUS_SUCCESS
;
415 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject
,
416 IN LPWSTR ObjectName
,
417 IN LSA_DB_OBJECT_TYPE ObjectType
,
418 IN ACCESS_MASK DesiredAccess
,
419 OUT PLSA_DB_OBJECT
*DbObject
)
421 PLSA_DB_OBJECT NewObject
;
422 OBJECT_ATTRIBUTES ObjectAttributes
;
423 UNICODE_STRING KeyName
;
424 HANDLE ParentKeyHandle
;
425 HANDLE ObjectKeyHandle
;
428 if (DbObject
== NULL
)
429 return STATUS_INVALID_PARAMETER
;
431 if (ParentObject
== NULL
)
432 ParentKeyHandle
= SecurityKeyHandle
;
434 ParentKeyHandle
= ParentObject
->KeyHandle
;
436 RtlInitUnicodeString(&KeyName
,
439 InitializeObjectAttributes(&ObjectAttributes
,
441 OBJ_CASE_INSENSITIVE
,
445 Status
= NtOpenKey(&ObjectKeyHandle
,
448 if (!NT_SUCCESS(Status
))
453 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
455 sizeof(LSA_DB_OBJECT
));
456 if (NewObject
== NULL
)
458 NtClose(ObjectKeyHandle
);
459 return STATUS_NO_MEMORY
;
462 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
463 NewObject
->RefCount
= 1;
464 NewObject
->ObjectType
= ObjectType
;
465 NewObject
->Access
= DesiredAccess
;
466 NewObject
->KeyHandle
= ObjectKeyHandle
;
467 NewObject
->ParentObject
= ParentObject
;
469 if (ParentObject
!= NULL
)
470 ParentObject
->RefCount
++;
472 *DbObject
= NewObject
;
474 return STATUS_SUCCESS
;
479 LsapValidateDbObject(LSAPR_HANDLE Handle
,
480 LSA_DB_OBJECT_TYPE ObjectType
,
481 ACCESS_MASK DesiredAccess
,
482 PLSA_DB_OBJECT
*DbObject
)
484 PLSA_DB_OBJECT LocalObject
= (PLSA_DB_OBJECT
)Handle
;
485 BOOLEAN bValid
= FALSE
;
489 if (LocalObject
->Signature
== LSAP_DB_SIGNATURE
)
491 if ((ObjectType
== LsaDbIgnoreObject
) ||
492 (LocalObject
->ObjectType
== ObjectType
))
496 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
503 return STATUS_INVALID_HANDLE
;
505 if (DesiredAccess
!= 0)
507 /* Check for granted access rights */
508 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
510 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
511 LocalObject
->Access
, DesiredAccess
);
512 return STATUS_ACCESS_DENIED
;
516 if (DbObject
!= NULL
)
517 *DbObject
= LocalObject
;
519 return STATUS_SUCCESS
;
524 LsapCloseDbObject(PLSA_DB_OBJECT DbObject
)
526 PLSA_DB_OBJECT ParentObject
= NULL
;
527 NTSTATUS Status
= STATUS_SUCCESS
;
529 DbObject
->RefCount
--;
531 if (DbObject
->RefCount
> 0)
532 return STATUS_SUCCESS
;
534 if (DbObject
->KeyHandle
!= NULL
)
535 NtClose(DbObject
->KeyHandle
);
537 if (DbObject
->ParentObject
!= NULL
)
538 ParentObject
= DbObject
->ParentObject
;
540 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
542 if (ParentObject
!= NULL
)
544 ParentObject
->RefCount
--;
546 if (ParentObject
->RefCount
== 0)
547 Status
= LsapCloseDbObject(ParentObject
);
555 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject
,
556 LPWSTR AttributeName
,
557 LPVOID AttributeData
,
560 OBJECT_ATTRIBUTES ObjectAttributes
;
561 UNICODE_STRING KeyName
;
565 RtlInitUnicodeString(&KeyName
,
568 InitializeObjectAttributes(&ObjectAttributes
,
570 OBJ_CASE_INSENSITIVE
,
574 Status
= NtCreateKey(&AttributeKey
,
579 REG_OPTION_NON_VOLATILE
,
581 if (!NT_SUCCESS(Status
))
587 Status
= RtlpNtSetValueKey(AttributeKey
,
592 NtClose(AttributeKey
);
599 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject
,
600 LPWSTR AttributeName
,
601 LPVOID AttributeData
,
602 PULONG AttributeSize
)
604 OBJECT_ATTRIBUTES ObjectAttributes
;
605 UNICODE_STRING KeyName
;
610 RtlInitUnicodeString(&KeyName
,
613 InitializeObjectAttributes(&ObjectAttributes
,
615 OBJ_CASE_INSENSITIVE
,
619 Status
= NtOpenKey(&AttributeKey
,
622 if (!NT_SUCCESS(Status
))
627 ValueSize
= *AttributeSize
;
628 Status
= RtlpNtQueryValueKey(AttributeKey
,
633 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
638 if (AttributeData
== NULL
|| *AttributeSize
== 0)
640 *AttributeSize
= ValueSize
;
641 Status
= STATUS_SUCCESS
;
644 else if (*AttributeSize
< ValueSize
)
646 *AttributeSize
= ValueSize
;
647 Status
= STATUS_BUFFER_OVERFLOW
;
651 Status
= RtlpNtQueryValueKey(AttributeKey
,
656 if (NT_SUCCESS(Status
))
658 *AttributeSize
= ValueSize
;
662 NtClose(AttributeKey
);