aa04e13a8014b6c976c1a97afad720c8484bb1c0
[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 PSECURITY_DESCRIPTOR PolicySd = NULL;
248 ULONG PolicySdSize = 0;
249 ULONG AuditEventsCount;
250 ULONG AuditEventsSize;
251 ULONG i;
252 NTSTATUS Status;
253
254 /* Initialize the default quota limits */
255 QuotaInfo.QuotaLimits.PagedPoolLimit = 0x2000000;
256 QuotaInfo.QuotaLimits.NonPagedPoolLimit = 0x100000;
257 QuotaInfo.QuotaLimits.MinimumWorkingSetSize = 0x10000;
258 QuotaInfo.QuotaLimits.MaximumWorkingSetSize = 0xF000000;
259 QuotaInfo.QuotaLimits.PagefileLimit = 0;
260 QuotaInfo.QuotaLimits.TimeLimit.QuadPart = 0;
261
262 /* Initialize the audit log attribute */
263 AuditLogInfo.AuditLogPercentFull = 0;
264 AuditLogInfo.MaximumLogSize = 0; // DWORD
265 AuditLogInfo.AuditRetentionPeriod.QuadPart = 0; // LARGE_INTEGER
266 AuditLogInfo.AuditLogFullShutdownInProgress = 0; // BYTE
267 AuditLogInfo.TimeToShutdown.QuadPart = 0; // LARGE_INTEGER
268 AuditLogInfo.NextAuditRecordId = 0; // DWORD
269
270 /* Initialize the Audit Events attribute */
271 AuditEventsCount = AuditCategoryAccountLogon - AuditCategorySystem + 1;
272 AuditEventsSize = sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA) + AuditEventsCount * sizeof(DWORD);
273 AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(),
274 HEAP_ZERO_MEMORY,
275 AuditEventsSize);
276 if (AuditEventsInfo == NULL)
277 return STATUS_INSUFFICIENT_RESOURCES;
278
279 AuditEventsInfo->AuditingMode = FALSE;
280 AuditEventsInfo->MaximumAuditEventCount = AuditEventsCount;
281 for (i = 0; i < AuditEventsCount; i++)
282 AuditEventsInfo->AuditEvents[i] = 0;
283
284 /* Initialize the DNS Domain GUID attribute */
285 memset(&DnsDomainGuid, 0, sizeof(GUID));
286
287 /* Initialize the modification attribute */
288 ModificationInfo.ModifiedId.QuadPart = 0;
289 NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime);
290
291 /* Create a random domain SID */
292 Status = LsapCreateRandomDomainSid(&AccountDomainSid);
293 if (!NT_SUCCESS(Status))
294 goto done;
295
296 Status = LsapCreatePolicySd(&PolicySd,
297 &PolicySdSize);
298 if (!NT_SUCCESS(Status))
299 goto done;
300
301 /* Open the 'Policy' object */
302 Status = LsapOpenDbObject(NULL,
303 NULL,
304 L"Policy",
305 LsaDbPolicyObject,
306 0,
307 TRUE,
308 &PolicyObject);
309 if (!NT_SUCCESS(Status))
310 goto done;
311
312 LsapSetObjectAttribute(PolicyObject,
313 L"PolPrDmN",
314 NULL,
315 0);
316
317 LsapSetObjectAttribute(PolicyObject,
318 L"PolPrDmS",
319 NULL,
320 0);
321
322 LsapSetObjectAttribute(PolicyObject,
323 L"PolAcDmN",
324 NULL,
325 0);
326
327 LsapSetObjectAttribute(PolicyObject,
328 L"PolAcDmS",
329 AccountDomainSid,
330 RtlLengthSid(AccountDomainSid));
331
332 /* Set the default quota limits attribute */
333 LsapSetObjectAttribute(PolicyObject,
334 L"DefQuota",
335 &QuotaInfo,
336 sizeof(POLICY_DEFAULT_QUOTA_INFO));
337
338 /* Set the modification attribute */
339 LsapSetObjectAttribute(PolicyObject,
340 L"PolMod",
341 &ModificationInfo,
342 sizeof(POLICY_MODIFICATION_INFO));
343
344 /* Set the audit full attribute */
345 LsapSetObjectAttribute(PolicyObject,
346 L"PolAdtFl",
347 &AuditFullInfo,
348 sizeof(POLICY_AUDIT_FULL_QUERY_INFO));
349
350 /* Set the audit log attribute */
351 LsapSetObjectAttribute(PolicyObject,
352 L"PolAdtLg",
353 &AuditLogInfo,
354 sizeof(POLICY_AUDIT_LOG_INFO));
355
356 /* Set the audit events attribute */
357 LsapSetObjectAttribute(PolicyObject,
358 L"PolAdtEv",
359 &AuditEventsInfo,
360 AuditEventsSize);
361
362 /* Set the DNS Domain Name attribute */
363 LsapSetObjectAttribute(PolicyObject,
364 L"PolDnDDN",
365 NULL,
366 0);
367
368 /* Set the DNS Forest Name attribute */
369 LsapSetObjectAttribute(PolicyObject,
370 L"PolDnTrN",
371 NULL,
372 0);
373
374 /* Set the DNS Domain GUID attribute */
375 LsapSetObjectAttribute(PolicyObject,
376 L"PolDnDmG",
377 &DnsDomainGuid,
378 sizeof(GUID));
379
380 /* Set the Sceurity Descriptor */
381 LsapSetObjectAttribute(PolicyObject,
382 L"SecDesc",
383 PolicySd,
384 PolicySdSize);
385
386 done:
387 if (AuditEventsInfo != NULL)
388 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo);
389
390 if (PolicyObject != NULL)
391 LsapCloseDbObject(PolicyObject);
392
393 if (AccountDomainSid != NULL)
394 RtlFreeSid(AccountDomainSid);
395
396 if (PolicySd != NULL)
397 RtlFreeHeap(RtlGetProcessHeap(), 0, PolicySd);
398
399 return Status;
400 }
401
402
403 static NTSTATUS
404 LsapUpdateDatabase(VOID)
405 {
406 return STATUS_SUCCESS;
407 }
408
409
410 static NTSTATUS
411 LsapGetDomainInfo(VOID)
412 {
413 PLSA_DB_OBJECT PolicyObject = NULL;
414 PUNICODE_STRING DomainName = NULL;
415 ULONG AttributeSize;
416 LPWSTR SidString = NULL;
417 NTSTATUS Status;
418
419 /* Get the built-in domain SID and name */
420 Status = RtlAllocateAndInitializeSid(&NtAuthority,
421 1,
422 SECURITY_BUILTIN_DOMAIN_RID,
423 0, 0, 0, 0, 0, 0, 0,
424 &BuiltinDomainSid);
425 if (!NT_SUCCESS(Status))
426 return Status;
427
428 /**/
429 RtlInitUnicodeString(&BuiltinDomainName,
430 L"BUILTIN");
431
432 /* Open the 'Policy' object */
433 Status = LsapOpenDbObject(NULL,
434 NULL,
435 L"Policy",
436 LsaDbPolicyObject,
437 0,
438 TRUE,
439 &PolicyObject);
440 if (!NT_SUCCESS(Status))
441 goto done;
442
443 /* Get the account domain SID */
444 AttributeSize = 0;
445 Status = LsapGetObjectAttribute(PolicyObject,
446 L"PolAcDmS",
447 NULL,
448 &AttributeSize);
449 if (!NT_SUCCESS(Status))
450 goto done;
451
452 if (AttributeSize > 0)
453 {
454 AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(),
455 HEAP_ZERO_MEMORY,
456 AttributeSize);
457 if (AccountDomainSid == NULL)
458 {
459 Status = STATUS_INSUFFICIENT_RESOURCES;
460 goto done;
461 }
462
463 Status = LsapGetObjectAttribute(PolicyObject,
464 L"PolAcDmS",
465 AccountDomainSid,
466 &AttributeSize);
467 if (!NT_SUCCESS(Status))
468 goto done;
469 }
470
471 /* Get the account domain name */
472 AttributeSize = 0;
473 Status = LsapGetObjectAttribute(PolicyObject,
474 L"PolAcDmN",
475 NULL,
476 &AttributeSize);
477 if (!NT_SUCCESS(Status))
478 goto done;
479
480 if (AttributeSize > 0)
481 {
482 DomainName = RtlAllocateHeap(RtlGetProcessHeap(),
483 HEAP_ZERO_MEMORY,
484 AttributeSize);
485 if (DomainName == NULL)
486 {
487 Status = STATUS_INSUFFICIENT_RESOURCES;
488 goto done;
489 }
490
491 Status = LsapGetObjectAttribute(PolicyObject,
492 L"PolAcDmN",
493 DomainName,
494 &AttributeSize);
495 if (!NT_SUCCESS(Status))
496 goto done;
497
498 DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer);
499
500 AccountDomainName.Length = DomainName->Length;
501 AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR);
502 AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
503 HEAP_ZERO_MEMORY,
504 AccountDomainName.MaximumLength);
505 if (AccountDomainName.Buffer == NULL)
506 {
507 ERR("Failed to allocate the account domain name buffer\n");
508 Status = STATUS_INSUFFICIENT_RESOURCES;
509 goto done;
510 }
511
512 RtlCopyMemory(AccountDomainName.Buffer,
513 DomainName->Buffer,
514 DomainName->Length);
515 }
516
517 ConvertSidToStringSidW(BuiltinDomainSid, &SidString);
518 TRACE("Builtin Domain SID: %S\n", SidString);
519 LocalFree(SidString);
520 SidString = NULL;
521
522 TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName);
523
524 ConvertSidToStringSidW(AccountDomainSid, &SidString);
525 TRACE("Account Domain SID: %S\n", SidString);
526 LocalFree(SidString);
527 SidString = NULL;
528
529 TRACE("Account Domain Name: %wZ\n", &AccountDomainName);
530
531 done:
532 if (DomainName != NULL)
533 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName);
534
535 if (PolicyObject != NULL)
536 LsapCloseDbObject(PolicyObject);
537
538 return Status;
539 }
540
541
542 NTSTATUS
543 LsapInitDatabase(VOID)
544 {
545 NTSTATUS Status;
546
547 TRACE("LsapInitDatabase()\n");
548
549 Status = LsapOpenServiceKey();
550 if (!NT_SUCCESS(Status))
551 {
552 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
553 return Status;
554 }
555
556 if (!LsapIsDatabaseInstalled())
557 {
558 Status = LsapCreateDatabaseKeys();
559 if (!NT_SUCCESS(Status))
560 {
561 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status);
562 return Status;
563 }
564
565 Status = LsapCreateDatabaseObjects();
566 if (!NT_SUCCESS(Status))
567 {
568 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status);
569 return Status;
570 }
571 }
572 else
573 {
574 Status = LsapUpdateDatabase();
575 if (!NT_SUCCESS(Status))
576 {
577 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
578 return Status;
579 }
580 }
581
582 Status = LsapGetDomainInfo();
583 if (!NT_SUCCESS(Status))
584 {
585 ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status);
586 return Status;
587 }
588
589 TRACE("LsapInitDatabase() done\n");
590
591 return STATUS_SUCCESS;
592 }
593
594
595 NTSTATUS
596 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
597 IN LPWSTR ContainerName,
598 IN LPWSTR ObjectName,
599 IN LSA_DB_OBJECT_TYPE ObjectType,
600 IN ACCESS_MASK DesiredAccess,
601 IN BOOLEAN Trusted,
602 OUT PLSA_DB_OBJECT *DbObject)
603 {
604 PLSA_DB_OBJECT NewObject;
605 OBJECT_ATTRIBUTES ObjectAttributes;
606 UNICODE_STRING KeyName;
607 HANDLE ParentKeyHandle;
608 HANDLE ContainerKeyHandle = NULL;
609 HANDLE ObjectKeyHandle = NULL;
610 NTSTATUS Status;
611
612 if (DbObject == NULL)
613 return STATUS_INVALID_PARAMETER;
614
615 if (ParentObject == NULL)
616 ParentKeyHandle = SecurityKeyHandle;
617 else
618 ParentKeyHandle = ParentObject->KeyHandle;
619
620 if (ContainerName != NULL)
621 {
622 /* Open the container key */
623 RtlInitUnicodeString(&KeyName,
624 ContainerName);
625
626 InitializeObjectAttributes(&ObjectAttributes,
627 &KeyName,
628 OBJ_CASE_INSENSITIVE,
629 ParentKeyHandle,
630 NULL);
631
632 Status = NtOpenKey(&ContainerKeyHandle,
633 KEY_ALL_ACCESS,
634 &ObjectAttributes);
635 if (!NT_SUCCESS(Status))
636 {
637 return Status;
638 }
639
640 /* Open the object key */
641 RtlInitUnicodeString(&KeyName,
642 ObjectName);
643
644 InitializeObjectAttributes(&ObjectAttributes,
645 &KeyName,
646 OBJ_CASE_INSENSITIVE,
647 ContainerKeyHandle,
648 NULL);
649
650 Status = NtCreateKey(&ObjectKeyHandle,
651 KEY_ALL_ACCESS,
652 &ObjectAttributes,
653 0,
654 NULL,
655 0,
656 NULL);
657
658 NtClose(ContainerKeyHandle);
659
660 if (!NT_SUCCESS(Status))
661 {
662 return Status;
663 }
664 }
665 else
666 {
667 RtlInitUnicodeString(&KeyName,
668 ObjectName);
669
670 InitializeObjectAttributes(&ObjectAttributes,
671 &KeyName,
672 OBJ_CASE_INSENSITIVE,
673 ParentKeyHandle,
674 NULL);
675
676 Status = NtCreateKey(&ObjectKeyHandle,
677 KEY_ALL_ACCESS,
678 &ObjectAttributes,
679 0,
680 NULL,
681 0,
682 NULL);
683 if (!NT_SUCCESS(Status))
684 {
685 return Status;
686 }
687 }
688
689 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
690 0,
691 sizeof(LSA_DB_OBJECT));
692 if (NewObject == NULL)
693 {
694 NtClose(ObjectKeyHandle);
695 return STATUS_NO_MEMORY;
696 }
697
698 NewObject->Signature = LSAP_DB_SIGNATURE;
699 NewObject->RefCount = 1;
700 NewObject->ObjectType = ObjectType;
701 NewObject->Access = DesiredAccess;
702 NewObject->KeyHandle = ObjectKeyHandle;
703 NewObject->ParentObject = ParentObject;
704 NewObject->Trusted = Trusted;
705
706 if (ParentObject != NULL)
707 ParentObject->RefCount++;
708
709 *DbObject = NewObject;
710
711 return STATUS_SUCCESS;
712 }
713
714
715 NTSTATUS
716 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
717 IN LPWSTR ContainerName,
718 IN LPWSTR ObjectName,
719 IN LSA_DB_OBJECT_TYPE ObjectType,
720 IN ACCESS_MASK DesiredAccess,
721 IN BOOLEAN Trusted,
722 OUT PLSA_DB_OBJECT *DbObject)
723 {
724 PLSA_DB_OBJECT NewObject;
725 OBJECT_ATTRIBUTES ObjectAttributes;
726 UNICODE_STRING KeyName;
727 HANDLE ParentKeyHandle;
728 HANDLE ContainerKeyHandle = NULL;
729 HANDLE ObjectKeyHandle = NULL;
730 NTSTATUS Status;
731
732 if (DbObject == NULL)
733 return STATUS_INVALID_PARAMETER;
734
735 if (ParentObject == NULL)
736 ParentKeyHandle = SecurityKeyHandle;
737 else
738 ParentKeyHandle = ParentObject->KeyHandle;
739
740 if (ContainerName != NULL)
741 {
742 /* Open the container key */
743 RtlInitUnicodeString(&KeyName,
744 ContainerName);
745
746 InitializeObjectAttributes(&ObjectAttributes,
747 &KeyName,
748 OBJ_CASE_INSENSITIVE,
749 ParentKeyHandle,
750 NULL);
751
752 Status = NtOpenKey(&ContainerKeyHandle,
753 KEY_ALL_ACCESS,
754 &ObjectAttributes);
755 if (!NT_SUCCESS(Status))
756 {
757 return Status;
758 }
759
760 /* Open the object key */
761 RtlInitUnicodeString(&KeyName,
762 ObjectName);
763
764 InitializeObjectAttributes(&ObjectAttributes,
765 &KeyName,
766 OBJ_CASE_INSENSITIVE,
767 ContainerKeyHandle,
768 NULL);
769
770 Status = NtOpenKey(&ObjectKeyHandle,
771 KEY_ALL_ACCESS,
772 &ObjectAttributes);
773
774 NtClose(ContainerKeyHandle);
775
776 if (!NT_SUCCESS(Status))
777 {
778 return Status;
779 }
780 }
781 else
782 {
783 /* Open the object key */
784 RtlInitUnicodeString(&KeyName,
785 ObjectName);
786
787 InitializeObjectAttributes(&ObjectAttributes,
788 &KeyName,
789 OBJ_CASE_INSENSITIVE,
790 ParentKeyHandle,
791 NULL);
792
793 Status = NtOpenKey(&ObjectKeyHandle,
794 KEY_ALL_ACCESS,
795 &ObjectAttributes);
796 if (!NT_SUCCESS(Status))
797 {
798 return Status;
799 }
800 }
801
802 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
803 0,
804 sizeof(LSA_DB_OBJECT));
805 if (NewObject == NULL)
806 {
807 NtClose(ObjectKeyHandle);
808 return STATUS_NO_MEMORY;
809 }
810
811 NewObject->Signature = LSAP_DB_SIGNATURE;
812 NewObject->RefCount = 1;
813 NewObject->ObjectType = ObjectType;
814 NewObject->Access = DesiredAccess;
815 NewObject->KeyHandle = ObjectKeyHandle;
816 NewObject->ParentObject = ParentObject;
817 NewObject->Trusted = Trusted;
818
819 if (ParentObject != NULL)
820 ParentObject->RefCount++;
821
822 *DbObject = NewObject;
823
824 return STATUS_SUCCESS;
825 }
826
827
828 NTSTATUS
829 LsapValidateDbObject(LSAPR_HANDLE Handle,
830 LSA_DB_OBJECT_TYPE ObjectType,
831 ACCESS_MASK DesiredAccess,
832 PLSA_DB_OBJECT *DbObject)
833 {
834 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
835 BOOLEAN bValid = FALSE;
836
837 _SEH2_TRY
838 {
839 if (LocalObject->Signature == LSAP_DB_SIGNATURE)
840 {
841 if ((ObjectType == LsaDbIgnoreObject) ||
842 (LocalObject->ObjectType == ObjectType))
843 bValid = TRUE;
844 }
845 }
846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
847 {
848 bValid = FALSE;
849 }
850 _SEH2_END;
851
852 if (bValid == FALSE)
853 return STATUS_INVALID_HANDLE;
854
855 if (DesiredAccess != 0)
856 {
857 /* Check for granted access rights */
858 if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
859 {
860 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
861 LocalObject->Access, DesiredAccess);
862 return STATUS_ACCESS_DENIED;
863 }
864 }
865
866 if (DbObject != NULL)
867 *DbObject = LocalObject;
868
869 return STATUS_SUCCESS;
870 }
871
872
873 NTSTATUS
874 LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
875 {
876 PLSA_DB_OBJECT ParentObject = NULL;
877 NTSTATUS Status = STATUS_SUCCESS;
878
879 DbObject->RefCount--;
880
881 if (DbObject->RefCount > 0)
882 return STATUS_SUCCESS;
883
884 if (DbObject->KeyHandle != NULL)
885 NtClose(DbObject->KeyHandle);
886
887 if (DbObject->ParentObject != NULL)
888 ParentObject = DbObject->ParentObject;
889
890 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
891
892 if (ParentObject != NULL)
893 {
894 ParentObject->RefCount--;
895
896 if (ParentObject->RefCount == 0)
897 Status = LsapCloseDbObject(ParentObject);
898 }
899
900 return Status;
901 }
902
903
904 NTSTATUS
905 LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject)
906 {
907 PLSA_DB_OBJECT ParentObject = NULL;
908 WCHAR KeyName[64];
909 ULONG Index;
910 NTSTATUS Status = STATUS_SUCCESS;
911
912 DbObject->RefCount--;
913
914 if (DbObject->RefCount > 0)
915 return STATUS_SUCCESS;
916
917 if (DbObject->KeyHandle != NULL)
918 {
919 Index = 0;
920
921 while (TRUE)
922 {
923 Status = LsapRegEnumerateSubKey(DbObject->KeyHandle,
924 Index,
925 64 * sizeof(WCHAR),
926 KeyName);
927 if (!NT_SUCCESS(Status))
928 break;
929
930 TRACE("Index: %lu\n", Index);
931 TRACE("Key name: %S\n", KeyName);
932
933 Status = LsapRegDeleteSubKey(DbObject->KeyHandle,
934 KeyName);
935 if (!NT_SUCCESS(Status))
936 break;
937 }
938
939 if (Status == STATUS_NO_MORE_ENTRIES)
940 Status = STATUS_SUCCESS;
941
942 LsapRegDeleteKey(DbObject->KeyHandle);
943
944 NtClose(DbObject->KeyHandle);
945 }
946
947 if (DbObject->ParentObject != NULL)
948 ParentObject = DbObject->ParentObject;
949
950 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
951
952 if (ParentObject != NULL)
953 {
954 ParentObject->RefCount--;
955
956 if (ParentObject->RefCount == 0)
957 Status = LsapCloseDbObject(ParentObject);
958 }
959
960 return Status;
961 }
962
963
964 NTSTATUS
965 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
966 LPWSTR AttributeName,
967 LPVOID AttributeData,
968 ULONG AttributeSize)
969 {
970 OBJECT_ATTRIBUTES ObjectAttributes;
971 UNICODE_STRING KeyName;
972 HANDLE AttributeKey;
973 NTSTATUS Status;
974
975 RtlInitUnicodeString(&KeyName,
976 AttributeName);
977
978 InitializeObjectAttributes(&ObjectAttributes,
979 &KeyName,
980 OBJ_CASE_INSENSITIVE,
981 DbObject->KeyHandle,
982 NULL);
983
984 Status = NtCreateKey(&AttributeKey,
985 KEY_SET_VALUE,
986 &ObjectAttributes,
987 0,
988 NULL,
989 REG_OPTION_NON_VOLATILE,
990 NULL);
991 if (!NT_SUCCESS(Status))
992 {
993
994 return Status;
995 }
996
997 Status = RtlpNtSetValueKey(AttributeKey,
998 REG_NONE,
999 AttributeData,
1000 AttributeSize);
1001
1002 NtClose(AttributeKey);
1003
1004 return Status;
1005 }
1006
1007
1008 NTSTATUS
1009 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
1010 LPWSTR AttributeName,
1011 LPVOID AttributeData,
1012 PULONG AttributeSize)
1013 {
1014 OBJECT_ATTRIBUTES ObjectAttributes;
1015 UNICODE_STRING KeyName;
1016 HANDLE AttributeKey;
1017 ULONG ValueSize;
1018 NTSTATUS Status;
1019
1020 RtlInitUnicodeString(&KeyName,
1021 AttributeName);
1022
1023 InitializeObjectAttributes(&ObjectAttributes,
1024 &KeyName,
1025 OBJ_CASE_INSENSITIVE,
1026 DbObject->KeyHandle,
1027 NULL);
1028
1029 Status = NtOpenKey(&AttributeKey,
1030 KEY_QUERY_VALUE,
1031 &ObjectAttributes);
1032 if (!NT_SUCCESS(Status))
1033 {
1034 return Status;
1035 }
1036
1037 ValueSize = *AttributeSize;
1038 Status = RtlpNtQueryValueKey(AttributeKey,
1039 NULL,
1040 NULL,
1041 &ValueSize,
1042 0);
1043 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
1044 {
1045 goto Done;
1046 }
1047
1048 if (AttributeData == NULL || *AttributeSize == 0)
1049 {
1050 *AttributeSize = ValueSize;
1051 Status = STATUS_SUCCESS;
1052 goto Done;
1053 }
1054 else if (*AttributeSize < ValueSize)
1055 {
1056 *AttributeSize = ValueSize;
1057 Status = STATUS_BUFFER_OVERFLOW;
1058 goto Done;
1059 }
1060
1061 Status = RtlpNtQueryValueKey(AttributeKey,
1062 NULL,
1063 AttributeData,
1064 &ValueSize,
1065 0);
1066 if (NT_SUCCESS(Status))
1067 {
1068 *AttributeSize = ValueSize;
1069 }
1070
1071 Done:
1072 NtClose(AttributeKey);
1073
1074 return Status;
1075 }
1076
1077 /* EOF */
1078