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 memset(&DnsDomainGuid, 0, sizeof(GUID)); 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 LsapSetObjectAttribute(PolicyObject, 303 L"PolPrDmN", 304 NULL, 305 0); 306 307 LsapSetObjectAttribute(PolicyObject, 308 L"PolPrDmS", 309 NULL, 310 0); 311 312 LsapSetObjectAttribute(PolicyObject, 313 L"PolAcDmN", 314 NULL, 315 0); 316 317 LsapSetObjectAttribute(PolicyObject, 318 L"PolAcDmS", 319 AccountDomainSid, 320 RtlLengthSid(AccountDomainSid)); 321 322 /* Set the default quota limits attribute */ 323 LsapSetObjectAttribute(PolicyObject, 324 L"DefQuota", 325 &QuotaInfo, 326 sizeof(POLICY_DEFAULT_QUOTA_INFO)); 327 328 /* Set the modification attribute */ 329 LsapSetObjectAttribute(PolicyObject, 330 L"PolMod", 331 &ModificationInfo, 332 sizeof(POLICY_MODIFICATION_INFO)); 333 334 /* Set the audit full attribute */ 335 LsapSetObjectAttribute(PolicyObject, 336 L"PolAdtFl", 337 &AuditFullInfo, 338 sizeof(POLICY_AUDIT_FULL_QUERY_INFO)); 339 340 /* Set the audit log attribute */ 341 LsapSetObjectAttribute(PolicyObject, 342 L"PolAdtLg", 343 &AuditLogInfo, 344 sizeof(POLICY_AUDIT_LOG_INFO)); 345 346 /* Set the audit events attribute */ 347 LsapSetObjectAttribute(PolicyObject, 348 L"PolAdtEv", 349 AuditEventsInfo, 350 sizeof(LSAP_POLICY_AUDIT_EVENTS_DATA)); 351 352 /* Set the DNS Domain Name attribute */ 353 LsapSetObjectAttribute(PolicyObject, 354 L"PolDnDDN", 355 NULL, 356 0); 357 358 /* Set the DNS Forest Name attribute */ 359 LsapSetObjectAttribute(PolicyObject, 360 L"PolDnTrN", 361 NULL, 362 0); 363 364 /* Set the DNS Domain GUID attribute */ 365 LsapSetObjectAttribute(PolicyObject, 366 L"PolDnDmG", 367 &DnsDomainGuid, 368 sizeof(GUID)); 369 370 /* Set the Sceurity Descriptor */ 371 LsapSetObjectAttribute(PolicyObject, 372 L"SecDesc", 373 PolicySd, 374 PolicySdSize); 375 376 done: 377 if (AuditEventsInfo != NULL) 378 RtlFreeHeap(RtlGetProcessHeap(), 0, AuditEventsInfo); 379 380 if (PolicyObject != NULL) 381 LsapCloseDbObject(PolicyObject); 382 383 if (AccountDomainSid != NULL) 384 RtlFreeSid(AccountDomainSid); 385 386 if (PolicySd != NULL) 387 RtlFreeHeap(RtlGetProcessHeap(), 0, PolicySd); 388 389 return Status; 390 } 391 392 393 static NTSTATUS 394 LsapUpdateDatabase(VOID) 395 { 396 return STATUS_SUCCESS; 397 } 398 399 400 static NTSTATUS 401 LsapGetDomainInfo(VOID) 402 { 403 PLSA_DB_OBJECT PolicyObject = NULL; 404 PUNICODE_STRING DomainName = NULL; 405 ULONG AttributeSize; 406 LPWSTR SidString = NULL; 407 NTSTATUS Status; 408 409 /* Get the built-in domain SID and name */ 410 Status = RtlAllocateAndInitializeSid(&NtAuthority, 411 1, 412 SECURITY_BUILTIN_DOMAIN_RID, 413 0, 0, 0, 0, 0, 0, 0, 414 &BuiltinDomainSid); 415 if (!NT_SUCCESS(Status)) 416 return Status; 417 418 /**/ 419 RtlInitUnicodeString(&BuiltinDomainName, 420 L"BUILTIN"); 421 422 /* Open the 'Policy' object */ 423 Status = LsapOpenDbObject(NULL, 424 NULL, 425 L"Policy", 426 LsaDbPolicyObject, 427 0, 428 TRUE, 429 &PolicyObject); 430 if (!NT_SUCCESS(Status)) 431 goto done; 432 433 /* Get the account domain SID */ 434 AttributeSize = 0; 435 Status = LsapGetObjectAttribute(PolicyObject, 436 L"PolAcDmS", 437 NULL, 438 &AttributeSize); 439 if (!NT_SUCCESS(Status)) 440 goto done; 441 442 if (AttributeSize > 0) 443 { 444 AccountDomainSid = RtlAllocateHeap(RtlGetProcessHeap(), 445 HEAP_ZERO_MEMORY, 446 AttributeSize); 447 if (AccountDomainSid == NULL) 448 { 449 Status = STATUS_INSUFFICIENT_RESOURCES; 450 goto done; 451 } 452 453 Status = LsapGetObjectAttribute(PolicyObject, 454 L"PolAcDmS", 455 AccountDomainSid, 456 &AttributeSize); 457 if (!NT_SUCCESS(Status)) 458 goto done; 459 } 460 461 /* Get the account domain name */ 462 AttributeSize = 0; 463 Status = LsapGetObjectAttribute(PolicyObject, 464 L"PolAcDmN", 465 NULL, 466 &AttributeSize); 467 if (!NT_SUCCESS(Status)) 468 goto done; 469 470 if (AttributeSize > 0) 471 { 472 DomainName = RtlAllocateHeap(RtlGetProcessHeap(), 473 HEAP_ZERO_MEMORY, 474 AttributeSize); 475 if (DomainName == NULL) 476 { 477 Status = STATUS_INSUFFICIENT_RESOURCES; 478 goto done; 479 } 480 481 Status = LsapGetObjectAttribute(PolicyObject, 482 L"PolAcDmN", 483 DomainName, 484 &AttributeSize); 485 if (!NT_SUCCESS(Status)) 486 goto done; 487 488 DomainName->Buffer = (LPWSTR)((ULONG_PTR)DomainName + (ULONG_PTR)DomainName->Buffer); 489 490 AccountDomainName.Length = DomainName->Length; 491 AccountDomainName.MaximumLength = DomainName->Length + sizeof(WCHAR); 492 AccountDomainName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 493 HEAP_ZERO_MEMORY, 494 AccountDomainName.MaximumLength); 495 if (AccountDomainName.Buffer == NULL) 496 { 497 ERR("Failed to allocate the account domain name buffer\n"); 498 Status = STATUS_INSUFFICIENT_RESOURCES; 499 goto done; 500 } 501 502 RtlCopyMemory(AccountDomainName.Buffer, 503 DomainName->Buffer, 504 DomainName->Length); 505 } 506 507 ConvertSidToStringSidW(BuiltinDomainSid, &SidString); 508 TRACE("Builtin Domain SID: %S\n", SidString); 509 LocalFree(SidString); 510 SidString = NULL; 511 512 TRACE("Builtin Domain Name: %wZ\n", &BuiltinDomainName); 513 514 ConvertSidToStringSidW(AccountDomainSid, &SidString); 515 TRACE("Account Domain SID: %S\n", SidString); 516 LocalFree(SidString); 517 SidString = NULL; 518 519 TRACE("Account Domain Name: %wZ\n", &AccountDomainName); 520 521 done: 522 if (DomainName != NULL) 523 RtlFreeHeap(RtlGetProcessHeap(), 0, DomainName); 524 525 if (PolicyObject != NULL) 526 LsapCloseDbObject(PolicyObject); 527 528 return Status; 529 } 530 531 532 NTSTATUS 533 LsapInitDatabase(VOID) 534 { 535 NTSTATUS Status; 536 537 TRACE("LsapInitDatabase()\n"); 538 539 Status = LsapOpenServiceKey(); 540 if (!NT_SUCCESS(Status)) 541 { 542 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status); 543 return Status; 544 } 545 546 if (!LsapIsDatabaseInstalled()) 547 { 548 Status = LsapCreateDatabaseKeys(); 549 if (!NT_SUCCESS(Status)) 550 { 551 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status); 552 return Status; 553 } 554 555 Status = LsapCreateDatabaseObjects(); 556 if (!NT_SUCCESS(Status)) 557 { 558 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status); 559 return Status; 560 } 561 } 562 else 563 { 564 Status = LsapUpdateDatabase(); 565 if (!NT_SUCCESS(Status)) 566 { 567 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status); 568 return Status; 569 } 570 } 571 572 Status = LsapGetDomainInfo(); 573 if (!NT_SUCCESS(Status)) 574 { 575 ERR("Failed to get the domain information (Status: 0x%08lx)\n", Status); 576 return Status; 577 } 578 579 TRACE("LsapInitDatabase() done\n"); 580 581 return STATUS_SUCCESS; 582 } 583 584 585 NTSTATUS 586 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject, 587 IN LPWSTR ContainerName, 588 IN LPWSTR ObjectName, 589 IN LSA_DB_OBJECT_TYPE ObjectType, 590 IN ACCESS_MASK DesiredAccess, 591 IN BOOLEAN Trusted, 592 OUT PLSA_DB_OBJECT *DbObject) 593 { 594 PLSA_DB_OBJECT NewObject; 595 OBJECT_ATTRIBUTES ObjectAttributes; 596 UNICODE_STRING KeyName; 597 HANDLE ParentKeyHandle; 598 HANDLE ContainerKeyHandle = NULL; 599 HANDLE ObjectKeyHandle = NULL; 600 NTSTATUS Status; 601 602 if (DbObject == NULL) 603 return STATUS_INVALID_PARAMETER; 604 605 if (ParentObject == NULL) 606 ParentKeyHandle = SecurityKeyHandle; 607 else 608 ParentKeyHandle = ParentObject->KeyHandle; 609 610 if (ContainerName != NULL) 611 { 612 /* Open the container key */ 613 RtlInitUnicodeString(&KeyName, 614 ContainerName); 615 616 InitializeObjectAttributes(&ObjectAttributes, 617 &KeyName, 618 OBJ_CASE_INSENSITIVE, 619 ParentKeyHandle, 620 NULL); 621 622 Status = NtOpenKey(&ContainerKeyHandle, 623 KEY_ALL_ACCESS, 624 &ObjectAttributes); 625 if (!NT_SUCCESS(Status)) 626 { 627 return Status; 628 } 629 630 /* Open the object key */ 631 RtlInitUnicodeString(&KeyName, 632 ObjectName); 633 634 InitializeObjectAttributes(&ObjectAttributes, 635 &KeyName, 636 OBJ_CASE_INSENSITIVE, 637 ContainerKeyHandle, 638 NULL); 639 640 Status = NtCreateKey(&ObjectKeyHandle, 641 KEY_ALL_ACCESS, 642 &ObjectAttributes, 643 0, 644 NULL, 645 0, 646 NULL); 647 648 NtClose(ContainerKeyHandle); 649 650 if (!NT_SUCCESS(Status)) 651 { 652 return Status; 653 } 654 } 655 else 656 { 657 RtlInitUnicodeString(&KeyName, 658 ObjectName); 659 660 InitializeObjectAttributes(&ObjectAttributes, 661 &KeyName, 662 OBJ_CASE_INSENSITIVE, 663 ParentKeyHandle, 664 NULL); 665 666 Status = NtCreateKey(&ObjectKeyHandle, 667 KEY_ALL_ACCESS, 668 &ObjectAttributes, 669 0, 670 NULL, 671 0, 672 NULL); 673 if (!NT_SUCCESS(Status)) 674 { 675 return Status; 676 } 677 } 678 679 NewObject = RtlAllocateHeap(RtlGetProcessHeap(), 680 0, 681 sizeof(LSA_DB_OBJECT)); 682 if (NewObject == NULL) 683 { 684 NtClose(ObjectKeyHandle); 685 return STATUS_NO_MEMORY; 686 } 687 688 NewObject->Signature = LSAP_DB_SIGNATURE; 689 NewObject->RefCount = 1; 690 NewObject->ObjectType = ObjectType; 691 NewObject->Access = DesiredAccess; 692 NewObject->KeyHandle = ObjectKeyHandle; 693 NewObject->ParentObject = ParentObject; 694 NewObject->Trusted = Trusted; 695 696 if (ParentObject != NULL) 697 ParentObject->RefCount++; 698 699 *DbObject = NewObject; 700 701 return STATUS_SUCCESS; 702 } 703 704 705 NTSTATUS 706 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject, 707 IN LPWSTR ContainerName, 708 IN LPWSTR ObjectName, 709 IN LSA_DB_OBJECT_TYPE ObjectType, 710 IN ACCESS_MASK DesiredAccess, 711 IN BOOLEAN Trusted, 712 OUT PLSA_DB_OBJECT *DbObject) 713 { 714 PLSA_DB_OBJECT NewObject; 715 OBJECT_ATTRIBUTES ObjectAttributes; 716 UNICODE_STRING KeyName; 717 HANDLE ParentKeyHandle; 718 HANDLE ContainerKeyHandle = NULL; 719 HANDLE ObjectKeyHandle = NULL; 720 NTSTATUS Status; 721 722 if (DbObject == NULL) 723 return STATUS_INVALID_PARAMETER; 724 725 if (ParentObject == NULL) 726 ParentKeyHandle = SecurityKeyHandle; 727 else 728 ParentKeyHandle = ParentObject->KeyHandle; 729 730 if (ContainerName != NULL) 731 { 732 /* Open the container key */ 733 RtlInitUnicodeString(&KeyName, 734 ContainerName); 735 736 InitializeObjectAttributes(&ObjectAttributes, 737 &KeyName, 738 OBJ_CASE_INSENSITIVE, 739 ParentKeyHandle, 740 NULL); 741 742 Status = NtOpenKey(&ContainerKeyHandle, 743 KEY_ALL_ACCESS, 744 &ObjectAttributes); 745 if (!NT_SUCCESS(Status)) 746 { 747 return Status; 748 } 749 750 /* Open the object key */ 751 RtlInitUnicodeString(&KeyName, 752 ObjectName); 753 754 InitializeObjectAttributes(&ObjectAttributes, 755 &KeyName, 756 OBJ_CASE_INSENSITIVE, 757 ContainerKeyHandle, 758 NULL); 759 760 Status = NtOpenKey(&ObjectKeyHandle, 761 KEY_ALL_ACCESS, 762 &ObjectAttributes); 763 764 NtClose(ContainerKeyHandle); 765 766 if (!NT_SUCCESS(Status)) 767 { 768 return Status; 769 } 770 } 771 else 772 { 773 /* Open the object key */ 774 RtlInitUnicodeString(&KeyName, 775 ObjectName); 776 777 InitializeObjectAttributes(&ObjectAttributes, 778 &KeyName, 779 OBJ_CASE_INSENSITIVE, 780 ParentKeyHandle, 781 NULL); 782 783 Status = NtOpenKey(&ObjectKeyHandle, 784 KEY_ALL_ACCESS, 785 &ObjectAttributes); 786 if (!NT_SUCCESS(Status)) 787 { 788 return Status; 789 } 790 } 791 792 NewObject = RtlAllocateHeap(RtlGetProcessHeap(), 793 0, 794 sizeof(LSA_DB_OBJECT)); 795 if (NewObject == NULL) 796 { 797 NtClose(ObjectKeyHandle); 798 return STATUS_NO_MEMORY; 799 } 800 801 NewObject->Signature = LSAP_DB_SIGNATURE; 802 NewObject->RefCount = 1; 803 NewObject->ObjectType = ObjectType; 804 NewObject->Access = DesiredAccess; 805 NewObject->KeyHandle = ObjectKeyHandle; 806 NewObject->ParentObject = ParentObject; 807 NewObject->Trusted = Trusted; 808 809 if (ParentObject != NULL) 810 ParentObject->RefCount++; 811 812 *DbObject = NewObject; 813 814 return STATUS_SUCCESS; 815 } 816 817 818 NTSTATUS 819 LsapValidateDbObject(LSAPR_HANDLE Handle, 820 LSA_DB_OBJECT_TYPE ObjectType, 821 ACCESS_MASK DesiredAccess, 822 PLSA_DB_OBJECT *DbObject) 823 { 824 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle; 825 BOOLEAN bValid = FALSE; 826 827 _SEH2_TRY 828 { 829 if (LocalObject->Signature == LSAP_DB_SIGNATURE) 830 { 831 if ((ObjectType == LsaDbIgnoreObject) || 832 (LocalObject->ObjectType == ObjectType)) 833 bValid = TRUE; 834 } 835 } 836 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 837 { 838 bValid = FALSE; 839 } 840 _SEH2_END; 841 842 if (bValid == FALSE) 843 return STATUS_INVALID_HANDLE; 844 845 if (DesiredAccess != 0) 846 { 847 /* Check for granted access rights */ 848 if ((LocalObject->Access & DesiredAccess) != DesiredAccess) 849 { 850 ERR("LsapValidateDbObject access check failed %08lx %08lx\n", 851 LocalObject->Access, DesiredAccess); 852 return STATUS_ACCESS_DENIED; 853 } 854 } 855 856 if (DbObject != NULL) 857 *DbObject = LocalObject; 858 859 return STATUS_SUCCESS; 860 } 861 862 863 NTSTATUS 864 LsapCloseDbObject(PLSA_DB_OBJECT DbObject) 865 { 866 PLSA_DB_OBJECT ParentObject = NULL; 867 NTSTATUS Status = STATUS_SUCCESS; 868 869 DbObject->RefCount--; 870 871 if (DbObject->RefCount > 0) 872 return STATUS_SUCCESS; 873 874 if (DbObject->KeyHandle != NULL) 875 NtClose(DbObject->KeyHandle); 876 877 if (DbObject->ParentObject != NULL) 878 ParentObject = DbObject->ParentObject; 879 880 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject); 881 882 if (ParentObject != NULL) 883 { 884 ParentObject->RefCount--; 885 886 if (ParentObject->RefCount == 0) 887 Status = LsapCloseDbObject(ParentObject); 888 } 889 890 return Status; 891 } 892 893 894 NTSTATUS 895 LsapDeleteDbObject(IN PLSA_DB_OBJECT DbObject) 896 { 897 PLSA_DB_OBJECT ParentObject = NULL; 898 WCHAR KeyName[64]; 899 ULONG Index; 900 NTSTATUS Status = STATUS_SUCCESS; 901 902 DbObject->RefCount--; 903 904 if (DbObject->RefCount > 0) 905 return STATUS_SUCCESS; 906 907 if (DbObject->KeyHandle != NULL) 908 { 909 Index = 0; 910 911 while (TRUE) 912 { 913 Status = LsapRegEnumerateSubKey(DbObject->KeyHandle, 914 Index, 915 64 * sizeof(WCHAR), 916 KeyName); 917 if (!NT_SUCCESS(Status)) 918 break; 919 920 TRACE("Index: %lu\n", Index); 921 TRACE("Key name: %S\n", KeyName); 922 923 Status = LsapRegDeleteSubKey(DbObject->KeyHandle, 924 KeyName); 925 if (!NT_SUCCESS(Status)) 926 break; 927 } 928 929 if (Status == STATUS_NO_MORE_ENTRIES) 930 Status = STATUS_SUCCESS; 931 932 LsapRegDeleteKey(DbObject->KeyHandle); 933 934 NtClose(DbObject->KeyHandle); 935 } 936 937 if (DbObject->ParentObject != NULL) 938 ParentObject = DbObject->ParentObject; 939 940 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject); 941 942 if (ParentObject != NULL) 943 { 944 ParentObject->RefCount--; 945 946 if (ParentObject->RefCount == 0) 947 Status = LsapCloseDbObject(ParentObject); 948 } 949 950 return Status; 951 } 952 953 954 NTSTATUS 955 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject, 956 LPWSTR AttributeName, 957 LPVOID AttributeData, 958 ULONG AttributeSize) 959 { 960 OBJECT_ATTRIBUTES ObjectAttributes; 961 UNICODE_STRING KeyName; 962 HANDLE AttributeKey; 963 NTSTATUS Status; 964 965 RtlInitUnicodeString(&KeyName, 966 AttributeName); 967 968 InitializeObjectAttributes(&ObjectAttributes, 969 &KeyName, 970 OBJ_CASE_INSENSITIVE, 971 DbObject->KeyHandle, 972 NULL); 973 974 Status = NtCreateKey(&AttributeKey, 975 KEY_SET_VALUE, 976 &ObjectAttributes, 977 0, 978 NULL, 979 REG_OPTION_NON_VOLATILE, 980 NULL); 981 if (!NT_SUCCESS(Status)) 982 { 983 ERR("NtCreateKey failed for '%S' with status 0x%lx\n", 984 AttributeName, Status); 985 return Status; 986 } 987 988 Status = RtlpNtSetValueKey(AttributeKey, 989 REG_NONE, 990 AttributeData, 991 AttributeSize); 992 993 NtClose(AttributeKey); 994 995 if (!NT_SUCCESS(Status)) 996 { 997 ERR("RtlpNtSetValueKey failed for '%S' with status 0x%lx\n", 998 AttributeName, Status); 999 } 1000 1001 return Status; 1002 } 1003 1004 1005 NTSTATUS 1006 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject, 1007 LPWSTR AttributeName, 1008 LPVOID AttributeData, 1009 PULONG AttributeSize) 1010 { 1011 OBJECT_ATTRIBUTES ObjectAttributes; 1012 UNICODE_STRING KeyName; 1013 HANDLE AttributeKey; 1014 ULONG ValueSize; 1015 NTSTATUS Status; 1016 1017 RtlInitUnicodeString(&KeyName, 1018 AttributeName); 1019 1020 InitializeObjectAttributes(&ObjectAttributes, 1021 &KeyName, 1022 OBJ_CASE_INSENSITIVE, 1023 DbObject->KeyHandle, 1024 NULL); 1025 1026 Status = NtOpenKey(&AttributeKey, 1027 KEY_QUERY_VALUE, 1028 &ObjectAttributes); 1029 if (!NT_SUCCESS(Status)) 1030 { 1031 return Status; 1032 } 1033 1034 ValueSize = *AttributeSize; 1035 Status = RtlpNtQueryValueKey(AttributeKey, 1036 NULL, 1037 NULL, 1038 &ValueSize, 1039 0); 1040 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) 1041 { 1042 goto Done; 1043 } 1044 1045 if (AttributeData == NULL || *AttributeSize == 0) 1046 { 1047 *AttributeSize = ValueSize; 1048 Status = STATUS_SUCCESS; 1049 goto Done; 1050 } 1051 else if (*AttributeSize < ValueSize) 1052 { 1053 *AttributeSize = ValueSize; 1054 Status = STATUS_BUFFER_OVERFLOW; 1055 goto Done; 1056 } 1057 1058 Status = RtlpNtQueryValueKey(AttributeKey, 1059 NULL, 1060 AttributeData, 1061 &ValueSize, 1062 0); 1063 if (NT_SUCCESS(Status)) 1064 { 1065 *AttributeSize = ValueSize; 1066 } 1067 1068 Done: 1069 NtClose(AttributeKey); 1070 1071 return Status; 1072 } 1073 1074 1075 NTSTATUS 1076 LsapDeleteObjectAttribute(PLSA_DB_OBJECT DbObject, 1077 LPWSTR AttributeName) 1078 { 1079 return LsapRegDeleteSubKey(DbObject->KeyHandle, 1080 AttributeName); 1081 } 1082 1083 /* EOF */ 1084 1085