[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:
@@ -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)
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user