From 0e9bf73d2b8da55aedd25061faefe6a22d9613d3 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Mon, 4 Jun 2012 17:17:31 -0500 Subject: Add control over session key enctype negotiation Adds a principal string attribute named "session_enctypes" which can specify what enctypes the principal supports for session keys. (For what it's worth, this actually allows one to list des-cbc-md5 as a supported session key enctype, though obviously this hardly matters now.) Add a [realms] section parameter for specifying whether to assume that principals (which lack the session_enctypes attribute) support des-cbc-crc for session keys. This allows those who still need to use allow_weak_crypto=true, for whatever reason, to start reducing the number of tickets issued with des-cbc-crc session keys to clients which still give des-cbc-crc preference in their default_tgs_enctypes list. [ghudson@mit.edu: Miscellaneous edits, cleanups, and fixes; refactored test script; documented session_enctypes attribute] --- src/kdc/extern.h | 2 ++ src/kdc/kdc_util.c | 84 ++++++++++++++++++++++++------------------------------ src/kdc/kdc_util.h | 10 ------- src/kdc/main.c | 6 ++++ 4 files changed, 45 insertions(+), 57 deletions(-) (limited to 'src/kdc') diff --git a/src/kdc/extern.h b/src/kdc/extern.h index 3866c6c1f..c601e5702 100644 --- a/src/kdc/extern.h +++ b/src/kdc/extern.h @@ -70,6 +70,7 @@ typedef struct __kdc_realm_data { krb5_deltat realm_maxrlife; /* Maximum renewable life for realm */ krb5_boolean realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */ krb5_boolean realm_restrict_anon; /* Anon to local TGT only */ + krb5_boolean realm_assume_des_crc_sess; /* Assume princs support des-cbc-crc for session keys */ } kdc_realm_t; extern kdc_realm_t **kdc_realmlist; @@ -91,6 +92,7 @@ kdc_realm_t *find_realm_data (char *, krb5_ui_4); #define tgs_server kdc_active_realm->realm_tgsprinc #define reject_bad_transit kdc_active_realm->realm_reject_bad_transit #define restrict_anon kdc_active_realm->realm_restrict_anon +#define assume_des_crc_sess kdc_active_realm->realm_assume_des_crc_sess /* various externs for KDC */ extern krb5_data empty_string; /* an empty string */ diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 2f4af733d..3f3b40680 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -1516,60 +1516,50 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server, return 0; } -/* - * This function returns 1 if the dbentry has a key for a specified - * keytype, and 0 if not. - */ -int -dbentry_has_key_for_enctype(krb5_context context, krb5_db_entry *client, - krb5_enctype enctype) +/* Return true if we believe server can support enctype as a session key. */ +krb5_boolean +dbentry_supports_enctype(krb5_context context, krb5_db_entry *server, + krb5_enctype enctype) { krb5_error_code retval; krb5_key_data *datap; + char *etypes_str = NULL; + krb5_enctype default_enctypes[1] = { 0 }; + krb5_enctype *etypes; + size_t i; + + /* Look up the supported session key enctypes list in the KDB. */ + retval = krb5_dbe_get_string(context, server, KRB5_KDB_SK_SESSION_ENCTYPES, + &etypes_str); + if (retval == 0 && etypes_str != NULL && *etypes_str != '\0') { + /* Pass a fake profile key for tracing of unrecognized tokens. */ + retval = krb5int_parse_enctype_list(context, "KDB-session_etypes", + etypes_str, default_enctypes, + &etypes); + free(etypes_str); + if (retval == 0 && etypes != NULL && etypes[0]) { + for (i = 0; etypes[i]; i++) + if (enctype == etypes[i]) + return TRUE; + return FALSE; + } + /* Fall through on error or empty list */ + } else { + free(etypes_str); + } - retval = krb5_dbe_find_enctype(context, client, enctype, - -1, 0, &datap); - if (retval) - return 0; - else - return 1; -} + /* If configured to, assume every server without a session_enctypes + * attribute supports DES_CBC_CRC. */ + if (assume_des_crc_sess && enctype == ENCTYPE_DES_CBC_CRC) + return TRUE; -/* - * This function returns 1 if the entity referenced by this - * structure can support the a particular encryption system, and 0 if - * not. - * - * XXX eventually this information should be looked up in the - * database. Since it isn't, we use some hueristics and attribute - * options bits for now. - */ -int -dbentry_supports_enctype(krb5_context context, krb5_db_entry *client, - krb5_enctype enctype) -{ - /* - * If it's DES_CBC_MD5, there's a bit in the attribute mask which - * checks to see if we support it. For now, treat it as always - * clear. - * - * In theory everything's supposed to support DES_CBC_MD5, but - * that's not the reality.... - */ + /* Due to an ancient interop problem, assume nothing supports des-cbc-md5 + * unless there's a session_enctypes explicitly saying that it does. */ if (enctype == ENCTYPE_DES_CBC_MD5) - return 0; + return FALSE; - /* - * XXX we assume everything can understand DES_CBC_CRC - */ - if (enctype == ENCTYPE_DES_CBC_CRC) - return 1; - - /* - * If we have a key for the encryption system, we assume it's - * supported. - */ - return dbentry_has_key_for_enctype(context, client, enctype); + /* Assume the server supports any enctype it has a long-term key for. */ + return !krb5_dbe_find_enctype(context, server, enctype, -1, 0, &datap); } /* diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 55aafaeb7..0cd7989fc 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -89,16 +89,6 @@ validate_tgs_request (krb5_kdc_req *, krb5_db_entry, int fetch_asn1_field (unsigned char *, unsigned int, unsigned int, krb5_data *); -int -dbentry_has_key_for_enctype (krb5_context context, - krb5_db_entry *client, - krb5_enctype enctype); - -int -dbentry_supports_enctype (krb5_context context, - krb5_db_entry *client, - krb5_enctype enctype); - krb5_enctype select_session_keytype (krb5_context context, krb5_db_entry *server, diff --git a/src/kdc/main.c b/src/kdc/main.c index 36753b7f0..b119dd53a 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -369,6 +369,12 @@ init_realm(kdc_realm_t *rdp, char *realm, char *def_mpname, else rdp->realm_reject_bad_transit = 1; + /* Handle assume des-cbc-crc is supported for session keys */ + if (rparams && rparams->realm_assume_des_crc_sess_valid) + rdp->realm_assume_des_crc_sess = rparams->realm_assume_des_crc_sess; + else + rdp->realm_assume_des_crc_sess = 1; + /* Handle ticket maximum life */ rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ? rparams->realm_max_life : KRB5_KDB_MAX_LIFE; -- cgit