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