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