Changeset 988 for vendor/current/source4/kdc/db-glue.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/kdc/db-glue.c
r740 r988 33 33 #include "system/kerberos.h" 34 34 #include "auth/kerberos/kerberos.h" 35 #include <hdb.h>35 #include "kdc/sdb.h" 36 36 #include "kdc/samba_kdc.h" 37 #include "kdc/ kdc-policy.h"37 #include "kdc/db-glue.h" 38 38 39 39 #define SAMBA_KVNO_GET_KRBTGT(kvno) \ … … 66 66 }; 67 67 68 static KerberosTime ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, KerberosTime default_val) 68 69 static time_t ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, time_t default_val) 69 70 { 70 71 const char *tmp; … … 84 85 } 85 86 86 static HDBFlags uf2HDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type)87 static struct SDBFlags uf2SDBFlags(krb5_context context, uint32_t userAccountControl, enum samba_kdc_ent_type ent_type) 87 88 { 88 HDBFlags flags = int2HDBFlags(0);89 struct SDBFlags flags = int2SDBFlags(0); 89 90 90 91 /* we don't allow kadmin deletes */ … … 131 132 } 132 133 if (userAccountControl & UF_LOCKOUT) { 133 flags. invalid= 1;134 flags.locked_out = 1; 134 135 } 135 136 /* … … 158 159 flags.ok_as_delegate = 1; 159 160 } 161 if (userAccountControl & UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION) { 162 /* 163 * this is confusing... 164 * 165 * UF_TRUSTED_FOR_DELEGATION 166 * => ok_as_delegate 167 * 168 * and 169 * 170 * UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 171 * => trusted_for_delegation 172 */ 173 flags.trusted_for_delegation = 1; 174 } 160 175 if (!(userAccountControl & UF_NOT_DELEGATED)) { 161 176 flags.forwardable = 1; … … 174 189 static int samba_kdc_entry_destructor(struct samba_kdc_entry *p) 175 190 { 176 hdb_entry_ex *entry_ex = p->entry_ex; 177 free_hdb_entry(&entry_ex->entry); 178 return 0; 179 } 180 181 static void samba_kdc_free_entry(krb5_context context, hdb_entry_ex *entry_ex) 182 { 183 /* this function is called only from hdb_free_entry(). 184 * Make sure we neutralize the destructor or we will 185 * get a double free later when hdb_free_entry() will 186 * try to call free_hdb_entry() */ 187 talloc_set_destructor(entry_ex->ctx, NULL); 188 189 /* now proceed to free the talloc part */ 190 talloc_free(entry_ex->ctx); 191 if (p->entry_ex != NULL) { 192 struct sdb_entry_ex *entry_ex = p->entry_ex; 193 free_sdb_entry(&entry_ex->entry); 194 } 195 196 return 0; 191 197 } 192 198 … … 199 205 uint32_t userAccountControl, 200 206 enum samba_kdc_ent_type ent_type, 201 hdb_entry_ex *entry_ex)207 struct sdb_entry_ex *entry_ex) 202 208 { 203 209 krb5_error_code ret = 0; … … 359 365 if (kdc_db_ctx->rodc) { 360 366 /* We are on an RODC, but don't have keys for this account. Signal this to the caller */ 361 return HDB_ERR_NOT_FOUND_HERE; 367 /* TODO: We need to call a generalised version of auth_sam_trigger_repl_secret from here */ 368 return SDB_ERR_NOT_FOUND_HERE; 362 369 } 363 370 … … 370 377 /* allocate space to decode into */ 371 378 entry_ex->entry.keys.len = 0; 372 entry_ex->entry.keys.val = calloc(allocated_keys, sizeof( Key));379 entry_ex->entry.keys.val = calloc(allocated_keys, sizeof(struct sdb_key)); 373 380 if (entry_ex->entry.keys.val == NULL) { 374 381 ret = ENOMEM; … … 377 384 378 385 if (hash && (supported_enctypes & ENC_RC4_HMAC_MD5)) { 379 Key key; 380 381 key.mkvno = 0; 382 key.salt = NULL; /* No salt for this enc type */ 383 384 ret = krb5_keyblock_init(context, 385 ENCTYPE_ARCFOUR_HMAC, 386 hash->hash, sizeof(hash->hash), 387 &key.key); 386 struct sdb_key key = {}; 387 388 ret = smb_krb5_keyblock_init_contents(context, 389 ENCTYPE_ARCFOUR_HMAC, 390 hash->hash, 391 sizeof(hash->hash), 392 &key.key); 388 393 if (ret) { 389 394 goto out; … … 396 401 if (pkb4) { 397 402 for (i=0; i < pkb4->num_keys; i++) { 398 Key key;403 struct sdb_key key = {}; 399 404 400 405 if (!pkb4->keys[i].value) continue; … … 403 408 continue; 404 409 } 405 406 key.mkvno = 0;407 key.salt = NULL;408 410 409 411 if (pkb4->salt.string) { … … 418 420 } 419 421 420 key.salt->type = hdb_pw_salt; 421 422 ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length); 422 key.salt->type = KRB5_PW_SALT; 423 424 ret = krb5_copy_data_contents(&key.salt->salt, 425 salt.data, 426 salt.length); 423 427 if (ret) { 424 428 free(key.salt); … … 430 434 /* TODO: maybe pass the iteration_count somehow... */ 431 435 432 ret = krb5_keyblock_init(context,433 pkb4->keys[i].keytype,434 pkb4->keys[i].value->data,435 pkb4->keys[i].value->length,436 &key.key);436 ret = smb_krb5_keyblock_init_contents(context, 437 pkb4->keys[i].keytype, 438 pkb4->keys[i].value->data, 439 pkb4->keys[i].value->length, 440 &key.key); 437 441 if (ret == KRB5_PROG_ETYPE_NOSUPP) { 438 442 DEBUG(2,("Unsupported keytype ignored - type %u\n", … … 443 447 if (ret) { 444 448 if (key.salt) { 445 free_Salt(key.salt);449 kerberos_free_data_contents(context, &key.salt->salt); 446 450 free(key.salt); 447 451 key.salt = NULL; … … 455 459 } else if (pkb3) { 456 460 for (i=0; i < pkb3->num_keys; i++) { 457 Key key;461 struct sdb_key key = {}; 458 462 459 463 if (!pkb3->keys[i].value) continue; … … 462 466 continue; 463 467 } 464 465 key.mkvno = 0;466 key.salt = NULL;467 468 468 469 if (pkb3->salt.string) { … … 477 478 } 478 479 479 key.salt->type = hdb_pw_salt; 480 481 ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length); 480 key.salt->type = KRB5_PW_SALT; 481 482 ret = krb5_copy_data_contents(&key.salt->salt, 483 salt.data, 484 salt.length); 482 485 if (ret) { 483 486 free(key.salt); … … 487 490 } 488 491 489 ret = krb5_keyblock_init(context,490 pkb3->keys[i].keytype,491 pkb3->keys[i].value->data,492 pkb3->keys[i].value->length,493 &key.key);492 ret = smb_krb5_keyblock_init_contents(context, 493 pkb3->keys[i].keytype, 494 pkb3->keys[i].value->data, 495 pkb3->keys[i].value->length, 496 &key.key); 494 497 if (ret) { 495 498 if (key.salt) { 496 free_Salt(key.salt);499 kerberos_free_data_contents(context, &key.salt->salt); 497 500 free(key.salt); 498 501 key.salt = NULL; … … 515 518 } 516 519 return ret; 520 } 521 522 static int principal_comp_strcmp_int(krb5_context context, 523 krb5_const_principal principal, 524 unsigned int component, 525 const char *string, 526 bool do_strcasecmp) 527 { 528 const char *p; 529 size_t len; 530 531 #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) 532 p = krb5_principal_get_comp_string(context, principal, component); 533 if (p == NULL) { 534 return -1; 535 } 536 len = strlen(p); 537 #else 538 krb5_data *d; 539 if (component >= krb5_princ_size(context, principal)) { 540 return -1; 541 } 542 543 d = krb5_princ_component(context, principal, component); 544 if (d == NULL) { 545 return -1; 546 } 547 548 p = d->data; 549 len = d->length; 550 #endif 551 if (do_strcasecmp) { 552 return strncasecmp(p, string, len); 553 } else { 554 return strncmp(p, string, len); 555 } 556 } 557 558 static int principal_comp_strcasecmp(krb5_context context, 559 krb5_const_principal principal, 560 unsigned int component, 561 const char *string) 562 { 563 return principal_comp_strcmp_int(context, principal, 564 component, string, true); 565 } 566 567 static int principal_comp_strcmp(krb5_context context, 568 krb5_const_principal principal, 569 unsigned int component, 570 const char *string) 571 { 572 return principal_comp_strcmp_int(context, principal, 573 component, string, false); 517 574 } 518 575 … … 522 579 static krb5_error_code samba_kdc_message2entry(krb5_context context, 523 580 struct samba_kdc_db_context *kdc_db_ctx, 524 TALLOC_CTX *mem_ctx, krb5_const_principal principal, 581 TALLOC_CTX *mem_ctx, 582 krb5_const_principal principal, 525 583 enum samba_kdc_ent_type ent_type, 526 584 unsigned flags, 527 585 struct ldb_dn *realm_dn, 528 586 struct ldb_message *msg, 529 hdb_entry_ex *entry_ex)587 struct sdb_entry_ex *entry_ex) 530 588 { 531 589 struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; 532 590 uint32_t userAccountControl; 591 uint32_t msDS_User_Account_Control_Computed; 533 592 unsigned int i; 534 593 krb5_error_code ret = 0; … … 563 622 } 564 623 565 memset(entry_ex, 0, sizeof(*entry_ex));566 567 p = talloc (mem_ctx, struct samba_kdc_entry);624 ZERO_STRUCTP(entry_ex); 625 626 p = talloc_zero(mem_ctx, struct samba_kdc_entry); 568 627 if (!p) { 569 628 ret = ENOMEM; … … 572 631 573 632 p->kdc_db_ctx = kdc_db_ctx; 574 p->entry_ex = entry_ex;575 633 p->realm_dn = talloc_reference(p, realm_dn); 576 634 if (!p->realm_dn) { … … 581 639 talloc_set_destructor(p, samba_kdc_entry_destructor); 582 640 583 /* make sure we do not have bogus data in there */584 memset(&entry_ex->entry, 0, sizeof(hdb_entry));585 586 641 entry_ex->ctx = p; 587 entry_ex->free_entry = samba_kdc_free_entry;588 642 589 643 userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); 590 644 591 592 entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); 593 if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { 594 krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); 645 msDS_User_Account_Control_Computed 646 = ldb_msg_find_attr_as_uint(msg, 647 "msDS-User-Account-Control-Computed", 648 UF_ACCOUNTDISABLE); 649 650 /* 651 * This brings in the lockout flag, block the account if not 652 * found. We need the weird UF_ACCOUNTDISABLE check because 653 * we do not want to fail open if the value is not returned, 654 * but 0 is a valid value (all OK) 655 */ 656 if (msDS_User_Account_Control_Computed == UF_ACCOUNTDISABLE) { 657 ret = EINVAL; 658 krb5_set_error_message(context, ret, "samba_kdc_message2entry: " 659 "no msDS-User-Account-Control-Computed present"); 660 goto out; 595 661 } else { 596 ret = copy_Principal(principal, entry_ex->entry.principal); 662 userAccountControl |= msDS_User_Account_Control_Computed; 663 } 664 665 /* 666 * If we are set to canonicalize, we get back the fixed UPPER 667 * case realm, and the real username (ie matching LDAP 668 * samAccountName) 669 * 670 * Otherwise, if we are set to enterprise, we 671 * get back the whole principal as-sent 672 * 673 * Finally, if we are not set to canonicalize, we get back the 674 * fixed UPPER case realm, but the as-sent username 675 */ 676 677 if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { 678 if (flags & (SDB_F_CANON)) { 679 /* 680 * When requested to do so, ensure that the 681 * both realm values in the principal are set 682 * to the upper case, canonical realm 683 */ 684 ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, 685 lpcfg_realm(lp_ctx), "krbtgt", 686 lpcfg_realm(lp_ctx), NULL); 687 if (ret) { 688 krb5_clear_error_message(context); 689 goto out; 690 } 691 smb_krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST); 692 } else { 693 ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); 694 if (ret) { 695 krb5_clear_error_message(context); 696 goto out; 697 } 698 /* 699 * this appears to be required regardless of 700 * the canonicalize flag from the client 701 */ 702 ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); 703 if (ret) { 704 krb5_clear_error_message(context); 705 goto out; 706 } 707 } 708 709 } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { 710 ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); 597 711 if (ret) { 598 712 krb5_clear_error_message(context); 599 713 goto out; 600 714 } 601 602 /* While we have copied the client principal, tests 603 * show that Win2k3 returns the 'corrected' realm, not 604 * the client-specified realm. This code attempts to 605 * replace the client principal's realm with the one 606 * we determine from our records */ 607 608 /* this has to be with malloc() */ 609 krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); 715 } else if (flags & SDB_F_CANON && flags & SDB_F_FOR_AS_REQ) { 716 /* 717 * SDB_F_CANON maps from the canonicalize flag in the 718 * packet, and has a different meaning between AS-REQ 719 * and TGS-REQ. We only change the principal in the AS-REQ case 720 */ 721 ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); 722 if (ret) { 723 krb5_clear_error_message(context); 724 goto out; 725 } 726 } else { 727 ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); 728 if (ret) { 729 krb5_clear_error_message(context); 730 goto out; 731 } 732 733 if (smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) { 734 /* While we have copied the client principal, tests 735 * show that Win2k3 returns the 'corrected' realm, not 736 * the client-specified realm. This code attempts to 737 * replace the client principal's realm with the one 738 * we determine from our records */ 739 740 /* this has to be with malloc() */ 741 ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); 742 if (ret) { 743 krb5_clear_error_message(context); 744 goto out; 745 } 746 } 610 747 } 611 748 612 749 /* First try and figure out the flags based on the userAccountControl */ 613 entry_ex->entry.flags = uf2 HDBFlags(context, userAccountControl, ent_type);750 entry_ex->entry.flags = uf2SDBFlags(context, userAccountControl, ent_type); 614 751 615 752 /* Windows 2008 seems to enforce this (very sensible) rule by … … 624 761 } 625 762 } 626 627 if (flags & HDB_F_ADMIN_DATA) { 763 /* 764 * To give the correct type of error to the client, we must 765 * not just return the entry without .server set, we must 766 * pretend the principal does not exist. Otherwise we may 767 * return ERR_POLICY instead of 768 * KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 769 */ 770 if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && entry_ex->entry.flags.server == 0) { 771 ret = SDB_ERR_NOENTRY; 772 krb5_set_error_message(context, ret, "samba_kdc_message2entry: no servicePrincipalName present for this server, refusing with no-such-entry"); 773 goto out; 774 } 775 if (flags & SDB_F_ADMIN_DATA) { 628 776 /* These (created_by, modified_by) parts of the entry are not relevant for Samba4's use 629 777 * of the Heimdal KDC. They are stored in a the traditional … … 634 782 entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); 635 783 /* use 'kadmin' for now (needed by mit_samba) */ 636 krb5_make_principal(context, 637 &entry_ex->entry.created_by.principal, 638 lpcfg_realm(lp_ctx), "kadmin", NULL); 639 640 entry_ex->entry.modified_by = (Event *) malloc(sizeof(Event)); 784 785 ret = smb_krb5_make_principal(context, 786 &entry_ex->entry.created_by.principal, 787 lpcfg_realm(lp_ctx), "kadmin", NULL); 788 if (ret) { 789 krb5_clear_error_message(context); 790 goto out; 791 } 792 793 entry_ex->entry.modified_by = (struct sdb_event *) malloc(sizeof(struct sdb_event)); 641 794 if (entry_ex->entry.modified_by == NULL) { 642 795 ret = ENOMEM; … … 648 801 entry_ex->entry.modified_by->time = ldb_msg_find_krb5time_ldap_time(msg, "whenChanged", 0); 649 802 /* use 'kadmin' for now (needed by mit_samba) */ 650 krb5_make_principal(context, 651 &entry_ex->entry.modified_by->principal, 652 lpcfg_realm(lp_ctx), "kadmin", NULL); 803 ret = smb_krb5_make_principal(context, 804 &entry_ex->entry.modified_by->principal, 805 lpcfg_realm(lp_ctx), "kadmin", NULL); 806 if (ret) { 807 krb5_clear_error_message(context); 808 goto out; 809 } 653 810 } 654 811 … … 664 821 665 822 if (rid == DOMAIN_RID_KRBTGT) { 823 char *realm = NULL; 824 666 825 entry_ex->entry.valid_end = NULL; 667 826 entry_ex->entry.pw_end = NULL; … … 669 828 entry_ex->entry.flags.invalid = 0; 670 829 entry_ex->entry.flags.server = 1; 830 831 realm = smb_krb5_principal_get_realm(context, principal); 832 if (realm == NULL) { 833 ret = ENOMEM; 834 goto out; 835 } 671 836 672 837 /* Don't mark all requests for the krbtgt/realm as … … 675 840 * Instead, only do it when request is for the kpasswd service */ 676 841 if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER 677 && principal->name.name_string.len== 2678 && ( strcmp(principal->name.name_string.val[0], "kadmin") == 0)679 && ( strcmp(principal->name.name_string.val[1], "changepw") == 0)680 && lpcfg_is_my_domain_or_realm(lp_ctx, principal->realm)) {842 && krb5_princ_size(context, principal) == 2 843 && (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) 844 && (principal_comp_strcmp(context, principal, 1, "changepw") == 0) 845 && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { 681 846 entry_ex->entry.flags.change_pw = 1; 682 847 } 848 849 SAFE_FREE(realm); 850 683 851 entry_ex->entry.flags.client = 0; 684 852 entry_ex->entry.flags.forwardable = 1; … … 748 916 749 917 if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER) { 750 *entry_ex->entry.max_life = nt_time_to_unix(kdc_db_ctx->policy.service_tkt_lifetime);918 *entry_ex->entry.max_life = kdc_db_ctx->policy.svc_tkt_lifetime; 751 919 } else if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT || ent_type == SAMBA_KDC_ENT_TYPE_CLIENT) { 752 *entry_ex->entry.max_life = nt_time_to_unix(kdc_db_ctx->policy.user_tkt_lifetime);920 *entry_ex->entry.max_life = kdc_db_ctx->policy.usr_tkt_lifetime; 753 921 } else { 754 *entry_ex->entry.max_life = MIN( nt_time_to_unix(kdc_db_ctx->policy.service_tkt_lifetime),755 nt_time_to_unix(kdc_db_ctx->policy.user_tkt_lifetime));922 *entry_ex->entry.max_life = MIN(kdc_db_ctx->policy.svc_tkt_lifetime, 923 kdc_db_ctx->policy.usr_tkt_lifetime); 756 924 } 757 925 … … 762 930 } 763 931 764 *entry_ex->entry.max_renew = nt_time_to_unix(kdc_db_ctx->policy.user_tkt_renewaltime); 765 766 entry_ex->entry.generation = NULL; 932 *entry_ex->entry.max_renew = kdc_db_ctx->policy.renewal_lifetime; 767 933 768 934 /* Get keys from the db */ … … 771 937 ent_type, entry_ex); 772 938 if (ret) { 773 /* Could be bo ugus data in the entry, or out of memory */939 /* Could be bogus data in the entry, or out of memory */ 774 940 goto out; 775 941 } … … 789 955 } 790 956 for (i=0; i < entry_ex->entry.etypes->len; i++) { 791 entry_ex->entry.etypes->val[i] = entry_ex->entry.keys.val[i].key.keytype;957 entry_ex->entry.etypes->val[i] = KRB5_KEY_TYPE(&entry_ex->entry.keys.val[i].key); 792 958 } 793 959 … … 798 964 if (ret != 0) { 799 965 /* This doesn't free ent itself, that is for the eventual caller to do */ 800 hdb_free_entry(context, entry_ex); 966 sdb_free_entry(entry_ex); 967 ZERO_STRUCTP(entry_ex); 801 968 } else { 802 969 talloc_steal(kdc_db_ctx, entry_ex->ctx); … … 808 975 /* 809 976 * Construct an hdb_entry from a directory entry. 977 * The kvno is what the remote client asked for 810 978 */ 811 979 static krb5_error_code samba_kdc_trust_message2entry(krb5_context context, … … 814 982 enum trust_direction direction, 815 983 struct ldb_dn *realm_dn, 984 unsigned flags, 985 uint32_t kvno, 816 986 struct ldb_message *msg, 817 hdb_entry_ex *entry_ex)987 struct sdb_entry_ex *entry_ex) 818 988 { 819 989 struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; 820 const char *dnsdomain; 821 const char *realm = lpcfg_realm(lp_ctx); 822 DATA_BLOB password_utf16; 823 struct samr_Password password_hash; 990 const char *our_realm = lpcfg_realm(lp_ctx); 991 const char *dnsdomain = NULL; 992 char *partner_realm = NULL; 993 const char *realm = NULL; 994 const char *krbtgt_realm = NULL; 995 DATA_BLOB password_utf16 = data_blob_null; 996 DATA_BLOB password_utf8 = data_blob_null; 997 struct samr_Password _password_hash; 998 const struct samr_Password *password_hash = NULL; 824 999 const struct ldb_val *password_val; 825 1000 struct trustAuthInOutBlob password_blob; 826 1001 struct samba_kdc_entry *p; 827 1002 bool use_previous = false; 1003 uint32_t current_kvno; 1004 uint32_t previous_kvno; 1005 uint32_t num_keys = 0; 828 1006 enum ndr_err_code ndr_err; 829 1007 int ret, trust_direction_flags; 830 1008 unsigned int i; 1009 struct AuthenticationInformationArray *auth_array; 1010 struct timeval tv; 1011 NTTIME an_hour_ago; 1012 uint32_t *auth_kvno; 1013 bool preferr_current = false; 1014 uint32_t supported_enctypes = ENC_RC4_HMAC_MD5; 1015 1016 if (dsdb_functional_level(kdc_db_ctx->samdb) >= DS_DOMAIN_FUNCTION_2008) { 1017 supported_enctypes = ldb_msg_find_attr_as_uint(msg, 1018 "msDS-SupportedEncryptionTypes", 1019 supported_enctypes); 1020 } 1021 1022 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0); 1023 if (!(trust_direction_flags & direction)) { 1024 krb5_clear_error_message(context); 1025 ret = SDB_ERR_NOENTRY; 1026 goto out; 1027 } 1028 1029 dnsdomain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL); 1030 if (dnsdomain == NULL) { 1031 krb5_clear_error_message(context); 1032 ret = SDB_ERR_NOENTRY; 1033 goto out; 1034 } 1035 partner_realm = strupper_talloc(mem_ctx, dnsdomain); 1036 if (partner_realm == NULL) { 1037 krb5_clear_error_message(context); 1038 ret = ENOMEM; 1039 goto out; 1040 } 1041 1042 if (direction == INBOUND) { 1043 realm = our_realm; 1044 krbtgt_realm = partner_realm; 1045 1046 password_val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming"); 1047 } else { /* OUTBOUND */ 1048 realm = partner_realm; 1049 krbtgt_realm = our_realm; 1050 1051 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing"); 1052 } 1053 1054 if (password_val == NULL) { 1055 krb5_clear_error_message(context); 1056 ret = SDB_ERR_NOENTRY; 1057 goto out; 1058 } 1059 1060 ndr_err = ndr_pull_struct_blob(password_val, mem_ctx, &password_blob, 1061 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob); 1062 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 1063 krb5_clear_error_message(context); 1064 ret = EINVAL; 1065 goto out; 1066 } 831 1067 832 1068 p = talloc(mem_ctx, struct samba_kdc_entry); … … 837 1073 838 1074 p->kdc_db_ctx = kdc_db_ctx; 839 p->entry_ex = entry_ex;840 1075 p->realm_dn = realm_dn; 841 1076 … … 843 1078 844 1079 /* make sure we do not have bogus data in there */ 845 memset(&entry_ex->entry, 0, sizeof( hdb_entry));1080 memset(&entry_ex->entry, 0, sizeof(struct sdb_entry)); 846 1081 847 1082 entry_ex->ctx = p; 848 entry_ex->free_entry = samba_kdc_free_entry;849 1083 850 1084 /* use 'whenCreated' */ 851 1085 entry_ex->entry.created_by.time = ldb_msg_find_krb5time_ldap_time(msg, "whenCreated", 0); 852 1086 /* use 'kadmin' for now (needed by mit_samba) */ 853 krb5_make_principal(context, 854 &entry_ex->entry.created_by.principal, 855 realm, "kadmin", NULL); 856 857 entry_ex->entry.valid_start = NULL; 858 859 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0); 860 861 if (direction == INBOUND) { 862 password_val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming"); 863 864 } else { /* OUTBOUND */ 865 dnsdomain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL); 866 /* replace realm */ 867 realm = strupper_talloc(mem_ctx, dnsdomain); 868 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing"); 869 } 870 871 if (!password_val || !(trust_direction_flags & direction)) { 872 ret = ENOENT; 873 goto out; 874 } 875 876 ndr_err = ndr_pull_struct_blob(password_val, mem_ctx, &password_blob, 877 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob); 878 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 879 ret = EINVAL; 880 goto out; 881 } 882 883 entry_ex->entry.kvno = -1; 884 for (i=0; i < password_blob.count; i++) { 885 if (password_blob.current.array[i].AuthType == TRUST_AUTH_TYPE_VERSION) { 886 entry_ex->entry.kvno = password_blob.current.array[i].AuthInfo.version.version; 887 } 888 } 889 890 for (i=0; i < password_blob.count; i++) { 891 if (password_blob.current.array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) { 892 password_utf16 = data_blob_const(password_blob.current.array[i].AuthInfo.clear.password, 893 password_blob.current.array[i].AuthInfo.clear.size); 894 /* In the future, generate all sorts of 895 * hashes, but for now we can't safely convert 896 * the random strings windows uses into 897 * utf8 */ 898 899 /* but as it is utf16 already, we can get the NT password/arcfour-hmac-md5 key */ 900 mdfour(password_hash.hash, password_utf16.data, password_utf16.length); 901 break; 902 } else if (password_blob.current.array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) { 903 password_hash = password_blob.current.array[i].AuthInfo.nt4owf.password; 904 break; 905 } 906 } 907 908 if (i < password_blob.count) { 909 Key key; 910 /* Must have found a cleartext or MD4 password */ 911 entry_ex->entry.keys.val = calloc(1, sizeof(Key)); 912 913 key.mkvno = 0; 914 key.salt = NULL; /* No salt for this enc type */ 915 916 if (entry_ex->entry.keys.val == NULL) { 917 ret = ENOMEM; 918 goto out; 919 } 920 921 ret = krb5_keyblock_init(context, 922 ENCTYPE_ARCFOUR_HMAC, 923 password_hash.hash, sizeof(password_hash.hash), 924 &key.key); 925 926 entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; 927 entry_ex->entry.keys.len++; 928 } 929 930 entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); 931 932 ret = copy_Principal(principal, entry_ex->entry.principal); 1087 ret = smb_krb5_make_principal(context, 1088 &entry_ex->entry.created_by.principal, 1089 realm, "kadmin", NULL); 933 1090 if (ret) { 934 1091 krb5_clear_error_message(context); … … 936 1093 } 937 1094 938 /* While we have copied the client principal, tests 939 * show that Win2k3 returns the 'corrected' realm, not 940 * the client-specified realm. This code attempts to 941 * replace the client principal's realm with the one 942 * we determine from our records */ 943 944 krb5_principal_set_realm(context, entry_ex->entry.principal, realm); 945 entry_ex->entry.flags = int2HDBFlags(0); 1095 /* 1096 * We always need to generate the canonicalized principal 1097 * with the values of our database. 1098 */ 1099 ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, realm, 1100 "krbtgt", krbtgt_realm, NULL); 1101 if (ret) { 1102 krb5_clear_error_message(context); 1103 goto out; 1104 } 1105 smb_krb5_principal_set_type(context, entry_ex->entry.principal, 1106 KRB5_NT_SRV_INST); 1107 1108 entry_ex->entry.valid_start = NULL; 1109 1110 /* we need to work out if we are going to use the current or 1111 * the previous password hash. 1112 * We base this on the kvno the client passes in. If the kvno 1113 * passed in is equal to the current kvno in our database then 1114 * we use the current structure. If it is the current kvno-1, 1115 * then we use the previous substrucure. 1116 */ 1117 1118 /* 1119 * Windows preferrs the previous key for one hour. 1120 */ 1121 tv = timeval_current(); 1122 if (tv.tv_sec > 3600) { 1123 tv.tv_sec -= 3600; 1124 } 1125 an_hour_ago = timeval_to_nttime(&tv); 1126 1127 /* first work out the current kvno */ 1128 current_kvno = 0; 1129 for (i=0; i < password_blob.count; i++) { 1130 struct AuthenticationInformation *a = 1131 &password_blob.current.array[i]; 1132 1133 if (a->LastUpdateTime <= an_hour_ago) { 1134 preferr_current = true; 1135 } 1136 1137 if (a->AuthType == TRUST_AUTH_TYPE_VERSION) { 1138 current_kvno = a->AuthInfo.version.version; 1139 } 1140 } 1141 if (current_kvno == 0) { 1142 previous_kvno = 255; 1143 } else { 1144 previous_kvno = current_kvno - 1; 1145 } 1146 for (i=0; i < password_blob.count; i++) { 1147 struct AuthenticationInformation *a = 1148 &password_blob.previous.array[i]; 1149 1150 if (a->AuthType == TRUST_AUTH_TYPE_VERSION) { 1151 previous_kvno = a->AuthInfo.version.version; 1152 } 1153 } 1154 1155 /* work out whether we will use the previous or current 1156 password */ 1157 if (password_blob.previous.count == 0) { 1158 /* there is no previous password */ 1159 use_previous = false; 1160 } else if (!(flags & SDB_F_KVNO_SPECIFIED)) { 1161 /* 1162 * If not specified we use the lowest kvno 1163 * for the first hour after an update. 1164 */ 1165 if (preferr_current) { 1166 use_previous = false; 1167 } else if (previous_kvno < current_kvno) { 1168 use_previous = true; 1169 } else { 1170 use_previous = false; 1171 } 1172 } else if (kvno == current_kvno) { 1173 /* 1174 * Exact match ... 1175 */ 1176 use_previous = false; 1177 } else if (kvno == previous_kvno) { 1178 /* 1179 * Exact match ... 1180 */ 1181 use_previous = true; 1182 } else { 1183 /* 1184 * Fallback to the current one for anything else 1185 */ 1186 use_previous = false; 1187 } 1188 1189 if (use_previous) { 1190 auth_array = &password_blob.previous; 1191 auth_kvno = &previous_kvno; 1192 } else { 1193 auth_array = &password_blob.current; 1194 auth_kvno = ¤t_kvno; 1195 } 1196 1197 /* use the kvno the client specified, if available */ 1198 if (flags & SDB_F_KVNO_SPECIFIED) { 1199 entry_ex->entry.kvno = kvno; 1200 } else { 1201 entry_ex->entry.kvno = *auth_kvno; 1202 } 1203 1204 for (i=0; i < auth_array->count; i++) { 1205 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) { 1206 bool ok; 1207 1208 password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password, 1209 auth_array->array[i].AuthInfo.clear.size); 1210 if (password_utf16.length == 0) { 1211 break; 1212 } 1213 1214 if (supported_enctypes & ENC_RC4_HMAC_MD5) { 1215 mdfour(_password_hash.hash, password_utf16.data, password_utf16.length); 1216 if (password_hash == NULL) { 1217 num_keys += 1; 1218 } 1219 password_hash = &_password_hash; 1220 } 1221 1222 if (!(supported_enctypes & (ENC_HMAC_SHA1_96_AES128|ENC_HMAC_SHA1_96_AES256))) { 1223 break; 1224 } 1225 1226 ok = convert_string_talloc(mem_ctx, 1227 CH_UTF16MUNGED, CH_UTF8, 1228 password_utf16.data, 1229 password_utf16.length, 1230 (void *)&password_utf8.data, 1231 &password_utf8.length); 1232 if (!ok) { 1233 krb5_clear_error_message(context); 1234 ret = ENOMEM; 1235 goto out; 1236 } 1237 1238 if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { 1239 num_keys += 1; 1240 } 1241 if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { 1242 num_keys += 1; 1243 } 1244 break; 1245 } else if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_NT4OWF) { 1246 if (supported_enctypes & ENC_RC4_HMAC_MD5) { 1247 password_hash = &auth_array->array[i].AuthInfo.nt4owf.password; 1248 num_keys += 1; 1249 } 1250 } 1251 } 1252 1253 /* Must have found a cleartext or MD4 password */ 1254 if (num_keys == 0) { 1255 DEBUG(1,(__location__ ": no usable key found\n")); 1256 krb5_clear_error_message(context); 1257 ret = SDB_ERR_NOENTRY; 1258 goto out; 1259 } 1260 1261 entry_ex->entry.keys.val = calloc(num_keys, sizeof(struct sdb_key)); 1262 if (entry_ex->entry.keys.val == NULL) { 1263 krb5_clear_error_message(context); 1264 ret = ENOMEM; 1265 goto out; 1266 } 1267 1268 if (password_utf8.length != 0) { 1269 struct sdb_key key = {}; 1270 krb5_const_principal salt_principal = entry_ex->entry.principal; 1271 krb5_data salt; 1272 krb5_data cleartext_data; 1273 1274 cleartext_data.data = discard_const_p(char, password_utf8.data); 1275 cleartext_data.length = password_utf8.length; 1276 1277 ret = smb_krb5_get_pw_salt(context, 1278 salt_principal, 1279 &salt); 1280 if (ret != 0) { 1281 goto out; 1282 } 1283 1284 if (supported_enctypes & ENC_HMAC_SHA1_96_AES256) { 1285 ret = smb_krb5_create_key_from_string(context, 1286 salt_principal, 1287 &salt, 1288 &cleartext_data, 1289 ENCTYPE_AES256_CTS_HMAC_SHA1_96, 1290 &key.key); 1291 if (ret != 0) { 1292 kerberos_free_data_contents(context, &salt); 1293 goto out; 1294 } 1295 1296 entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; 1297 entry_ex->entry.keys.len++; 1298 } 1299 1300 if (supported_enctypes & ENC_HMAC_SHA1_96_AES128) { 1301 ret = smb_krb5_create_key_from_string(context, 1302 salt_principal, 1303 &salt, 1304 &cleartext_data, 1305 ENCTYPE_AES128_CTS_HMAC_SHA1_96, 1306 &key.key); 1307 if (ret != 0) { 1308 kerberos_free_data_contents(context, &salt); 1309 goto out; 1310 } 1311 1312 entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; 1313 entry_ex->entry.keys.len++; 1314 } 1315 1316 kerberos_free_data_contents(context, &salt); 1317 } 1318 1319 if (password_hash != NULL) { 1320 struct sdb_key key = {}; 1321 1322 ret = smb_krb5_keyblock_init_contents(context, 1323 ENCTYPE_ARCFOUR_HMAC, 1324 password_hash->hash, 1325 sizeof(password_hash->hash), 1326 &key.key); 1327 if (ret != 0) { 1328 goto out; 1329 } 1330 1331 entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; 1332 entry_ex->entry.keys.len++; 1333 } 1334 1335 entry_ex->entry.flags = int2SDBFlags(0); 946 1336 entry_ex->entry.flags.immutable = 1; 947 1337 entry_ex->entry.flags.invalid = 0; … … 954 1344 955 1345 entry_ex->entry.max_renew = NULL; 956 957 entry_ex->entry.generation = NULL;958 1346 959 1347 entry_ex->entry.etypes = malloc(sizeof(*(entry_ex->entry.etypes))); … … 971 1359 } 972 1360 for (i=0; i < entry_ex->entry.etypes->len; i++) { 973 entry_ex->entry.etypes->val[i] = entry_ex->entry.keys.val[i].key.keytype; 974 } 975 1361 entry_ex->entry.etypes->val[i] = KRB5_KEY_TYPE(&entry_ex->entry.keys.val[i].key); 1362 } 976 1363 977 1364 p->msg = talloc_steal(p, msg); 978 1365 979 1366 out: 1367 TALLOC_FREE(partner_realm); 1368 980 1369 if (ret != 0) { 981 1370 /* This doesn't free ent itself, that is for the eventual caller to do */ 982 hdb_free_entry(context,entry_ex);1371 sdb_free_entry(entry_ex); 983 1372 } else { 984 1373 talloc_steal(kdc_db_ctx, entry_ex->ctx); … … 995 1384 struct ldb_message **pmsg) 996 1385 { 997 int lret; 998 krb5_error_code ret; 999 char *filter = NULL; 1386 NTSTATUS status; 1000 1387 const char * const *attrs = trust_attrs; 1001 1388 1002 struct ldb_result *res = NULL; 1003 filter = talloc_asprintf(mem_ctx, "(&(objectClass=trustedDomain)(|(flatname=%s)(trustPartner=%s)))", realm, realm); 1004 1005 if (!filter) { 1006 ret = ENOMEM; 1007 krb5_set_error_message(context, ret, "talloc_asprintf: out of memory"); 1389 status = dsdb_trust_search_tdo(ldb_ctx, realm, realm, 1390 attrs, mem_ctx, pmsg); 1391 if (NT_STATUS_IS_OK(status)) { 1392 return 0; 1393 } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { 1394 return SDB_ERR_NOENTRY; 1395 } else if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) { 1396 int ret = ENOMEM; 1397 krb5_set_error_message(context, ret, "get_sam_result_trust: out of memory"); 1008 1398 return ret; 1009 } 1010 1011 lret = ldb_search(ldb_ctx, mem_ctx, &res, 1012 ldb_get_default_basedn(ldb_ctx), 1013 LDB_SCOPE_SUBTREE, attrs, "%s", filter); 1014 if (lret != LDB_SUCCESS) { 1015 DEBUG(3, ("Failed to search for %s: %s\n", filter, ldb_errstring(ldb_ctx))); 1016 return HDB_ERR_NOENTRY; 1017 } else if (res->count == 0 || res->count > 1) { 1018 DEBUG(3, ("Failed find a single entry for %s: got %d\n", filter, res->count)); 1019 talloc_free(res); 1020 return HDB_ERR_NOENTRY; 1021 } 1022 talloc_steal(mem_ctx, res->msgs); 1023 *pmsg = res->msgs[0]; 1024 talloc_free(res); 1025 return 0; 1399 } else { 1400 int ret = EINVAL; 1401 krb5_set_error_message(context, ret, "get_sam_result_trust: %s", nt_errstr(status)); 1402 return ret; 1403 } 1026 1404 } 1027 1405 … … 1032 1410 const char **attrs, 1033 1411 struct ldb_dn **realm_dn, 1034 struct ldb_message **msg) { 1412 struct ldb_message **msg) 1413 { 1035 1414 NTSTATUS nt_status; 1036 char *principal_string; 1037 krb5_error_code ret; 1038 1039 ret = krb5_unparse_name(context, principal, &principal_string); 1040 1041 if (ret != 0) { 1042 return ret; 1415 char *principal_string = NULL; 1416 1417 if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { 1418 principal_string = smb_krb5_principal_get_comp_string(mem_ctx, context, 1419 principal, 0); 1420 if (principal_string == NULL) { 1421 return ENOMEM; 1422 } 1423 } else { 1424 char *principal_string_m = NULL; 1425 krb5_error_code ret; 1426 1427 ret = krb5_unparse_name(context, principal, &principal_string_m); 1428 if (ret != 0) { 1429 return ret; 1430 } 1431 1432 principal_string = talloc_strdup(mem_ctx, principal_string_m); 1433 SAFE_FREE(principal_string_m); 1434 if (principal_string == NULL) { 1435 return ENOMEM; 1436 } 1043 1437 } 1044 1438 … … 1046 1440 mem_ctx, principal_string, attrs, 1047 1441 realm_dn, msg); 1048 free(principal_string);1049 1442 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { 1050 return HDB_ERR_NOENTRY; 1443 krb5_principal fallback_principal = NULL; 1444 unsigned int num_comp; 1445 char *fallback_realm = NULL; 1446 char *fallback_account = NULL; 1447 krb5_error_code ret; 1448 1449 ret = krb5_parse_name(context, principal_string, 1450 &fallback_principal); 1451 TALLOC_FREE(principal_string); 1452 if (ret != 0) { 1453 return ret; 1454 } 1455 1456 num_comp = krb5_princ_size(context, fallback_principal); 1457 fallback_realm = smb_krb5_principal_get_realm(context, 1458 fallback_principal); 1459 if (fallback_realm == NULL) { 1460 krb5_free_principal(context, fallback_principal); 1461 return ENOMEM; 1462 } 1463 1464 if (num_comp == 1) { 1465 size_t len; 1466 1467 fallback_account = smb_krb5_principal_get_comp_string(mem_ctx, 1468 context, fallback_principal, 0); 1469 if (fallback_account == NULL) { 1470 krb5_free_principal(context, fallback_principal); 1471 SAFE_FREE(fallback_realm); 1472 return ENOMEM; 1473 } 1474 1475 len = strlen(fallback_account); 1476 if (len >= 2 && fallback_account[len - 1] == '$') { 1477 TALLOC_FREE(fallback_account); 1478 } 1479 } 1480 krb5_free_principal(context, fallback_principal); 1481 fallback_principal = NULL; 1482 1483 if (fallback_account != NULL) { 1484 char *with_dollar; 1485 1486 with_dollar = talloc_asprintf(mem_ctx, "%s$", 1487 fallback_account); 1488 if (with_dollar == NULL) { 1489 SAFE_FREE(fallback_realm); 1490 return ENOMEM; 1491 } 1492 TALLOC_FREE(fallback_account); 1493 1494 ret = smb_krb5_make_principal(context, 1495 &fallback_principal, 1496 fallback_realm, 1497 with_dollar, NULL); 1498 TALLOC_FREE(with_dollar); 1499 if (ret != 0) { 1500 SAFE_FREE(fallback_realm); 1501 return ret; 1502 } 1503 } 1504 SAFE_FREE(fallback_realm); 1505 1506 if (fallback_principal != NULL) { 1507 char *fallback_string = NULL; 1508 1509 ret = krb5_unparse_name(context, 1510 fallback_principal, 1511 &fallback_string); 1512 if (ret != 0) { 1513 krb5_free_principal(context, fallback_principal); 1514 return ret; 1515 } 1516 1517 nt_status = sam_get_results_principal(kdc_db_ctx->samdb, 1518 mem_ctx, 1519 fallback_string, 1520 attrs, 1521 realm_dn, msg); 1522 SAFE_FREE(fallback_string); 1523 } 1524 krb5_free_principal(context, fallback_principal); 1525 fallback_principal = NULL; 1526 } 1527 TALLOC_FREE(principal_string); 1528 1529 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { 1530 return SDB_ERR_NOENTRY; 1051 1531 } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MEMORY)) { 1052 1532 return ENOMEM; … … 1055 1535 } 1056 1536 1057 return ret;1537 return 0; 1058 1538 } 1059 1539 … … 1063 1543 krb5_const_principal principal, 1064 1544 unsigned flags, 1065 hdb_entry_ex *entry_ex) {1545 struct sdb_entry_ex *entry_ex) { 1066 1546 struct ldb_dn *realm_dn; 1067 1547 krb5_error_code ret; … … 1069 1549 1070 1550 ret = samba_kdc_lookup_client(context, kdc_db_ctx, 1071 1072 1551 mem_ctx, principal, user_attrs, 1552 &realm_dn, &msg); 1073 1553 if (ret != 0) { 1074 1554 return ret; … … 1087 1567 krb5_const_principal principal, 1088 1568 unsigned flags, 1089 uint32_t k rbtgt_number,1090 hdb_entry_ex *entry_ex)1569 uint32_t kvno, 1570 struct sdb_entry_ex *entry_ex) 1091 1571 { 1092 1572 struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; … … 1094 1574 struct ldb_message *msg = NULL; 1095 1575 struct ldb_dn *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); 1096 1097 krb5_principal alloc_principal = NULL; 1098 if (principal->name.name_string.len != 2 1099 || (strcmp(principal->name.name_string.val[0], KRB5_TGS_NAME) != 0)) { 1576 char *realm_from_princ, *realm_from_princ_malloc; 1577 char *realm_princ_comp = smb_krb5_principal_get_comp_string(mem_ctx, context, principal, 1); 1578 1579 realm_from_princ_malloc = smb_krb5_principal_get_realm(context, principal); 1580 if (realm_from_princ_malloc == NULL) { 1581 /* can't happen */ 1582 return SDB_ERR_NOENTRY; 1583 } 1584 realm_from_princ = talloc_strdup(mem_ctx, realm_from_princ_malloc); 1585 free(realm_from_princ_malloc); 1586 if (realm_from_princ == NULL) { 1587 return SDB_ERR_NOENTRY; 1588 } 1589 1590 if (krb5_princ_size(context, principal) != 2 1591 || (principal_comp_strcmp(context, principal, 0, KRB5_TGS_NAME) != 0)) { 1100 1592 /* Not a krbtgt */ 1101 return HDB_ERR_NOENTRY;1593 return SDB_ERR_NOENTRY; 1102 1594 } 1103 1595 1104 1596 /* krbtgt case. Either us or a trusted realm */ 1105 1597 1106 if (lpcfg_is_my_domain_or_realm(lp_ctx, principal->realm)1107 && lpcfg_is_my_domain_or_realm(lp_ctx, principal->name.name_string.val[1])) {1598 if (lpcfg_is_my_domain_or_realm(lp_ctx, realm_from_princ) 1599 && lpcfg_is_my_domain_or_realm(lp_ctx, realm_princ_comp)) { 1108 1600 /* us, or someone quite like us */ 1109 1601 /* Cludge, cludge cludge. If the realm part of krbtgt/realm, … … 1112 1604 1113 1605 int lret; 1606 unsigned int krbtgt_number; 1607 /* w2k8r2 sometimes gives us a kvno of 255 for inter-domain 1608 trust tickets. We don't yet know what this means, but we do 1609 seem to need to treat it as unspecified */ 1610 if (flags & SDB_F_KVNO_SPECIFIED) { 1611 krbtgt_number = SAMBA_KVNO_GET_KRBTGT(kvno); 1612 if (kdc_db_ctx->rodc) { 1613 if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) { 1614 return SDB_ERR_NOT_FOUND_HERE; 1615 } 1616 } 1617 } else { 1618 krbtgt_number = kdc_db_ctx->my_krbtgt_number; 1619 } 1114 1620 1115 1621 if (krbtgt_number == kdc_db_ctx->my_krbtgt_number) { 1116 1622 lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx, 1117 1623 &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE, 1118 krbtgt_attrs, 0,1624 krbtgt_attrs, DSDB_SEARCH_NO_GLOBAL_CATALOG, 1119 1625 "(objectClass=user)"); 1120 1626 } else { … … 1125 1631 &msg, realm_dn, LDB_SCOPE_SUBTREE, 1126 1632 krbtgt_attrs, 1127 DSDB_SEARCH_SHOW_EXTENDED_DN ,1633 DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG, 1128 1634 "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=%u))", (unsigned)(krbtgt_number)); 1129 1635 } … … 1132 1638 krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!", 1133 1639 (unsigned)(krbtgt_number)); 1134 krb5_set_error_message(context, HDB_ERR_NOENTRY,1640 krb5_set_error_message(context, SDB_ERR_NOENTRY, 1135 1641 "samba_kdc_fetch: could not find KRBTGT number %u in DB!", 1136 1642 (unsigned)(krbtgt_number)); 1137 return HDB_ERR_NOENTRY;1643 return SDB_ERR_NOENTRY; 1138 1644 } else if (lret != LDB_SUCCESS) { 1139 1645 krb5_warnx(context, "samba_kdc_fetch: could not find KRBTGT number %u in DB!", 1140 1646 (unsigned)(krbtgt_number)); 1141 krb5_set_error_message(context, HDB_ERR_NOENTRY,1647 krb5_set_error_message(context, SDB_ERR_NOENTRY, 1142 1648 "samba_kdc_fetch: could not find KRBTGT number %u in DB!", 1143 1649 (unsigned)(krbtgt_number)); 1144 return HDB_ERR_NOENTRY; 1145 } 1146 1147 if (flags & HDB_F_CANON) { 1148 ret = krb5_copy_principal(context, principal, &alloc_principal); 1149 if (ret) { 1150 return ret; 1151 } 1152 1153 /* When requested to do so, ensure that the 1154 * both realm values in the principal are set 1155 * to the upper case, canonical realm */ 1156 free(alloc_principal->name.name_string.val[1]); 1157 alloc_principal->name.name_string.val[1] = strdup(lpcfg_realm(lp_ctx)); 1158 if (!alloc_principal->name.name_string.val[1]) { 1159 ret = ENOMEM; 1160 krb5_set_error_message(context, ret, "samba_kdc_fetch: strdup() failed!"); 1161 return ret; 1162 } 1163 principal = alloc_principal; 1650 return SDB_ERR_NOENTRY; 1164 1651 } 1165 1652 … … 1167 1654 principal, SAMBA_KDC_ENT_TYPE_KRBTGT, 1168 1655 flags, realm_dn, msg, entry_ex); 1169 if (flags & HDB_F_CANON) {1170 /* This is again copied in the message2entry call */1171 krb5_free_principal(context, alloc_principal);1172 }1173 1656 if (ret != 0) { 1174 1657 krb5_warnx(context, "samba_kdc_fetch: self krbtgt message2entry failed"); … … 1182 1665 /* Either an inbound or outbound trust */ 1183 1666 1184 if (strcasecmp(lpcfg_realm(lp_ctx), principal->realm) == 0) {1667 if (strcasecmp(lpcfg_realm(lp_ctx), realm_from_princ) == 0) { 1185 1668 /* look for inbound trust */ 1186 1669 direction = INBOUND; 1187 realm = principal->name.name_string.val[1];1188 } else if ( strcasecmp(lpcfg_realm(lp_ctx), principal->name.name_string.val[1]) == 0) {1670 realm = realm_princ_comp; 1671 } else if (principal_comp_strcasecmp(context, principal, 1, lpcfg_realm(lp_ctx)) == 0) { 1189 1672 /* look for outbound trust */ 1190 1673 direction = OUTBOUND; 1191 realm = principal->realm;1674 realm = realm_from_princ; 1192 1675 } else { 1193 1676 krb5_warnx(context, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')", 1194 principal->realm, principal->name.name_string.val[1]); 1195 krb5_set_error_message(context, HDB_ERR_NOENTRY, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')", 1196 principal->realm, principal->name.name_string.val[1]); 1197 return HDB_ERR_NOENTRY; 1677 realm_from_princ, 1678 realm_princ_comp); 1679 krb5_set_error_message(context, SDB_ERR_NOENTRY, "samba_kdc_fetch: not our realm for trusts ('%s', '%s')", 1680 realm_from_princ, 1681 realm_princ_comp); 1682 return SDB_ERR_NOENTRY; 1198 1683 } 1199 1684 … … 1211 1696 1212 1697 ret = samba_kdc_trust_message2entry(context, kdc_db_ctx, mem_ctx, 1213 1214 realm_dn, msg, entry_ex);1698 principal, direction, 1699 realm_dn, flags, kvno, msg, entry_ex); 1215 1700 if (ret != 0) { 1216 krb5_warnx(context, "samba_kdc_fetch: trust_message2entry failed"); 1701 krb5_warnx(context, "samba_kdc_fetch: trust_message2entry failed for %s", 1702 ldb_dn_get_linearized(msg->dn)); 1703 krb5_set_error_message(context, ret, "samba_kdc_fetch: " 1704 "trust_message2entry failed for %s", 1705 ldb_dn_get_linearized(msg->dn)); 1217 1706 } 1218 1707 return ret; … … 1222 1711 1223 1712 static krb5_error_code samba_kdc_lookup_server(krb5_context context, 1224 struct samba_kdc_db_context *kdc_db_ctx, 1225 TALLOC_CTX *mem_ctx, 1226 krb5_const_principal principal, 1227 const char **attrs, 1228 struct ldb_dn **realm_dn, 1229 struct ldb_message **msg) 1713 struct samba_kdc_db_context *kdc_db_ctx, 1714 TALLOC_CTX *mem_ctx, 1715 krb5_const_principal principal, 1716 unsigned flags, 1717 const char **attrs, 1718 struct ldb_dn **realm_dn, 1719 struct ldb_message **msg) 1230 1720 { 1231 1721 krb5_error_code ret; 1232 if (principal->name.name_string.len >= 2) { 1722 if ((smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) 1723 && krb5_princ_size(context, principal) >= 2) { 1233 1724 /* 'normal server' case */ 1234 1725 int ldb_ret; … … 1253 1744 1254 1745 if (!NT_STATUS_IS_OK(nt_status)) { 1255 return HDB_ERR_NOENTRY;1746 return SDB_ERR_NOENTRY; 1256 1747 } 1257 1748 … … 1259 1750 mem_ctx, 1260 1751 msg, user_dn, LDB_SCOPE_BASE, 1261 attrs, DSDB_SEARCH_SHOW_EXTENDED_DN, "(objectClass=*)"); 1752 attrs, 1753 DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG, 1754 "(objectClass=*)"); 1262 1755 if (ldb_ret != LDB_SUCCESS) { 1263 return HDB_ERR_NOENTRY; 1264 } 1265 1756 return SDB_ERR_NOENTRY; 1757 } 1758 return 0; 1759 } else if (!(flags & SDB_F_FOR_AS_REQ) 1760 && smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { 1761 /* 1762 * The behaviour of accepting an 1763 * KRB5_NT_ENTERPRISE_PRINCIPAL server principal 1764 * containing a UPN only applies to TGS-REQ packets, 1765 * not AS-REQ packets. 1766 */ 1767 return samba_kdc_lookup_client(context, kdc_db_ctx, 1768 mem_ctx, principal, attrs, 1769 realm_dn, msg); 1266 1770 } else { 1771 /* 1772 * This case is for: 1773 * - the AS-REQ, where we only accept 1774 * samAccountName based lookups for the server, no 1775 * matter if the name is an 1776 * KRB5_NT_ENTERPRISE_PRINCIPAL or not 1777 * - for the TGS-REQ when we are not given an 1778 * KRB5_NT_ENTERPRISE_PRINCIPAL, which also must 1779 * only lookup samAccountName based names. 1780 */ 1267 1781 int lret; 1782 char *short_princ; 1783 krb5_principal enterprise_principal = NULL; 1784 krb5_const_principal used_principal = NULL; 1785 char *name1 = NULL; 1786 size_t len1 = 0; 1268 1787 char *filter = NULL; 1269 char *short_princ; 1270 const char *realm; 1788 1789 if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { 1790 char *str = NULL; 1791 /* Need to reparse the enterprise principal to find the real target */ 1792 if (krb5_princ_size(context, principal) != 1) { 1793 ret = KRB5_PARSE_MALFORMED; 1794 krb5_set_error_message(context, ret, "samba_kdc_lookup_server: request for an " 1795 "enterprise principal with wrong (%d) number of components", 1796 krb5_princ_size(context, principal)); 1797 return ret; 1798 } 1799 str = smb_krb5_principal_get_comp_string(mem_ctx, context, principal, 0); 1800 if (str == NULL) { 1801 return KRB5_PARSE_MALFORMED; 1802 } 1803 ret = krb5_parse_name(context, str, 1804 &enterprise_principal); 1805 talloc_free(str); 1806 if (ret) { 1807 return ret; 1808 } 1809 used_principal = enterprise_principal; 1810 } else { 1811 used_principal = principal; 1812 } 1813 1271 1814 /* server as client principal case, but we must not lookup userPrincipalNames */ 1272 1815 *realm_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); 1273 realm = krb5_principal_get_realm(context, principal); 1274 1275 /* TODO: Check if it is our realm, otherwise give referall */ 1276 1277 ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ); 1816 1817 /* TODO: Check if it is our realm, otherwise give referral */ 1818 1819 ret = krb5_unparse_name_flags(context, used_principal, 1820 KRB5_PRINCIPAL_UNPARSE_NO_REALM | 1821 KRB5_PRINCIPAL_UNPARSE_DISPLAY, 1822 &short_princ); 1823 used_principal = NULL; 1824 krb5_free_principal(context, enterprise_principal); 1825 enterprise_principal = NULL; 1278 1826 1279 1827 if (ret != 0) { … … 1283 1831 } 1284 1832 1833 name1 = ldb_binary_encode_string(mem_ctx, short_princ); 1834 SAFE_FREE(short_princ); 1835 if (name1 == NULL) { 1836 return ENOMEM; 1837 } 1838 len1 = strlen(name1); 1839 if (len1 >= 1 && name1[len1 - 1] != '$') { 1840 filter = talloc_asprintf(mem_ctx, 1841 "(&(objectClass=user)(|(samAccountName=%s)(samAccountName=%s$)))", 1842 name1, name1); 1843 if (filter == NULL) { 1844 return ENOMEM; 1845 } 1846 } else { 1847 filter = talloc_asprintf(mem_ctx, 1848 "(&(objectClass=user)(samAccountName=%s))", 1849 name1); 1850 if (filter == NULL) { 1851 return ENOMEM; 1852 } 1853 } 1854 1285 1855 lret = dsdb_search_one(kdc_db_ctx->samdb, mem_ctx, msg, 1286 1856 *realm_dn, LDB_SCOPE_SUBTREE, 1287 1857 attrs, 1288 DSDB_SEARCH_SHOW_EXTENDED_DN, 1289 "(&(objectClass=user)(samAccountName=%s))", 1290 ldb_binary_encode_string(mem_ctx, short_princ)); 1291 free(short_princ); 1858 DSDB_SEARCH_SHOW_EXTENDED_DN | DSDB_SEARCH_NO_GLOBAL_CATALOG, 1859 "%s", filter); 1292 1860 if (lret == LDB_ERR_NO_SUCH_OBJECT) { 1293 DEBUG(3, ("Failed find a entry for %s\n", filter)); 1294 return HDB_ERR_NOENTRY; 1861 DEBUG(10, ("Failed to find an entry for %s filter:%s\n", 1862 name1, filter)); 1863 return SDB_ERR_NOENTRY; 1864 } 1865 if (lret == LDB_ERR_CONSTRAINT_VIOLATION) { 1866 DEBUG(10, ("Failed to find unique entry for %s filter:%s\n", 1867 name1, filter)); 1868 return SDB_ERR_NOENTRY; 1295 1869 } 1296 1870 if (lret != LDB_SUCCESS) { 1297 DEBUG( 3, ("Failed single search forfor %s - %s\n",1298 filter, ldb_errstring(kdc_db_ctx->samdb)));1299 return HDB_ERR_NOENTRY;1300 } 1301 }1302 1303 return 0;1871 DEBUG(0, ("Failed single search for %s - %s\n", 1872 name1, ldb_errstring(kdc_db_ctx->samdb))); 1873 return SDB_ERR_NOENTRY; 1874 } 1875 return 0; 1876 } 1877 return SDB_ERR_NOENTRY; 1304 1878 } 1879 1880 1305 1881 1306 1882 static krb5_error_code samba_kdc_fetch_server(krb5_context context, … … 1309 1885 krb5_const_principal principal, 1310 1886 unsigned flags, 1311 hdb_entry_ex *entry_ex)1887 struct sdb_entry_ex *entry_ex) 1312 1888 { 1313 1889 krb5_error_code ret; … … 1316 1892 1317 1893 ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, principal, 1318 server_attrs, &realm_dn, &msg);1894 flags, server_attrs, &realm_dn, &msg); 1319 1895 if (ret != 0) { 1320 1896 return ret; … … 1332 1908 } 1333 1909 1910 static krb5_error_code samba_kdc_lookup_realm(krb5_context context, 1911 struct samba_kdc_db_context *kdc_db_ctx, 1912 TALLOC_CTX *mem_ctx, 1913 krb5_const_principal principal, 1914 unsigned flags, 1915 struct sdb_entry_ex *entry_ex) 1916 { 1917 TALLOC_CTX *frame = talloc_stackframe(); 1918 NTSTATUS status; 1919 krb5_error_code ret; 1920 char *_realm = NULL; 1921 bool check_realm = false; 1922 const char *realm = NULL; 1923 struct dsdb_trust_routing_table *trt = NULL; 1924 const struct lsa_TrustDomainInfoInfoEx *tdo = NULL; 1925 unsigned int num_comp; 1926 bool ok; 1927 char *upper = NULL; 1928 1929 num_comp = krb5_princ_size(context, principal); 1930 1931 if (flags & SDB_F_GET_CLIENT) { 1932 if (flags & SDB_F_FOR_AS_REQ) { 1933 check_realm = true; 1934 } 1935 } 1936 if (flags & SDB_F_GET_SERVER) { 1937 if (flags & SDB_F_FOR_TGS_REQ) { 1938 check_realm = true; 1939 } 1940 } 1941 1942 if (!check_realm) { 1943 TALLOC_FREE(frame); 1944 return 0; 1945 } 1946 1947 _realm = smb_krb5_principal_get_realm(context, principal); 1948 if (_realm == NULL) { 1949 TALLOC_FREE(frame); 1950 return ENOMEM; 1951 } 1952 1953 /* 1954 * The requested realm needs to be our own 1955 */ 1956 ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, _realm); 1957 if (!ok) { 1958 /* 1959 * The request is not for us... 1960 */ 1961 SAFE_FREE(_realm); 1962 TALLOC_FREE(frame); 1963 return SDB_ERR_NOENTRY; 1964 } 1965 1966 realm = talloc_strdup(frame, _realm); 1967 SAFE_FREE(_realm); 1968 if (realm == NULL) { 1969 TALLOC_FREE(frame); 1970 return ENOMEM; 1971 } 1972 1973 if (smb_krb5_principal_get_type(context, principal) == KRB5_NT_ENTERPRISE_PRINCIPAL) { 1974 char *principal_string = NULL; 1975 krb5_principal enterprise_principal = NULL; 1976 char *enterprise_realm = NULL; 1977 1978 if (num_comp != 1) { 1979 TALLOC_FREE(frame); 1980 return SDB_ERR_NOENTRY; 1981 } 1982 1983 principal_string = smb_krb5_principal_get_comp_string(frame, context, 1984 principal, 0); 1985 if (principal_string == NULL) { 1986 TALLOC_FREE(frame); 1987 return ENOMEM; 1988 } 1989 1990 ret = krb5_parse_name(context, principal_string, 1991 &enterprise_principal); 1992 TALLOC_FREE(principal_string); 1993 if (ret) { 1994 TALLOC_FREE(frame); 1995 return ret; 1996 } 1997 1998 enterprise_realm = smb_krb5_principal_get_realm(context, 1999 enterprise_principal); 2000 krb5_free_principal(context, enterprise_principal); 2001 if (enterprise_realm != NULL) { 2002 realm = talloc_strdup(frame, enterprise_realm); 2003 SAFE_FREE(enterprise_realm); 2004 if (realm == NULL) { 2005 TALLOC_FREE(frame); 2006 return ENOMEM; 2007 } 2008 } 2009 } 2010 2011 if (flags & SDB_F_GET_SERVER) { 2012 char *service_realm = NULL; 2013 2014 ret = principal_comp_strcmp(context, principal, 0, KRB5_TGS_NAME); 2015 if (ret == 0) { 2016 /* 2017 * we need to search krbtgt/ locally 2018 */ 2019 TALLOC_FREE(frame); 2020 return 0; 2021 } 2022 2023 /* 2024 * We need to check the last component against the routing table. 2025 * 2026 * Note this works only with 2 or 3 component principals, e.g: 2027 * 2028 * servicePrincipalName: ldap/W2K8R2-219.bla.base 2029 * servicePrincipalName: ldap/W2K8R2-219.bla.base/bla.base 2030 * servicePrincipalName: ldap/W2K8R2-219.bla.base/ForestDnsZones.bla.base 2031 * servicePrincipalName: ldap/W2K8R2-219.bla.base/DomainDnsZones.bla.base 2032 */ 2033 2034 if (num_comp == 2 || num_comp == 3) { 2035 service_realm = smb_krb5_principal_get_comp_string(frame, 2036 context, 2037 principal, 2038 num_comp - 1); 2039 } 2040 2041 if (service_realm != NULL) { 2042 realm = service_realm; 2043 } 2044 } 2045 2046 ok = lpcfg_is_my_domain_or_realm(kdc_db_ctx->lp_ctx, realm); 2047 if (ok) { 2048 /* 2049 * skip the expensive routing lookup 2050 */ 2051 TALLOC_FREE(frame); 2052 return 0; 2053 } 2054 2055 status = dsdb_trust_routing_table_load(kdc_db_ctx->samdb, 2056 frame, &trt); 2057 if (!NT_STATUS_IS_OK(status)) { 2058 TALLOC_FREE(frame); 2059 return EINVAL; 2060 } 2061 2062 tdo = dsdb_trust_routing_by_name(trt, realm); 2063 if (tdo == NULL) { 2064 /* 2065 * This principal has to be local 2066 */ 2067 TALLOC_FREE(frame); 2068 return 0; 2069 } 2070 2071 if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) { 2072 /* 2073 * TODO: handle the routing within the forest 2074 * 2075 * This should likely be handled in 2076 * samba_kdc_message2entry() in case we're 2077 * a global catalog. We'd need to check 2078 * if realm_dn is our own domain and derive 2079 * the dns domain name from realm_dn and check that 2080 * against the routing table or fallback to 2081 * the tdo we found here. 2082 * 2083 * But for now we don't support multiple domains 2084 * in our forest correctly anyway. 2085 * 2086 * Just search in our local database. 2087 */ 2088 TALLOC_FREE(frame); 2089 return 0; 2090 } 2091 2092 ZERO_STRUCT(entry_ex->entry); 2093 2094 ret = krb5_copy_principal(context, principal, 2095 &entry_ex->entry.principal); 2096 if (ret) { 2097 TALLOC_FREE(frame); 2098 return ret; 2099 } 2100 2101 upper = strupper_talloc(frame, tdo->domain_name.string); 2102 if (upper == NULL) { 2103 TALLOC_FREE(frame); 2104 return ENOMEM; 2105 } 2106 2107 ret = smb_krb5_principal_set_realm(context, 2108 entry_ex->entry.principal, 2109 upper); 2110 if (ret) { 2111 TALLOC_FREE(frame); 2112 return ret; 2113 } 2114 2115 TALLOC_FREE(frame); 2116 return SDB_ERR_WRONG_REALM; 2117 } 2118 1334 2119 krb5_error_code samba_kdc_fetch(krb5_context context, 1335 2120 struct samba_kdc_db_context *kdc_db_ctx, … … 1337 2122 unsigned flags, 1338 2123 krb5_kvno kvno, 1339 hdb_entry_ex *entry_ex)2124 struct sdb_entry_ex *entry_ex) 1340 2125 { 1341 krb5_error_code ret = HDB_ERR_NOENTRY;2126 krb5_error_code ret = SDB_ERR_NOENTRY; 1342 2127 TALLOC_CTX *mem_ctx; 1343 unsigned int krbtgt_number;1344 if (flags & HDB_F_KVNO_SPECIFIED) {1345 krbtgt_number = SAMBA_KVNO_GET_KRBTGT(kvno);1346 if (kdc_db_ctx->rodc) {1347 if (krbtgt_number != kdc_db_ctx->my_krbtgt_number) {1348 return HDB_ERR_NOT_FOUND_HERE;1349 }1350 }1351 } else {1352 krbtgt_number = kdc_db_ctx->my_krbtgt_number;1353 }1354 2128 1355 2129 mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_fetch context"); … … 1360 2134 } 1361 2135 1362 if (flags & HDB_F_GET_CLIENT) { 2136 ret = samba_kdc_lookup_realm(context, kdc_db_ctx, mem_ctx, 2137 principal, flags, entry_ex); 2138 if (ret != 0) { 2139 goto done; 2140 } 2141 2142 ret = SDB_ERR_NOENTRY; 2143 2144 if (flags & SDB_F_GET_CLIENT) { 1363 2145 ret = samba_kdc_fetch_client(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex); 1364 if (ret != HDB_ERR_NOENTRY) goto done;1365 } 1366 if (flags & HDB_F_GET_SERVER) {2146 if (ret != SDB_ERR_NOENTRY) goto done; 2147 } 2148 if (flags & SDB_F_GET_SERVER) { 1367 2149 /* krbtgt fits into this situation for trusted realms, and for resolving different versions of our own realm name */ 1368 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, k rbtgt_number, entry_ex);1369 if (ret != HDB_ERR_NOENTRY) goto done;2150 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry_ex); 2151 if (ret != SDB_ERR_NOENTRY) goto done; 1370 2152 1371 2153 /* We return 'no entry' if it does not start with krbtgt/, so move to the common case quickly */ 1372 2154 ret = samba_kdc_fetch_server(context, kdc_db_ctx, mem_ctx, principal, flags, entry_ex); 1373 if (ret != HDB_ERR_NOENTRY) goto done;1374 } 1375 if (flags & HDB_F_GET_KRBTGT) {1376 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, k rbtgt_number, entry_ex);1377 if (ret != HDB_ERR_NOENTRY) goto done;2155 if (ret != SDB_ERR_NOENTRY) goto done; 2156 } 2157 if (flags & SDB_F_GET_KRBTGT) { 2158 ret = samba_kdc_fetch_krbtgt(context, kdc_db_ctx, mem_ctx, principal, flags, kvno, entry_ex); 2159 if (ret != SDB_ERR_NOENTRY) goto done; 1378 2160 } 1379 2161 … … 1392 2174 static krb5_error_code samba_kdc_seq(krb5_context context, 1393 2175 struct samba_kdc_db_context *kdc_db_ctx, 1394 hdb_entry_ex *entry)2176 struct sdb_entry_ex *entry) 1395 2177 { 1396 2178 krb5_error_code ret; 1397 2179 struct samba_kdc_seq *priv = kdc_db_ctx->seq_ctx; 2180 const char *realm = lpcfg_realm(kdc_db_ctx->lp_ctx); 2181 struct ldb_message *msg = NULL; 2182 const char *sAMAccountName = NULL; 2183 krb5_principal principal = NULL; 1398 2184 TALLOC_CTX *mem_ctx; 1399 hdb_entry_ex entry_ex;1400 memset(&entry_ex, '\0', sizeof(entry_ex));1401 2185 1402 2186 if (!priv) { 1403 return HDB_ERR_NOENTRY;2187 return SDB_ERR_NOENTRY; 1404 2188 } 1405 2189 … … 1412 2196 } 1413 2197 1414 if (priv->index < priv->count) { 1415 ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx, 1416 NULL, SAMBA_KDC_ENT_TYPE_ANY, 1417 HDB_F_ADMIN_DATA|HDB_F_GET_ANY, 1418 priv->realm_dn, priv->msgs[priv->index++], entry); 1419 } else { 1420 ret = HDB_ERR_NOENTRY; 2198 while (priv->index < priv->count) { 2199 msg = priv->msgs[priv->index++]; 2200 2201 sAMAccountName = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL); 2202 if (sAMAccountName != NULL) { 2203 break; 2204 } 2205 } 2206 2207 if (sAMAccountName == NULL) { 2208 ret = SDB_ERR_NOENTRY; 2209 goto out; 2210 } 2211 2212 ret = smb_krb5_make_principal(context, &principal, 2213 realm, sAMAccountName, NULL); 2214 if (ret != 0) { 2215 goto out; 2216 } 2217 2218 ret = samba_kdc_message2entry(context, kdc_db_ctx, mem_ctx, 2219 principal, SAMBA_KDC_ENT_TYPE_ANY, 2220 SDB_F_ADMIN_DATA|SDB_F_GET_ANY, 2221 priv->realm_dn, msg, entry); 2222 2223 out: 2224 if (principal != NULL) { 2225 krb5_free_principal(context, principal); 1421 2226 } 1422 2227 … … 1433 2238 krb5_error_code samba_kdc_firstkey(krb5_context context, 1434 2239 struct samba_kdc_db_context *kdc_db_ctx, 1435 hdb_entry_ex *entry)2240 struct sdb_entry_ex *entry) 1436 2241 { 1437 2242 struct ldb_context *ldb_ctx = kdc_db_ctx->samdb; … … 1473 2278 return ret; 1474 2279 } 1475 1476 lret = ldb_search(ldb_ctx, priv, &res, 1477 priv->realm_dn, LDB_SCOPE_SUBTREE, user_attrs, 1478 "(objectClass=user)"); 2280 krb5_free_default_realm(context, realm); 2281 2282 lret = dsdb_search(ldb_ctx, priv, &res, 2283 priv->realm_dn, LDB_SCOPE_SUBTREE, user_attrs, 2284 DSDB_SEARCH_NO_GLOBAL_CATALOG, 2285 "(objectClass=user)"); 1479 2286 1480 2287 if (lret != LDB_SUCCESS) { 1481 2288 TALLOC_FREE(priv); 1482 return HDB_ERR_NOENTRY;2289 return SDB_ERR_NOENTRY; 1483 2290 } 1484 2291 … … 1502 2309 krb5_error_code samba_kdc_nextkey(krb5_context context, 1503 2310 struct samba_kdc_db_context *kdc_db_ctx, 1504 hdb_entry_ex *entry)2311 struct sdb_entry_ex *entry) 1505 2312 { 1506 2313 return samba_kdc_seq(context, kdc_db_ctx, entry); … … 1510 2317 * 1511 2318 * This is currently a very nasty hack - allowing only delegation to itself. 1512 *1513 * This is shared between the constrained delegation and S4U2Self code.1514 2319 */ 1515 2320 krb5_error_code 1516 samba_kdc_check_ identical_client_and_server(krb5_context context,1517 1518 hdb_entry_ex *entry,1519 2321 samba_kdc_check_s4u2self(krb5_context context, 2322 struct samba_kdc_db_context *kdc_db_ctx, 2323 struct samba_kdc_entry *skdc_entry, 2324 krb5_const_principal target_principal) 1520 2325 { 1521 2326 krb5_error_code ret; 1522 krb5_principal enterprise_prinicpal = NULL;1523 2327 struct ldb_dn *realm_dn; 1524 2328 struct ldb_message *msg; 1525 2329 struct dom_sid *orig_sid; 1526 2330 struct dom_sid *target_sid; 1527 struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry);1528 2331 const char *delegation_check_attrs[] = { 1529 2332 "objectSid", NULL 1530 2333 }; 1531 2334 1532 TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_ constrained_delegation");2335 TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_s4u2self"); 1533 2336 1534 2337 if (!mem_ctx) { 1535 2338 ret = ENOMEM; 1536 krb5_set_error_message(context, ret, "samba_kdc_ fetch: talloc_named() failed!");2339 krb5_set_error_message(context, ret, "samba_kdc_check_s4u2self: talloc_named() failed!"); 1537 2340 return ret; 1538 2341 } 1539 2342 1540 if (target_principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {1541 /* Need to reparse the enterprise principal to find the real target */1542 if (target_principal->name.name_string.len != 1) {1543 ret = KRB5_PARSE_MALFORMED;1544 krb5_set_error_message(context, ret, "samba_kdc_check_constrained_delegation: request for delegation to enterprise principal with wrong (%d) number of components",1545 target_principal->name.name_string.len);1546 talloc_free(mem_ctx);1547 return ret;1548 }1549 ret = krb5_parse_name(context, target_principal->name.name_string.val[0],1550 &enterprise_prinicpal);1551 if (ret) {1552 talloc_free(mem_ctx);1553 return ret;1554 }1555 target_principal = enterprise_prinicpal;1556 }1557 1558 2343 ret = samba_kdc_lookup_server(context, kdc_db_ctx, mem_ctx, target_principal, 1559 delegation_check_attrs, &realm_dn, &msg); 1560 1561 krb5_free_principal(context, enterprise_prinicpal); 2344 SDB_F_GET_CLIENT|SDB_F_GET_SERVER, 2345 delegation_check_attrs, &realm_dn, &msg); 1562 2346 1563 2347 if (ret != 0) { … … 1566 2350 } 1567 2351 1568 orig_sid = samdb_result_dom_sid(mem_ctx, p->msg, "objectSid");2352 orig_sid = samdb_result_dom_sid(mem_ctx, skdc_entry->msg, "objectSid"); 1569 2353 target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); 1570 2354 … … 1589 2373 samba_kdc_check_pkinit_ms_upn_match(krb5_context context, 1590 2374 struct samba_kdc_db_context *kdc_db_ctx, 1591 hdb_entry_ex *entry,2375 struct samba_kdc_entry *skdc_entry, 1592 2376 krb5_const_principal certificate_principal) 1593 2377 { … … 1597 2381 struct dom_sid *orig_sid; 1598 2382 struct dom_sid *target_sid; 1599 struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry);1600 2383 const char *ms_upn_check_attrs[] = { 1601 2384 "objectSid", NULL … … 1611 2394 1612 2395 ret = samba_kdc_lookup_client(context, kdc_db_ctx, 1613 1614 2396 mem_ctx, certificate_principal, 2397 ms_upn_check_attrs, &realm_dn, &msg); 1615 2398 1616 2399 if (ret != 0) { … … 1619 2402 } 1620 2403 1621 orig_sid = samdb_result_dom_sid(mem_ctx, p->msg, "objectSid");2404 orig_sid = samdb_result_dom_sid(mem_ctx, skdc_entry->msg, "objectSid"); 1622 2405 target_sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid"); 1623 2406 … … 1627 2410 if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { 1628 2411 talloc_free(mem_ctx); 2412 #ifdef KRB5_KDC_ERR_CLIENT_NAME_MISMATCH /* Heimdal */ 1629 2413 return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; 2414 #elif defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */ 2415 return KRB5KDC_ERR_CLIENT_NAME_MISMATCH; 2416 #endif 1630 2417 } 1631 2418 1632 2419 talloc_free(mem_ctx); 1633 2420 return ret; 2421 } 2422 2423 /* 2424 * Check if a given entry may delegate to this target principal 2425 * with S4U2Proxy. 2426 */ 2427 krb5_error_code 2428 samba_kdc_check_s4u2proxy(krb5_context context, 2429 struct samba_kdc_db_context *kdc_db_ctx, 2430 struct samba_kdc_entry *skdc_entry, 2431 krb5_const_principal target_principal) 2432 { 2433 krb5_error_code ret; 2434 char *tmp = NULL; 2435 const char *client_dn = NULL; 2436 const char *target_principal_name = NULL; 2437 struct ldb_message_element *el; 2438 struct ldb_val val; 2439 unsigned int i; 2440 bool found = false; 2441 2442 TALLOC_CTX *mem_ctx = talloc_named(kdc_db_ctx, 0, "samba_kdc_check_s4u2proxy"); 2443 2444 if (!mem_ctx) { 2445 ret = ENOMEM; 2446 krb5_set_error_message(context, ret, 2447 "samba_kdc_check_s4u2proxy:" 2448 " talloc_named() failed!"); 2449 return ret; 2450 } 2451 2452 client_dn = ldb_dn_get_linearized(skdc_entry->msg->dn); 2453 if (!client_dn) { 2454 if (errno == 0) { 2455 errno = ENOMEM; 2456 } 2457 ret = errno; 2458 krb5_set_error_message(context, ret, 2459 "samba_kdc_check_s4u2proxy:" 2460 " ldb_dn_get_linearized() failed!"); 2461 return ret; 2462 } 2463 2464 /* 2465 * The main heimdal code already checked that the target_principal 2466 * belongs to the same realm as the client. 2467 * 2468 * So we just need the principal without the realm, 2469 * as that is what is configured in the "msDS-AllowedToDelegateTo" 2470 * attribute. 2471 */ 2472 ret = krb5_unparse_name_flags(context, target_principal, 2473 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &tmp); 2474 if (ret) { 2475 talloc_free(mem_ctx); 2476 krb5_set_error_message(context, ret, 2477 "samba_kdc_check_s4u2proxy:" 2478 " krb5_unparse_name() failed!"); 2479 return ret; 2480 } 2481 DEBUG(10,("samba_kdc_check_s4u2proxy: client[%s] for target[%s]\n", 2482 client_dn, tmp)); 2483 2484 target_principal_name = talloc_strdup(mem_ctx, tmp); 2485 SAFE_FREE(tmp); 2486 if (target_principal_name == NULL) { 2487 ret = ENOMEM; 2488 krb5_set_error_message(context, ret, 2489 "samba_kdc_check_s4u2proxy:" 2490 " talloc_strdup() failed!"); 2491 return ret; 2492 } 2493 2494 el = ldb_msg_find_element(skdc_entry->msg, "msDS-AllowedToDelegateTo"); 2495 if (el == NULL) { 2496 goto bad_option; 2497 } 2498 2499 val = data_blob_string_const(target_principal_name); 2500 2501 for (i=0; i<el->num_values; i++) { 2502 struct ldb_val *val1 = &val; 2503 struct ldb_val *val2 = &el->values[i]; 2504 int cmp; 2505 2506 if (val1->length != val2->length) { 2507 continue; 2508 } 2509 2510 cmp = strncasecmp((const char *)val1->data, 2511 (const char *)val2->data, 2512 val1->length); 2513 if (cmp != 0) { 2514 continue; 2515 } 2516 2517 found = true; 2518 break; 2519 } 2520 2521 if (!found) { 2522 goto bad_option; 2523 } 2524 2525 DEBUG(10,("samba_kdc_check_s4u2proxy: client[%s] allowed target[%s]\n", 2526 client_dn, tmp)); 2527 talloc_free(mem_ctx); 2528 return 0; 2529 2530 bad_option: 2531 krb5_set_error_message(context, ret, 2532 "samba_kdc_check_s4u2proxy: client[%s] " 2533 "not allowed for delegation to target[%s]", 2534 client_dn, 2535 target_principal_name); 2536 talloc_free(mem_ctx); 2537 return KRB5KDC_ERR_BADOPTION; 1634 2538 } 1635 2539 … … 1656 2560 kdc_db_ctx->lp_ctx = base_ctx->lp_ctx; 1657 2561 1658 kdc_get_policy(base_ctx->lp_ctx, NULL, &kdc_db_ctx->policy); 2562 /* get default kdc policy */ 2563 lpcfg_default_kdc_policy(base_ctx->lp_ctx, 2564 &kdc_db_ctx->policy.svc_tkt_lifetime, 2565 &kdc_db_ctx->policy.usr_tkt_lifetime, 2566 &kdc_db_ctx->policy.renewal_lifetime); 1659 2567 1660 2568 session_info = system_session(kdc_db_ctx->lp_ctx); … … 1667 2575 base_ctx->lp_ctx, session_info, 0); 1668 2576 if (kdc_db_ctx->samdb == NULL) { 1669 DEBUG(1, (" hdb_samba4_create: Cannot open samdb for KDC backend!"));2577 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot open samdb for KDC backend!")); 1670 2578 talloc_free(kdc_db_ctx); 1671 2579 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; … … 1675 2583 ldb_ret = samdb_rodc(kdc_db_ctx->samdb, &kdc_db_ctx->rodc); 1676 2584 if (ldb_ret != LDB_SUCCESS) { 1677 DEBUG(1, (" hdb_samba4_create: Cannot determine if we are an RODC in KDC backend: %s\n",2585 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot determine if we are an RODC in KDC backend: %s\n", 1678 2586 ldb_errstring(kdc_db_ctx->samdb))); 1679 2587 talloc_free(kdc_db_ctx); … … 1686 2594 struct ldb_dn *server_dn = samdb_server_dn(kdc_db_ctx->samdb, kdc_db_ctx); 1687 2595 if (!server_dn) { 1688 DEBUG(1, (" hdb_samba4_create: Cannot determine server DN in KDC backend: %s\n",2596 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot determine server DN in KDC backend: %s\n", 1689 2597 ldb_errstring(kdc_db_ctx->samdb))); 1690 2598 talloc_free(kdc_db_ctx); … … 1695 2603 "serverReference", &account_dn); 1696 2604 if (ldb_ret != LDB_SUCCESS) { 1697 DEBUG(1, (" hdb_samba4_create: Cannot determine server account in KDC backend: %s\n",2605 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot determine server account in KDC backend: %s\n", 1698 2606 ldb_errstring(kdc_db_ctx->samdb))); 1699 2607 talloc_free(kdc_db_ctx); … … 1705 2613 talloc_free(account_dn); 1706 2614 if (ldb_ret != LDB_SUCCESS) { 1707 DEBUG(1, (" hdb_samba4_create: Cannot determine RODC krbtgt account in KDC backend: %s\n",2615 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot determine RODC krbtgt account in KDC backend: %s\n", 1708 2616 ldb_errstring(kdc_db_ctx->samdb))); 1709 2617 talloc_free(kdc_db_ctx); … … 1714 2622 &msg, kdc_db_ctx->krbtgt_dn, LDB_SCOPE_BASE, 1715 2623 secondary_keytab, 1716 0,2624 DSDB_SEARCH_NO_GLOBAL_CATALOG, 1717 2625 "(&(objectClass=user)(msDS-SecondaryKrbTgtNumber=*))"); 1718 2626 if (ldb_ret != LDB_SUCCESS) { 1719 DEBUG(1, (" hdb_samba4_create: Cannot read krbtgt account %s in KDC backend to get msDS-SecondaryKrbTgtNumber: %s: %s\n",2627 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot read krbtgt account %s in KDC backend to get msDS-SecondaryKrbTgtNumber: %s: %s\n", 1720 2628 ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn), 1721 2629 ldb_errstring(kdc_db_ctx->samdb), … … 1726 2634 my_krbtgt_number = ldb_msg_find_attr_as_int(msg, "msDS-SecondaryKrbTgtNumber", -1); 1727 2635 if (my_krbtgt_number == -1) { 1728 DEBUG(1, (" hdb_samba4_create: Cannot read msDS-SecondaryKrbTgtNumber from krbtgt account %s in KDC backend: got %d\n",2636 DEBUG(1, ("samba_kdc_setup_db_ctx: Cannot read msDS-SecondaryKrbTgtNumber from krbtgt account %s in KDC backend: got %d\n", 1729 2637 ldb_dn_get_linearized(kdc_db_ctx->krbtgt_dn), 1730 2638 my_krbtgt_number)); … … 1737 2645 kdc_db_ctx->my_krbtgt_number = 0; 1738 2646 ldb_ret = dsdb_search_one(kdc_db_ctx->samdb, kdc_db_ctx, 1739 &msg, NULL, LDB_SCOPE_SUBTREE, 2647 &msg, 2648 ldb_get_default_basedn(kdc_db_ctx->samdb), 2649 LDB_SCOPE_SUBTREE, 1740 2650 krbtgt_attrs, 1741 0,2651 DSDB_SEARCH_NO_GLOBAL_CATALOG, 1742 2652 "(&(objectClass=user)(samAccountName=krbtgt))"); 1743 2653
Note:
See TracChangeset
for help on using the changeset viewer.