[LSASRV]
[reactos.git] / reactos / dll / win32 / lsasrv / database.c
1 /*
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
7 */
8
9 /* INCLUDES ****************************************************************/
10
11 #include "lsasrv.h"
12
13 WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
14
15
16 /* GLOBALS *****************************************************************/
17
18 static HANDLE SecurityKeyHandle = NULL;
19
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};
25
26 PSID BuiltinDomainSid = NULL;
27 PSID AccountDomainSid = NULL;
28 UNICODE_STRING BuiltinDomainName = {0, 0, NULL};
29 UNICODE_STRING AccountDomainName = {0, 0, NULL};
30
31
32 /* FUNCTIONS ***************************************************************/
33
34 static NTSTATUS
35 LsapOpenServiceKey(VOID)
36 {
37 OBJECT_ATTRIBUTES ObjectAttributes;
38 UNICODE_STRING KeyName;
39 NTSTATUS Status;
40
41 RtlInitUnicodeString(&KeyName,
42 L"\\Registry\\Machine\\SECURITY");
43
44 InitializeObjectAttributes(&ObjectAttributes,
45 &KeyName,
46 OBJ_CASE_INSENSITIVE,
47 NULL,
48 NULL);
49
50 Status = RtlpNtOpenKey(&SecurityKeyHandle,
51 KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
52 &ObjectAttributes,
53 0);
54
55 return Status;
56 }
57
58
59 static BOOLEAN
60 LsapIsDatabaseInstalled(VOID)
61 {
62 OBJECT_ATTRIBUTES ObjectAttributes;
63 UNICODE_STRING KeyName;
64 HANDLE KeyHandle;
65 NTSTATUS Status;
66
67 RtlInitUnicodeString(&KeyName,
68 L"Policy");
69
70 InitializeObjectAttributes(&ObjectAttributes,
71 &KeyName,
72 OBJ_CASE_INSENSITIVE,
73 SecurityKeyHandle,
74 NULL);
75
76 Status = RtlpNtOpenKey(&KeyHandle,
77 KEY_READ,
78 &ObjectAttributes,
79 0);
80 if (!NT_SUCCESS(Status))
81 return FALSE;
82
83 NtClose(KeyHandle);
84
85 return TRUE;
86 }
87
88
89 static NTSTATUS
90 LsapCreateDatabaseKeys(VOID)
91 {
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;
99
100 TRACE("LsapInstallDatabase()\n");
101
102 /* Create the 'Policy' key */
103 RtlInitUnicodeString(&KeyName,
104 L"Policy");
105
106 InitializeObjectAttributes(&ObjectAttributes,
107 &KeyName,
108 OBJ_CASE_INSENSITIVE,
109 SecurityKeyHandle,
110 NULL);
111
112 Status = NtCreateKey(&PolicyKeyHandle,
113 KEY_ALL_ACCESS,
114 &ObjectAttributes,
115 0,
116 NULL,
117 0,
118 NULL);
119 if (!NT_SUCCESS(Status))
120 {
121 ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
122 goto Done;
123 }
124
125 /* Create the 'Accounts' key */
126 RtlInitUnicodeString(&KeyName,
127 L"Accounts");
128
129 InitializeObjectAttributes(&ObjectAttributes,
130 &KeyName,
131 OBJ_CASE_INSENSITIVE,
132 PolicyKeyHandle,
133 NULL);
134
135 Status = NtCreateKey(&AccountsKeyHandle,
136 KEY_ALL_ACCESS,
137 &ObjectAttributes,
138 0,
139 NULL,
140 0,
141 NULL);
142 if (!NT_SUCCESS(Status))
143 {
144 ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
145 goto Done;
146 }
147
148 /* Create the 'Domains' key */
149 RtlInitUnicodeString(&KeyName,
150 L"Domains");
151
152 InitializeObjectAttributes(&ObjectAttributes,
153 &KeyName,
154 OBJ_CASE_INSENSITIVE,
155 PolicyKeyHandle,
156 NULL);
157
158 Status = NtCreateKey(&DomainsKeyHandle,
159 KEY_ALL_ACCESS,
160 &ObjectAttributes,
161 0,
162 NULL,
163 0,
164 NULL);
165 if (!NT_SUCCESS(Status))
166 {
167 ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
168 goto Done;
169 }
170
171 /* Create the 'Secrets' key */
172 RtlInitUnicodeString(&KeyName,
173 L"Secrets");
174
175 InitializeObjectAttributes(&ObjectAttributes,
176 &KeyName,
177 OBJ_CASE_INSENSITIVE,
178 PolicyKeyHandle,
179 NULL);
180
181 Status = NtCreateKey(&SecretsKeyHandle,
182 KEY_ALL_ACCESS,
183 &ObjectAttributes,
184 0,
185 NULL,
186 0,
187 NULL);
188 if (!NT_SUCCESS(Status))
189 {
190 ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
191 goto Done;
192 }
193
194 Done:
195 if (SecretsKeyHandle != NULL)
196 NtClose(SecretsKeyHandle);
197
198 if (DomainsKeyHandle != NULL)
199 NtClose(DomainsKeyHandle);
200
201 if (AccountsKeyHandle != NULL)
202 NtClose(AccountsKeyHandle);
203
204 if (PolicyKeyHandle != NULL)
205 NtClose(PolicyKeyHandle);
206
207 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
208
209 return Status;
210 }
211
212
213 static NTSTATUS
214 LsapCreateRandomDomainSid(OUT PSID *Sid)
215 {
216 LARGE_INTEGER SystemTime;
217 PULONG Seed;
218
219 NtQuerySystemTime(&SystemTime);
220 Seed = &SystemTime.u.LowPart;
221
222 return RtlAllocateAndInitializeSid(&NtAuthority,
223 4,
224 SECURITY_NT_NON_UNIQUE,
225 RtlUniform(Seed),
226 RtlUniform(Seed),
227 RtlUniform(Seed),
228 SECURITY_NULL_RID,
229 SECURITY_NULL_RID,
230 SECURITY_NULL_RID,
231 SECURITY_NULL_RID,
232 Sid);
233 }
234
235
236 static NTSTATUS
237 LsapCreateDatabaseObjects(VOID)
238 {
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;
244 GUID DnsDomainGuid;
245 PLSA_DB_OBJECT PolicyObject = NULL;
246 PSID AccountDomainSid = NULL;
247 ULONG AuditEventsCount;
248 ULONG AuditEventsSize;
249 ULONG i;
250 NTSTATUS Status;
251
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;
259
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
267
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(),
272 0,
273 AuditEventsSize);
274 if (AuditEventsInfo == NULL)
275 return STATUS_INSUFFICIENT_RESOURCES;
276
277 AuditEventsInfo->AuditingMode = FALSE;
278 AuditEventsInfo->MaximumAuditEventCount = AuditEventsCount;
279 for (i = 0; i < AuditEventsCount; i++)
280 AuditEventsInfo->AuditEvents[i] = 0;
281
282 /* Initialize the DNS Domain GUID attribute */
283 memset(&DnsDomainGuid, 0, sizeof(GUID));
284
285 /* Initialize the modification attribute */
286 ModificationInfo.ModifiedId.QuadPart = 0;
287 NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime);
288
289 /* Create a random domain SID */
290 Status = LsapCreateRandomDomainSid(&AccountDomainSid);
291 if (!NT_SUCCESS(Status))
292 goto done;
293
294 /* Open the 'Policy' object */
295 Status = LsapOpenDbObject(NULL,
296 NULL,
297 L"Policy",
298 LsaDbPolicyObject,
299 0,
300 &PolicyObject);
301 if (!NT_SUCCESS(Status))
302 goto done;
303
304 LsapSetObjectAttribute(PolicyObject,
305 L"PolPrDmN",
306 NULL,
307 0);
308
309 LsapSetObjectAttribute(PolicyObject,
310 L"PolPrDmS",
311 NULL,
312 0);
313
314 LsapSetObjectAttribute(PolicyObject,
315 L"PolAcDmN",
316 NULL,
317 0);
318
319 LsapSetObjectAttribute(PolicyObject,
320 L"PolAcDmS",
321 AccountDomainSid,
322 RtlLengthSid(AccountDomainSid));
323
324 /* Set the default quota limits attribute */
325 LsapSetObjectAttribute(PolicyObject,
326 L"DefQuota",
327 &QuotaInfo,
328 sizeof(POLICY_DEFAULT_QUOTA_INFO));
329
330 /* Set the modification attribute */
331 LsapSetObjectAttribute(PolicyObject,
332 L"PolMod",
333 &ModificationInfo,
334 sizeof(POLICY_MODIFICATION_INFO));
335
336 /* Set the audit full attribute */
337 LsapSetObjectAttribute(PolicyObject,
338 L"PolAdtFl",
339 &AuditFullInfo,
340 sizeof(POLICY_AUDIT_FULL_QUERY_INFO));
341
342 /* Set the audit log attribute */
343 LsapSetObjectAttribute(PolicyObject,
344 L"PolAdtLg",
345 &AuditLogInfo,
346 sizeof(POLICY_AUDIT_LOG_INFO));
347
348 /* Set the audit events attribute */
349 LsapSetObjectAttribute(PolicyObject,
350 L"PolAdtEv",
351 &AuditEventsInfo,
352 AuditEventsSize);
353
354 /* Set the DNS Domain Name attribute */
355 LsapSetObjectAttribute(PolicyObject,
356 L"PolDnDDN",
357 NULL,
358 0);
359
360 /* Set the DNS Forest Name attribute */
361 LsapSetObjectAttribute(PolicyObject,
362 L"PolDnTrN",
363 NULL,
364 0);
365
366 /* Set the DNS Domain GUID attribute */
367 LsapSetObjectAttribute(PolicyObject,
368 L"PolDnDmG",
369 &DnsDomainGuid,
370 sizeof(GUID));
371
372 done:
373 if (AuditEventsInfo != NULL)
374 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo);
375
376 if (PolicyObject != NULL)
377 LsapCloseDbObject(PolicyObject);
378
379 if (AccountDomainSid != NULL)
380 RtlFreeSid(AccountDomainSid);
381
382 return Status;
383 }
384
385
386 static NTSTATUS
387 LsapUpdateDatabase(VOID)
388 {
389 return STATUS_SUCCESS;
390 }
391
392
393 static NTSTATUS
394 LsapGetDomainInfo(VOID)
395 {
396 PLSA_DB_OBJECT PolicyObject = NULL;
397 PUNICODE_STRING DomainName = NULL;
398 ULONG AttributeSize;
399 LPWSTR SidString = NULL;
400 NTSTATUS Status;
401
402 /* Get the built-in domain SID and name */
403 Status = RtlAllocateAndInitializeSid(&NtAuthority,
404 1,
405 SECURITY_BUILTIN_DOMAIN_RID,
406 0, 0, 0, 0, 0, 0, 0,
407 &BuiltinDomainSid);
408 if (!NT_SUCCESS(Status))
409 return Status;
410
411 /**/
412 RtlInitUnicodeString(&BuiltinDomainName,
413 L"BUILTIN");
414
415 /* Open the 'Policy' object */
416 Status = LsapOpenDbObject(NULL,
417 NULL,
418 L"Policy",
419 LsaDbPolicyObject,
420 0,
421 &PolicyObject);
422 if (!NT_SUCCESS(Status))
423 goto done;
424
425 /* Get the account domain SID */
426 AttributeSize = 0;
427 Status = LsapGetObjectAttribute(PolicyObject,
428 L"PolAcDmS",
429 NULL,
430 &AttributeSize);
431 if (!NT_SUCCESS(Status))
432 goto done;
433
434 if (AttributeSize > 0)
435 {
436 AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(),
437 HEAP_ZERO_MEMORY,
438 AttributeSize);
439 if (AccountDomainSid == NULL)
440 {
441 Status = STATUS_INSUFFICIENT_RESOURCES;
442 goto done;
443 }
444
445 Status = LsapGetObjectAttribute(PolicyObject,
446 L"PolAcDmS",
447 AccountDomainSid,
448 &AttributeSize);
449 if (!NT_SUCCESS(Status))
450 goto done;
451 }
452
453 /* Get the account domain name */
454 AttributeSize = 0;
455 Status = LsapGetObjectAttribute(PolicyObject,
456 L"PolAcDmN",
457 NULL,
458 &AttributeSize);
459 if (!NT_SUCCESS(Status))
460 goto done;
461
462 if (AttributeSize > 0)
463 {
464 DomainName = RtlAllocateHeap(RtlGetProcessHeap(),
465 HEAP_ZERO_MEMORY,
466 AttributeSize);
467 if (DomainName == NULL)
468 {
469 Status = STATUS_INSUFFICIENT_RESOURCES;
470 goto done;
471 }
472
473 Status = LsapGetObjectAttribute(PolicyObject,
474 L"PolAcDmN",
475 DomainName,
476 &AttributeSize);
477 if (!NT_SUCCESS(Status))
478 goto done;
479
480 DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer);
481
482 AccountDomainName.Length = DomainName->Length;
483 AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR);
484 AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
485 HEAP_ZERO_MEMORY,
486 AccountDomainName.MaximumLength);
487 if (AccountDomainName.Buffer == NULL)
488 {
489 ERR("Failed to allocate the account domain name buffer\n");
490 Status = STATUS_INSUFFICIENT_RESOURCES;
491 goto done;
492 }
493
494 RtlCopyMemory(AccountDomainName.Buffer,
495 DomainName->Buffer,
496 DomainName->Length);
497 }
498
499 ConvertSidToStringSidW(BuiltinDomainSid, &SidString);
500 TRACE("Builtin Domain SID: %S\n", SidString);
501 LocalFree(SidString);
502 SidString = NULL;
503
504 TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName);
505
506 ConvertSidToStringSidW(AccountDomainSid, &SidString);
507 TRACE("Account Domain SID: %S\n", SidString);
508 LocalFree(SidString);
509 SidString = NULL;
510
511 TRACE("Account Domain Name: %wZ\n", &AccountDomainName);
512
513 done:
514 if (DomainName != NULL)
515 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName);
516
517 if (PolicyObject != NULL)
518 LsapCloseDbObject(PolicyObject);
519
520 return Status;
521 }
522
523
524 NTSTATUS
525 LsapInitDatabase(VOID)
526 {
527 NTSTATUS Status;
528
529 TRACE("LsapInitDatabase()\n");
530
531 Status = LsapOpenServiceKey();
532 if (!NT_SUCCESS(Status))
533 {
534 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
535 return Status;
536 }
537
538 if (!LsapIsDatabaseInstalled())
539 {
540 Status = LsapCreateDatabaseKeys();
541 if (!NT_SUCCESS(Status))
542 {
543 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status);
544 return Status;
545 }
546
547 Status = LsapCreateDatabaseObjects();
548 if (!NT_SUCCESS(Status))
549 {
550 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status);
551 return Status;
552 }
553 }
554 else
555 {
556 Status = LsapUpdateDatabase();
557 if (!NT_SUCCESS(Status))
558 {
559 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
560 return Status;
561 }
562 }
563
564 Status = LsapGetDomainInfo();
565 if (!NT_SUCCESS(Status))
566 {
567 ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status);
568 return Status;
569 }
570
571 TRACE("LsapInitDatabase() done\n");
572
573 return STATUS_SUCCESS;
574 }
575
576
577 NTSTATUS
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)
584 {
585 PLSA_DB_OBJECT NewObject;
586 OBJECT_ATTRIBUTES ObjectAttributes;
587 UNICODE_STRING KeyName;
588 HANDLE ParentKeyHandle;
589 HANDLE ContainerKeyHandle = NULL;
590 HANDLE ObjectKeyHandle = NULL;
591 NTSTATUS Status;
592
593 if (DbObject == NULL)
594 return STATUS_INVALID_PARAMETER;
595
596 if (ParentObject == NULL)
597 ParentKeyHandle = SecurityKeyHandle;
598 else
599 ParentKeyHandle = ParentObject->KeyHandle;
600
601 if (ContainerName != NULL)
602 {
603 /* Open the container key */
604 RtlInitUnicodeString(&KeyName,
605 ContainerName);
606
607 InitializeObjectAttributes(&ObjectAttributes,
608 &KeyName,
609 OBJ_CASE_INSENSITIVE,
610 ParentKeyHandle,
611 NULL);
612
613 Status = NtOpenKey(&ContainerKeyHandle,
614 KEY_ALL_ACCESS,
615 &ObjectAttributes);
616 if (!NT_SUCCESS(Status))
617 {
618 return Status;
619 }
620
621 /* Open the object key */
622 RtlInitUnicodeString(&KeyName,
623 ObjectName);
624
625 InitializeObjectAttributes(&ObjectAttributes,
626 &KeyName,
627 OBJ_CASE_INSENSITIVE,
628 ContainerKeyHandle,
629 NULL);
630
631 Status = NtCreateKey(&ObjectKeyHandle,
632 KEY_ALL_ACCESS,
633 &ObjectAttributes,
634 0,
635 NULL,
636 0,
637 NULL);
638
639 NtClose(ContainerKeyHandle);
640
641 if (!NT_SUCCESS(Status))
642 {
643 return Status;
644 }
645 }
646 else
647 {
648 RtlInitUnicodeString(&KeyName,
649 ObjectName);
650
651 InitializeObjectAttributes(&ObjectAttributes,
652 &KeyName,
653 OBJ_CASE_INSENSITIVE,
654 ParentKeyHandle,
655 NULL);
656
657 Status = NtCreateKey(&ObjectKeyHandle,
658 KEY_ALL_ACCESS,
659 &ObjectAttributes,
660 0,
661 NULL,
662 0,
663 NULL);
664 if (!NT_SUCCESS(Status))
665 {
666 return Status;
667 }
668 }
669
670 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
671 0,
672 sizeof(LSA_DB_OBJECT));
673 if (NewObject == NULL)
674 {
675 NtClose(ObjectKeyHandle);
676 return STATUS_NO_MEMORY;
677 }
678
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;
685
686 if (ParentObject != NULL)
687 ParentObject->RefCount++;
688
689 *DbObject = NewObject;
690
691 return STATUS_SUCCESS;
692 }
693
694
695 NTSTATUS
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)
702 {
703 PLSA_DB_OBJECT NewObject;
704 OBJECT_ATTRIBUTES ObjectAttributes;
705 UNICODE_STRING KeyName;
706 HANDLE ParentKeyHandle;
707 HANDLE ContainerKeyHandle = NULL;
708 HANDLE ObjectKeyHandle = NULL;
709 NTSTATUS Status;
710
711 if (DbObject == NULL)
712 return STATUS_INVALID_PARAMETER;
713
714 if (ParentObject == NULL)
715 ParentKeyHandle = SecurityKeyHandle;
716 else
717 ParentKeyHandle = ParentObject->KeyHandle;
718
719 if (ContainerName != NULL)
720 {
721 /* Open the container key */
722 RtlInitUnicodeString(&KeyName,
723 ContainerName);
724
725 InitializeObjectAttributes(&ObjectAttributes,
726 &KeyName,
727 OBJ_CASE_INSENSITIVE,
728 ParentKeyHandle,
729 NULL);
730
731 Status = NtOpenKey(&ContainerKeyHandle,
732 KEY_ALL_ACCESS,
733 &ObjectAttributes);
734 if (!NT_SUCCESS(Status))
735 {
736 return Status;
737 }
738
739 /* Open the object key */
740 RtlInitUnicodeString(&KeyName,
741 ObjectName);
742
743 InitializeObjectAttributes(&ObjectAttributes,
744 &KeyName,
745 OBJ_CASE_INSENSITIVE,
746 ContainerKeyHandle,
747 NULL);
748
749 Status = NtOpenKey(&ObjectKeyHandle,
750 KEY_ALL_ACCESS,
751 &ObjectAttributes);
752
753 NtClose(ContainerKeyHandle);
754
755 if (!NT_SUCCESS(Status))
756 {
757 return Status;
758 }
759 }
760 else
761 {
762 /* Open the object key */
763 RtlInitUnicodeString(&KeyName,
764 ObjectName);
765
766 InitializeObjectAttributes(&ObjectAttributes,
767 &KeyName,
768 OBJ_CASE_INSENSITIVE,
769 ParentKeyHandle,
770 NULL);
771
772 Status = NtOpenKey(&ObjectKeyHandle,
773 KEY_ALL_ACCESS,
774 &ObjectAttributes);
775 if (!NT_SUCCESS(Status))
776 {
777 return Status;
778 }
779 }
780
781 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
782 0,
783 sizeof(LSA_DB_OBJECT));
784 if (NewObject == NULL)
785 {
786 NtClose(ObjectKeyHandle);
787 return STATUS_NO_MEMORY;
788 }
789
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;
796
797 if (ParentObject != NULL)
798 ParentObject->RefCount++;
799
800 *DbObject = NewObject;
801
802 return STATUS_SUCCESS;
803 }
804
805
806 NTSTATUS
807 LsapValidateDbObject(LSAPR_HANDLE Handle,
808 LSA_DB_OBJECT_TYPE ObjectType,
809 ACCESS_MASK DesiredAccess,
810 PLSA_DB_OBJECT *DbObject)
811 {
812 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
813 BOOLEAN bValid = FALSE;
814
815 _SEH2_TRY
816 {
817 if (LocalObject->Signature == LSAP_DB_SIGNATURE)
818 {
819 if ((ObjectType == LsaDbIgnoreObject) ||
820 (LocalObject->ObjectType == ObjectType))
821 bValid = TRUE;
822 }
823 }
824 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
825 {
826 bValid = FALSE;
827 }
828 _SEH2_END;
829
830 if (bValid == FALSE)
831 return STATUS_INVALID_HANDLE;
832
833 if (DesiredAccess != 0)
834 {
835 /* Check for granted access rights */
836 if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
837 {
838 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
839 LocalObject->Access, DesiredAccess);
840 return STATUS_ACCESS_DENIED;
841 }
842 }
843
844 if (DbObject != NULL)
845 *DbObject = LocalObject;
846
847 return STATUS_SUCCESS;
848 }
849
850
851 NTSTATUS
852 LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
853 {
854 PLSA_DB_OBJECT ParentObject = NULL;
855 NTSTATUS Status = STATUS_SUCCESS;
856
857 DbObject->RefCount--;
858
859 if (DbObject->RefCount > 0)
860 return STATUS_SUCCESS;
861
862 if (DbObject->KeyHandle != NULL)
863 NtClose(DbObject->KeyHandle);
864
865 if (DbObject->ParentObject != NULL)
866 ParentObject = DbObject->ParentObject;
867
868 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
869
870 if (ParentObject != NULL)
871 {
872 ParentObject->RefCount--;
873
874 if (ParentObject->RefCount == 0)
875 Status = LsapCloseDbObject(ParentObject);
876 }
877
878 return Status;
879 }
880
881
882 NTSTATUS
883 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
884 LPWSTR AttributeName,
885 LPVOID AttributeData,
886 ULONG AttributeSize)
887 {
888 OBJECT_ATTRIBUTES ObjectAttributes;
889 UNICODE_STRING KeyName;
890 HANDLE AttributeKey;
891 NTSTATUS Status;
892
893 RtlInitUnicodeString(&KeyName,
894 AttributeName);
895
896 InitializeObjectAttributes(&ObjectAttributes,
897 &KeyName,
898 OBJ_CASE_INSENSITIVE,
899 DbObject->KeyHandle,
900 NULL);
901
902 Status = NtCreateKey(&AttributeKey,
903 KEY_SET_VALUE,
904 &ObjectAttributes,
905 0,
906 NULL,
907 REG_OPTION_NON_VOLATILE,
908 NULL);
909 if (!NT_SUCCESS(Status))
910 {
911
912 return Status;
913 }
914
915 Status = RtlpNtSetValueKey(AttributeKey,
916 REG_NONE,
917 AttributeData,
918 AttributeSize);
919
920 NtClose(AttributeKey);
921
922 return Status;
923 }
924
925
926 NTSTATUS
927 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
928 LPWSTR AttributeName,
929 LPVOID AttributeData,
930 PULONG AttributeSize)
931 {
932 OBJECT_ATTRIBUTES ObjectAttributes;
933 UNICODE_STRING KeyName;
934 HANDLE AttributeKey;
935 ULONG ValueSize;
936 NTSTATUS Status;
937
938 RtlInitUnicodeString(&KeyName,
939 AttributeName);
940
941 InitializeObjectAttributes(&ObjectAttributes,
942 &KeyName,
943 OBJ_CASE_INSENSITIVE,
944 DbObject->KeyHandle,
945 NULL);
946
947 Status = NtOpenKey(&AttributeKey,
948 KEY_QUERY_VALUE,
949 &ObjectAttributes);
950 if (!NT_SUCCESS(Status))
951 {
952 return Status;
953 }
954
955 ValueSize = *AttributeSize;
956 Status = RtlpNtQueryValueKey(AttributeKey,
957 NULL,
958 NULL,
959 &ValueSize,
960 0);
961 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
962 {
963 goto Done;
964 }
965
966 if (AttributeData == NULL || *AttributeSize == 0)
967 {
968 *AttributeSize = ValueSize;
969 Status = STATUS_SUCCESS;
970 goto Done;
971 }
972 else if (*AttributeSize < ValueSize)
973 {
974 *AttributeSize = ValueSize;
975 Status = STATUS_BUFFER_OVERFLOW;
976 goto Done;
977 }
978
979 Status = RtlpNtQueryValueKey(AttributeKey,
980 NULL,
981 AttributeData,
982 &ValueSize,
983 0);
984 if (NT_SUCCESS(Status))
985 {
986 *AttributeSize = ValueSize;
987 }
988
989 Done:
990 NtClose(AttributeKey);
991
992 return Status;
993 }
994
995 /* EOF */
996