From e0c545139c54d6612687b0458b56ce34419a3a36 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Fri, 13 Feb 2009 15:55:32 +0000 Subject: [PATCH] Implement TGS authenticator subkey usage Implement support for use of a subkey in the TGS req. This is needed by FAST TGS support. The interface to krb5_send_tgs changed in order to gain a subkey output parameter. Since this is a private interface it was renamed to krb5int_send_tgs and removed from the export list. * send_tgs.c: generate a subkey and return to caller * decode_kdc_rep.c: Use subkey keyusage * gc_via_tkt.c: pass in subkey to decode_kdc_rep * send_tgs.c: use subkey for encrypting authorization data ticket: 6393 tags: enhancement git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21993 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 11 ++++-- src/lib/krb5/krb/decode_kdc.c | 7 +--- src/lib/krb5/krb/gc_via_tkt.c | 10 +++-- src/lib/krb5/krb/send_tgs.c | 69 ++++++++++++++++++++++------------- src/lib/krb5/libkrb5.exports | 1 - 5 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 61d1aa18f..79d1cf1cd 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -2523,7 +2523,7 @@ krb5_error_code KRB5_CALLCONV krb5_get_default_config_files void KRB5_CALLCONV krb5_free_config_files (char **filenames); -krb5_error_code krb5_send_tgs +krb5_error_code krb5int_send_tgs (krb5_context, krb5_flags, const krb5_ticket_times *, @@ -2534,11 +2534,16 @@ krb5_error_code krb5_send_tgs krb5_pa_data * const *, const krb5_data *, krb5_creds *, - krb5_response * ); + krb5_response * , krb5_keyblock **subkey); + /* The subkey field is an output parameter; if a + * tgs-rep is received then the subkey will be filled + * in with the subkey needed to decrypt the TGS + * response. Otherwise it will be set to null. + */ krb5_error_code krb5_decode_kdc_rep (krb5_context, krb5_data *, - const krb5_keyblock *, + const krb5_keyblock *, krb5_kdc_rep ** ); krb5_error_code krb5_rd_req_decoded diff --git a/src/lib/krb5/krb/decode_kdc.c b/src/lib/krb5/krb/decode_kdc.c index cdfc4ffbd..a75bbf266 100644 --- a/src/lib/krb5/krb/decode_kdc.c +++ b/src/lib/krb5/krb/decode_kdc.c @@ -53,12 +53,7 @@ krb5_decode_kdc_rep(krb5_context context, krb5_data *enc_rep, const krb5_keybloc usage = KRB5_KEYUSAGE_AS_REP_ENCPART; retval = decode_krb5_as_rep(enc_rep, &local_dec_rep); } else if (krb5_is_tgs_rep(enc_rep)) { - usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY; - /* KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY would go here, except - that this client code base doesn't ever put a subkey in the - tgs_req authenticator, so the tgs_rep is never encrypted in - one. (Check send_tgs.c:krb5_send_tgs_basic(), near the top - where authent.subkey is set to 0) */ + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY; retval = decode_krb5_tgs_rep(enc_rep, &local_dec_rep); } else { return KRB5KRB_AP_ERR_MSG_TYPE; diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c index 82972b7fc..059da828a 100644 --- a/src/lib/krb5/krb/gc_via_tkt.c +++ b/src/lib/krb5/krb/gc_via_tkt.c @@ -154,6 +154,7 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt, krb5_error *err_reply; krb5_response tgsrep; krb5_enctype *enctypes = 0; + krb5_keyblock *subkey = NULL; #ifdef DEBUG_REFERRALS printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off"); @@ -200,12 +201,12 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt, enctypes[1] = 0; } - retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, enctypes, + retval = krb5int_send_tgs(context, kdcoptions, &in_cred->times, enctypes, in_cred->server, address, in_cred->authdata, 0, /* no padata */ (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY) ? &in_cred->second_ticket : NULL, - tkt, &tgsrep); + tkt, &tgsrep, &subkey); if (enctypes) free(enctypes); if (retval) { @@ -280,7 +281,7 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt, } if ((retval = krb5_decode_kdc_rep(context, &tgsrep.response, - &tkt->keyblock, &dec_rep))) + subkey, &dec_rep))) goto error_4; if (dec_rep->msg_type != KRB5_TGS_REP) { @@ -334,6 +335,9 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt, &in_cred->second_ticket, out_cred); error_3:; + if (subkey != NULL) + krb5_free_keyblock(context, subkey); + memset(dec_rep->enc_part2->session->contents, 0, dec_rep->enc_part2->session->length); krb5_free_kdc_rep(context, dec_rep); diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 83914c498..9a10b9271 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -30,7 +30,7 @@ #include "k5-int.h" /* - Sends a request to the TGS and waits for a response. +Constructs a TGS request options is used for the options in the KRB_TGS_REQ. timestruct values are used for from, till, rtime " " " enctype is used for enctype " " ", and to encrypt the authorization data, @@ -48,7 +48,8 @@ returns system errors */ static krb5_error_code -krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cred, krb5_data *outbuf) +tgs_construct_tgsreq(krb5_context context, krb5_data *in_data, + krb5_creds *in_cred, krb5_data *outbuf, krb5_keyblock **subkey) { krb5_error_code retval; krb5_checksum checksum; @@ -56,6 +57,12 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre krb5_ap_req request; krb5_data * scratch; krb5_data * toutbuf; + checksum.contents = NULL; +/* Generate subkey*/ + if ((retval = krb5_generate_subkey( context, &in_cred->keyblock, + subkey)) != 0) + return retval; + /* Generate checksum */ if ((retval = krb5_c_make_checksum(context, context->kdc_req_sumtype, @@ -63,43 +70,42 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, in_data, &checksum))) { free(checksum.contents); - return(retval); + goto cleanup; } /* gen authenticator */ - authent.subkey = 0; + authent.subkey = *subkey; /*owned by caller*/ authent.seq_number = 0; authent.checksum = &checksum; authent.client = in_cred->client; authent.authorization_data = in_cred->authdata; if ((retval = krb5_us_timeofday(context, &authent.ctime, - &authent.cusec))) { - free(checksum.contents); - return(retval); - } + &authent.cusec))) + goto cleanup; + /* encode the authenticator */ - if ((retval = encode_krb5_authenticator(&authent, &scratch))) { - free(checksum.contents); - return(retval); - } + if ((retval = encode_krb5_authenticator(&authent, &scratch))) + goto cleanup; + free(checksum.contents); + checksum.contents = NULL; - request.authenticator.ciphertext.data = 0; + request.authenticator.ciphertext.data = NULL; request.authenticator.kvno = 0; request.ap_options = 0; request.ticket = 0; if ((retval = decode_krb5_ticket(&(in_cred)->ticket, &request.ticket))) /* Cleanup scratch and scratch data */ - goto cleanup_data; + goto cleanup; /* call the encryption routine */ if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock, KRB5_KEYUSAGE_TGS_REQ_AUTH, scratch, &request.authenticator))) - goto cleanup_ticket; + goto cleanup; retval = encode_krb5_ap_req(&request, &toutbuf); *outbuf = *toutbuf; @@ -110,25 +116,30 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre request.authenticator.ciphertext.length); free(request.authenticator.ciphertext.data); -cleanup_ticket: + cleanup: +if (request.ticket) krb5_free_ticket(context, request.ticket); -cleanup_data: - memset(scratch->data, 0, scratch->length); + if (scratch != NULL && scratch->data != NULL) { +zap(scratch->data, scratch->length); free(scratch->data); - free(scratch); + } + if (*subkey && retval != 0) { + krb5_free_keyblock(context, *subkey); + *subkey = NULL; + } return retval; } krb5_error_code -krb5_send_tgs(krb5_context context, krb5_flags kdcoptions, +krb5int_send_tgs(krb5_context context, krb5_flags kdcoptions, const krb5_ticket_times *timestruct, const krb5_enctype *ktypes, krb5_const_principal sname, krb5_address *const *addrs, krb5_authdata *const *authorization_data, krb5_pa_data *const *padata, const krb5_data *second_ticket, - krb5_creds *in_cred, krb5_response *rep) + krb5_creds *in_cred, krb5_response *rep, krb5_keyblock **subkey) { krb5_error_code retval; krb5_kdc_req tgsreq; @@ -140,6 +151,8 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions, krb5_pa_data ap_req_padata; int tcp_only = 0, use_master; + assert (subkey != NULL); + *subkey = NULL; /* * in_creds MUST be a valid credential NOT just a partially filled in * place holder for us to get credentials for the caller. @@ -170,8 +183,8 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions, if ((retval = encode_krb5_authdata(authorization_data, &scratch))) return(retval); - if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock, - KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, + if ((retval = krb5_encrypt_helper(context, *subkey, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, scratch, &tgsreq.authorization_data))) { free(tgsreq.authorization_data.ciphertext.data); @@ -212,7 +225,8 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions, /* * Get an ap_req. */ - if ((retval = krb5_send_tgs_basic(context, scratch, in_cred, &scratch2))) { + if ((retval = tgs_construct_tgsreq(context, scratch, in_cred + , &scratch2, subkey))) { krb5_free_data(context, scratch); goto send_tgs_error_2; } @@ -275,7 +289,7 @@ send_again: tcp_only = 1; krb5_free_error(context, err_reply); free(rep->response.data); - rep->response.data = 0; + rep->response.data = NULL; goto send_again; } krb5_free_error(context, err_reply); @@ -303,6 +317,11 @@ send_tgs_error_1:; tgsreq.authorization_data.ciphertext.length); free(tgsreq.authorization_data.ciphertext.data); } + if (rep->message_type != KRB5_TGS_REP && *subkey){ + krb5_free_keyblock(context, *subkey); + *subkey = NULL; + } + return retval; } diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index c69aead5d..2671ebca5 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -449,7 +449,6 @@ krb5_recvauth_version krb5_register_serializer krb5_salttype_to_string krb5_secure_config_files -krb5_send_tgs krb5_sendauth krb5_sendto_kdc krb5_ser_address_init -- 2.26.2