[HEIMDAL-533] KDC sends TGS-REP encrypted in session key not authenticator

From RFC 4120, page 35

   In preparing the authentication header, the client can select a sub-
   session key under which the response from the Kerberos server will be
   encrypted.  If the client selects a sub-session key, care must be
   taken to ensure the randomness of the selected sub-session key.

The client library alread handle this case.

Thanks to Sam Hartman to report this though Debian
This commit is contained in:
Love Hornquist Astrand
2009-10-11 08:46:53 -07:00
parent 8e08aa0a15
commit 678f9f9f07
2 changed files with 56 additions and 30 deletions

View File

@@ -261,6 +261,7 @@ _kdc_encode_reply(krb5_context context,
krb5_enctype etype, krb5_enctype etype,
int skvno, const EncryptionKey *skey, int skvno, const EncryptionKey *skey,
int ckvno, const EncryptionKey *reply_key, int ckvno, const EncryptionKey *reply_key,
int rk_is_subkey,
const char **e_text, const char **e_text,
krb5_data *reply) krb5_data *reply)
{ {
@@ -341,7 +342,7 @@ _kdc_encode_reply(krb5_context context,
} else { } else {
krb5_encrypt_EncryptedData(context, krb5_encrypt_EncryptedData(context,
crypto, crypto,
KRB5_KU_TGS_REP_ENC_PART_SESSION, rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
buf, buf,
len, len,
ckvno, ckvno,
@@ -1757,7 +1758,7 @@ _kdc_as_rep(krb5_context context,
ret = _kdc_encode_reply(context, config, ret = _kdc_encode_reply(context, config,
&rep, &et, &ek, setype, server->entry.kvno, &rep, &et, &ek, setype, server->entry.kvno,
&skey->key, client->entry.kvno, &skey->key, client->entry.kvno,
reply_key, &e_text, reply); reply_key, 0, &e_text, reply);
free_EncTicketPart(&et); free_EncTicketPart(&et);
free_EncKDCRepPart(&ek); free_EncKDCRepPart(&ek);
if (ret) if (ret)

View File

@@ -671,6 +671,8 @@ tgs_make_reply(krb5_context context,
KDC_REQ_BODY *b, KDC_REQ_BODY *b,
krb5_const_principal tgt_name, krb5_const_principal tgt_name,
const EncTicketPart *tgt, const EncTicketPart *tgt,
const krb5_keyblock *replykey,
int rk_is_subkey,
const EncryptionKey *serverkey, const EncryptionKey *serverkey,
const krb5_keyblock *sessionkey, const krb5_keyblock *sessionkey,
krb5_kvno kvno, krb5_kvno kvno,
@@ -931,7 +933,8 @@ tgs_make_reply(krb5_context context,
ret = _kdc_encode_reply(context, config, ret = _kdc_encode_reply(context, config,
&rep, &et, &ek, et.key.keytype, &rep, &et, &ek, et.key.keytype,
kvno, kvno,
serverkey, 0, &tgt->key, e_text, reply); serverkey, 0, replykey, rk_is_subkey,
e_text, reply);
if (is_weak) if (is_weak)
krb5_enctype_disable(context, et.key.keytype); krb5_enctype_disable(context, et.key.keytype);
@@ -1081,7 +1084,9 @@ tgs_parse_request(krb5_context context,
const struct sockaddr *from_addr, const struct sockaddr *from_addr,
time_t **csec, time_t **csec,
int **cusec, int **cusec,
AuthorizationData **auth_data) AuthorizationData **auth_data,
krb5_keyblock **replykey,
int *rk_is_subkey)
{ {
krb5_ap_req ap_req; krb5_ap_req ap_req;
krb5_error_code ret; krb5_error_code ret;
@@ -1091,10 +1096,13 @@ tgs_parse_request(krb5_context context,
krb5_flags verify_ap_req_flags; krb5_flags verify_ap_req_flags;
krb5_crypto crypto; krb5_crypto crypto;
Key *tkey; Key *tkey;
krb5_keyblock *subkey = NULL;
unsigned usage;
*auth_data = NULL; *auth_data = NULL;
*csec = NULL; *csec = NULL;
*cusec = NULL; *cusec = NULL;
*replykey = NULL;
memset(&ap_req, 0, sizeof(ap_req)); memset(&ap_req, 0, sizeof(ap_req));
ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
@@ -1223,37 +1231,42 @@ tgs_parse_request(krb5_context context,
goto out; goto out;
} }
if (b->enc_authorization_data) { usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY; *rk_is_subkey = 1;
krb5_keyblock *subkey;
krb5_data ad;
ret = krb5_auth_con_getremotesubkey(context, ac, &subkey); ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
if(ret){ if(ret){
krb5_auth_con_free(context, ac);
kdc_log(context, config, 0, "Failed to get remote subkey: %s",
krb5_get_err_text(context, ret));
goto out;
}
if(subkey == NULL){
usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
*rk_is_subkey = 0;
ret = krb5_auth_con_getkey(context, ac, &subkey);
if(ret) {
krb5_auth_con_free(context, ac); krb5_auth_con_free(context, ac);
kdc_log(context, config, 0, "Failed to get remote subkey: %s", kdc_log(context, config, 0, "Failed to get session key: %s",
krb5_get_err_text(context, ret)); krb5_get_err_text(context, ret));
goto out; goto out;
} }
if(subkey == NULL){ }
usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION; if(subkey == NULL){
ret = krb5_auth_con_getkey(context, ac, &subkey); krb5_auth_con_free(context, ac);
if(ret) { kdc_log(context, config, 0,
krb5_auth_con_free(context, ac); "Failed to get key for enc-authorization-data");
kdc_log(context, config, 0, "Failed to get session key: %s", ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
krb5_get_err_text(context, ret)); goto out;
goto out; }
}
} *replykey = subkey;
if(subkey == NULL){
krb5_auth_con_free(context, ac); if (b->enc_authorization_data) {
kdc_log(context, config, 0, krb5_data ad;
"Failed to get key for enc-authorization-data");
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
ret = krb5_crypto_init(context, subkey, 0, &crypto); ret = krb5_crypto_init(context, subkey, 0, &crypto);
krb5_free_keyblock(context, subkey);
if (ret) { if (ret) {
krb5_auth_con_free(context, ac); krb5_auth_con_free(context, ac);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
@@ -1381,6 +1394,8 @@ tgs_build_reply(krb5_context context,
KDC_REQ_BODY *b, KDC_REQ_BODY *b,
hdb_entry_ex *krbtgt, hdb_entry_ex *krbtgt,
krb5_enctype krbtgt_etype, krb5_enctype krbtgt_etype,
const krb5_keyblock *replykey,
int rk_is_subkey,
krb5_ticket *ticket, krb5_ticket *ticket,
krb5_data *reply, krb5_data *reply,
const char *from, const char *from,
@@ -1954,6 +1969,8 @@ server_lookup:
b, b,
client_principal, client_principal,
tgt, tgt,
replykey,
rk_is_subkey,
ekey, ekey,
&sessionkey, &sessionkey,
kvno, kvno,
@@ -2020,6 +2037,8 @@ _kdc_tgs_rep(krb5_context context,
const char *e_text = NULL; const char *e_text = NULL;
krb5_enctype krbtgt_etype = ETYPE_NULL; krb5_enctype krbtgt_etype = ETYPE_NULL;
krb5_keyblock *replykey = NULL;
int rk_is_subkey = 0;
time_t *csec = NULL; time_t *csec = NULL;
int *cusec = NULL; int *cusec = NULL;
@@ -2047,7 +2066,9 @@ _kdc_tgs_rep(krb5_context context,
&e_text, &e_text,
from, from_addr, from, from_addr,
&csec, &cusec, &csec, &cusec,
&auth_data); &auth_data,
&replykey,
&rk_is_subkey);
if (ret) { if (ret) {
kdc_log(context, config, 0, kdc_log(context, config, 0,
"Failed parsing TGS-REQ from %s", from); "Failed parsing TGS-REQ from %s", from);
@@ -2060,6 +2081,8 @@ _kdc_tgs_rep(krb5_context context,
&req->req_body, &req->req_body,
krbtgt, krbtgt,
krbtgt_etype, krbtgt_etype,
replykey,
rk_is_subkey,
ticket, ticket,
data, data,
from, from,
@@ -2080,6 +2103,8 @@ _kdc_tgs_rep(krb5_context context,
} }
out: out:
if (replykey)
krb5_free_keyblock(context, replykey);
if(ret && data->data == NULL){ if(ret && data->data == NULL){
krb5_mk_error(context, krb5_mk_error(context,
ret, ret,