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