[LSASRV] LsapLogonUser creates an impersonation token for a network logon
[reactos.git] / 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 #include "lsasrv.h"
10
11 /* GLOBALS *****************************************************************/
12
13 static HANDLE SecurityKeyHandle = NULL;
14
15 SID_IDENTIFIER_AUTHORITY NullSidAuthority = {SECURITY_NULL_SID_AUTHORITY};
16 SID_IDENTIFIER_AUTHORITY WorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
17 SID_IDENTIFIER_AUTHORITY LocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
18 SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
19 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
20
21 PSID BuiltinDomainSid = NULL;
22 PSID AccountDomainSid = NULL;
23 UNICODE_STRING BuiltinDomainName = {0, 0, NULL};
24 UNICODE_STRING AccountDomainName = {0, 0, NULL};
25
26
27 /* FUNCTIONS ***************************************************************/
28
29 static NTSTATUS
30 LsapOpenServiceKey(VOID)
31 {
32 OBJECT_ATTRIBUTES ObjectAttributes;
33 UNICODE_STRING KeyName;
34 NTSTATUS Status;
35
36 RtlInitUnicodeString(&KeyName,
37 L"\\Registry\\Machine\\SECURITY");
38
39 InitializeObjectAttributes(&ObjectAttributes,
40 &KeyName,
41 OBJ_CASE_INSENSITIVE,
42 NULL,
43 NULL);
44
45 Status = RtlpNtOpenKey(&SecurityKeyHandle,
46 KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
47 &ObjectAttributes,
48 0);
49
50 return Status;
51 }
52
53
54 static BOOLEAN
55 LsapIsDatabaseInstalled(VOID)
56 {
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 UNICODE_STRING KeyName;
59 HANDLE KeyHandle;
60 NTSTATUS Status;
61
62 RtlInitUnicodeString(&KeyName,
63 L"Policy");
64
65 InitializeObjectAttributes(&ObjectAttributes,
66 &KeyName,
67 OBJ_CASE_INSENSITIVE,
68 SecurityKeyHandle,
69 NULL);
70
71 Status = RtlpNtOpenKey(&KeyHandle,
72 KEY_READ,
73 &ObjectAttributes,
74 0);
75 if (!NT_SUCCESS(Status))
76 return FALSE;
77
78 NtClose(KeyHandle);
79
80 return TRUE;
81 }
82
83
84 static NTSTATUS
85 LsapCreateDatabaseKeys(VOID)
86 {
87 OBJECT_ATTRIBUTES ObjectAttributes;
88 UNICODE_STRING KeyName;
89 HANDLE PolicyKeyHandle = NULL;
90 HANDLE AccountsKeyHandle = NULL;
91 HANDLE DomainsKeyHandle = NULL;
92 HANDLE SecretsKeyHandle = NULL;
93 NTSTATUS Status = STATUS_SUCCESS;
94
95 TRACE("LsapInstallDatabase()\n");
96
97 /* Create the 'Policy' key */
98 RtlInitUnicodeString(&KeyName,
99 L"Policy");
100
101 InitializeObjectAttributes(&ObjectAttributes,
102 &KeyName,
103 OBJ_CASE_INSENSITIVE,
104 SecurityKeyHandle,
105 NULL);
106
107 Status = NtCreateKey(&PolicyKeyHandle,
108 KEY_ALL_ACCESS,
109 &ObjectAttributes,
110 0,
111 NULL,
112 0,
113 NULL);
114 if (!NT_SUCCESS(Status))
115 {
116 ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
117 goto Done;
118 }
119
120 /* Create the 'Accounts' key */
121 RtlInitUnicodeString(&KeyName,
122 L"Accounts");
123
124 InitializeObjectAttributes(&ObjectAttributes,
125 &KeyName,
126 OBJ_CASE_INSENSITIVE,
127 PolicyKeyHandle,
128 NULL);
129
130 Status = NtCreateKey(&AccountsKeyHandle,
131 KEY_ALL_ACCESS,
132 &ObjectAttributes,
133 0,
134 NULL,
135 0,
136 NULL);
137 if (!NT_SUCCESS(Status))
138 {
139 ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
140 goto Done;
141 }
142
143 /* Create the 'Domains' key */
144 RtlInitUnicodeString(&KeyName,
145 L"Domains");
146
147 InitializeObjectAttributes(&ObjectAttributes,
148 &KeyName,
149 OBJ_CASE_INSENSITIVE,
150 PolicyKeyHandle,
151 NULL);
152
153 Status = NtCreateKey(&DomainsKeyHandle,
154 KEY_ALL_ACCESS,
155 &ObjectAttributes,
156 0,
157 NULL,
158 0,
159 NULL);
160 if (!NT_SUCCESS(Status))
161 {
162 ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
163 goto Done;
164 }
165
166 /* Create the 'Secrets' key */
167 RtlInitUnicodeString(&KeyName,
168 L"Secrets");
169
170 InitializeObjectAttributes(&ObjectAttributes,
171 &KeyName,
172 OBJ_CASE_INSENSITIVE,
173 PolicyKeyHandle,
174 NULL);
175
176 Status = NtCreateKey(&SecretsKeyHandle,
177 KEY_ALL_ACCESS,
178 &ObjectAttributes,
179 0,
180 NULL,
181 0,
182 NULL);
183 if (!NT_SUCCESS(Status))
184 {
185 ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
186 goto Done;
187 }
188
189 Done:
190 if (SecretsKeyHandle != NULL)
191 NtClose(SecretsKeyHandle);
192
193 if (DomainsKeyHandle != NULL)
194 NtClose(DomainsKeyHandle);
195
196 if (AccountsKeyHandle != NULL)
197 NtClose(AccountsKeyHandle);
198
199 if (PolicyKeyHandle != NULL)
200 NtClose(PolicyKeyHandle);
201
202 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
203
204 return Status;
205 }
206
207
208 static NTSTATUS
209 LsapCreateRandomDomainSid(OUT PSID *Sid)
210 {
211 LARGE_INTEGER SystemTime;
212 PULONG Seed;
213
214 NtQuerySystemTime(&SystemTime);
215 Seed = &SystemTime.u.LowPart;
216
217 return RtlAllocateAndInitializeSid(&NtAuthority,
218 4,
219 SECURITY_NT_NON_UNIQUE,
220 RtlUniform(Seed),
221 RtlUniform(Seed),
222 RtlUniform(Seed),
223 SECURITY_NULL_RID,
224 SECURITY_NULL_RID,
225 SECURITY_NULL_RID,
226 SECURITY_NULL_RID,
227 Sid);
228 }
229
230
231 static NTSTATUS
232 LsapCreateDatabaseObjects(VOID)
233 {
234 PLSAP_POLICY_AUDIT_EVENTS_DATA AuditEventsInfo = NULL;
235 POLICY_DEFAULT_QUOTA_INFO QuotaInfo;
236 POLICY_MODIFICATION_INFO ModificationInfo;
237 POLICY_AUDIT_FULL_QUERY_INFO AuditFullInfo = {FALSE, FALSE};
238 POLICY_AUDIT_LOG_INFO AuditLogInfo;
239 GUID DnsDomainGuid;
240 PLSA_DB_OBJECT PolicyObject = NULL;
241 PSID AccountDomainSid = NULL;
242 PSECURITY_DESCRIPTOR PolicySd = NULL;
243 ULONG PolicySdSize = 0;
244 ULONG i;
245 NTSTATUS Status;
246
247 /* Initialize the default quota limits */
248 QuotaInfo.QuotaLimits.PagedPoolLimit = 0x2000000;
249 QuotaInfo.QuotaLimits.NonPagedPoolLimit = 0x100000;
250 QuotaInfo.QuotaLimits.MinimumWorkingSetSize = 0x10000;
251 QuotaInfo.QuotaLimits.MaximumWorkingSetSize = 0xF000000;
252 QuotaInfo.QuotaLimits.PagefileLimit = 0;
253 QuotaInfo.QuotaLimits.TimeLimit.QuadPart = 0;
254
255 /* Initialize the audit log attribute */
256 AuditLogInfo.AuditLogPercentFull = 0;
257 AuditLogInfo.MaximumLogSize = 0; // DWORD
258 AuditLogInfo.AuditRetentionPeriod.QuadPart = 0; // LARGE_INTEGER
259 AuditLogInfo.AuditLogFullShutdownInProgress = 0; // BYTE
260 AuditLogInfo.TimeToShutdown.QuadPart = 0; // LARGE_INTEGER
261 AuditLogInfo.NextAuditRecordId = 0; // DWORD
262
263 /* Initialize the Audit Events attribute */
264 AuditEventsInfo = RtlAllocateHeap(RtlGetProcessHeap(),
265 HEAP_ZERO_MEMORY,
266 sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA));
267 if (AuditEventsInfo == NULL)
268 return STATUS_INSUFFICIENT_RESOURCES;
269
270 AuditEventsInfo->AuditingMode = FALSE;
271 AuditEventsInfo->MaximumAuditEventCount = POLICY_AUDIT_EVENT_TYPE_COUNT;
272 for (i = 0; i < POLICY_AUDIT_EVENT_TYPE_COUNT; i++)
273 AuditEventsInfo->AuditEvents[i] = 0;
274
275 /* Initialize the DNS Domain GUID attribute */
276 RtlZeroMemory(&DnsDomainGuid, sizeof(DnsDomainGuid));
277
278 /* Initialize the modification attribute */
279 ModificationInfo.ModifiedId.QuadPart = 0;
280 NtQuerySystemTime(&ModificationInfo.DatabaseCreationTime);
281
282 /* Create a random domain SID */
283 Status = LsapCreateRandomDomainSid(&AccountDomainSid);
284 if (!NT_SUCCESS(Status))
285 goto done;
286
287 Status = LsapCreatePolicySd(&PolicySd, &PolicySdSize);
288 if (!NT_SUCCESS(Status))
289 goto done;
290
291 /* Open the 'Policy' object */
292 Status = LsapOpenDbObject(NULL,
293 NULL,
294 L"Policy",
295 LsaDbPolicyObject,
296 0,
297 TRUE,
298 &PolicyObject);
299 if (!NT_SUCCESS(Status))
300 goto done;
301
302 /* Set the Primary Domain Name attribute */
303 LsapSetObjectAttribute(PolicyObject,
304 L"PolPrDmN",
305 NULL,
306 0);
307
308 /* Set the Primary Domain SID attribute */
309 LsapSetObjectAttribute(PolicyObject,
310 L"PolPrDmS",
311 NULL,
312 0);
313
314 /* Set the Account Domain Name attribute */
315 LsapSetObjectAttribute(PolicyObject,
316 L"PolAcDmN",
317 NULL,
318 0);
319
320 /* Set the Account Domain SID attribute */
321 LsapSetObjectAttribute(PolicyObject,
322 L"PolAcDmS",
323 AccountDomainSid,
324 RtlLengthSid(AccountDomainSid));
325
326 /* Set the default quota limits attribute */
327 LsapSetObjectAttribute(PolicyObject,
328 L"DefQuota",
329 &QuotaInfo,
330 sizeof(QuotaInfo));
331
332 /* Set the modification attribute */
333 LsapSetObjectAttribute(PolicyObject,
334 L"PolMod",
335 &ModificationInfo,
336 sizeof(ModificationInfo));
337
338 /* Set the audit full attribute */
339 LsapSetObjectAttribute(PolicyObject,
340 L"PolAdtFl",
341 &AuditFullInfo,
342 sizeof(AuditFullInfo));
343
344 /* Set the audit log attribute */
345 LsapSetObjectAttribute(PolicyObject,
346 L"PolAdtLg",
347 &AuditLogInfo,
348 sizeof(AuditLogInfo));
349
350 /* Set the audit events attribute */
351 LsapSetObjectAttribute(PolicyObject,
352 L"PolAdtEv",
353 AuditEventsInfo,
354 sizeof(*AuditEventsInfo));
355
356 /* Set the DNS Domain Name attribute */
357 LsapSetObjectAttribute(PolicyObject,
358 L"PolDnDDN",
359 NULL,
360 0);
361
362 /* Set the DNS Forest Name attribute */
363 LsapSetObjectAttribute(PolicyObject,
364 L"PolDnTrN",
365 NULL,
366 0);
367
368 /* Set the DNS Domain GUID attribute */
369 LsapSetObjectAttribute(PolicyObject,
370 L"PolDnDmG",
371 &DnsDomainGuid,
372 sizeof(DnsDomainGuid));
373
374 /* Set the Security Descriptor */
375 LsapSetObjectAttribute(PolicyObject,
376 L"SecDesc",
377 PolicySd,
378 PolicySdSize);
379
380 done:
381 if (AuditEventsInfo != NULL)
382 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo);
383
384 if (PolicyObject != NULL)
385 LsapCloseDbObject(PolicyObject);
386
387 if (AccountDomainSid != NULL)
388 RtlFreeSid(AccountDomainSid);
389
390 if (PolicySd != NULL)
391 RtlFreeHeap(RtlGetProcessHeap(), 0, PolicySd);
392
393 return Status;
394 }
395
396
397 static NTSTATUS
398 LsapUpdateDatabase(VOID)
399 {
400 return STATUS_SUCCESS;
401 }
402
403
404 static NTSTATUS
405 LsapGetDomainInfo(VOID)
406 {
407 PLSA_DB_OBJECT PolicyObject = NULL;
408 PUNICODE_STRING DomainName = NULL;
409 ULONG AttributeSize;
410 LPWSTR SidString = NULL;
411 NTSTATUS Status;
412
413 /* Get the built-in domain SID and name */
414 Status = RtlAllocateAndInitializeSid(&NtAuthority,
415 1,
416 SECURITY_BUILTIN_DOMAIN_RID,
417 0, 0, 0, 0, 0, 0, 0,
418 &BuiltinDomainSid);
419 if (!NT_SUCCESS(Status))
420 return Status;
421
422 /**/
423 RtlInitUnicodeString(&BuiltinDomainName,
424 L"BUILTIN");
425
426 /* Open the 'Policy' object */
427 Status = LsapOpenDbObject(NULL,
428 NULL,
429 L"Policy",
430 LsaDbPolicyObject,
431 0,
432 TRUE,
433 &PolicyObject);
434 if (!NT_SUCCESS(Status))
435 goto done;
436
437 /* Get the account domain SID */
438 AttributeSize = 0;
439 Status = LsapGetObjectAttribute(PolicyObject,
440 L"PolAcDmS",
441 NULL,
442 &AttributeSize);
443 if (!NT_SUCCESS(Status))
444 goto done;
445
446 if (AttributeSize > 0)
447 {
448 AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(),
449 HEAP_ZERO_MEMORY,
450 AttributeSize);
451 if (AccountDomainSid == NULL)
452 {
453 Status = STATUS_INSUFFICIENT_RESOURCES;
454 goto done;
455 }
456
457 Status = LsapGetObjectAttribute(PolicyObject,
458 L"PolAcDmS",
459 AccountDomainSid,
460 &AttributeSize);
461 if (!NT_SUCCESS(Status))
462 goto done;
463 }
464
465 /* Get the account domain name */
466 AttributeSize = 0;
467 Status = LsapGetObjectAttribute(PolicyObject,
468 L"PolAcDmN",
469 NULL,
470 &AttributeSize);
471 if (!NT_SUCCESS(Status))
472 goto done;
473
474 if (AttributeSize > 0)
475 {
476 DomainName = RtlAllocateHeap(RtlGetProcessHeap(),
477 HEAP_ZERO_MEMORY,
478 AttributeSize);
479 if (DomainName == NULL)
480 {
481 Status = STATUS_INSUFFICIENT_RESOURCES;
482 goto done;
483 }
484
485 Status = LsapGetObjectAttribute(PolicyObject,
486 L"PolAcDmN",
487 DomainName,
488 &AttributeSize);
489 if (!NT_SUCCESS(Status))
490 goto done;
491
492 DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer);
493
494 AccountDomainName.Length = DomainName->Length;
495 AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR);
496 AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
497 HEAP_ZERO_MEMORY,
498 AccountDomainName.MaximumLength);
499 if (AccountDomainName.Buffer == NULL)
500 {
501 ERR("Failed to allocate the account domain name buffer\n");
502 Status = STATUS_INSUFFICIENT_RESOURCES;
503 goto done;
504 }
505
506 RtlCopyMemory(AccountDomainName.Buffer,
507 DomainName->Buffer,
508 DomainName->Length);
509 }
510
511 ConvertSidToStringSidW(BuiltinDomainSid, &SidString);
512 TRACE("Builtin Domain SID: %S\n", SidString);
513 LocalFree(SidString);
514 SidString = NULL;
515
516 TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName);
517
518 ConvertSidToStringSidW(AccountDomainSid, &SidString);
519 TRACE("Account Domain SID: %S\n", SidString);
520 LocalFree(SidString);
521 SidString = NULL;
522
523 TRACE("Account Domain Name: %wZ\n", &AccountDomainName);
524
525 done:
526 if (DomainName != NULL)
527 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName);
528
529 if (PolicyObject != NULL)
530 LsapCloseDbObject(PolicyObject);
531
532 return Status;
533 }
534
535
536 NTSTATUS
537 LsapInitDatabase(VOID)
538 {
539 NTSTATUS Status;
540
541 TRACE("LsapInitDatabase()\n");
542
543 Status = LsapOpenServiceKey();
544 if (!NT_SUCCESS(Status))
545 {
546 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
547 return Status;
548 }
549
550 if (!LsapIsDatabaseInstalled())
551 {
552 Status = LsapCreateDatabaseKeys();
553 if (!NT_SUCCESS(Status))
554 {
555 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status);
556 return Status;
557 }
558
559 Status = LsapCreateDatabaseObjects();
560 if (!NT_SUCCESS(Status))
561 {
562 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status);
563 return Status;
564 }
565 }
566 else
567 {
568 Status = LsapUpdateDatabase();
569 if (!NT_SUCCESS(Status))
570 {
571 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
572 return Status;
573 }
574 }
575
576 Status = LsapGetDomainInfo();
577 if (!NT_SUCCESS(Status))
578 {
579 ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status);
580 return Status;
581 }
582
583 TRACE("LsapInitDatabase() done\n");
584
585 return STATUS_SUCCESS;
586 }
587
588
589 NTSTATUS
590 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
591 IN LPWSTR ContainerName,
592 IN LPWSTR ObjectName,
593 IN LSA_DB_OBJECT_TYPE ObjectType,
594 IN ACCESS_MASK DesiredAccess,
595 IN BOOLEAN Trusted,
596 OUT PLSA_DB_OBJECT *DbObject)
597 {
598 PLSA_DB_OBJECT NewObject;
599 OBJECT_ATTRIBUTES ObjectAttributes;
600 UNICODE_STRING KeyName;
601 HANDLE ParentKeyHandle;
602 HANDLE ContainerKeyHandle = NULL;
603 HANDLE ObjectKeyHandle = NULL;
604 NTSTATUS Status;
605
606 if (DbObject == NULL)
607 return STATUS_INVALID_PARAMETER;
608
609 if (ParentObject == NULL)
610 ParentKeyHandle = SecurityKeyHandle;
611 else
612 ParentKeyHandle = ParentObject->KeyHandle;
613
614 if (ContainerName != NULL)
615 {
616 /* Open the container key */
617 RtlInitUnicodeString(&KeyName,
618 ContainerName);
619
620 InitializeObjectAttributes(&ObjectAttributes,
621 &KeyName,
622 OBJ_CASE_INSENSITIVE,
623 ParentKeyHandle,
624 NULL);
625
626 Status = NtOpenKey(&ContainerKeyHandle,
627 KEY_ALL_ACCESS,
628 &ObjectAttributes);
629 if (!NT_SUCCESS(Status))
630 {
631 return Status;
632 }
633
634 /* Open the object key */
635 RtlInitUnicodeString(&KeyName,
636 ObjectName);
637
638 InitializeObjectAttributes(&ObjectAttributes,
639 &KeyName,
640 OBJ_CASE_INSENSITIVE,
641 ContainerKeyHandle,
642 NULL);
643
644 Status = NtCreateKey(&ObjectKeyHandle,
645 KEY_ALL_ACCESS,
646 &ObjectAttributes,
647 0,
648 NULL,
649 0,
650 NULL);
651
652 NtClose(ContainerKeyHandle);
653
654 if (!NT_SUCCESS(Status))
655 {
656 return Status;
657 }
658 }
659 else
660 {
661 RtlInitUnicodeString(&KeyName,
662 ObjectName);
663
664 InitializeObjectAttributes(&ObjectAttributes,
665 &KeyName,
666 OBJ_CASE_INSENSITIVE,
667 ParentKeyHandle,
668 NULL);
669
670 Status = NtCreateKey(&ObjectKeyHandle,
671 KEY_ALL_ACCESS,
672 &ObjectAttributes,
673 0,
674 NULL,
675 0,
676 NULL);
677 if (!NT_SUCCESS(Status))
678 {
679 return Status;
680 }
681 }
682
683 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
684 0,
685 sizeof(LSA_DB_OBJECT));
686 if (NewObject == NULL)
687 {
688 NtClose(ObjectKeyHandle);
689 return STATUS_NO_MEMORY;
690 }
691
692 NewObject->Signature = LSAP_DB_SIGNATURE;
693 NewObject->RefCount = 1;
694 NewObject->ObjectType = ObjectType;
695 NewObject->Access = DesiredAccess;
696 NewObject->KeyHandle = ObjectKeyHandle;
697 NewObject->ParentObject = ParentObject;
698 NewObject->Trusted = Trusted;
699
700 if (ParentObject != NULL)
701 ParentObject->RefCount++;
702
703 *DbObject = NewObject;
704
705 return STATUS_SUCCESS;
706 }
707
708
709 NTSTATUS
710 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
711 IN LPWSTR ContainerName,
712 IN LPWSTR ObjectName,
713 IN LSA_DB_OBJECT_TYPE ObjectType,
714 IN ACCESS_MASK DesiredAccess,
715 IN BOOLEAN Trusted,
716 OUT PLSA_DB_OBJECT *DbObject)
717 {
718 PLSA_DB_OBJECT NewObject;
719 OBJECT_ATTRIBUTES ObjectAttributes;
720 UNICODE_STRING KeyName;
721 HANDLE ParentKeyHandle;
722 HANDLE ContainerKeyHandle = NULL;
723 HANDLE ObjectKeyHandle = NULL;
724 NTSTATUS Status;
725
726 if (DbObject == NULL)
727 return STATUS_INVALID_PARAMETER;
728
729 if (ParentObject == NULL)
730 ParentKeyHandle = SecurityKeyHandle;
731 else
732 ParentKeyHandle = ParentObject->KeyHandle;
733
734 if (ContainerName != NULL)
735 {
736 /* Open the container key */
737 RtlInitUnicodeString(&KeyName,
738 ContainerName);
739
740 InitializeObjectAttributes(&ObjectAttributes,
741 &KeyName,
742 OBJ_CASE_INSENSITIVE,
743 ParentKeyHandle,
744 NULL);
745
746 Status = NtOpenKey(&ContainerKeyHandle,
747 KEY_ALL_ACCESS,
748 &ObjectAttributes);
749 if (!NT_SUCCESS(Status))
750 {
751 return Status;
752 }
753
754 /* Open the object key */
755 RtlInitUnicodeString(&KeyName,
756 ObjectName);
757
758 InitializeObjectAttributes(&ObjectAttributes,
759 &KeyName,
760 OBJ_CASE_INSENSITIVE,
761 ContainerKeyHandle,
762 NULL);
763
764 Status = NtOpenKey(&ObjectKeyHandle,
765 KEY_ALL_ACCESS,
766 &ObjectAttributes);
767
768 NtClose(ContainerKeyHandle);
769
770 if (!NT_SUCCESS(Status))
771 {
772 return Status;
773 }
774 }
775 else
776 {
777 /* Open the object key */
778 RtlInitUnicodeString(&KeyName,
779 ObjectName);
780
781 InitializeObjectAttributes(&ObjectAttributes,
782 &KeyName,
783 OBJ_CASE_INSENSITIVE,
784 ParentKeyHandle,
785 NULL);
786
787 Status = NtOpenKey(&ObjectKeyHandle,
788 KEY_ALL_ACCESS,
789 &ObjectAttributes);
790 if (!NT_SUCCESS(Status))
791 {
792 return Status;
793 }
794 }
795
796 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
797 0,
798 sizeof(LSA_DB_OBJECT));
799 if (NewObject == NULL)
800 {
801 NtClose(ObjectKeyHandle);
802 return STATUS_NO_MEMORY;
803 }
804
805 NewObject->Signature = LSAP_DB_SIGNATURE;
806 NewObject->RefCount = 1;
807 NewObject->ObjectType = ObjectType;
808 NewObject->Access = DesiredAccess;
809 NewObject->KeyHandle = ObjectKeyHandle;
810 NewObject->ParentObject = ParentObject;
811 NewObject->Trusted = Trusted;
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 sizeof(KeyName),
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 ERR("NtCreateKey failed for '%S' with status 0x%lx\n",
988 AttributeName, Status);
989 return Status;
990 }
991
992 Status = RtlpNtSetValueKey(AttributeKey,
993 REG_NONE,
994 AttributeData,
995 AttributeSize);
996
997 NtClose(AttributeKey);
998
999 if (!NT_SUCCESS(Status))
1000 {
1001 ERR("RtlpNtSetValueKey failed for '%S' with status 0x%lx\n",
1002 AttributeName, Status);
1003 }
1004
1005 return Status;
1006 }
1007
1008
1009 NTSTATUS
1010 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
1011 LPWSTR AttributeName,
1012 LPVOID AttributeData,
1013 PULONG AttributeSize)
1014 {
1015 OBJECT_ATTRIBUTES ObjectAttributes;
1016 UNICODE_STRING KeyName;
1017 HANDLE AttributeKey;
1018 ULONG ValueSize;
1019 NTSTATUS Status;
1020
1021 RtlInitUnicodeString(&KeyName,
1022 AttributeName);
1023
1024 InitializeObjectAttributes(&ObjectAttributes,
1025 &KeyName,
1026 OBJ_CASE_INSENSITIVE,
1027 DbObject->KeyHandle,
1028 NULL);
1029
1030 Status = NtOpenKey(&AttributeKey,
1031 KEY_QUERY_VALUE,
1032 &ObjectAttributes);
1033 if (!NT_SUCCESS(Status))
1034 {
1035 return Status;
1036 }
1037
1038 ValueSize = *AttributeSize;
1039 Status = RtlpNtQueryValueKey(AttributeKey,
1040 NULL,
1041 NULL,
1042 &ValueSize,
1043 0);
1044 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
1045 {
1046 goto Done;
1047 }
1048
1049 if (AttributeData == NULL || *AttributeSize == 0)
1050 {
1051 *AttributeSize = ValueSize;
1052 Status = STATUS_SUCCESS;
1053 goto Done;
1054 }
1055 else if (*AttributeSize < ValueSize)
1056 {
1057 *AttributeSize = ValueSize;
1058 Status = STATUS_BUFFER_OVERFLOW;
1059 goto Done;
1060 }
1061
1062 Status = RtlpNtQueryValueKey(AttributeKey,
1063 NULL,
1064 AttributeData,
1065 &ValueSize,
1066 0);
1067 if (NT_SUCCESS(Status))
1068 {
1069 *AttributeSize = ValueSize;
1070 }
1071
1072 Done:
1073 NtClose(AttributeKey);
1074
1075 return Status;
1076 }
1077
1078
1079 NTSTATUS
1080 LsapDeleteObjectAttribute(PLSA_DB_OBJECT DbObject,
1081 LPWSTR AttributeName)
1082 {
1083 return LsapRegDeleteSubKey(DbObject->KeyHandle,
1084 AttributeName);
1085 }
1086
1087 /* EOF */