diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index fb88aa9f8..a3156a206 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -59,17 +59,6 @@ realloc_method_data(METHOD_DATA *md) return 0; } -static void -set_salt_padata (METHOD_DATA *md, Salt *salt) -{ - if (salt) { - realloc_method_data(md); - md->val[md->len - 1].padata_type = salt->type; - der_copy_octet_string(&salt->salt, - &md->val[md->len - 1].padata_value); - } -} - const PA_DATA* _kdc_find_padata(const KDC_REQ *req, int *start, int type) { @@ -127,7 +116,7 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key) 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) + Key **ret_key) { int i; krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; @@ -148,7 +137,6 @@ _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, continue; } *ret_key = key; - *ret_etype = etypes[i]; ret = 0; if (is_default_salt_p(&def_salt, key)) { krb5_free_salt (context, def_salt); @@ -912,13 +900,14 @@ _kdc_as_rep(krb5_context context, const char *e_text = NULL; krb5_crypto crypto; Key *ckey, *skey; - EncryptionKey *reply_key; + EncryptionKey *reply_key, session_key; int flags = 0; #ifdef PKINIT pk_client_params *pkp = NULL; #endif memset(&rep, 0, sizeof(rep)); + memset(&session_key, 0, sizeof(session_key)); krb5_data_zero(&e_data); if (f.canonicalize) @@ -1009,18 +998,58 @@ _kdc_as_rep(krb5_context context, memset(&ek, 0, sizeof(ek)); /* - * Find the client key for reply encryption and pa-type salt, Pick - * the client key upfront before the other keys because that is - * going to affect what enctypes we are going to use in - * ETYPE-INFO{,2}. + * Select a session enctype from the list of the crypto systems + * supported enctype, is supported by the client and is one of the + * enctype of the enctype of the krbtgt. + * + * The later is used as a hint what enctype all KDC are supporting + * to make sure a newer version of KDC wont generate a session + * enctype that and older version of a KDC in the same realm can't + * decrypt. + * + * But if the KDC admin is paranoid and doesn't want to have "no + * the best" enctypes on the krbtgt, lets save the best pick from + * the client list and hope that that will work for any other + * KDCs. */ + { + const krb5_enctype *p; + krb5_enctype clientbest = ETYPE_NULL; + int i, j; - ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, - &ckey, &cetype); - if (ret) { - kdc_log(context, config, 0, - "Client (%s) has no support for etypes", client_name); - goto out; + p = krb5_kerberos_enctypes(context); + + sessionetype = ETYPE_NULL; + + for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + + for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) { + Key *dummy; + /* check with client */ + if (p[i] != b->etype.val[j]) + continue; + /* save best of union of { client, crypto system } */ + if (clientbest == ETYPE_NULL) + clientbest = p[i]; + /* check with krbtgt */ + ret = hdb_enctype2key(context, &server->entry, p[i], &dummy); + if (ret) + continue; + sessionetype = p[i]; + } + } + /* if krbtgt had no shared keys with client, pick clients best */ + if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) { + sessionetype = clientbest; + } else if (sessionetype == ETYPE_NULL) { + kdc_log(context, config, 0, + "Client (%s) from %s has no common enctypes with KDC" + "to use for the session key", + client_name, from); + goto out; + } } /* @@ -1230,7 +1259,9 @@ _kdc_as_rep(krb5_context context, } et.flags.pre_authent = 1; - ret = krb5_enctype_to_string(context,pa_key->key.keytype, &str); + reply_key = &pa_key->key; + + ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str); if (ret) str = NULL; @@ -1300,7 +1331,9 @@ _kdc_as_rep(krb5_context context, /* * If there is a client key, send ETYPE_INFO{,2} */ - if (ckey) { + ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, + &ckey); + if (ret == 0) { /* * RFC4120 requires: @@ -1371,63 +1404,6 @@ _kdc_as_rep(krb5_context context, if(ret) goto out; - /* - * Select a session enctype from the list of the crypto systems - * supported enctype, is supported by the client and is one of the - * enctype of the enctype of the krbtgt. - * - * The later is used as a hint what enctype all KDC are supporting - * to make sure a newer version of KDC wont generate a session - * enctype that and older version of a KDC in the same realm can't - * decrypt. - * - * But if the KDC admin is paranoid and doesn't want to have "no - * the best" enctypes on the krbtgt, lets save the best pick from - * the client list and hope that that will work for any other - * KDCs. - */ - { - const krb5_enctype *p; - krb5_enctype clientbest = ETYPE_NULL; - int i, j; - - p = krb5_kerberos_enctypes(context); - - sessionetype = ETYPE_NULL; - - for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) { - if (krb5_enctype_valid(context, p[i]) != 0) - continue; - - for (j = 0; j < b->etype.len && sessionetype == ETYPE_NULL; j++) { - Key *dummy; - /* check with client */ - if (p[i] != b->etype.val[j]) - continue; - /* save best of union of { client, crypto system } */ - if (clientbest == ETYPE_NULL) - clientbest = p[i]; - /* check with krbtgt */ - ret = hdb_enctype2key(context, &server->entry, p[i], &dummy); - if (ret) - continue; - sessionetype = p[i]; - } - } - /* if krbtgt had no shared keys with client, pick clients best */ - if (clientbest != ETYPE_NULL && sessionetype == ETYPE_NULL) { - sessionetype = clientbest; - } else if (sessionetype == ETYPE_NULL) { - kdc_log(context, config, 0, - "Client (%s) from %s has no common enctypes with KDC" - "to use for the session key", - client_name, from); - goto out; - } - } - - log_as_req(context, config, cetype, setype, b); - if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey || (f.request_anonymous && !config->allow_anonymous)) { ret = KRB5KDC_ERR_BADOPTION; @@ -1642,12 +1618,13 @@ _kdc_as_rep(krb5_context context, goto out; } else #endif - if (ckey) { - reply_key = &ckey->key; + { ret = krb5_generate_random_keyblock(context, sessionetype, &et.key); if (ret) goto out; - } else { + } + + if (reply_key == NULL) { e_text = "Client have no reply key"; ret = KRB5KDC_ERR_CLIENT_NOTYET; goto out; @@ -1657,9 +1634,6 @@ _kdc_as_rep(krb5_context context, if (ret) goto out; - if (ckey) - set_salt_padata (rep.padata, ckey->salt); - /* Add signing of alias referral */ if (f.canonicalize) { PA_ClientCanonicalized canon; @@ -1765,6 +1739,8 @@ _kdc_as_rep(krb5_context context, if (ret) goto out; + log_as_req(context, config, reply_key->keytype, setype, b); + ret = _kdc_encode_reply(context, config, &rep, &et, &ek, setype, server->entry.kvno, &skey->key, client->entry.kvno, diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c index 4f587cf1b..0071c832f 100644 --- a/kdc/krb5tgs.c +++ b/kdc/krb5tgs.c @@ -1633,14 +1633,15 @@ server_lookup: } else { Key *skey; - ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len, - &skey, &etype); + ret = _kdc_find_etype(context, server, + b->etype.val, b->etype.len, &skey); if(ret) { kdc_log(context, config, 0, "Server (%s) has no support for etypes", spn); goto out; } ekey = &skey->key; + etype = skey->key.keytype; kvno = server->entry.kvno; }