xref: /reactos/dll/win32/lsasrv/database.c (revision c2c66aff)
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 */
1088