From: Ken Raeburn Date: Fri, 30 Jan 2009 16:45:10 +0000 (+0000) Subject: merge to trunk r21834; no conflicts; tested on mac and linux X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=280f976cd7530f8c1d548403fddfa3e7fdd68f71;p=thirdparty%2Fkrb5.git merge to trunk r21834; no conflicts; tested on mac and linux git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mkey_migrate@21835 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/adm_proto.h b/src/include/adm_proto.h index 9d7002027b..9028da1a4e 100644 --- a/src/include/adm_proto.h +++ b/src/include/adm_proto.h @@ -97,6 +97,7 @@ krb5_error_code krb5_read_realm_params (krb5_context, krb5_realm_params **); krb5_error_code krb5_free_realm_params (krb5_context, krb5_realm_params *); +krb5_boolean match_config_pattern(const char *, const char *); /* str_conv.c */ krb5_error_code diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 063c303108..7de6c1a605 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1228,6 +1228,8 @@ struct _krb5_context { /* For Sun iprop code; does this really have to be here? */ struct _kdb_log_context *kdblog_context; + + krb5_boolean allow_weak_crypto; }; /* could be used in a table to find an etype and initialize a block */ @@ -2318,6 +2320,8 @@ typedef struct krb5_boolean krb5_is_permitted_enctype_ext ( krb5_context, krb5_etypes_permitted *); +krb5_boolean KRB5_CALLCONV krb5_c_weak_enctype(krb5_enctype); + krb5_error_code krb5_kdc_rep_decrypt_proc (krb5_context, const krb5_keyblock *, diff --git a/src/kadmin/testing/proto/krb5.conf.proto b/src/kadmin/testing/proto/krb5.conf.proto index c2648d6c67..b6ce16bff5 100644 --- a/src/kadmin/testing/proto/krb5.conf.proto +++ b/src/kadmin/testing/proto/krb5.conf.proto @@ -2,6 +2,7 @@ default_realm = __REALM__ default_keytab_name = FILE:__K5ROOT__/v5srvtab dns_fallback = no + allow_weak_crypto = true [realms] __REALM__ = { diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index f5bc3de0a3..1fb6812a5a 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -1,4 +1,3 @@ -/* -*- mode: c; indent-tabs-mode: nil -*- */ /* * kdc/do_tgs_req.c * @@ -71,21 +70,18 @@ #include "policy.h" #include "extern.h" #include "adm_proto.h" +#include -static void -find_alternate_tgs (krb5_kdc_req *, krb5_db_entry *, - krb5_boolean *, int *); +static void +find_alternate_tgs(krb5_kdc_req *,krb5_db_entry *, + krb5_boolean *,int *); -static krb5_error_code -prepare_error_tgs (krb5_kdc_req *, krb5_ticket *, - int, krb5_principal, - krb5_data **, const char *); +static krb5_error_code +prepare_error_tgs(krb5_kdc_req *,krb5_ticket *,int, + krb5_principal,krb5_data **,const char *); static krb5_int32 -is_substr (char *, krb5_data *); - -static krb5_int32 -prep_reprocess_req(krb5_kdc_req *, krb5_principal *); +prep_reprocess_req(krb5_kdc_req *,krb5_principal *); /*ARGSUSED*/ krb5_error_code @@ -190,7 +186,6 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from, } db_ref_done = FALSE; - ref_tgt_again: nprincs = 1; if ((errcode = krb5_unparse_name(kdc_context, request->server, &sname))) { @@ -1066,35 +1061,14 @@ find_alternate_tgs(krb5_kdc_req *request, krb5_db_entry *server, return; } -/* is_substr - verfies if d1 contains d2->data with head/trail-ing whitespaces - */ -static krb5_int32 -is_substr ( char *d1, krb5_data *d2) -{ - krb5_boolean ret = FALSE; - char *new_d2 = 0, *d2_formated = 0; - if ( d1 && d2 && d2->data && (d2->length+2 <= strlen(d1))){ - new_d2 = calloc(1,d2->length+1); - if (new_d2 != NULL) { - strlcpy(new_d2,d2->data,d2->length+1); - if (asprintf( &d2_formated, "%c%s%c",' ',new_d2,' ') < 0) - ret = ENOMEM; - else if (d2_formated != 0 && strstr(d1, d2_formated) != NULL) - ret = TRUE; - free(new_d2); - free(d2_formated); - } - } - return ret; -} - static krb5_int32 prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) { krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH; + size_t len = 0; char **realms, **cpp, *temp_buf=NULL; krb5_data *comp1 = NULL, *comp2 = NULL; - krb5_int32 host_based_srv_listed = 0, no_host_referral_listed = 0; + char *comp1_str = NULL; /* By now we know that server principal name is unknown. * If CANONICALIZE flag is set in the request @@ -1111,39 +1085,33 @@ prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) */ if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) == TRUE && - !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && + !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) && krb5_princ_size(kdc_context, request->server) == 2) { comp1 = krb5_princ_component(kdc_context, request->server, 0); comp2 = krb5_princ_component(kdc_context, request->server, 1); - host_based_srv_listed = FALSE; - no_host_referral_listed = TRUE; - if (kdc_active_realm->realm_host_based_services != NULL) { - host_based_srv_listed = is_substr(kdc_active_realm->realm_host_based_services, comp1); - if (host_based_srv_listed == ENOMEM) { - retval = ENOMEM; - goto cleanup; - } - } - if (kdc_active_realm->realm_no_host_referral != NULL) { - no_host_referral_listed = is_substr(kdc_active_realm->realm_no_host_referral,comp1); - if (no_host_referral_listed == ENOMEM) { - retval = ENOMEM; - goto cleanup; - } - } - if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || - (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && + comp1_str = calloc(1,comp1->length+1); + if (!comp1_str) { + retval = ENOMEM; + goto cleanup; + } + strlcpy(comp1_str,comp1->data,comp1->length+1); + + if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST || + (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN && kdc_active_realm->realm_host_based_services != NULL && - (host_based_srv_listed == TRUE || - strchr(kdc_active_realm->realm_host_based_services, '*')))) && + (match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE || + match_config_pattern(kdc_active_realm->realm_host_based_services, "*") == TRUE))) && (kdc_active_realm->realm_no_host_referral == NULL || - (!strchr(kdc_active_realm->realm_host_based_services, '*') && - no_host_referral_listed == FALSE))) { + (match_config_pattern(kdc_active_realm->realm_no_host_referral, "*") == FALSE && + match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) { - if (memchr(comp2->data, '.', comp2->length) == NULL) - goto cleanup; + for (len=0; len < comp2->length; len++) { + if (comp2->data[len] == '.') break; + } + if (len == comp2->length) + goto cleanup; temp_buf = calloc(1, comp2->length+1); if (!temp_buf){ retval = ENOMEM; @@ -1180,6 +1148,7 @@ prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ) } } cleanup: + free(comp1_str); return retval; } diff --git a/src/kdc/main.c b/src/kdc/main.c index 0e9b6910a9..0c9ea2f27a 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -170,83 +170,55 @@ finish_realm(kdc_realm_t *rdp) } static krb5_error_code -handle_referrals(krb5_realm_params *rparams, char *no_refrls, char *host_based_srvcs, kdc_realm_t *rdp ) +handle_referral_params(krb5_realm_params *rparams, + char *no_refrls, char *host_based_srvcs, + kdc_realm_t *rdp ) { - int i = 0; krb5_error_code retval = 0; - if (no_refrls == NULL || strchr(no_refrls, '*') == NULL) { - if (no_refrls != NULL){ - if (rparams && rparams->realm_no_host_referral) { - if (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", - " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0) + + if (no_refrls && match_config_pattern(no_refrls, "*") == TRUE) + rdp->realm_no_host_referral = strdup("*"); + else { + if (rparams && rparams->realm_no_host_referral) { + if (match_config_pattern(rparams->realm_no_host_referral, "*") == TRUE) + rdp->realm_no_host_referral = strdup("*"); + else if (no_refrls && (asprintf(&(rdp->realm_no_host_referral), "%s%s%s%s%s", + " ", no_refrls," ",rparams->realm_no_host_referral, " ") < 0)) + retval = ENOMEM; + else if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", + rparams->realm_no_host_referral, " ") < 0) + retval = ENOMEM; + } else if( no_refrls != NULL && asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls, " ") < 0) + retval = ENOMEM; + else + rdp->realm_no_host_referral = NULL; + } + + if (rdp->realm_no_host_referral && match_config_pattern(rdp->realm_no_host_referral, "*") == TRUE) { + rdp->realm_host_based_services = NULL; + return 0; + } + + if (host_based_srvcs && (match_config_pattern(host_based_srvcs, "*") == TRUE)) + rdp->realm_host_based_services = strdup("*"); + else { + if (rparams && rparams->realm_host_based_services) { + if (match_config_pattern(rparams->realm_host_based_services, "*") == TRUE) + rdp->realm_host_based_services = strdup("*"); + else if (host_based_srvcs && asprintf(&(rdp->realm_host_based_services), "%s%s%s%s%s", + " ", host_based_srvcs," ",rparams->realm_host_based_services, " ") < 0) retval = ENOMEM; - } else { - if(asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", no_refrls, " ") < 0) + else if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", + rparams->realm_host_based_services, " ") < 0) retval = ENOMEM; - } - } else { - if (rparams && rparams->realm_no_host_referral) { - if (asprintf(&(rdp->realm_no_host_referral),"%s%s%s", " ", - rparams->realm_no_host_referral, " ") < 0) + } else if(host_based_srvcs != NULL && asprintf(&(rdp->realm_host_based_services),"%s%s%s", + " ", host_based_srvcs, " ") < 0) retval = ENOMEM; - } else - rdp->realm_no_host_referral = NULL; - } - - if (rdp->realm_no_host_referral && - strlen(rdp->realm_no_host_referral) > 1 && strchr(rdp->realm_no_host_referral, '*') != NULL) { - rdp->realm_no_host_referral = strdup("*"); - } else { - /* only if no_host_referral != "*" */ - - if ((host_based_srvcs != NULL && strchr(host_based_srvcs,'*') != NULL) || - (rparams && rparams->realm_host_based_services && - strchr(rparams->realm_host_based_services,'*') != NULL)) { - if (asprintf(&(rdp->realm_host_based_services),"%s", "*") < 0) - retval = ENOMEM; - } else { - if (host_based_srvcs != NULL) { - if (rparams && rparams->realm_host_based_services) { - if (asprintf(&(rdp->realm_host_based_services),"%s%s%s%s%s", - " ", host_based_srvcs," ",rparams->realm_host_based_services," ") < 0) - retval = ENOMEM; - } else - if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", - host_based_srvcs, " ") < 0) - retval = ENOMEM; - } else { - if (rparams && rparams->realm_host_based_services) { - if (asprintf(&(rdp->realm_host_based_services),"%s%s%s", " ", - rparams->realm_host_based_services, " ") < 0) - retval = ENOMEM; - } else - rdp->realm_host_based_services = NULL; - } - } - - /* Walk realm_host_based_services and realm_no_host_referral and replace all ',' with whitespace */ - i = 0; - while (rdp && rdp->realm_host_based_services && (rdp->realm_host_based_services)[i] != 0){ - if ((rdp->realm_host_based_services)[i] == ',') - (rdp->realm_host_based_services)[i] = ' '; - i++; - } - i = 0; - while (rdp && rdp->realm_no_host_referral && ( rdp->realm_no_host_referral)[i] != 0){ - if ((rdp->realm_no_host_referral)[i] == ',') - (rdp->realm_no_host_referral)[i] = ' '; - i++; - } - } - } else { - if (no_refrls != NULL && strchr(no_refrls,'*') != NULL) { - if (asprintf(&(rdp->realm_no_host_referral),"%s", "*") < 0) - retval = ENOMEM; - } else - rdp->realm_no_host_referral = NULL; + else + rdp->realm_host_based_services = NULL; } - return retval; + return 0; } /* * Initialize a realm control structure from the alternate profile or from @@ -337,7 +309,7 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE; /* Handle KDC referrals */ - kret = handle_referrals(rparams, no_refrls, host_based_srvcs, rdp); + kret = handle_referral_params(rparams, no_refrls, host_based_srvcs, rdp); if (kret == ENOMEM) goto whoops; @@ -533,12 +505,12 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) { int c; char *db_name = (char *) NULL; + char *lrealm = (char *) NULL; char *mkey_name = (char *) NULL; char *rcname = KDCRCACHE; - char *lrealm; krb5_error_code retval; krb5_enctype menctype = ENCTYPE_UNKNOWN; - kdc_realm_t *rdatap; + kdc_realm_t *rdatap = NULL; krb5_boolean manual = FALSE; char *default_udp_ports = 0; char *default_tcp_ports = 0; @@ -563,20 +535,13 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) hierarchy[1] = "kdc_max_dgram_reply_size"; if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) max_dgram_reply_size = MAX_DGRAM_SIZE; - /* The service name "*" means any service. */ hierarchy[1] = "no_host_referral"; - if (!krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)){ - if (no_refrls != NULL && strlen(no_refrls) && strchr(no_refrls, '*')) { - no_refrls = strdup("*"); - } - } - if (no_refrls == 0 || strchr(no_refrls, '*') == NULL) { + if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)) + no_refrls = 0; + if (!no_refrls || match_config_pattern(no_refrls, "*") == FALSE) { hierarchy[1] = "host_based_services"; - if (!krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) { - if (strchr(host_based_srvcs, '*')) { - host_based_srvcs = strdup("*"); - } - } + if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) + host_based_srvcs = 0; } /* aprof_init can return 0 with aprof == NULL */ @@ -875,3 +840,4 @@ int main(int argc, char **argv) return errout; } + diff --git a/src/lib/crypto/etypes.c b/src/lib/crypto/etypes.c index c300f3b2c1..1c969ae020 100644 --- a/src/lib/crypto/etypes.c +++ b/src/lib/crypto/etypes.c @@ -49,7 +49,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_des_string_to_key, NULL, /*PRF*/ CKSUMTYPE_RSA_MD5, - NULL /*AEAD*/ }, + NULL, /*AEAD*/ + ETYPE_WEAK }, { ENCTYPE_DES_CBC_MD4, "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", &krb5int_enc_des, &krb5int_hash_md4, @@ -58,7 +59,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_des_string_to_key, NULL, /*PRF*/ CKSUMTYPE_RSA_MD4, - NULL /*AEAD*/ }, + NULL, /*AEAD*/ + ETYPE_WEAK }, { ENCTYPE_DES_CBC_MD5, "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", &krb5int_enc_des, &krb5int_hash_md5, @@ -67,7 +69,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_des_string_to_key, NULL, /*PRF*/ CKSUMTYPE_RSA_MD5, - NULL /*AEAD*/ }, + NULL, /*AEAD*/ + ETYPE_WEAK }, { ENCTYPE_DES_CBC_RAW, "des-cbc-raw", { 0 }, "DES cbc mode raw", &krb5int_enc_des, NULL, @@ -76,7 +79,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_des_string_to_key, NULL, /*PRF*/ 0, - &krb5int_aead_raw }, + &krb5int_aead_raw, + ETYPE_WEAK }, { ENCTYPE_DES3_CBC_RAW, "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", &krb5int_enc_des3, NULL, @@ -85,7 +89,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_dk_string_to_key, NULL, /*PRF*/ 0, - &krb5int_aead_raw }, + &krb5int_aead_raw, + ETYPE_WEAK }, { ENCTYPE_DES3_CBC_SHA1, "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, @@ -96,7 +101,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_dk_string_to_key, NULL, /*PRF*/ CKSUMTYPE_HMAC_SHA1_DES3, - &krb5int_aead_dk }, + &krb5int_aead_dk, + 0 /*flags*/ }, { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1", { 0 }, "DES with HMAC/sha1", @@ -106,7 +112,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_dk_string_to_key, NULL, /*PRF*/ 0, - NULL }, + NULL, + ETYPE_WEAK }, { ENCTYPE_ARCFOUR_HMAC, "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, "ArcFour with HMAC/md5", @@ -117,7 +124,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, NULL, /*PRF*/ CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, + &krb5int_aead_arcfour, + 0 /*flags*/ }, { ENCTYPE_ARCFOUR_HMAC_EXP, "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, "Exportable ArcFour with HMAC/md5", @@ -128,7 +136,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, NULL, /*PRF*/ CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, + &krb5int_aead_arcfour, + 0 /*flags*/ }, { ENCTYPE_AES128_CTS_HMAC_SHA1_96, "aes128-cts-hmac-sha1-96", { "aes128-cts" }, @@ -139,7 +148,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_aes_string_to_key, krb5int_dk_prf, CKSUMTYPE_HMAC_SHA1_96_AES128, - &krb5int_aead_aes }, + &krb5int_aead_aes, + 0 /*flags*/ }, { ENCTYPE_AES256_CTS_HMAC_SHA1_96, "aes256-cts-hmac-sha1-96", { "aes256-cts" }, "AES-256 CTS mode with 96-bit SHA-1 HMAC", @@ -149,7 +159,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { krb5int_aes_string_to_key, krb5int_dk_prf, CKSUMTYPE_HMAC_SHA1_96_AES256, - &krb5int_aead_aes }, + &krb5int_aead_aes, + 0 /*flags*/ }, }; const int krb5_enctypes_length = diff --git a/src/lib/crypto/etypes.h b/src/lib/crypto/etypes.h index af2718d826..17b448cee9 100644 --- a/src/lib/crypto/etypes.h +++ b/src/lib/crypto/etypes.h @@ -60,7 +60,10 @@ struct krb5_keytypes { krb5_prf_func prf; krb5_cksumtype required_ctype; const struct krb5_aead_provider *aead; + krb5_flags flags; }; +#define ETYPE_WEAK 1 + extern const struct krb5_keytypes krb5_enctypes_list[]; extern const int krb5_enctypes_length; diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports index 867d9a2329..3cb79de26b 100644 --- a/src/lib/crypto/libk5crypto.exports +++ b/src/lib/crypto/libk5crypto.exports @@ -45,6 +45,7 @@ krb5_c_valid_cksumtype krb5_c_valid_enctype krb5_c_verify_checksum krb5_c_verify_checksum_iov +krb5_c_weak_enctype krb5_calculate_checksum krb5_checksum_size krb5_cksumtype_to_string diff --git a/src/lib/crypto/valid_enctype.c b/src/lib/crypto/valid_enctype.c index f36023084a..7b9a92a899 100644 --- a/src/lib/crypto/valid_enctype.c +++ b/src/lib/crypto/valid_enctype.c @@ -45,3 +45,24 @@ valid_enctype(krb5_enctype etype) { return krb5_c_valid_enctype (etype); } + +krb5_boolean KRB5_CALLCONV +krb5_c_weak_enctype(krb5_enctype etype) +{ + int i; + const struct krb5_keytypes *k; + + for (i = 0; i < krb5_enctypes_length; i++) { +#if 0 + if (krb5_enctypes_list[i].etype == etype && + krb5_enctypes_list[i].flags | ETYPE_WEAK) + return(1); +#endif + k = &krb5_enctypes_list[i]; + if (k->etype == etype && (k->flags & ETYPE_WEAK)) { + return(1); + } + } + + return(0); +} diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 2d8ca15a94..7fb35a5c81 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -39,6 +39,7 @@ #include #include +krb5_boolean match_config_pattern(const char *, const char*); static krb5_key_salt_tuple *copy_key_salt_tuple(ksalt, len) krb5_key_salt_tuple *ksalt; krb5_int32 len; @@ -294,22 +295,22 @@ krb5_aprof_get_string_all(acontext, hierarchy, stringp) { krb5_error_code kret=0; char **values; - int lastidx; - char *tmp; - size_t buf_size=0; + int lastidx = 0; + char *tmp = NULL ; + size_t buf_size = 0; kret = krb5_aprof_getvals(acontext, hierarchy, &values); if (!kret) { for (lastidx=0; values[lastidx]; lastidx++); lastidx--; - buf_size = strlen(values[0])+2; + buf_size = strlen(values[0])+3; for (lastidx=1; values[lastidx]; lastidx++){ - buf_size += strlen(values[lastidx]+1); + buf_size += strlen(values[lastidx]) + 3; } } if (buf_size > 0) { *stringp = calloc(1,buf_size); - if (stringp == NULL){ + if (*stringp == NULL){ profile_free_list(values); return ENOMEM; } @@ -1028,25 +1029,19 @@ krb5_read_realm_params(kcontext, realm, rparamp) rparams->realm_reject_bad_transit_valid = 1; } - hierarchy[2] = "no_host_referral"; - if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls)) { - - if (strchr(no_refrls, '*')) - no_refrls = strdup("*"); - rparams->realm_no_host_referral = no_refrls; - } else + hierarchy[2] = "no_host_referral"; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &no_refrls)) + rparams->realm_no_host_referral = no_refrls; + else no_refrls = 0; - if (no_refrls == 0 || strlen(no_refrls) == 0 || strncmp(no_refrls, "*",1) != 0) { - hierarchy[2] = "host_based_services"; - if (!krb5_aprof_get_string_all(aprofile, hierarchy, &host_based_srvcs)){ - if (strchr(host_based_srvcs, '*')) - host_based_srvcs = strdup("*"); - rparams->realm_host_based_services = host_based_srvcs; - } else - host_based_srvcs = 0; - } - + if (!no_refrls || match_config_pattern(no_refrls, "*") == FALSE) { + hierarchy[2] = "host_based_services"; + if (!krb5_aprof_get_string_all(aprofile, hierarchy, &host_based_srvcs)) + rparams->realm_host_based_services = host_based_srvcs; + else + host_based_srvcs = 0; + } /* Get the value for the default principal flags */ hierarchy[2] = "default_principal_flags"; @@ -1105,7 +1100,7 @@ cleanup: krb5_error_code krb5_free_realm_params(kcontext, rparams) krb5_context kcontext; - krb5_realm_params *rparams; + krb5_realm_params *rparams; { if (rparams) { free(rparams->realm_profile); @@ -1122,4 +1117,29 @@ krb5_free_realm_params(kcontext, rparams) } return(0); } +/* + * match_config_pattern - + * returns TRUE is the pattern is found in the attr's list of values. + * Otherwise - FALSE. + * In conf file the values are separates by commas or whitespaces. + */ +krb5_boolean +match_config_pattern(const char *string, const char *pattern) +{ + const char *ptr; + char next = '\0'; + int len = strlen(pattern); + + for (ptr = strstr(string,pattern); ptr != 0; ptr = strstr(ptr+len,pattern)) { + if (ptr == string || isspace(*(ptr-1)) || *(ptr-1) ==',') { + next = *(ptr + len); + if (next == '\0' || isspace(next) || next ==',') { + return TRUE; + } + } + } + return FALSE; +} + + diff --git a/src/lib/kadm5/srv/libkadm5srv.exports b/src/lib/kadm5/srv/libkadm5srv.exports index 444987130a..0ec02719b4 100644 --- a/src/lib/kadm5/srv/libkadm5srv.exports +++ b/src/lib/kadm5/srv/libkadm5srv.exports @@ -84,6 +84,7 @@ krb5_klog_syslog krb5_read_realm_params krb5_string_to_flags krb5_string_to_keysalts +match_config_pattern master_db master_keyblock master_keylist diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index f916660f9d..bab143e6f8 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -171,6 +171,12 @@ init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc) if ((retval = krb5_os_init_context(ctx, kdc))) goto cleanup; + retval = profile_get_boolean(ctx->profile, "libdefaults", + "allow_weak_crypto", NULL, 0, &tmp); + if (retval) + goto cleanup; + ctx->allow_weak_crypto = tmp; + /* initialize the prng (not well, but passable) */ if ((retval = krb5_c_random_os_entropy( ctx, 0, NULL)) !=0) goto cleanup; @@ -289,6 +295,8 @@ krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes) for (i = 0; ktypes[i]; i++) { if (!krb5_c_valid_enctype(ktypes[i])) return KRB5_PROG_ETYPE_NOSUPP; + if (!context->allow_weak_crypto && krb5_c_weak_enctype(ktypes[i])) + return KRB5_PROG_ETYPE_NOSUPP; } /* Now copy the default ktypes into the context pointer */ @@ -314,6 +322,7 @@ get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profst unsigned int ctx_count, krb5_enctype *ctx_list) { krb5_enctype *old_ktypes; + krb5_enctype ktype; if (ctx_count) { /* application-set defaults */ @@ -367,9 +376,11 @@ get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profst j = 0; i = 1; while (1) { - if (! krb5_string_to_enctype(sp, &old_ktypes[j])) + if (!krb5_string_to_enctype(sp, &ktype) && + (context->allow_weak_crypto || !krb5_c_weak_enctype(ktype))) { + old_ktypes[j] = ktype; j++; - + } if (i++ >= count) break; @@ -410,6 +421,8 @@ krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes) for (i = 0; ktypes[i]; i++) { if (!krb5_c_valid_enctype(ktypes[i])) return KRB5_PROG_ETYPE_NOSUPP; + if (!context->allow_weak_crypto && krb5_c_weak_enctype(ktypes[i])) + return KRB5_PROG_ETYPE_NOSUPP; } /* Now copy the default ktypes into the context pointer */ diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 85d52f171d..a082b82587 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -1,3 +1,4 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ /* * lib/krb5/krb/sendauth.c * @@ -8,7 +9,7 @@ * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. - * + * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright @@ -22,7 +23,7 @@ * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. - * + * * * convenience sendauth/recvauth functions */ @@ -39,198 +40,197 @@ static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0"; krb5_error_code KRB5_CALLCONV krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, - krb5_pointer fd, char *appl_version, krb5_principal client, - krb5_principal server, krb5_flags ap_req_options, - krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, - krb5_error **error, krb5_ap_rep_enc_part **rep_result, - krb5_creds **out_creds) + krb5_pointer fd, char *appl_version, krb5_principal client, + krb5_principal server, krb5_flags ap_req_options, + krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, + krb5_error **error, krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds) { - krb5_octet result; - krb5_creds creds; - krb5_creds * credsp = NULL; - krb5_creds * credspout = NULL; - krb5_error_code retval = 0; - krb5_data inbuf, outbuf[2]; - int len; - krb5_ccache use_ccache = 0; - - if (error) - *error = 0; - - /* - * First, send over the length of the sendauth version string; - * then, we send over the sendauth version. Next, we send - * over the length of the application version strings followed - * by the string itself. - */ - outbuf[0].length = strlen(sendauth_version) + 1; - outbuf[0].data = (char *) sendauth_version; - outbuf[1].length = strlen(appl_version) + 1; - outbuf[1].data = appl_version; - if ((retval = krb5int_write_messages(context, fd, outbuf, 2))) - return(retval); - /* - * Now, read back a byte: 0 means no error, 1 means bad sendauth - * version, 2 means bad application version - */ + krb5_octet result; + krb5_creds creds; + krb5_creds * credsp = NULL; + krb5_creds * credspout = NULL; + krb5_error_code retval = 0; + krb5_data inbuf, outbuf[2]; + int len; + krb5_ccache use_ccache = 0; + + if (error) + *error = 0; + + /* + * First, send over the length of the sendauth version string; + * then, we send over the sendauth version. Next, we send + * over the length of the application version strings followed + * by the string itself. + */ + outbuf[0].length = strlen(sendauth_version) + 1; + outbuf[0].data = (char *) sendauth_version; + outbuf[1].length = strlen(appl_version) + 1; + outbuf[1].data = appl_version; + if ((retval = krb5int_write_messages(context, fd, outbuf, 2))) + return(retval); + /* + * Now, read back a byte: 0 means no error, 1 means bad sendauth + * version, 2 means bad application version + */ if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1) - return((len < 0) ? errno : ECONNABORTED); + return((len < 0) ? errno : ECONNABORTED); if (result == 1) - return(KRB5_SENDAUTH_BADAUTHVERS); + return(KRB5_SENDAUTH_BADAUTHVERS); else if (result == 2) - return(KRB5_SENDAUTH_BADAPPLVERS); + return(KRB5_SENDAUTH_BADAPPLVERS); else if (result != 0) - return(KRB5_SENDAUTH_BADRESPONSE); - /* - * We're finished with the initial negotiations; let's get and - * send over the authentication header. (The AP_REQ message) - */ - - /* - * If no credentials were provided, try getting it from the - * credentials cache. - */ - memset((char *)&creds, 0, sizeof(creds)); - - /* - * See if we need to access the credentials cache - */ - if (!in_creds || !in_creds->ticket.length) { - if (ccache) - use_ccache = ccache; - else if ((retval = krb5int_cc_default(context, &use_ccache))) - goto error_return; - } - if (!in_creds) { - if ((retval = krb5_copy_principal(context, server, - &creds.server))) - goto error_return; - if (client) - retval = krb5_copy_principal(context, client, - &creds.client); - else - retval = krb5_cc_get_principal(context, use_ccache, - &creds.client); - if (retval) { - krb5_free_principal(context, creds.server); - goto error_return; - } - /* creds.times.endtime = 0; -- memset 0 takes care of this - zero means "as long as possible" */ - /* creds.keyblock.enctype = 0; -- as well as this. - zero means no session enctype - preference */ - in_creds = &creds; - } - if (!in_creds->ticket.length) { - if ((retval = krb5_get_credentials(context, 0, - use_ccache, in_creds, &credsp))) - goto error_return; - credspout = credsp; - } else { - credsp = in_creds; - } - - if (ap_req_options & AP_OPTS_USE_SUBKEY) { - /* Provide some more fodder for random number code. - This isn't strong cryptographically; the point here is - not to guarantee randomness, but to make it less likely - that multiple sessions could pick the same subkey. */ - char rnd_data[1024]; - GETPEERNAME_ARG3_TYPE len2; - krb5_data d; - d.length = sizeof (rnd_data); - d.data = rnd_data; - len2 = sizeof (rnd_data); - if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data, - &len2) == 0) { - d.length = len2; - (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d); - } - len2 = sizeof (rnd_data); - if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data, - &len2) == 0) { - d.length = len2; - (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d); - } - } - - if ((retval = krb5_mk_req_extended(context, auth_context, - ap_req_options, in_data, credsp, - &outbuf[0]))) - goto error_return; - - /* - * First write the length of the AP_REQ message, then write - * the message itself. - */ - retval = krb5_write_message(context, fd, &outbuf[0]); - free(outbuf[0].data); - if (retval) - goto error_return; - - /* - * Now, read back a message. If it was a null message (the - * length was zero) then there was no error. If not, we the - * authentication was rejected, and we need to return the - * error structure. - */ - if ((retval = krb5_read_message(context, fd, &inbuf))) - goto error_return; - - if (inbuf.length) { - if (error) { - if ((retval = krb5_rd_error(context, &inbuf, error))) { - free(inbuf.data); - goto error_return; - } - } - retval = KRB5_SENDAUTH_REJECTED; - free(inbuf.data); - goto error_return; - } - - /* - * If we asked for mutual authentication, we should now get a - * length field, followed by a AP_REP message - */ - if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { - krb5_ap_rep_enc_part *repl = 0; - - if ((retval = krb5_read_message(context, fd, &inbuf))) - goto error_return; - - if ((retval = krb5_rd_rep(context, *auth_context, &inbuf, - &repl))) { - if (repl) - krb5_free_ap_rep_enc_part(context, repl); - free(inbuf.data); - goto error_return; - } - - free(inbuf.data); - /* - * If the user wants to look at the AP_REP message, - * copy it for him - */ - if (rep_result) - *rep_result = repl; - else - krb5_free_ap_rep_enc_part(context, repl); - } - retval = 0; /* Normal return */ - if (out_creds) { - *out_creds = credsp; - credspout = NULL; - } + return(KRB5_SENDAUTH_BADRESPONSE); + /* + * We're finished with the initial negotiations; let's get and + * send over the authentication header. (The AP_REQ message) + */ + + /* + * If no credentials were provided, try getting it from the + * credentials cache. + */ + memset((char *)&creds, 0, sizeof(creds)); + + /* + * See if we need to access the credentials cache + */ + if (!in_creds || !in_creds->ticket.length) { + if (ccache) + use_ccache = ccache; + else if ((retval = krb5int_cc_default(context, &use_ccache))) + goto error_return; + } + if (!in_creds) { + if ((retval = krb5_copy_principal(context, server, + &creds.server))) + goto error_return; + if (client) + retval = krb5_copy_principal(context, client, + &creds.client); + else + retval = krb5_cc_get_principal(context, use_ccache, + &creds.client); + if (retval) { + krb5_free_principal(context, creds.server); + goto error_return; + } + /* creds.times.endtime = 0; -- memset 0 takes care of this + zero means "as long as possible" */ + /* creds.keyblock.enctype = 0; -- as well as this. + zero means no session enctype + preference */ + in_creds = &creds; + } + if (!in_creds->ticket.length) { + if ((retval = krb5_get_credentials(context, 0, + use_ccache, in_creds, &credsp))) + goto error_return; + credspout = credsp; + } else { + credsp = in_creds; + } + + if (ap_req_options & AP_OPTS_USE_SUBKEY) { + /* Provide some more fodder for random number code. + This isn't strong cryptographically; the point here is + not to guarantee randomness, but to make it less likely + that multiple sessions could pick the same subkey. */ + char rnd_data[1024]; + GETPEERNAME_ARG3_TYPE len2; + krb5_data d; + d.length = sizeof (rnd_data); + d.data = rnd_data; + len2 = sizeof (rnd_data); + if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data, + &len2) == 0) { + d.length = len2; + (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d); + } + len2 = sizeof (rnd_data); + if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data, + &len2) == 0) { + d.length = len2; + (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d); + } + } + + outbuf[0].data = NULL; /* Coverity is confused otherwise */ + if ((retval = krb5_mk_req_extended(context, auth_context, + ap_req_options, in_data, credsp, + &outbuf[0]))) + goto error_return; + + /* + * First write the length of the AP_REQ message, then write + * the message itself. + */ + retval = krb5_write_message(context, fd, &outbuf[0]); + free(outbuf[0].data); + if (retval) + goto error_return; + + /* + * Now, read back a message. If it was a null message (the + * length was zero) then there was no error. If not, we the + * authentication was rejected, and we need to return the + * error structure. + */ + if ((retval = krb5_read_message(context, fd, &inbuf))) + goto error_return; + + if (inbuf.length) { + if (error) { + if ((retval = krb5_rd_error(context, &inbuf, error))) { + free(inbuf.data); + goto error_return; + } + } + retval = KRB5_SENDAUTH_REJECTED; + free(inbuf.data); + goto error_return; + } + + /* + * If we asked for mutual authentication, we should now get a + * length field, followed by a AP_REP message + */ + if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { + krb5_ap_rep_enc_part *repl = 0; + + if ((retval = krb5_read_message(context, fd, &inbuf))) + goto error_return; + + if ((retval = krb5_rd_rep(context, *auth_context, &inbuf, + &repl))) { + if (repl) + krb5_free_ap_rep_enc_part(context, repl); + free(inbuf.data); + goto error_return; + } + + free(inbuf.data); + /* + * If the user wants to look at the AP_REP message, + * copy it for him + */ + if (rep_result) + *rep_result = repl; + else + krb5_free_ap_rep_enc_part(context, repl); + } + retval = 0; /* Normal return */ + if (out_creds) { + *out_creds = credsp; + credspout = NULL; + } error_return: krb5_free_cred_contents(context, &creds); if (credspout != NULL) - krb5_free_creds(context, credspout); + krb5_free_creds(context, credspout); if (!ccache && use_ccache) - krb5_cc_close(context, use_ccache); + krb5_cc_close(context, use_ccache); return(retval); } - - diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp index 2c6c56f736..aa53f333f3 100644 --- a/src/tests/dejagnu/config/default.exp +++ b/src/tests/dejagnu/config/default.exp @@ -1024,6 +1024,7 @@ proc setup_krb5_conf { {type client} } { puts $conffile "\[libdefaults\]" puts $conffile " default_realm = $REALMNAME" puts $conffile " dns_lookup_kdc = false" + puts $conffile " allow_weak_crypto = true" if [info exists default_tgs_enctypes($type)] { puts $conffile \ " default_tgs_enctypes = $default_tgs_enctypes($type)"