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 PLSA_DB_OBJECT PolicyObject
= NULL
;
230 PSID AccountDomainSid
= NULL
;
233 /* Create a random domain SID */
234 Status
= LsapCreateRandomDomainSid(&AccountDomainSid
);
235 if (!NT_SUCCESS(Status
))
238 /* Open the 'Policy' object */
239 Status
= LsapOpenDbObject(NULL
,
244 if (!NT_SUCCESS(Status
))
247 LsapSetObjectAttribute(PolicyObject
,
252 LsapSetObjectAttribute(PolicyObject
,
257 LsapSetObjectAttribute(PolicyObject
,
262 LsapSetObjectAttribute(PolicyObject
,
265 RtlLengthSid(AccountDomainSid
));
268 if (PolicyObject
!= NULL
)
269 LsapCloseDbObject(PolicyObject
);
271 if (AccountDomainSid
!= NULL
)
272 RtlFreeSid(AccountDomainSid
);
279 LsapUpdateDatabase(VOID
)
281 return STATUS_SUCCESS
;
286 LsapInitDatabase(VOID
)
290 TRACE("LsapInitDatabase()\n");
292 Status
= LsapOpenServiceKey();
293 if (!NT_SUCCESS(Status
))
295 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status
);
299 if (!LsapIsDatabaseInstalled())
301 Status
= LsapCreateDatabaseKeys();
302 if (!NT_SUCCESS(Status
))
304 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status
);
308 Status
= LsapCreateDatabaseObjects();
309 if (!NT_SUCCESS(Status
))
311 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status
);
317 Status
= LsapUpdateDatabase();
318 if (!NT_SUCCESS(Status
))
320 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status
);
325 TRACE("LsapInitDatabase() done\n");
327 return STATUS_SUCCESS
;
332 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject
,
333 IN LPWSTR ObjectName
,
334 IN LSA_DB_OBJECT_TYPE ObjectType
,
335 IN ACCESS_MASK DesiredAccess
,
336 OUT PLSA_DB_OBJECT
*DbObject
)
338 PLSA_DB_OBJECT NewObject
;
339 OBJECT_ATTRIBUTES ObjectAttributes
;
340 UNICODE_STRING KeyName
;
341 HANDLE ParentKeyHandle
;
342 HANDLE ObjectKeyHandle
;
345 if (DbObject
== NULL
)
346 return STATUS_INVALID_PARAMETER
;
348 if (ParentObject
== NULL
)
349 ParentKeyHandle
= SecurityKeyHandle
;
351 ParentKeyHandle
= ParentObject
->KeyHandle
;
353 RtlInitUnicodeString(&KeyName
,
356 InitializeObjectAttributes(&ObjectAttributes
,
358 OBJ_CASE_INSENSITIVE
,
362 Status
= NtCreateKey(&ObjectKeyHandle
,
369 if (!NT_SUCCESS(Status
))
374 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
376 sizeof(LSA_DB_OBJECT
));
377 if (NewObject
== NULL
)
379 NtClose(ObjectKeyHandle
);
380 return STATUS_NO_MEMORY
;
383 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
384 NewObject
->RefCount
= 1;
385 NewObject
->ObjectType
= ObjectType
;
386 NewObject
->Access
= DesiredAccess
;
387 NewObject
->KeyHandle
= ObjectKeyHandle
;
388 NewObject
->ParentObject
= ParentObject
;
390 if (ParentObject
!= NULL
)
391 ParentObject
->RefCount
++;
393 *DbObject
= NewObject
;
395 return STATUS_SUCCESS
;
400 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject
,
401 IN LPWSTR ObjectName
,
402 IN LSA_DB_OBJECT_TYPE ObjectType
,
403 IN ACCESS_MASK DesiredAccess
,
404 OUT PLSA_DB_OBJECT
*DbObject
)
406 PLSA_DB_OBJECT NewObject
;
407 OBJECT_ATTRIBUTES ObjectAttributes
;
408 UNICODE_STRING KeyName
;
409 HANDLE ParentKeyHandle
;
410 HANDLE ObjectKeyHandle
;
413 if (DbObject
== NULL
)
414 return STATUS_INVALID_PARAMETER
;
416 if (ParentObject
== NULL
)
417 ParentKeyHandle
= SecurityKeyHandle
;
419 ParentKeyHandle
= ParentObject
->KeyHandle
;
421 RtlInitUnicodeString(&KeyName
,
424 InitializeObjectAttributes(&ObjectAttributes
,
426 OBJ_CASE_INSENSITIVE
,
430 Status
= NtOpenKey(&ObjectKeyHandle
,
433 if (!NT_SUCCESS(Status
))
438 NewObject
= RtlAllocateHeap(RtlGetProcessHeap(),
440 sizeof(LSA_DB_OBJECT
));
441 if (NewObject
== NULL
)
443 NtClose(ObjectKeyHandle
);
444 return STATUS_NO_MEMORY
;
447 NewObject
->Signature
= LSAP_DB_SIGNATURE
;
448 NewObject
->RefCount
= 1;
449 NewObject
->ObjectType
= ObjectType
;
450 NewObject
->Access
= DesiredAccess
;
451 NewObject
->KeyHandle
= ObjectKeyHandle
;
452 NewObject
->ParentObject
= ParentObject
;
454 if (ParentObject
!= NULL
)
455 ParentObject
->RefCount
++;
457 *DbObject
= NewObject
;
459 return STATUS_SUCCESS
;
464 LsapValidateDbObject(LSAPR_HANDLE Handle
,
465 LSA_DB_OBJECT_TYPE ObjectType
,
466 ACCESS_MASK DesiredAccess
,
467 PLSA_DB_OBJECT
*DbObject
)
469 PLSA_DB_OBJECT LocalObject
= (PLSA_DB_OBJECT
)Handle
;
470 BOOLEAN bValid
= FALSE
;
474 if (LocalObject
->Signature
== LSAP_DB_SIGNATURE
)
476 if ((ObjectType
== LsaDbIgnoreObject
) ||
477 (LocalObject
->ObjectType
== ObjectType
))
481 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
488 return STATUS_INVALID_HANDLE
;
490 if (DesiredAccess
!= 0)
492 /* Check for granted access rights */
493 if ((LocalObject
->Access
& DesiredAccess
) != DesiredAccess
)
495 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
496 LocalObject
->Access
, DesiredAccess
);
497 return STATUS_ACCESS_DENIED
;
501 if (DbObject
!= NULL
)
502 *DbObject
= LocalObject
;
504 return STATUS_SUCCESS
;
509 LsapCloseDbObject(PLSA_DB_OBJECT DbObject
)
511 PLSA_DB_OBJECT ParentObject
= NULL
;
512 NTSTATUS Status
= STATUS_SUCCESS
;
514 DbObject
->RefCount
--;
516 if (DbObject
->RefCount
> 0)
517 return STATUS_SUCCESS
;
519 if (DbObject
->KeyHandle
!= NULL
)
520 NtClose(DbObject
->KeyHandle
);
522 if (DbObject
->ParentObject
!= NULL
)
523 ParentObject
= DbObject
->ParentObject
;
525 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject
);
527 if (ParentObject
!= NULL
)
529 ParentObject
->RefCount
--;
531 if (ParentObject
->RefCount
== 0)
532 Status
= LsapCloseDbObject(ParentObject
);
540 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject
,
541 LPWSTR AttributeName
,
542 LPVOID AttributeData
,
545 OBJECT_ATTRIBUTES ObjectAttributes
;
546 UNICODE_STRING KeyName
;
550 RtlInitUnicodeString(&KeyName
,
553 InitializeObjectAttributes(&ObjectAttributes
,
555 OBJ_CASE_INSENSITIVE
,
559 Status
= NtCreateKey(&AttributeKey
,
564 REG_OPTION_NON_VOLATILE
,
566 if (!NT_SUCCESS(Status
))
572 Status
= RtlpNtSetValueKey(AttributeKey
,
577 NtClose(AttributeKey
);
584 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject
,
585 LPWSTR AttributeName
,
586 LPVOID AttributeData
,
587 PULONG AttributeSize
)
589 OBJECT_ATTRIBUTES ObjectAttributes
;
590 UNICODE_STRING KeyName
;
595 RtlInitUnicodeString(&KeyName
,
598 InitializeObjectAttributes(&ObjectAttributes
,
600 OBJ_CASE_INSENSITIVE
,
604 Status
= NtOpenKey(&AttributeKey
,
607 if (!NT_SUCCESS(Status
))
612 ValueSize
= *AttributeSize
;
613 Status
= RtlpNtQueryValueKey(AttributeKey
,
618 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
623 if (AttributeData
== NULL
|| *AttributeSize
== 0)
625 *AttributeSize
= ValueSize
;
626 Status
= STATUS_SUCCESS
;
629 else if (*AttributeSize
< ValueSize
)
631 *AttributeSize
= ValueSize
;
632 Status
= STATUS_BUFFER_OVERFLOW
;
636 Status
= RtlpNtQueryValueKey(AttributeKey
,
641 if (NT_SUCCESS(Status
))
643 *AttributeSize
= ValueSize
;
647 NtClose(AttributeKey
);