# HG changeset patch # User Shawn Emery # Date 1258072834 25200 # Node ID 1e27eb9fbdd728ddaac57a34268020ba7fab2bcf # Parent 40daac51fc0c6ef5ac14f67b33248891bc228e15 6885980 Need case-insensitive keytab lookups for MS interop 6885387 gsskrb5_extract_authz_data_from_sec_context() fails with service ticket sent by Windows 7 client 6858400 kclient cant join Windows AD domain if hostname is 20 characters or longer 6867203 Solaris acceptors fail in Windows 2000 environment 6868908 Solaris acceptors should have returned KRB5KRB_AP_ERR_MODIFIED for Microsoft interoperability 6867208 Windows client cannot recover from KRB5KRB_AP_ERR_SKEW error diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/cmd/krb5/kadmin/kclient/kclient.sh --- a/usr/src/cmd/krb5/kadmin/kclient/kclient.sh Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/cmd/krb5/kadmin/kclient/kclient.sh Thu Nov 12 17:40:34 2009 -0700 @@ -29,6 +29,7 @@ # be generated and local host's keytab file setup. The script # can also optionally setup the system to do kerberized nfs and # bringover a master krb5.conf copy from a specified location. +# function cleanup { @@ -1156,6 +1157,8 @@ function join_domain { typeset -u upcase_nodename + typeset -l locase_nodename + typeset -L15 string15 typeset netbios_nodename fqdn container=Computers @@ -1175,7 +1178,16 @@ dom=$domain realm=$domain - upcase_nodename=$hostname + + if [[ ${#hostname} -gt 15 ]]; then + string15=$hostname + upcase_nodename=$string15 + locase_nodename=$string15 + else + upcase_nodename=$hostname + locase_nodename=$hostname + fi + netbios_nodename="${upcase_nodename}\$" fqdn=$hostname.$domain upn=host/${fqdn}@${realm} @@ -1313,9 +1325,10 @@ fi fi + [[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}" if $modify_existing; then cat > "$object" < /dev/null 2>&1 if [[ $? -ne 0 ]]; then - printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2 + printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2 error_message fi else + dn="CN=${upcase_nodename},${baseDN}" cat > "$object" < "$object" < "$object" < /dev/null 2>&1 cat > "$object" </dev/null 2>&1 if [[ $? -ne 0 ]]; then @@ -1507,10 +1522,10 @@ # # In Windows, unlike MIT based implementations we salt the keys with - # the UPN, which is based on the host/fqdn@realm elements, not with the - # individual SPN strings. + # the UPN, which is based on the host/string15@realm elements, not + # with the individual SPN strings. # - salt=host/${fqdn}@${realm} + salt=host/${locase_nodename}.${domain}@${realm} printf "%s" $newpw | $KSETPW -n -s $salt -v $kvno -k "$new_keytab" "${args[@]}" host/${fqdn}@${realm} > /dev/null 2>&1 if [[ $? -ne 0 ]] @@ -1519,16 +1534,6 @@ error_message fi - printf "%s" $newpw | $KSETPW -n -s $salt -v $kvno -k "$new_keytab" "${args[@]}" HOST/${fqdn}@${realm} > /dev/null 2>&1 - if [[ $? -ne 0 ]] - then - printf "$(gettext "Failed to set account password").\n" >&2 - error_message - fi - - # Could be setting ${netbios_nodename}@${realm}, but for now no one - # is requesting this. - printf "%s" $newpw | $KSETPW -n -s $salt -v $kvno -k "$new_keytab" "${args[@]}" nfs/${fqdn}@${realm} > /dev/null 2>&1 if [[ $? -ne 0 ]] then @@ -1557,13 +1562,20 @@ error_message fi + printf "%s" $newpw | $KSETPW -n -s $salt -v $kvno -k "$new_keytab" "${args[@]}" ${netbios_nodename}@${realm} > /dev/null 2>&1 + if [[ $? -ne 0 ]] + then + printf "$(gettext "Failed to set account password").\n" >&2 + error_message + fi + doKRB5config addDNSRR $dom setSMB $dom $dc - printf -- "\n---------------------------------------------------\n" + printf -- "---------------------------------------------------\n" printf "$(gettext "Setup COMPLETE").\n\n" kdestroy -q 1>$TMP_FILE 2>&1 diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/cmd/krb5/kadmin/kclient/ksetpw.c --- a/usr/src/cmd/krb5/kadmin/kclient/ksetpw.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/cmd/krb5/kadmin/kclient/ksetpw.c Thu Nov 12 17:40:34 2009 -0700 @@ -381,7 +381,7 @@ usage() { (void) fprintf(stderr, gettext("Usage: %s [-c ccache] [-k keytab] " - "[-e enctype_list] [-n] princ\n"), whoami); + "[-e enctype_list] [-s salt_name] [-n] princ\n"), whoami); (void) fprintf(stderr, gettext("\t-n\tDon't set the principal's password\n")); (void) fprintf(stderr, gettext("\tenctype_list is a comma or whitespace" diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c --- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c Thu Nov 12 17:40:34 2009 -0700 @@ -1,9 +1,8 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - /* * lib/krb5/keytab/kt_file.c * @@ -77,6 +76,10 @@ extern const struct _krb5_kt_ops krb5_ktf_ops; extern const struct _krb5_kt_ops krb5_ktf_writable_ops; +extern krb5_boolean KRB5_CALLCONV +__krb5_principal_compare_case_ins(krb5_context context, + krb5_const_principal princ1, krb5_const_principal princ2); + krb5_error_code KRB5_CALLCONV krb5_ktfile_resolve (krb5_context, const char *, @@ -291,7 +294,20 @@ /* if the principal isn't the one requested, free new_entry and continue to the next. */ - if (!krb5_principal_compare(context, principal, new_entry.principal)) { + /* + * Solaris Kerberos: MS Interop requires that case insensitive + * comparisons of service and host components are performed for key + * table lookup, etc. Only called if the private environment variable + * MS_INTEROP is defined. + */ + if (krb5_getenv("MS_INTEROP")) { + if (!__krb5_principal_compare_case_ins(context, principal, + new_entry.principal)) { + krb5_kt_free_entry(context, &new_entry); + continue; + } + } else if (!krb5_principal_compare(context, principal, + new_entry.principal)) { krb5_kt_free_entry(context, &new_entry); continue; } diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_krb5/krb5/krb/princ_comp.c --- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/princ_comp.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/princ_comp.c Thu Nov 12 17:40:34 2009 -0700 @@ -1,4 +1,3 @@ -#pragma ident "%Z%%M% %I% %E% SMI" /* * lib/krb5/krb/princ_comp.c * @@ -29,6 +28,11 @@ * not. */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #include /*ARGSUSED*/ @@ -68,6 +72,35 @@ return TRUE; } +/* + * Solaris Kerberos: MS Interop requires that case insensitive comparisons of + * service and host components are performed for key table lookup, etc. Only + * called if the private environment variable MS_INTEROP is defined. + */ +krb5_boolean KRB5_CALLCONV +__krb5_principal_compare_case_ins(krb5_context context, + krb5_const_principal princ1, krb5_const_principal princ2) +{ + register int i; + krb5_int32 nelem; + + nelem = krb5_princ_size(context, princ1); + if (nelem != krb5_princ_size(context, princ2)) + return FALSE; + + if (! krb5_realm_compare(context, princ1, princ2)) + return FALSE; + + for (i = 0; i < (int) nelem; i++) { + register const krb5_data *p1 = krb5_princ_component(context, princ1, i); + register const krb5_data *p2 = krb5_princ_component(context, princ2, i); + if (p1->length != p2->length || + strncasecmp(p1->data, p2->data, p1->length)) + return FALSE; + } + return TRUE; +} + krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *r) { /* diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_krb5/mapfile-vers --- a/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers Thu Nov 12 17:40:34 2009 -0700 @@ -219,6 +219,7 @@ gss_krb5_copy_ccache; gss_mech_krb5; gss_mech_krb5_old; + gss_mech_krb5_wrong; gss_mech_set_krb5; gss_mech_set_krb5_both; gss_mech_set_krb5_old; diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c --- a/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c Thu Nov 12 17:40:34 2009 -0700 @@ -1,7 +1,3 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ /* * Copyright 2000, 2004 by the Massachusetts Institute of Technology. * All Rights Reserved. @@ -74,6 +70,11 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + #include "k5-int.h" #include "gssapiP_krb5.h" #ifdef HAVE_MEMORY_H @@ -381,6 +382,12 @@ input_token->length, 1))) { mech_used = gss_mech_krb5; } else if ((code == G_WRONG_MECH) && + !(code = g_verify_token_header(gss_mech_krb5_wrong, + (uint32_t *)&(ap_req.length), + &ptr, KG_TOK_CTX_AP_REQ, + input_token->length, 1))) { + mech_used = gss_mech_krb5_wrong; + } else if ((code == G_WRONG_MECH) && !(code = g_verify_token_header(gss_mech_krb5_old, (uint32_t *)&(ap_req.length), &ptr, KG_TOK_CTX_AP_REQ, @@ -1169,6 +1176,37 @@ */ memset(&krb_error_data, 0, sizeof(krb_error_data)); + /* + * Solaris Kerberos: We need to remap error conditions for buggy + * Windows clients if the MS_INTEROP env var has been set. + */ + if ((code == KRB5KRB_AP_ERR_BAD_INTEGRITY || + code == KRB5KRB_AP_ERR_NOKEY || code == KRB5KRB_AP_ERR_BADKEYVER) + && krb5_getenv("MS_INTEROP")) { + code = KRB5KRB_AP_ERR_MODIFIED; + major_status = GSS_S_CONTINUE_NEEDED; + } + + /* + * SUNW17PACresync / Solaris Kerberos + * Set e-data to Windows constant. + * (verified by MSFT) + * + * This facilitates the Windows CIFS client clock skew + * recovery feature. + */ + if (code == KRB5KRB_AP_ERR_SKEW && krb5_getenv("MS_INTEROP")) { + char *ms_e_data = "\x30\x05\xa1\x03\x02\x01\x02"; + int len = strlen(ms_e_data); + + krb_error_data.e_data.data = malloc(len); + if (krb_error_data.e_data.data) { + (void) memcpy(krb_error_data.e_data.data, ms_e_data, len); + krb_error_data.e_data.length = len; + } + major_status = GSS_S_CONTINUE_NEEDED; + } + code -= ERROR_TABLE_BASE_krb5; if (code < 0 || code > 128) code = 60 /* KRB_ERR_GENERIC */; @@ -1178,25 +1216,6 @@ &krb_error_data.susec); krb_error_data.server = cred->princ; - if (code == KRB5KRB_AP_ERR_SKEW) { - /* - * SUNW17PACresync / Solaris Kerberos - * Set e-data to Windows constant. - * (verified by MSFT) - * - * This facilitates the Windows CIFS client clock skew - * recovery feature. - */ - char *ms_e_data = "\x30\x05\xa1\x03\x02\x01\x02"; - int len = strlen(ms_e_data); - - krb_error_data.e_data.data = malloc(len); - if (krb_error_data.e_data.data) { - (void) memcpy(krb_error_data.e_data.data, ms_e_data, len); - krb_error_data.e_data.length = len; - } - } - code = krb5_mk_error(context, &krb_error_data, &scratch); if (code) goto cleanup; diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c --- a/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c Thu Nov 12 17:40:34 2009 -0700 @@ -1326,8 +1326,13 @@ gss_mech_initialize(oid) const gss_OID oid; { + /* + * Solaris Kerberos: We also want to use the same functions for KRB5 as + * we do for the MS KRB5 (krb5_mechanism_wrong). So both are valid. + */ /* ensure that the requested oid matches our oid */ - if (oid == NULL || !g_OID_equal(oid, &krb5_mechanism.mech_type)) { + if (oid == NULL || (!g_OID_equal(oid, &krb5_mechanism.mech_type) && + !g_OID_equal(oid, &krb5_mechanism_wrong.mech_type))) { (void) syslog(LOG_INFO, "krb5mech: gss_mech_initialize: bad oid"); return (NULL); } @@ -1379,16 +1384,13 @@ return major_status; } - /* * SUNW17PACresync / Solaris Kerberos - * MIT17 expects just 1 but our testing with Win2008 shows - * it returns 2. So we now handle that and rewhack mem mgmt as appro. + * MIT17 allows only count==1 which is correct for pre-Win2008 but + * our testing with Win2008 shows count==2 and Win7 count==3. */ - if (data_set == GSS_C_NO_BUFFER_SET || - (data_set->count != 1 && data_set->count != 2)) { + if ((data_set == GSS_C_NO_BUFFER_SET) || (data_set->count == 0)) { gss_release_buffer_set(minor_status, &data_set); - return GSS_S_FAILURE; } diff -r 40daac51fc0c -r 1e27eb9fbdd7 usr/src/lib/gss_mechs/mech_spnego/mech/spnego_mech.c --- a/usr/src/lib/gss_mechs/mech_spnego/mech/spnego_mech.c Thu Nov 12 15:28:55 2009 -0800 +++ b/usr/src/lib/gss_mechs/mech_spnego/mech/spnego_mech.c Thu Nov 12 17:40:34 2009 -0700 @@ -2598,6 +2598,21 @@ memcmp(mechs->elements[i].elements, spnego_mechanism.mech_type.elements, spnego_mechanism.mech_type.length)) { + /* + * Solaris Kerberos: gss_indicate_mechs is stupid as + * it never inferences any of the related OIDs of the + * mechanisms configured, e.g. KRB5_OLD, KRB5_WRONG. + * We add KRB5_WRONG here so that old MS clients can + * negotiate this mechanism, which allows extensions + * in Kerberos (clock skew adjustment, refresh ccache). + */ + if (is_kerb_mech(&mechs->elements[i])) { + extern gss_OID_desc * const gss_mech_krb5_wrong; + + major_status = + gss_add_oid_set_member(minor_status, + gss_mech_krb5_wrong, rmechs); + } major_status = gss_add_oid_set_member(minor_status, &mechs->elements[i], @@ -3098,10 +3113,18 @@ for (i = 0; i < mechset->count; i++) { gss_OID mech_oid = &mechset->elements[i]; + /* + * Solaris Kerberos: MIT compares against MS' wrong OID, but + * we actually want to select it if the client supports, as this + * will enable features on MS clients that allow credential + * refresh on rekeying and caching system times from servers. + */ +#if 0 /* Accept wrong mechanism OID from MS clients */ if (mech_oid->length == gss_mech_krb5_wrong_oid.length && memcmp(mech_oid->elements, gss_mech_krb5_wrong_oid.elements, mech_oid->length) == 0) - mech_oid = (gss_OID)&gss_mech_krb5_oid;; + mech_oid = (gss_OID)&gss_mech_krb5_oid; +#endif gss_test_oid_set_member(minor_status, mech_oid, supported_mechSet, &present); if (!present)