krb5_error_code _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, krb5_enctype *etypes, unsigned len, Key **ret_key, krb5_enctype *ret_etype) { int i; krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; krb5_salt def_salt; krb5_get_pw_salt (context, princ->entry.principal, &def_salt); for(i = 0; ret != 0 && i < len ; i++) { Key *key = NULL; if (krb5_enctype_valid(context, etypes[i]) != 0 && !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) continue; while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { if (key->key.keyvalue.length == 0) { ret = KRB5KDC_ERR_NULL_KEY; continue; } *ret_key = key; *ret_etype = etypes[i]; ret = 0; if (is_default_salt_p(&def_salt, key)) { krb5_free_salt (context, def_salt); return ret; } } } krb5_free_salt (context, def_salt); return ret; }
krb5_error_code _kdc_get_preferred_key(krb5_context context, krb5_kdc_configuration *config, hdb_entry_ex *h, const char *name, krb5_enctype *enctype, Key **key) { krb5_error_code ret; int i; if (config->use_strongest_server_key) { const krb5_enctype *p = krb5_kerberos_enctypes(context); for (i = 0; p[i] != (krb5_enctype)ETYPE_NULL; i++) { if (krb5_enctype_valid(context, p[i]) != 0 && !_kdc_is_weak_exception(h->entry.principal, p[i])) continue; ret = hdb_enctype2key(context, &h->entry, NULL, p[i], key); if (ret != 0) continue; if (enctype != NULL) *enctype = p[i]; return 0; } } else { *key = NULL; for (i = 0; i < h->entry.keys.len; i++) { if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype) != 0 && !_kdc_is_weak_exception(h->entry.principal, h->entry.keys.val[i].key.keytype)) continue; ret = hdb_enctype2key(context, &h->entry, NULL, h->entry.keys.val[i].key.keytype, key); if (ret != 0) continue; if (enctype != NULL) *enctype = (*key)->key.keytype; return 0; } } krb5_set_error_message(context, EINVAL, "No valid kerberos key found for %s", name); return EINVAL; /* XXX */ }
krb5_error_code _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key, krb5_boolean is_preauth, hdb_entry_ex *princ, krb5_enctype *etypes, unsigned len, krb5_enctype *ret_enctype, Key **ret_key) { krb5_error_code ret; krb5_salt def_salt; krb5_enctype enctype = ETYPE_NULL; Key *key; int i; /* We'll want to avoid keys with v4 salted keys in the pre-auth case... */ ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt); if (ret) return ret; ret = KRB5KDC_ERR_ETYPE_NOSUPP; if (use_strongest_session_key) { const krb5_enctype *p; krb5_enctype clientbest = ETYPE_NULL; int j; /* * Pick the strongest key that the KDC, target service, and * client all support, using the local cryptosystem enctype * list in strongest-to-weakest order to drive the search. * * This is not what RFC4120 says to do, but it encourages * adoption of stronger enctypes. This doesn't play well with * clients that have multiple Kerberos client implementations * available with different supported enctype lists. */ /* drive the search with local supported enctypes list */ p = krb5_kerberos_enctypes(context); for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) { if (krb5_enctype_valid(context, p[i]) != 0) continue; /* check that the client supports it too */ for (j = 0; j < len && enctype == ETYPE_NULL; j++) { if (p[i] != etypes[j]) continue; /* save best of union of { client, crypto system } */ if (clientbest == ETYPE_NULL) clientbest = p[i]; /* check target princ support */ ret = hdb_enctype2key(context, &princ->entry, p[i], &key); if (ret) continue; if (is_preauth && !is_default_salt_p(&def_salt, key)) continue; enctype = p[i]; } } if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL) enctype = clientbest; else if (enctype == ETYPE_NULL) ret = KRB5KDC_ERR_ETYPE_NOSUPP; if (ret == 0 && ret_enctype != NULL) *ret_enctype = enctype; if (ret == 0 && ret_key != NULL) *ret_key = key; } else { /* * Pick the first key from the client's enctype list that is * supported by the cryptosystem and by the given principal. * * RFC4120 says we SHOULD pick the first _strong_ key from the * client's list... not the first key... If the admin disallows * weak enctypes in krb5.conf and selects this key selection * algorithm, then we get exactly what RFC4120 says. */ for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) { if (krb5_enctype_valid(context, etypes[i]) != 0 && !_kdc_is_weak_exception(princ->entry.principal, etypes[i])) continue; while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) { if (key->key.keyvalue.length == 0) { ret = KRB5KDC_ERR_NULL_KEY; continue; } if (ret_key != NULL) *ret_key = key; if (ret_enctype != NULL) *ret_enctype = etypes[i]; ret = 0; if (is_preauth && is_default_salt_p(&def_salt, key)) goto out; } } } out: krb5_free_salt (context, def_salt); return ret; }