Redo client key handling for AS
Pick the replykey to be the same as the preauth key, this allows us to delay the picking of client key to when its needed, this means that we can have a reply keys for PKINIT that is independant of what keys the client have.
This commit is contained in:

committed by
Love Hornquist Astrand

parent
9a5b9ed720
commit
6df0783c7e
154
kdc/kerberos5.c
154
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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user