Changeset 988 for vendor/current/source4/kdc
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source4/kdc
- Files:
-
- 7 added
- 2 deleted
- 13 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 -
vendor/current/source4/kdc/db-glue.h
r740 r988 22 22 */ 23 23 24 struct sdb_entry_ex; 25 24 26 krb5_error_code samba_kdc_fetch(krb5_context context, 25 27 struct samba_kdc_db_context *kdc_db_ctx, … … 27 29 unsigned flags, 28 30 krb5_kvno kvno, 29 hdb_entry_ex *entry_ex);31 struct sdb_entry_ex *entry_ex); 30 32 31 33 krb5_error_code samba_kdc_firstkey(krb5_context context, 32 34 struct samba_kdc_db_context *kdc_db_ctx, 33 hdb_entry_ex *entry);35 struct sdb_entry_ex *entry); 34 36 35 37 krb5_error_code samba_kdc_nextkey(krb5_context context, 36 38 struct samba_kdc_db_context *kdc_db_ctx, 37 hdb_entry_ex *entry);39 struct sdb_entry_ex *entry); 38 40 39 41 krb5_error_code 40 samba_kdc_check_ identical_client_and_server(krb5_context context,41 42 hdb_entry_ex *entry,43 42 samba_kdc_check_s4u2self(krb5_context context, 43 struct samba_kdc_db_context *kdc_db_ctx, 44 struct samba_kdc_entry *skdc_entry, 45 krb5_const_principal target_principal); 44 46 45 47 krb5_error_code 46 48 samba_kdc_check_pkinit_ms_upn_match(krb5_context context, 47 49 struct samba_kdc_db_context *kdc_db_ctx, 48 hdb_entry_ex *entry,50 struct samba_kdc_entry *skdc_entry, 49 51 krb5_const_principal certificate_principal); 52 53 krb5_error_code 54 samba_kdc_check_s4u2proxy(krb5_context context, 55 struct samba_kdc_db_context *kdc_db_ctx, 56 struct samba_kdc_entry *skdc_entry, 57 krb5_const_principal target_principal); 50 58 51 59 NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_context *base_ctx, -
vendor/current/source4/kdc/hdb-samba4.c
r740 r988 36 36 #include "kdc/kdc-glue.h" 37 37 #include "kdc/db-glue.h" 38 #include "auth/auth_sam.h" 39 #include <ldb.h> 40 #include "sdb.h" 41 #include "sdb_hdb.h" 38 42 39 43 static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode) … … 86 90 { 87 91 struct samba_kdc_db_context *kdc_db_ctx; 88 89 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 90 struct samba_kdc_db_context); 91 92 return samba_kdc_fetch(context, kdc_db_ctx, principal, flags, kvno, entry_ex); 92 struct sdb_entry_ex sdb_entry_ex = {}; 93 krb5_error_code code, ret; 94 95 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 96 struct samba_kdc_db_context); 97 98 ret = samba_kdc_fetch(context, 99 kdc_db_ctx, 100 principal, 101 flags, 102 kvno, 103 &sdb_entry_ex); 104 switch (ret) { 105 case 0: 106 code = 0; 107 break; 108 case SDB_ERR_WRONG_REALM: 109 /* 110 * If SDB_ERR_WRONG_REALM is returned we need to process the 111 * sdb_entry to fill the principal in the HDB entry. 112 */ 113 code = HDB_ERR_WRONG_REALM; 114 break; 115 case SDB_ERR_NOENTRY: 116 return HDB_ERR_NOENTRY; 117 default: 118 return HDB_ERR_NOT_FOUND_HERE; 119 } 120 121 ret = sdb_entry_ex_to_hdb_entry_ex(context, &sdb_entry_ex, entry_ex); 122 sdb_free_entry(&sdb_entry_ex); 123 124 if (code != 0 && ret != 0) { 125 code = ret; 126 } 127 128 return code; 93 129 } 94 130 … … 97 133 { 98 134 struct samba_kdc_db_context *kdc_db_ctx; 99 100 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 101 struct samba_kdc_db_context); 102 103 return samba_kdc_firstkey(context, kdc_db_ctx, entry); 135 struct sdb_entry_ex sdb_entry_ex = {}; 136 krb5_error_code ret; 137 138 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 139 struct samba_kdc_db_context); 140 141 ret = samba_kdc_firstkey(context, kdc_db_ctx, &sdb_entry_ex); 142 switch (ret) { 143 case 0: 144 break; 145 case SDB_ERR_WRONG_REALM: 146 return HDB_ERR_WRONG_REALM; 147 case SDB_ERR_NOENTRY: 148 return HDB_ERR_NOENTRY; 149 default: 150 return HDB_ERR_NOT_FOUND_HERE; 151 } 152 153 ret = sdb_entry_ex_to_hdb_entry_ex(context, &sdb_entry_ex, entry); 154 sdb_free_entry(&sdb_entry_ex); 155 return ret; 104 156 } 105 157 … … 108 160 { 109 161 struct samba_kdc_db_context *kdc_db_ctx; 110 111 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 112 struct samba_kdc_db_context); 113 114 return samba_kdc_nextkey(context, kdc_db_ctx, entry); 162 struct sdb_entry_ex sdb_entry_ex = {}; 163 krb5_error_code ret; 164 165 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 166 struct samba_kdc_db_context); 167 168 ret = samba_kdc_nextkey(context, kdc_db_ctx, &sdb_entry_ex); 169 switch (ret) { 170 case 0: 171 break; 172 case SDB_ERR_WRONG_REALM: 173 return HDB_ERR_WRONG_REALM; 174 case SDB_ERR_NOENTRY: 175 return HDB_ERR_NOENTRY; 176 default: 177 return HDB_ERR_NOT_FOUND_HERE; 178 } 179 180 ret = sdb_entry_ex_to_hdb_entry_ex(context, &sdb_entry_ex, entry); 181 sdb_free_entry(&sdb_entry_ex); 182 return ret; 115 183 } 116 184 … … 122 190 123 191 static krb5_error_code 124 hdb_samba4_check_ identical_client_and_server(krb5_context context, HDB *db,192 hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db, 125 193 hdb_entry_ex *entry, 126 194 krb5_const_principal target_principal) 127 195 { 128 196 struct samba_kdc_db_context *kdc_db_ctx; 129 130 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 131 struct samba_kdc_db_context); 132 133 return samba_kdc_check_identical_client_and_server(context, kdc_db_ctx, 134 entry, 135 target_principal); 197 struct samba_kdc_entry *skdc_entry; 198 krb5_error_code ret; 199 200 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 201 struct samba_kdc_db_context); 202 skdc_entry = talloc_get_type_abort(entry->ctx, 203 struct samba_kdc_entry); 204 205 ret = samba_kdc_check_s4u2proxy(context, kdc_db_ctx, 206 skdc_entry, 207 target_principal); 208 switch (ret) { 209 case 0: 210 break; 211 case SDB_ERR_WRONG_REALM: 212 ret = HDB_ERR_WRONG_REALM; 213 break; 214 case SDB_ERR_NOENTRY: 215 ret = HDB_ERR_NOENTRY; 216 break; 217 default: 218 ret = HDB_ERR_NOT_FOUND_HERE; 219 break; 220 } 221 222 return ret; 136 223 } 137 224 … … 142 229 { 143 230 struct samba_kdc_db_context *kdc_db_ctx; 144 145 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 146 struct samba_kdc_db_context); 147 148 return samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx, 149 entry, 150 certificate_principal); 231 struct samba_kdc_entry *skdc_entry; 232 krb5_error_code ret; 233 234 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 235 struct samba_kdc_db_context); 236 skdc_entry = talloc_get_type_abort(entry->ctx, 237 struct samba_kdc_entry); 238 239 ret = samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx, 240 skdc_entry, 241 certificate_principal); 242 switch (ret) { 243 case 0: 244 break; 245 case SDB_ERR_WRONG_REALM: 246 ret = HDB_ERR_WRONG_REALM; 247 break; 248 case SDB_ERR_NOENTRY: 249 ret = HDB_ERR_NOENTRY; 250 break; 251 default: 252 ret = HDB_ERR_NOT_FOUND_HERE; 253 break; 254 } 255 256 return ret; 257 } 258 259 static krb5_error_code 260 hdb_samba4_check_s4u2self(krb5_context context, HDB *db, 261 hdb_entry_ex *entry, 262 krb5_const_principal target_principal) 263 { 264 struct samba_kdc_db_context *kdc_db_ctx; 265 struct samba_kdc_entry *skdc_entry; 266 krb5_error_code ret; 267 268 kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 269 struct samba_kdc_db_context); 270 skdc_entry = talloc_get_type_abort(entry->ctx, 271 struct samba_kdc_entry); 272 273 ret = samba_kdc_check_s4u2self(context, kdc_db_ctx, 274 skdc_entry, 275 target_principal); 276 switch (ret) { 277 case 0: 278 break; 279 case SDB_ERR_WRONG_REALM: 280 ret = HDB_ERR_WRONG_REALM; 281 break; 282 case SDB_ERR_NOENTRY: 283 ret = HDB_ERR_NOENTRY; 284 break; 285 default: 286 ret = HDB_ERR_NOT_FOUND_HERE; 287 break; 288 } 289 290 return ret; 291 } 292 293 static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db, 294 hdb_entry_ex *entry, 295 int hdb_auth_status) 296 { 297 struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db, 298 struct samba_kdc_db_context); 299 struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry); 300 301 struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); 302 303 if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) { 304 authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); 305 } else if (hdb_auth_status == HDB_AUTH_SUCCESS) { 306 authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg, 307 domain_dn, true); 308 } 309 return 0; 151 310 } 152 311 … … 162 321 NTSTATUS nt_status; 163 322 323 if (hdb_interface_version != HDB_INTERFACE_VERSION) { 324 krb5_set_error_message(context, EINVAL, "Heimdal HDB interface version mismatch between build-time and run-time libraries!"); 325 return NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION; 326 } 327 164 328 *db = talloc(base_ctx, HDB); 165 329 if (!*db) { … … 170 334 (*db)->hdb_master_key_set = 0; 171 335 (*db)->hdb_db = NULL; 172 (*db)->hdb_capability_flags = 0;336 (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL; 173 337 174 338 nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx); … … 197 361 (*db)->hdb_destroy = hdb_samba4_destroy; 198 362 199 (*db)->hdb_auth_status = NULL;200 (*db)->hdb_check_constrained_delegation = hdb_samba4_check_ identical_client_and_server;363 (*db)->hdb_auth_status = hdb_samba4_auth_status; 364 (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation; 201 365 (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match; 202 (*db)->hdb_check_s4u2self = hdb_samba4_check_ identical_client_and_server;366 (*db)->hdb_check_s4u2self = hdb_samba4_check_s4u2self; 203 367 204 368 return NT_STATUS_OK; 205 369 } 206 207 static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, const char *arg)208 {209 NTSTATUS nt_status;210 void *ptr;211 struct samba_kdc_base_context *base_ctx;212 213 if (sscanf(arg, "&%p", &ptr) != 1) {214 return EINVAL;215 }216 base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context);217 /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */218 nt_status = hdb_samba4_create_kdc(base_ctx, context, db);219 220 if (NT_STATUS_IS_OK(nt_status)) {221 return 0;222 }223 return EINVAL;224 }225 226 /* Only used in the hdb-backed keytab code227 * for a keytab of 'samba4&<address>', to find228 * kpasswd's key in the main DB, and to229 * copy all the keys into a file (libnet_keytab_export)230 *231 * The <address> is the string form of a pointer to a talloced struct hdb_samba_context232 */233 struct hdb_method hdb_samba4 = {234 .interface_version = HDB_INTERFACE_VERSION,235 .prefix = "samba4",236 .create = hdb_samba4_create237 }; -
vendor/current/source4/kdc/kdc-glue.h
r740 r988 82 82 DATA_BLOB *out); 83 83 84 /* from kdc-glue.c */ 85 int kdc_check_pac(krb5_context krb5_context, 86 DATA_BLOB server_sig, 87 struct PAC_SIGNATURE_DATA *kdc_sig, 88 hdb_entry_ex *ent); 84 89 #endif -
vendor/current/source4/kdc/kdc.c
r740 r988 33 33 #include "param/param.h" 34 34 #include "kdc/kdc-glue.h" 35 #include "kdc/pac-glue.h" 35 36 #include "dsdb/samdb/samdb.h" 36 37 #include "auth/session.h" 38 #include "libds/common/roles.h" 39 40 NTSTATUS server_service_kdc_init(void); 37 41 38 42 extern struct krb5plugin_windc_ftable windc_plugin_table; 39 extern struct hdb_method hdb_samba4;40 43 41 44 static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc, … … 616 619 struct kdc_udp_call *call = tevent_req_callback_data(subreq, 617 620 struct kdc_udp_call); 618 ssize_t ret;619 621 int sys_errno; 620 622 621 ret =tdgram_sendto_queue_recv(subreq, &sys_errno);623 tdgram_sendto_queue_recv(subreq, &sys_errno); 622 624 623 625 /* We don't care about errors */ … … 653 655 &kdc_socket->local_address); 654 656 if (ret != 0) { 655 status = map_nt_error_from_unix (errno);657 status = map_nt_error_from_unix_common(errno); 656 658 return status; 657 659 } … … 684 686 &kdc_udp_socket->dgram); 685 687 if (ret != 0) { 686 status = map_nt_error_from_unix (errno);688 status = map_nt_error_from_unix_common(errno); 687 689 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n", 688 690 address, port, nt_errstr(status))); … … 728 730 } 729 731 730 num_interfaces = iface_ count(ifaces);732 num_interfaces = iface_list_count(ifaces); 731 733 732 734 /* if we are allowing incoming packets from any address, then 733 735 we need to bind to the wildcard address */ 734 736 if (!lpcfg_bind_interfaces_only(lp_ctx)) { 735 if (kdc_port) { 736 status = kdc_add_socket(kdc, model_ops, 737 "kdc", "0.0.0.0", kdc_port, 738 kdc_process, false); 739 NT_STATUS_NOT_OK_RETURN(status); 740 } 741 742 if (kpasswd_port) { 743 status = kdc_add_socket(kdc, model_ops, 744 "kpasswd", "0.0.0.0", kpasswd_port, 745 kpasswdd_process, false); 746 NT_STATUS_NOT_OK_RETURN(status); 737 int num_binds = 0; 738 char **wcard = iface_list_wildcard(kdc); 739 NT_STATUS_HAVE_NO_MEMORY(wcard); 740 for (i=0; wcard[i]; i++) { 741 if (kdc_port) { 742 status = kdc_add_socket(kdc, model_ops, 743 "kdc", wcard[i], kdc_port, 744 kdc_process, false); 745 if (NT_STATUS_IS_OK(status)) { 746 num_binds++; 747 } 748 } 749 750 if (kpasswd_port) { 751 status = kdc_add_socket(kdc, model_ops, 752 "kpasswd", wcard[i], kpasswd_port, 753 kpasswdd_process, false); 754 if (NT_STATUS_IS_OK(status)) { 755 num_binds++; 756 } 757 } 758 } 759 talloc_free(wcard); 760 if (num_binds == 0) { 761 return NT_STATUS_INVALID_PARAMETER_MIX; 747 762 } 748 763 done_wildcard = true; … … 750 765 751 766 for (i=0; i<num_interfaces; i++) { 752 const char *address = talloc_strdup(tmp_ctx, iface_ n_ip(ifaces, i));767 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i)); 753 768 754 769 if (kdc_port) { … … 772 787 } 773 788 774 775 789 static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, 776 790 struct kdc_check_generic_kerberos *r) … … 781 795 struct kdc_server *kdc = talloc_get_type(msg->private_data, struct kdc_server); 782 796 enum ndr_err_code ndr_err; 783 krb5_enctype etype;784 797 int ret; 785 798 hdb_entry_ex ent; 786 799 krb5_principal principal; 787 krb5_keyblock keyblock;788 Key *key;789 800 790 801 /* There is no reply to this request */ … … 797 808 } 798 809 799 if (pac_validate.MessageType != 3) {810 if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) { 800 811 /* We don't implement any other message types - such as certificate validation - yet */ 801 812 return NT_STATUS_INVALID_PARAMETER; … … 810 821 srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data, 811 822 pac_validate.ChecksumLength); 812 813 if (pac_validate.SignatureType == CKSUMTYPE_HMAC_MD5) {814 etype = ETYPE_ARCFOUR_HMAC_MD5;815 } else {816 ret = krb5_cksumtype_to_enctype(kdc->smb_krb5_context->krb5_context, pac_validate.SignatureType,817 &etype);818 if (ret != 0) {819 return NT_STATUS_LOGON_FAILURE;820 }821 }822 823 823 824 ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal, … … 844 845 } 845 846 846 ret = hdb_enctype2key(kdc->smb_krb5_context->krb5_context, &ent.entry, etype, &key);847 848 if (ret != 0) {849 hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);850 krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);851 return NT_STATUS_LOGON_FAILURE;852 }853 854 keyblock = key->key;855 856 847 kdc_sig.type = pac_validate.SignatureType; 857 848 kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength], 858 849 pac_validate.SignatureLength); 859 ret = check_pac_checksum(msg, srv_sig, &kdc_sig, 860 kdc->smb_krb5_context->krb5_context, &keyblock);850 851 ret = kdc_check_pac(kdc->smb_krb5_context->krb5_context, srv_sig, &kdc_sig, &ent); 861 852 862 853 hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent); … … 889 880 task_server_terminate(task, "kdc: no KDC required in member server configuration", false); 890 881 return; 891 case ROLE_DOMAIN_CONTROLLER: 882 case ROLE_DOMAIN_PDC: 883 case ROLE_DOMAIN_BDC: 884 task_server_terminate(task, "Cannot start KDC as a 'classic Samba' DC", true); 885 return; 886 case ROLE_ACTIVE_DIRECTORY_DC: 892 887 /* Yes, we want a KDC */ 893 888 break; 894 889 } 895 890 896 load_interface s(task, lpcfg_interfaces(task->lp_ctx), &ifaces);897 898 if (iface_ count(ifaces) == 0) {891 load_interface_list(task, task->lp_ctx, &ifaces); 892 893 if (iface_list_count(ifaces) == 0) { 899 894 task_server_terminate(task, "kdc: no network interfaces configured", false); 900 895 return; … … 933 928 initialize_krb5_error_table(); 934 929 935 ret = smb_krb5_init_context(kdc, task-> event_ctx, task->lp_ctx, &kdc->smb_krb5_context);930 ret = smb_krb5_init_context(kdc, task->lp_ctx, &kdc->smb_krb5_context); 936 931 if (ret) { 937 932 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", … … 950 945 } 951 946 952 kdc->config->logf = kdc->smb_krb5_context->logf;947 kdc->config->logf = (krb5_log_facility *)kdc->smb_krb5_context->pvt_log_data; 953 948 kdc->config->db = talloc(kdc, struct HDB *); 954 949 if (!kdc->config->db) { … … 957 952 } 958 953 kdc->config->num_db = 1; 954 955 /* 956 * This restores the behavior before 957 * commit 255e3e18e00f717d99f3bc57c8a8895ff624f3c3 958 * s4:heimdal: import lorikeet-heimdal-201107150856 959 * (commit 48936803fae4a2fb362c79365d31f420c917b85b) 960 * 961 * as_use_strongest_session_key,preauth_use_strongest_session_key 962 * and tgs_use_strongest_session_key are input to the 963 * _kdc_find_etype() function. The old bahavior is in 964 * the use_strongest_session_key=FALSE code path. 965 * (The only remaining difference in _kdc_find_etype() 966 * is the is_preauth parameter.) 967 * 968 * The old behavior in the _kdc_get_preferred_key() 969 * function is use_strongest_server_key=TRUE. 970 */ 971 kdc->config->as_use_strongest_session_key = false; 972 kdc->config->preauth_use_strongest_session_key = false; 973 kdc->config->tgs_use_strongest_session_key = false; 974 kdc->config->use_strongest_server_key = true; 959 975 960 976 /* Register hdb-samba4 hooks for use as a keytab */ … … 979 995 ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, 980 996 PLUGIN_TYPE_DATA, "hdb", 981 &hdb_samba4 );997 &hdb_samba4_interface); 982 998 if(ret) { 983 999 task_server_terminate(task, "kdc: failed to register hdb plugin", true); -
vendor/current/source4/kdc/kpasswdd.c
r740 r988 31 31 #include "param/param.h" 32 32 #include "kdc/kdc-glue.h" 33 #include "dsdb/common/util.h" 34 #include "kdc/kpasswd_glue.h" 33 35 34 36 /* Return true if there is a valid error packet formed in the error_blob */ … … 112 114 switch (reject_reason) { 113 115 case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT: 114 reject_string = talloc_asprintf(mem_ctx, "Password too short, password must be at least %d characters long ",116 reject_string = talloc_asprintf(mem_ctx, "Password too short, password must be at least %d characters long.", 115 117 dominfo->min_password_length); 116 118 break; … … 119 121 break; 120 122 case SAM_PWD_CHANGE_PWD_IN_HISTORY: 121 reject_string = "Password is already in password history"; 123 reject_string = talloc_asprintf(mem_ctx, "Password is already in password history. New password must not match any of your %d previous passwords.", 124 dominfo->password_history_length); 122 125 break; 123 126 default: 124 reject_string = talloc_asprintf(mem_ctx, "Password must be at least %d characters long, and cannot match any of your %d previous passwords", 125 dominfo->min_password_length, dominfo->password_history_length); 127 reject_string = "Password change rejected, password changes may not be permitted on this account, or the minimum password age may not have elapsed."; 126 128 break; 127 129 } … … 156 158 { 157 159 NTSTATUS status; 160 NTSTATUS result = NT_STATUS_UNSUCCESSFUL; 158 161 enum samPwdChangeReason reject_reason; 159 162 struct samr_DomInfo1 *dominfo; 160 struct samr_Password *oldLmHash, *oldNtHash; 161 struct ldb_context *samdb; 162 const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL }; 163 struct ldb_message **res; 164 int ret; 165 166 /* Fetch the old hashes to get the old password in order to perform 167 * the password change operation. Naturally it would be much better to 168 * have a password hash from an authentication around but this doesn't 169 * seem to be the case here. */ 170 ret = gendb_search(kdc->samdb, mem_ctx, NULL, &res, attrs, 171 "(&(objectClass=user)(sAMAccountName=%s))", 172 session_info->info->account_name); 173 if (ret != 1) { 174 return kpasswdd_make_error_reply(kdc, mem_ctx, 175 KRB5_KPASSWD_ACCESSDENIED, 176 "No such user when changing password", 177 reply); 178 } 179 180 status = samdb_result_passwords(mem_ctx, kdc->task->lp_ctx, res[0], 181 &oldLmHash, &oldNtHash); 163 const char *error_string; 164 165 status = samdb_kpasswd_change_password(mem_ctx, 166 kdc->task->lp_ctx, 167 kdc->task->event_ctx, 168 kdc->samdb, 169 session_info, 170 password, 171 &reject_reason, 172 &dominfo, 173 &error_string, 174 &result); 182 175 if (!NT_STATUS_IS_OK(status)) { 183 return kpasswdd_make_error_reply(kdc, mem_ctx, 184 KRB5_KPASSWD_ACCESSDENIED, 185 "Not permitted to change password", 186 reply); 187 } 188 189 /* Start a SAM with user privileges for the password change */ 190 samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, 191 session_info, 0); 192 if (!samdb) { 193 return kpasswdd_make_error_reply(kdc, mem_ctx, 194 KRB5_KPASSWD_HARDERROR, 195 "Failed to open samdb", 196 reply); 197 } 198 199 DEBUG(3, ("Changing password of %s\\%s (%s)\n", 200 session_info->info->domain_name, 201 session_info->info->account_name, 202 dom_sid_string(mem_ctx, &session_info->security_token->sids[PRIMARY_USER_SID_INDEX]))); 203 204 /* Performs the password change */ 205 status = samdb_set_password_sid(samdb, mem_ctx, 206 &session_info->security_token->sids[PRIMARY_USER_SID_INDEX], 207 password, NULL, NULL, 208 oldLmHash, oldNtHash, /* this is a user password change */ 209 &reject_reason, 210 &dominfo); 211 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 212 status, 176 return kpasswdd_make_error_reply(kdc, 177 mem_ctx, 178 KRB5_KPASSWD_ACCESSDENIED, 179 error_string, 180 reply); 181 } 182 183 return kpasswd_make_pwchange_reply(kdc, 184 mem_ctx, 185 result, 213 186 reject_reason, 214 187 dominfo, 215 188 reply); 216 217 189 } 218 190 … … 228 200 229 201 if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security, 202 mem_ctx, 230 203 &session_info))) { 231 204 return kpasswdd_make_error_reply(kdc, mem_ctx, … … 239 212 { 240 213 DATA_BLOB password; 241 if (!convert_string_talloc_ convenience(mem_ctx, lpcfg_iconv_convenience(kdc->task->lp_ctx),214 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(kdc->task->lp_ctx), 242 215 CH_UTF8, CH_UTF16, 243 216 (const char *)input->data, 244 217 input->length, 245 (void **)&password.data, &pw_len , false)) {218 (void **)&password.data, &pw_len)) { 246 219 return false; 247 220 } … … 279 252 } 280 253 281 if (!convert_string_talloc_ convenience(mem_ctx, lpcfg_iconv_convenience(kdc->task->lp_ctx),254 if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(kdc->task->lp_ctx), 282 255 CH_UTF8, CH_UTF16, 283 256 (const char *)chpw.newpasswd.data, 284 257 chpw.newpasswd.length, 285 (void **)&password.data, &pw_len , false)) {258 (void **)&password.data, &pw_len)) { 286 259 free_ChangePasswdDataMS(&chpw); 287 260 return false; … … 544 517 * complex code */ 545 518 546 nt_status = gensec_set_ local_address(gensec_security, peer_addr);519 nt_status = gensec_set_remote_address(gensec_security, peer_addr); 547 520 if (!NT_STATUS_IS_OK(nt_status)) { 548 521 talloc_free(tmp_ctx); … … 567 540 568 541 /* Accept the AP-REQ and generate teh AP-REP we need for the reply */ 569 nt_status = gensec_update (gensec_security, tmp_ctx, ap_req, &ap_rep);542 nt_status = gensec_update_ev(gensec_security, tmp_ctx, kdc->task->event_ctx, ap_req, &ap_rep); 570 543 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { 571 544 -
vendor/current/source4/kdc/mit_samba.c
r740 r988 196 196 DATA_BLOB *pac_blob; 197 197 NTSTATUS nt_status; 198 struct samba_kdc_entry *skdc_entry; 199 200 skdc_entry = talloc_get_type_abort(client->ctx, 201 struct samba_kdc_entry); 198 202 199 203 tmp_ctx = talloc_named(ctx, 0, "mit_samba_get_pac_data context"); … … 202 206 } 203 207 204 nt_status = samba_kdc_get_pac_blob(tmp_ctx, client, &pac_blob);208 nt_status = samba_kdc_get_pac_blob(tmp_ctx, skdc_entry, &pac_blob); 205 209 if (!NT_STATUS_IS_OK(nt_status)) { 206 210 talloc_free(tmp_ctx); … … 231 235 krb5_pac pac = NULL; 232 236 int ret; 237 struct samba_kdc_entry *skdc_entry = NULL; 238 239 if (client) { 240 skdc_entry = talloc_get_type_abort(client->ctx, 241 struct samba_kdc_entry); 242 } 233 243 234 244 /* The user account may be set not to want the PAC */ 235 if (client && !samba_princ_needs_pac(client)) {245 if (client && !samba_princ_needs_pac(skdc_entry)) { 236 246 return EINVAL; 237 247 } … … 255 265 } 256 266 267 /* TODO: An implementation-specific decision will need to be 268 * made as to when to check the KDC pac signature, and how to 269 * untrust untrusted RODCs */ 257 270 nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context, 258 &pac, logon_blob);271 pac, logon_blob, NULL, NULL); 259 272 if (!NT_STATUS_IS_OK(nt_status)) { 260 273 DEBUG(0, ("Building PAC failed: %s\n", … … 278 291 talloc_free(tmp_ctx); 279 292 return ret; 293 } 294 295 /* provide header, function is exported but there are no public headers */ 296 297 krb5_error_code encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code); 298 299 /* this function allocates 'data' using malloc. 300 * The caller is responsible for freeing it */ 301 static void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data) 302 { 303 krb5_error_code ret = 0; 304 krb5_pa_data pa, *ppa = NULL; 305 krb5_data *d = NULL; 306 307 if (!e_data) 308 return; 309 310 e_data->data = NULL; 311 e_data->length = 0; 312 313 pa.magic = KV5M_PA_DATA; 314 pa.pa_type = KRB5_PADATA_PW_SALT; 315 pa.length = 12; 316 pa.contents = malloc(pa.length); 317 if (!pa.contents) { 318 return; 319 } 320 321 SIVAL(pa.contents, 0, NT_STATUS_V(nt_status)); 322 SIVAL(pa.contents, 4, 0); 323 SIVAL(pa.contents, 8, 1); 324 325 ppa = &pa; 326 327 ret = encode_krb5_padata_sequence(&ppa, &d); 328 free(pa.contents); 329 if (ret) { 330 return; 331 } 332 333 e_data->data = (uint8_t *)d->data; 334 e_data->length = d->length; 335 336 /* free d, not d->data - gd */ 337 free(d); 338 339 return; 280 340 } 281 341 … … 317 377 bool is_nt_enterprise_name) 318 378 { 379 #if 1 380 /* 381 * This is disabled because mit_samba_update_pac_data() does not handle 382 * S4U_DELEGATION_INFO 383 */ 384 385 return KRB5KDC_ERR_BADOPTION; 386 #else 319 387 krb5_principal target_principal; 320 388 int flags = 0; … … 331 399 } 332 400 333 ret = samba_kdc_check_ identical_client_and_server(ctx->context,334 335 336 401 ret = samba_kdc_check_s4u2proxy(ctx->context, 402 ctx->db_ctx, 403 skdc_entry, 404 target_principal); 337 405 338 406 krb5_free_principal(ctx->context, target_principal); 339 407 340 408 return ret; 409 #endif 341 410 } 342 411 -
vendor/current/source4/kdc/pac-glue.c
r740 r988 27 27 #include "auth/auth.h" 28 28 #include "auth/auth_sam_reply.h" 29 #include "kdc/kdc-glue.h" 29 #include "system/kerberos.h" 30 #include "auth/kerberos/kerberos.h" 31 #include "kdc/samba_kdc.h" 32 #include "kdc/pac-glue.h" 30 33 #include "param/param.h" 31 34 #include "librpc/gen_ndr/ndr_krb5pac.h" 35 #include "libcli/security/security.h" 36 #include "dsdb/samdb/samdb.h" 37 #include "auth/kerberos/pac_utils.h" 32 38 33 39 static … … 51 57 52 58 pac_info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO); 53 if (! mem_ctx) {59 if (!pac_info.logon_info.info) { 54 60 return NT_STATUS_NO_MEMORY; 55 61 } … … 72 78 krb5_error_code samba_make_krb5_pac(krb5_context context, 73 79 DATA_BLOB *pac_blob, 80 DATA_BLOB *deleg_blob, 74 81 krb5_pac *pac) 75 82 { 76 83 krb5_data pac_data; 84 krb5_data deleg_data; 77 85 krb5_error_code ret; 78 86 … … 82 90 } 83 91 84 ret = krb5_data_copy(&pac_data, pac_blob->data, pac_blob->length); 92 ret = krb5_copy_data_contents(&pac_data, 93 pac_blob->data, 94 pac_blob->length); 85 95 if (ret != 0) { 86 96 return ret; 87 97 } 88 98 99 ZERO_STRUCT(deleg_data); 100 if (deleg_blob) { 101 ret = krb5_copy_data_contents(&deleg_data, 102 deleg_blob->data, 103 deleg_blob->length); 104 if (ret != 0) { 105 kerberos_free_data_contents(context, &pac_data); 106 return ret; 107 } 108 } 109 89 110 ret = krb5_pac_init(context, pac); 90 111 if (ret != 0) { 91 krb5_data_free(&pac_data); 112 kerberos_free_data_contents(context, &pac_data); 113 kerberos_free_data_contents(context, &deleg_data); 92 114 return ret; 93 115 } 94 116 95 117 ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data); 96 k rb5_data_free(&pac_data);118 kerberos_free_data_contents(context, &pac_data); 97 119 if (ret != 0) { 120 kerberos_free_data_contents(context, &deleg_data); 98 121 return ret; 99 122 } 100 123 124 if (deleg_blob) { 125 ret = krb5_pac_add_buffer(context, *pac, 126 PAC_TYPE_CONSTRAINED_DELEGATION, 127 &deleg_data); 128 kerberos_free_data_contents(context, &deleg_data); 129 if (ret != 0) { 130 return ret; 131 } 132 } 133 101 134 return ret; 102 135 } 103 136 104 bool samba_princ_needs_pac(struct hdb_entry_ex *princ) 105 { 106 107 struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry); 137 bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry) 138 { 139 108 140 uint32_t userAccountControl; 109 141 110 111 142 /* The service account may be set not to want the PAC */ 112 userAccountControl = ldb_msg_find_attr_as_uint( p->msg, "userAccountControl", 0);143 userAccountControl = ldb_msg_find_attr_as_uint(skdc_entry->msg, "userAccountControl", 0); 113 144 if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) { 114 145 return false; … … 118 149 } 119 150 120 /* Was the krbtgt an RODC (and we are not) */ 121 bool samba_krbtgt_was_untrusted_rodc(struct hdb_entry_ex *princ) 122 { 123 124 struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry); 125 int rodc_krbtgt_number; 126 127 /* Determine if this was printed by an RODC */ 151 /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */ 152 int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, 153 bool *is_in_db, 154 bool *is_untrusted) 155 { 156 NTSTATUS status; 157 int rodc_krbtgt_number, trust_direction; 158 uint32_t rid; 159 160 TALLOC_CTX *mem_ctx = talloc_new(NULL); 161 if (!mem_ctx) { 162 return ENOMEM; 163 } 164 165 trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0); 166 167 if (trust_direction != 0) { 168 /* Domain trust - we cannot check the sig, but we trust it for a correct PAC 169 170 This is exactly where we should flag for SID 171 validation when we do inter-foreest trusts 172 */ 173 talloc_free(mem_ctx); 174 *is_untrusted = false; 175 *is_in_db = false; 176 return 0; 177 } 178 179 /* The lack of password controls etc applies to krbtgt by 180 * virtue of being that particular RID */ 181 status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"), NULL, &rid); 182 183 if (!NT_STATUS_IS_OK(status)) { 184 talloc_free(mem_ctx); 185 return EINVAL; 186 } 187 128 188 rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1); 129 if (rodc_krbtgt_number == -1) { 130 return false; 131 } else if (rodc_krbtgt_number != p->kdc_db_ctx->my_krbtgt_number) { 132 return true; 133 } 134 135 return false; 189 190 if (p->kdc_db_ctx->my_krbtgt_number == 0) { 191 if (rid == DOMAIN_RID_KRBTGT) { 192 *is_untrusted = false; 193 *is_in_db = true; 194 talloc_free(mem_ctx); 195 return 0; 196 } else if (rodc_krbtgt_number != -1) { 197 *is_in_db = true; 198 *is_untrusted = true; 199 talloc_free(mem_ctx); 200 return 0; 201 } 202 } else if ((rid != DOMAIN_RID_KRBTGT) && (rodc_krbtgt_number == p->kdc_db_ctx->my_krbtgt_number)) { 203 talloc_free(mem_ctx); 204 *is_untrusted = false; 205 *is_in_db = true; 206 return 0; 207 } else if (rid == DOMAIN_RID_KRBTGT) { 208 /* krbtgt viewed from an RODC */ 209 talloc_free(mem_ctx); 210 *is_untrusted = false; 211 *is_in_db = false; 212 return 0; 213 } 214 215 /* Another RODC */ 216 talloc_free(mem_ctx); 217 *is_untrusted = true; 218 *is_in_db = false; 219 return 0; 136 220 } 137 221 138 222 NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, 139 struct hdb_entry_ex *client,223 struct samba_kdc_entry *p, 140 224 DATA_BLOB **_pac_blob) 141 225 { 142 struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry);143 226 struct auth_user_info_dc *user_info_dc; 144 227 DATA_BLOB *pac_blob; … … 146 229 147 230 /* The user account may be set not to want the PAC */ 148 if ( ! samba_princ_needs_pac( client)) {231 if ( ! samba_princ_needs_pac(p)) { 149 232 *_pac_blob = NULL; 150 233 return NT_STATUS_OK; … … 183 266 NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, 184 267 krb5_context context, 185 krb5_pac *pac, DATA_BLOB *pac_blob) 268 const krb5_pac pac, DATA_BLOB *pac_blob, 269 struct PAC_SIGNATURE_DATA *pac_srv_sig, 270 struct PAC_SIGNATURE_DATA *pac_kdc_sig) 186 271 { 187 272 struct auth_user_info_dc *user_info_dc; … … 189 274 NTSTATUS nt_status; 190 275 191 ret = kerberos_pac_to_user_info_dc(mem_ctx, *pac,192 context, &user_info_dc, NULL, NULL);276 ret = kerberos_pac_to_user_info_dc(mem_ctx, pac, 277 context, &user_info_dc, pac_srv_sig, pac_kdc_sig); 193 278 if (ret) { 194 279 return NT_STATUS_UNSUCCESSFUL; … … 201 286 } 202 287 203 /* this function allocates 'data' using malloc. 204 * The caller is responsible for freeing it */ 205 void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data) 206 { 207 PA_DATA pa; 208 unsigned char *buf; 209 size_t len; 210 krb5_error_code ret = 0; 211 212 if (!e_data) 213 return; 214 215 pa.padata_type = KRB5_PADATA_PW_SALT; 216 pa.padata_value.length = 12; 217 pa.padata_value.data = malloc(pa.padata_value.length); 218 if (!pa.padata_value.data) { 219 e_data->length = 0; 220 e_data->data = NULL; 221 return; 222 } 223 224 SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status)); 225 SIVAL(pa.padata_value.data, 4, 0); 226 SIVAL(pa.padata_value.data, 8, 1); 227 228 ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret); 229 free(pa.padata_value.data); 230 231 e_data->data = buf; 232 e_data->length = len; 233 234 return; 288 NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx, 289 krb5_context context, 290 const krb5_pac pac, 291 const krb5_principal server_principal, 292 const krb5_principal proxy_principal, 293 DATA_BLOB *new_blob) 294 { 295 krb5_data old_data; 296 DATA_BLOB old_blob; 297 krb5_error_code ret; 298 NTSTATUS nt_status; 299 enum ndr_err_code ndr_err; 300 union PAC_INFO info; 301 struct PAC_CONSTRAINED_DELEGATION _d; 302 struct PAC_CONSTRAINED_DELEGATION *d = NULL; 303 char *server = NULL; 304 char *proxy = NULL; 305 uint32_t i; 306 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 307 308 if (tmp_ctx == NULL) { 309 return NT_STATUS_NO_MEMORY; 310 } 311 312 ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data); 313 if (ret == ENOENT) { 314 ZERO_STRUCT(old_data); 315 } else if (ret) { 316 talloc_free(tmp_ctx); 317 return NT_STATUS_UNSUCCESSFUL; 318 } 319 320 old_blob.length = old_data.length; 321 old_blob.data = (uint8_t *)old_data.data; 322 323 ZERO_STRUCT(info); 324 if (old_blob.length > 0) { 325 ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx, 326 &info, PAC_TYPE_CONSTRAINED_DELEGATION, 327 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); 328 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 329 kerberos_free_data_contents(context, &old_data); 330 nt_status = ndr_map_error2ntstatus(ndr_err); 331 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status))); 332 talloc_free(tmp_ctx); 333 return nt_status; 334 } 335 } else { 336 ZERO_STRUCT(_d); 337 info.constrained_delegation.info = &_d; 338 } 339 kerberos_free_data_contents(context, &old_data); 340 341 ret = krb5_unparse_name(context, server_principal, &server); 342 if (ret) { 343 talloc_free(tmp_ctx); 344 return NT_STATUS_INTERNAL_ERROR; 345 } 346 347 ret = krb5_unparse_name_flags(context, proxy_principal, 348 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &proxy); 349 if (ret) { 350 SAFE_FREE(server); 351 talloc_free(tmp_ctx); 352 return NT_STATUS_INTERNAL_ERROR; 353 } 354 355 d = info.constrained_delegation.info; 356 i = d->num_transited_services; 357 d->proxy_target.string = server; 358 d->transited_services = talloc_realloc(mem_ctx, d->transited_services, 359 struct lsa_String, i + 1); 360 d->transited_services[i].string = proxy; 361 d->num_transited_services = i + 1; 362 363 ndr_err = ndr_push_union_blob(new_blob, mem_ctx, 364 &info, PAC_TYPE_CONSTRAINED_DELEGATION, 365 (ndr_push_flags_fn_t)ndr_push_PAC_INFO); 366 SAFE_FREE(server); 367 SAFE_FREE(proxy); 368 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 369 kerberos_free_data_contents(context, &old_data); 370 nt_status = ndr_map_error2ntstatus(ndr_err); 371 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status))); 372 talloc_free(tmp_ctx); 373 return nt_status; 374 } 375 376 talloc_free(tmp_ctx); 377 return NT_STATUS_OK; 235 378 } 236 379 … … 241 384 242 385 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) 243 ret = KRB5KDC_ERR_KEY_EXP IRED;386 ret = KRB5KDC_ERR_KEY_EXP; 244 387 else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) 245 ret = KRB5KDC_ERR_KEY_EXP IRED;388 ret = KRB5KDC_ERR_KEY_EXP; 246 389 else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) 247 390 ret = KRB5KDC_ERR_CLIENT_REVOKED; … … 287 430 return nt_status; 288 431 } 289 -
vendor/current/source4/kdc/pac-glue.h
r740 r988 24 24 krb5_error_code samba_make_krb5_pac(krb5_context context, 25 25 DATA_BLOB *pac_blob, 26 DATA_BLOB *deleg_blob, 26 27 krb5_pac *pac); 27 28 28 bool samba_princ_needs_pac(struct hdb_entry_ex *princ);29 bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry); 29 30 30 bool samba_krbtgt_was_untrusted_rodc(struct hdb_entry_ex *princ); 31 int samba_krbtgt_is_in_db(struct samba_kdc_entry *skdc_entry, 32 bool *is_in_db, 33 bool *is_untrusted); 31 34 32 35 NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, 33 struct hdb_entry_ex *client,36 struct samba_kdc_entry *skdc_entry, 34 37 DATA_BLOB **_pac_blob); 35 38 36 39 NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, 37 40 krb5_context context, 38 krb5_pac *pac, DATA_BLOB *pac_blob); 41 const krb5_pac pac, DATA_BLOB *pac_blob, 42 struct PAC_SIGNATURE_DATA *pac_srv_sig, 43 struct PAC_SIGNATURE_DATA *pac_kdc_sig); 39 44 40 void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data); 45 NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx, 46 krb5_context context, 47 const krb5_pac pac, 48 const krb5_principal server_principal, 49 const krb5_principal proxy_principal, 50 DATA_BLOB *pac_blob); 41 51 42 52 krb5_error_code samba_kdc_map_policy_err(NTSTATUS nt_status); -
vendor/current/source4/kdc/proxy.c
r740 r988 557 557 state->out = data_blob_talloc(state, raw.data + 4, raw.length - 4); 558 558 if (state->out.length != raw.length - 4) { 559 tevent_req_ nomem(NULL,req);559 tevent_req_oom(req); 560 560 return; 561 561 } -
vendor/current/source4/kdc/samba_kdc.h
r740 r988 22 22 */ 23 23 24 #ifndef _SAMBA_KDC_H_ 25 #define _SAMBA_KDC_H_ 26 27 struct samba_kdc_policy { 28 time_t svc_tkt_lifetime; 29 time_t usr_tkt_lifetime; 30 time_t renewal_lifetime; 31 }; 32 24 33 struct samba_kdc_base_context { 25 34 struct tevent_context *ev_ctx; … … 37 46 unsigned int my_krbtgt_number; 38 47 struct ldb_dn *krbtgt_dn; 39 struct lsa_DomainInfoKerberospolicy;48 struct samba_kdc_policy policy; 40 49 }; 41 50 … … 44 53 struct ldb_message *msg; 45 54 struct ldb_dn *realm_dn; 46 hdb_entry_ex*entry_ex;55 void *entry_ex; 47 56 }; 57 58 extern struct hdb_method hdb_samba4_interface; 59 60 #endif /* _SAMBA_KDC_H_ */ -
vendor/current/source4/kdc/wdc-samba4.c
r740 r988 35 35 krb5_error_code ret; 36 36 NTSTATUS nt_status; 37 struct samba_kdc_entry *skdc_entry = 38 talloc_get_type_abort(client->ctx, 39 struct samba_kdc_entry); 37 40 38 41 mem_ctx = talloc_named(client->ctx, 0, "samba_get_pac context"); … … 41 44 } 42 45 43 nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob);46 nt_status = samba_kdc_get_pac_blob(mem_ctx, skdc_entry, &pac_blob); 44 47 if (!NT_STATUS_IS_OK(nt_status)) { 45 48 talloc_free(mem_ctx); … … 47 50 } 48 51 49 ret = samba_make_krb5_pac(context, pac_blob, pac);52 ret = samba_make_krb5_pac(context, pac_blob, NULL, pac); 50 53 51 54 talloc_free(mem_ctx); … … 57 60 static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context, 58 61 const krb5_principal client_principal, 62 const krb5_principal delegated_proxy_principal, 59 63 struct hdb_entry_ex *client, 60 64 struct hdb_entry_ex *server, … … 62 66 krb5_pac *pac) 63 67 { 64 struct samba_kdc_entry *p = talloc_get_type(server->ctx, struct samba_kdc_entry); 68 struct samba_kdc_entry *p = 69 talloc_get_type_abort(server->ctx, 70 struct samba_kdc_entry); 71 struct samba_kdc_entry *krbtgt_skdc_entry = 72 talloc_get_type_abort(krbtgt->ctx, 73 struct samba_kdc_entry); 65 74 TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context"); 66 75 DATA_BLOB *pac_blob; 76 DATA_BLOB *deleg_blob = NULL; 67 77 krb5_error_code ret; 68 78 NTSTATUS nt_status; 79 struct PAC_SIGNATURE_DATA *pac_srv_sig; 80 struct PAC_SIGNATURE_DATA *pac_kdc_sig; 81 bool is_in_db, is_untrusted; 69 82 70 83 if (!mem_ctx) { … … 73 86 74 87 /* The user account may be set not to want the PAC */ 75 if (!samba_princ_needs_pac( server)) {88 if (!samba_princ_needs_pac(p)) { 76 89 talloc_free(mem_ctx); 77 90 return EINVAL; … … 81 94 * RODC, then we need to regenerate the PAC - we can't trust 82 95 * it */ 83 if (samba_krbtgt_was_untrusted_rodc(krbtgt)) { 96 ret = samba_krbtgt_is_in_db(krbtgt_skdc_entry, &is_in_db, &is_untrusted); 97 if (ret != 0) { 98 talloc_free(mem_ctx); 99 return ret; 100 } 101 102 if (is_untrusted) { 103 struct samba_kdc_entry *client_skdc_entry = NULL; 104 84 105 if (client == NULL) { 85 106 return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; 86 107 } 87 nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob); 108 109 client_skdc_entry = talloc_get_type_abort(client->ctx, 110 struct samba_kdc_entry); 111 112 nt_status = samba_kdc_get_pac_blob(mem_ctx, client_skdc_entry, &pac_blob); 88 113 if (!NT_STATUS_IS_OK(nt_status)) { 89 114 talloc_free(mem_ctx); … … 97 122 } 98 123 124 pac_srv_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); 125 if (!pac_srv_sig) { 126 talloc_free(mem_ctx); 127 return ENOMEM; 128 } 129 130 pac_kdc_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA); 131 if (!pac_kdc_sig) { 132 talloc_free(mem_ctx); 133 return ENOMEM; 134 } 135 99 136 nt_status = samba_kdc_update_pac_blob(mem_ctx, context, 100 pac, pac_blob); 137 *pac, pac_blob, 138 pac_srv_sig, pac_kdc_sig); 101 139 if (!NT_STATUS_IS_OK(nt_status)) { 102 140 DEBUG(0, ("Building PAC failed: %s\n", … … 105 143 return EINVAL; 106 144 } 107 } 145 146 if (is_in_db) { 147 /* Now check the KDC signature, fetching the correct key based on the enc type */ 148 ret = kdc_check_pac(context, pac_srv_sig->signature, pac_kdc_sig, krbtgt); 149 if (ret != 0) { 150 DEBUG(1, ("PAC KDC signature failed to verify\n")); 151 talloc_free(mem_ctx); 152 return ret; 153 } 154 } 155 } 156 157 if (delegated_proxy_principal) { 158 deleg_blob = talloc_zero(mem_ctx, DATA_BLOB); 159 if (!deleg_blob) { 160 talloc_free(mem_ctx); 161 return ENOMEM; 162 } 163 164 nt_status = samba_kdc_update_delegation_info_blob(mem_ctx, 165 context, *pac, 166 server->entry.principal, 167 delegated_proxy_principal, 168 deleg_blob); 169 if (!NT_STATUS_IS_OK(nt_status)) { 170 DEBUG(0, ("Building PAC failed: %s\n", 171 nt_errstr(nt_status))); 172 talloc_free(mem_ctx); 173 return EINVAL; 174 } 175 } 176 108 177 /* We now completely regenerate this pac */ 109 178 krb5_pac_free(context, *pac); 110 179 111 ret = samba_make_krb5_pac(context, pac_blob, pac);180 ret = samba_make_krb5_pac(context, pac_blob, deleg_blob, pac); 112 181 113 182 talloc_free(mem_ctx); … … 133 202 } 134 203 135 if ( nb_name == NULL) {204 if ((nb_name == NULL) || (nb_name[0] == '\0')) { 136 205 return NULL; 137 206 } 138 207 139 208 /* Strip space padding */ 140 i = strlen(nb_name) - 1; 141 while (i > 0 && nb_name[i] == ' ') { 142 nb_name[i] = '\0'; 209 for (len = strlen(nb_name) - 1; 210 (len > 0) && (nb_name[len] == ' '); 211 --len) { 212 nb_name[len] = '\0'; 143 213 } 144 214 … … 155 225 return kdata; 156 226 } 227 228 /* this function allocates 'data' using malloc. 229 * The caller is responsible for freeing it */ 230 static void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data) 231 { 232 krb5_error_code ret = 0; 233 PA_DATA pa; 234 unsigned char *buf; 235 size_t len; 236 237 if (!e_data) 238 return; 239 240 e_data->data = NULL; 241 e_data->length = 0; 242 243 pa.padata_type = KRB5_PADATA_PW_SALT; 244 pa.padata_value.length = 12; 245 pa.padata_value.data = malloc(pa.padata_value.length); 246 if (!pa.padata_value.data) { 247 e_data->length = 0; 248 e_data->data = NULL; 249 return; 250 } 251 252 SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status)); 253 SIVAL(pa.padata_value.data, 4, 0); 254 SIVAL(pa.padata_value.data, 8, 1); 255 256 ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret); 257 free(pa.padata_value.data); 258 if (ret) { 259 return; 260 } 261 262 e_data->data = buf; 263 e_data->length = len; 264 265 return; 266 } 267 157 268 158 269 static krb5_error_code samba_wdc_check_client_access(void *priv, … … 213 324 214 325 struct krb5plugin_windc_ftable windc_plugin_table = { 215 .minor_version = KRB5_WINDC_PLUGIN G_MINOR,326 .minor_version = KRB5_WINDC_PLUGIN_MINOR, 216 327 .init = samba_wdc_plugin_init, 217 328 .fini = samba_wdc_plugin_fini, -
vendor/current/source4/kdc/wscript_build
r740 r988 1 1 #!/usr/bin/env python 2 2 3 # We do this because we do not want to depend on the KDC, only find and use it's header files. We do not want 4 if not bld.CONFIG_SET("USING_SYSTEM_KDC"): 5 kdc_include = "../heimdal/kdc" 6 else: 7 kdc_include = getattr(bld.env, "CPPPATH_KDC") 8 3 9 bld.SAMBA_MODULE('service_kdc', 4 source='kdc.c kpasswdd.c proxy.c', 5 subsystem='service', 6 init_function='server_service_kdc_init', 7 deps='kdc HDB_SAMBA4 WDC_SAMBA4 samba-hostconfig LIBTSOCKET LIBSAMBA_TSOCKET com_err samba_server_gensec', 8 internal_module=False, 10 source='kdc.c kpasswdd.c proxy.c', 11 subsystem='service', 12 init_function='server_service_kdc_init', 13 deps=''' 14 kdc 15 HDB_SAMBA4 16 WDC_SAMBA4 17 samba-hostconfig 18 LIBTSOCKET 19 LIBSAMBA_TSOCKET 20 com_err 21 samba_server_gensec 22 PAC_GLUE 23 KDC-GLUE 24 KPASSWD_GLUE 25 ''', 26 internal_module=False) 27 28 bld.SAMBA_LIBRARY('HDB_SAMBA4', 29 source='hdb-samba4.c hdb-samba4-plugin.c', 30 deps='ldb auth4_sam auth_sam_reply samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb', 31 includes=kdc_include, 32 private_library=True, 33 enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') 34 ) 35 36 # A plugin for Heimdal's kadmin for users who need to operate that tool 37 bld.SAMBA_LIBRARY('HDB_SAMBA4_PLUGIN', 38 source='hdb-samba4-plugin.c', 39 deps='hdb HDB_SAMBA4 samba-util samba-hostconfig ', 40 includes=kdc_include, 41 link_name='modules/hdb/hdb_samba4.so', 42 realname='hdb_samba4.so', 43 install_path='${MODULESDIR}/hdb', 44 enabled = (bld.CONFIG_SET("USING_SYSTEM_KRB5") and bld.CONFIG_SET("USING_SYSTEM_HDB")) 45 ) 46 47 bld.SAMBA_SUBSYSTEM('KDC-GLUE', 48 source='kdc-glue.c', 49 includes=kdc_include, 50 deps='hdb PAC_GLUE', 51 enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') 9 52 ) 10 11 12 bld.SAMBA_SUBSYSTEM('HDB_SAMBA4',13 source='hdb-samba4.c',14 deps='ldb auth4_sam auth_sam_reply credentials hdb db-glue samba-hostconfig com_err',15 includes='../heimdal/kdc',16 )17 18 53 19 54 bld.SAMBA_SUBSYSTEM('WDC_SAMBA4', 20 55 source='wdc-samba4.c', 21 includes='../heimdal/kdc', 22 deps='ldb auth4_sam auth_sam_reply credentials hdb PAC_GLUE samba-hostconfig com_err' 56 includes=kdc_include, 57 deps='ldb auth4_sam auth_sam_reply samba-credentials hdb PAC_GLUE samba-hostconfig com_err KDC-GLUE', 58 enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') 23 59 ) 24 60 61 bld.SAMBA_SUBSYSTEM('sdb', 62 source='sdb.c', 63 includes=kdc_include, 64 deps='talloc krb5', 65 ) 66 67 bld.SAMBA_SUBSYSTEM('sdb_hdb', 68 source='sdb_to_hdb.c', 69 includes=kdc_include, 70 deps='talloc sdb hdb', 71 autoproto='sdb_hdb.h', 72 enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') 73 ) 25 74 26 75 bld.SAMBA_SUBSYSTEM('PAC_GLUE', 27 76 source='pac-glue.c', 28 includes='../heimdal/kdc',29 deps='ldb auth4_sam auth_sam_reply credentials hdbsamba-hostconfig com_err'77 includes=kdc_include, 78 deps='ldb auth4_sam auth_sam_reply samba-credentials samba-hostconfig com_err' 30 79 ) 31 80 … … 39 88 bld.SAMBA_LIBRARY('db-glue', 40 89 source='db-glue.c', 41 deps='ldb auth4_sam auth_sam_reply credentials hdb samba-hostconfig com_err kdc-policy', 42 private_library=True 90 deps='ldb auth4_sam auth_sam_reply samba-credentials sdb samba-hostconfig com_err', 91 private_library=True, 92 includes=kdc_include, 43 93 ) 44 94 45 bld.SAMBA_LIBRARY('kdc-policy', 46 source='policy.c', 47 deps='samba-hostconfig authkrb5', 48 private_library=True, 49 autoproto = 'kdc-policy-proto.h' 50 ) 51 95 bld.SAMBA_SUBSYSTEM('KPASSWD_GLUE', 96 source='kpasswd_glue.c', 97 includes=kdc_include, 98 deps='ldb com_err') 52 99 53 100 bld.SAMBA_SUBSYSTEM('MIT_SAMBA', 54 source='mit_samba.c', 55 deps='ldb auth4_sam auth_sam_reply credentials hdb db-glue PAC_GLUE samba-hostconfig com_err' 56 ) 57 58 59 bld.SAMBA_LIBRARY('mit-samba', 60 source='', 61 deps='MIT_SAMBA', 62 external_library=True, 63 realname='mit_samba.so' 64 ) 65 101 source='mit_samba.c', 102 deps=''' 103 ldb 104 auth4_sam 105 auth_sam_reply 106 samba-credentials 107 hdb 108 db-glue 109 PAC_GLUE 110 samba-hostconfig 111 com_err 112 ''', 113 enabled=not bld.CONFIG_SET('SAMBA4_USES_HEIMDAL'))
Note:
See TracChangeset
for help on using the changeset viewer.