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