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 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 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 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 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 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 400 LsapUpdateDatabase(VOID) 401 { 402 return STATUS_SUCCESS; 403 } 404 405 406 static NTSTATUS 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 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 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 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 825 LsapValidateDbObject(LSAPR_HANDLE Handle, 826 LSA_DB_OBJECT_TYPE ObjectType, 827 ACCESS_MASK DesiredAccess, 828 PLSA_DB_OBJECT *DbObject) 829 { 830 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle; 831 BOOLEAN bValid = FALSE; 832 833 _SEH2_TRY 834 { 835 if (LocalObject->Signature == LSAP_DB_SIGNATURE) 836 { 837 if ((ObjectType == LsaDbIgnoreObject) || 838 (LocalObject->ObjectType == ObjectType)) 839 bValid = TRUE; 840 } 841 } 842 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 843 { 844 bValid = FALSE; 845 } 846 _SEH2_END; 847 848 if (bValid == FALSE) 849 return STATUS_INVALID_HANDLE; 850 851 if (DesiredAccess != 0) 852 { 853 /* Check for granted access rights */ 854 if ((LocalObject->Access & DesiredAccess) != DesiredAccess) 855 { 856 ERR("LsapValidateDbObject access check failed %08lx %08lx\n", 857 LocalObject->Access, DesiredAccess); 858 return STATUS_ACCESS_DENIED; 859 } 860 } 861 862 if (DbObject != NULL) 863 *DbObject = LocalObject; 864 865 return STATUS_SUCCESS; 866 } 867 868 869 NTSTATUS 870 LsapCloseDbObject(PLSA_DB_OBJECT DbObject) 871 { 872 PLSA_DB_OBJECT ParentObject = NULL; 873 NTSTATUS Status = STATUS_SUCCESS; 874 875 DbObject->RefCount--; 876 877 if (DbObject->RefCount > 0) 878 return STATUS_SUCCESS; 879 880 if (DbObject->KeyHandle != NULL) 881 NtClose(DbObject->KeyHandle); 882 883 if (DbObject->ParentObject != NULL) 884 ParentObject = DbObject->ParentObject; 885 886 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject); 887 888 if (ParentObject != NULL) 889 { 890 ParentObject->RefCount--; 891 892 if (ParentObject->RefCount == 0) 893 Status = LsapCloseDbObject(ParentObject); 894 } 895 896 return Status; 897 } 898 899 900 NTSTATUS 901 LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject) 902 { 903 PLSA_DB_OBJECT ParentObject = NULL; 904 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 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 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 1082 LsapDeleteObjectAttribute(PLSA_DB_OBJECT DbObject, 1083 LPWSTR AttributeName) 1084 { 1085 return LsapRegDeleteSubKey(DbObject->KeyHandle, 1086 AttributeName); 1087 } 1088 1089 /* EOF */ 1090