3ca4363d449a92b816e758711734ff58fe04642e
[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) + wcslen(ObjectName) + sizeof(WCHAR));
800 sizeof(LSA_DB_OBJECT));
801 if (NewObject == NULL)
802 {
803 NtClose(ObjectKeyHandle);
804 return STATUS_NO_MEMORY;
805 }
806
807 NewObject->Signature = LSAP_DB_SIGNATURE;
808 NewObject->RefCount = 1;
809 NewObject->ObjectType = ObjectType;
810 NewObject->Access = DesiredAccess;
811 NewObject->KeyHandle = ObjectKeyHandle;
812 NewObject->ParentObject = ParentObject;
813 // wcscpy(NewObject->Name, ObjectName);
814
815 if (ParentObject != NULL)
816 ParentObject->RefCount++;
817
818 *DbObject = NewObject;
819
820 return STATUS_SUCCESS;
821 }
822
823
824 NTSTATUS
825 LsapValidateDbObject(LSAPR_HANDLE Handle,
826 LSA_DB_OBJECT_TYPE ObjectType,
827 ACCESS_MASK DesiredAccess,
828 PLSA_DB_OBJECT *DbObject)
829 {
830 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
831 BOOLEAN bValid = FALSE;
832
833 _SEH2_TRY
834 {
835 if (LocalObject->Signature == LSAP_DB_SIGNATURE)
836 {
837 if ((ObjectType == LsaDbIgnoreObject) ||
838 (LocalObject->ObjectType == ObjectType))
839 bValid = TRUE;
840 }
841 }
842 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
843 {
844 bValid = FALSE;
845 }
846 _SEH2_END;
847
848 if (bValid == FALSE)
849 return STATUS_INVALID_HANDLE;
850
851 if (DesiredAccess != 0)
852 {
853 /* Check for granted access rights */
854 if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
855 {
856 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
857 LocalObject->Access, DesiredAccess);
858 return STATUS_ACCESS_DENIED;
859 }
860 }
861
862 if (DbObject != NULL)
863 *DbObject = LocalObject;
864
865 return STATUS_SUCCESS;
866 }
867
868
869 NTSTATUS
870 LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
871 {
872 PLSA_DB_OBJECT ParentObject = NULL;
873 NTSTATUS Status = STATUS_SUCCESS;
874
875 DbObject->RefCount--;
876
877 if (DbObject->RefCount > 0)
878 return STATUS_SUCCESS;
879
880 if (DbObject->KeyHandle != NULL)
881 NtClose(DbObject->KeyHandle);
882
883 if (DbObject->ParentObject != NULL)
884 ParentObject = DbObject->ParentObject;
885
886 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
887
888 if (ParentObject != NULL)
889 {
890 ParentObject->RefCount--;
891
892 if (ParentObject->RefCount == 0)
893 Status = LsapCloseDbObject(ParentObject);
894 }
895
896 return Status;
897 }
898
899
900 NTSTATUS
901 LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject)
902 {
903 PLSA_DB_OBJECT ParentObject = NULL;
904 #if 0
905 WCHAR KeyName[64];
906 ULONG EnumIndex;
907 #endif
908 NTSTATUS Status = STATUS_SUCCESS;
909
910 DbObject->RefCount--;
911
912 if (DbObject->RefCount > 0)
913 return STATUS_SUCCESS;
914
915 if (DbObject->KeyHandle != NULL)
916 {
917 #if 0
918 EnumIndex = 0;
919
920 while (TRUE)
921 {
922 Status = LsapRegEnumerateSubKey(DbObject->KeyHandle,
923 EnumIndex,
924 64 * sizeof(WCHAR),
925 KeyName);
926 if (!NT_SUCCESS(Status))
927 break;
928
929 TRACE("EnumIndex: %lu\n", EnumIndex);
930 TRACE("Key name: %S\n", KeyName);
931
932 Status = LsapRegDeleteKey(DbObject->KeyHandle,
933 KeyName);
934 if (!NT_SUCCESS(Status))
935 break;
936
937 // EnumIndex++;
938 }
939 #endif
940 NtClose(DbObject->KeyHandle);
941 }
942
943 if (DbObject->ParentObject != NULL)
944 {
945 ParentObject = DbObject->ParentObject;
946 #if 0
947 LsapRegDeleteKey(ParentObject->KeyHandle,
948 DbObject->Name);
949 #endif
950 }
951
952 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
953
954 if (ParentObject != NULL)
955 {
956 ParentObject->RefCount--;
957
958 if (ParentObject->RefCount == 0)
959 Status = LsapCloseDbObject(ParentObject);
960 }
961
962 return Status;
963 }
964
965
966 NTSTATUS
967 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
968 LPWSTR AttributeName,
969 LPVOID AttributeData,
970 ULONG AttributeSize)
971 {
972 OBJECT_ATTRIBUTES ObjectAttributes;
973 UNICODE_STRING KeyName;
974 HANDLE AttributeKey;
975 NTSTATUS Status;
976
977 RtlInitUnicodeString(&KeyName,
978 AttributeName);
979
980 InitializeObjectAttributes(&ObjectAttributes,
981 &KeyName,
982 OBJ_CASE_INSENSITIVE,
983 DbObject->KeyHandle,
984 NULL);
985
986 Status = NtCreateKey(&AttributeKey,
987 KEY_SET_VALUE,
988 &ObjectAttributes,
989 0,
990 NULL,
991 REG_OPTION_NON_VOLATILE,
992 NULL);
993 if (!NT_SUCCESS(Status))
994 {
995
996 return Status;
997 }
998
999 Status = RtlpNtSetValueKey(AttributeKey,
1000 REG_NONE,
1001 AttributeData,
1002 AttributeSize);
1003
1004 NtClose(AttributeKey);
1005
1006 return Status;
1007 }
1008
1009
1010 NTSTATUS
1011 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
1012 LPWSTR AttributeName,
1013 LPVOID AttributeData,
1014 PULONG AttributeSize)
1015 {
1016 OBJECT_ATTRIBUTES ObjectAttributes;
1017 UNICODE_STRING KeyName;
1018 HANDLE AttributeKey;
1019 ULONG ValueSize;
1020 NTSTATUS Status;
1021
1022 RtlInitUnicodeString(&KeyName,
1023 AttributeName);
1024
1025 InitializeObjectAttributes(&ObjectAttributes,
1026 &KeyName,
1027 OBJ_CASE_INSENSITIVE,
1028 DbObject->KeyHandle,
1029 NULL);
1030
1031 Status = NtOpenKey(&AttributeKey,
1032 KEY_QUERY_VALUE,
1033 &ObjectAttributes);
1034 if (!NT_SUCCESS(Status))
1035 {
1036 return Status;
1037 }
1038
1039 ValueSize = *AttributeSize;
1040 Status = RtlpNtQueryValueKey(AttributeKey,
1041 NULL,
1042 NULL,
1043 &ValueSize,
1044 0);
1045 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
1046 {
1047 goto Done;
1048 }
1049
1050 if (AttributeData == NULL || *AttributeSize == 0)
1051 {
1052 *AttributeSize = ValueSize;
1053 Status = STATUS_SUCCESS;
1054 goto Done;
1055 }
1056 else if (*AttributeSize < ValueSize)
1057 {
1058 *AttributeSize = ValueSize;
1059 Status = STATUS_BUFFER_OVERFLOW;
1060 goto Done;
1061 }
1062
1063 Status = RtlpNtQueryValueKey(AttributeKey,
1064 NULL,
1065 AttributeData,
1066 &ValueSize,
1067 0);
1068 if (NT_SUCCESS(Status))
1069 {
1070 *AttributeSize = ValueSize;
1071 }
1072
1073 Done:
1074 NtClose(AttributeKey);
1075
1076 return Status;
1077 }
1078
1079 /* EOF */
1080