From: Sam Hartman Date: Tue, 9 Feb 2010 19:15:07 +0000 (+0000) Subject: enc_padata can include empty sequence X-Git-Tag: krb5-1.9-beta1~356 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7a04b369aa71b0796f057cf5da57070a9c37c9c8;p=krb5.git enc_padata can include empty sequence There are two issues with return_enc_padata. 1) It often will return an empty sequence of enc_padata rather than not including the field 2) FAST negotiation is double supported in the referral tgs path and not supported in the non-referral path Rewrite the return_enc_padata logic to: * Split out referral interactions with kdb into its own function * Use add_pa_data_element ticket: 6656 target_version: 1.8 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23712 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 83d3101b6..a5b710043 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -623,7 +623,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, goto errout; } errcode = return_enc_padata(kdc_context, req_pkt, request, - as_encrypting_key, &server, &reply_encpart); + as_encrypting_key, &server, &reply_encpart, FALSE); if (errcode) { status = "KDC_RETURN_ENC_PADATA"; goto errout; diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 26fde1e0c..52256e7bd 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -948,31 +948,15 @@ tgt_again: status = "generating reply key"; goto cleanup; } - if (is_referral && isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE)) { - int idx = 0; - - errcode = return_enc_padata(kdc_context, pkt, request, - reply_key, &server, &reply_encpart); - if (errcode) { - status = "KDC_RETURN_ENC_PADATA"; - goto cleanup; - } - /* Not referral. */ - reply_encpart.enc_padata = calloc(3, sizeof(krb5_pa_data *)); - if (reply_encpart.enc_padata == NULL) { - errcode = ENOMEM; - status = "Allocating enc_padata"; - goto cleanup; - } - errcode = kdc_handle_protected_negotiation(pkt, request, reply_key, - reply_encpart.enc_padata, - &idx); - if (errcode != 0) { - status = "protected negotiation"; - goto cleanup; - } + errcode = return_enc_padata(kdc_context, pkt, request, + reply_key, &server, &reply_encpart, + is_referral && isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE)); + if (errcode) { + status = "KDC_RETURN_ENC_PADATA"; + goto cleanup; } + errcode = krb5_encode_kdc_rep(kdc_context, KRB5_TGS_REP, &reply_encpart, subkey ? 1 : 0, reply_key, diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index c5dfb1f9b..05df3940c 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -3084,48 +3084,52 @@ include_pac_p(krb5_context context, krb5_kdc_req *request) return retval; } -krb5_error_code -return_enc_padata(krb5_context context, krb5_data *req_pkt, - krb5_kdc_req *request, krb5_keyblock *reply_key, - krb5_db_entry *server, krb5_enc_kdc_rep_part *reply_encpart) +static krb5_error_code +return_referral_enc_padata( krb5_context context, + krb5_enc_kdc_rep_part *reply, krb5_db_entry *server) { - krb5_error_code code; + krb5_error_code code; krb5_tl_data tl_data; - krb5_pa_data *pa_data; - int idx = 0; + krb5_pa_data pa_data; - /* This should be initialized and only used for Win2K compat and other - * specific standardized uses such as FAST negotiation. */ - assert(reply_encpart->enc_padata == NULL); - reply_encpart->enc_padata = calloc(4, sizeof(krb5_pa_data *)); - if (reply_encpart->enc_padata == NULL) - return ENOMEM; tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA; code = krb5_dbe_lookup_tl_data(context, server, &tl_data); if (code || tl_data.tl_data_length == 0) - goto negotiate; /* no server referrals to return */ + return 0; - pa_data = (krb5_pa_data *)malloc(sizeof(*pa_data)); - if (pa_data == NULL) - return ENOMEM; - pa_data->magic = KV5M_PA_DATA; - pa_data->pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; - pa_data->length = tl_data.tl_data_length; - pa_data->contents = malloc(pa_data->length); - if (pa_data->contents == NULL) { - free(pa_data); - return ENOMEM; - } - memcpy(pa_data->contents, tl_data.tl_data_contents, tl_data.tl_data_length); + pa_data.magic = KV5M_PA_DATA; + pa_data.pa_type = KRB5_PADATA_SVR_REFERRAL_INFO; + pa_data.length = tl_data.tl_data_length; + pa_data.contents = tl_data.tl_data_contents; + return add_pa_data_element(context, &pa_data, &reply->enc_padata, FALSE); +} - reply_encpart->enc_padata[idx++] = pa_data; - reply_encpart->enc_padata[1] = NULL; -negotiate: - return kdc_handle_protected_negotiation(req_pkt, request, reply_key, - reply_encpart->enc_padata, &idx); +krb5_error_code +return_enc_padata(krb5_context context, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_keyblock *reply_key, + krb5_db_entry *server, krb5_enc_kdc_rep_part *reply_encpart, + krb5_boolean is_referral) +{ + krb5_error_code code = 0; + /* This should be initialized and only used for Win2K compat and other + * specific standardized uses such as FAST negotiation. */ + assert(reply_encpart->enc_padata == NULL); + if (is_referral) { + code = return_referral_enc_padata(context, reply_encpart, server); + if (code) + return code; + } + code = kdc_handle_protected_negotiation(req_pkt, request, reply_key, + &reply_encpart->enc_padata); + if (code) + goto cleanup; + /*Add potentially other enc_padata providers*/ +cleanup: + return code; } + #if 0 static krb5_error_code return_server_referral(krb5_context context, krb5_pa_data * padata, diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 281bcc8ee..95f495a82 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -2675,23 +2675,18 @@ kdc_get_ticket_endtime(krb5_context context, krb5_error_code kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request, const krb5_keyblock *reply_key, - krb5_pa_data **out_enc_padata, int *idx) + krb5_pa_data ***out_enc_padata) { krb5_error_code retval = 0; krb5_checksum checksum; krb5_data *out = NULL; - krb5_pa_data *pa; - assert(out_enc_padata != NULL); - pa = krb5int_find_pa_data(kdc_context, request->padata, + krb5_pa_data pa, *pa_in; + pa_in = krb5int_find_pa_data(kdc_context, request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP); - if (pa == NULL) + if (pa_in == NULL) return 0; - checksum.contents = NULL; - pa = malloc(sizeof(krb5_pa_data)); - if (pa == NULL) - return ENOMEM; - pa->magic = KV5M_PA_DATA; - pa->pa_type = KRB5_ENCPADATA_REQ_ENC_PA_REP; + pa.magic = KV5M_PA_DATA; + pa.pa_type = KRB5_ENCPADATA_REQ_ENC_PA_REP; retval = krb5_c_make_checksum(kdc_context,0, reply_key, KRB5_KEYUSAGE_AS_REQ, req_pkt, &checksum); if (retval != 0) @@ -2699,29 +2694,22 @@ kdc_handle_protected_negotiation(krb5_data *req_pkt, krb5_kdc_req *request, retval = encode_krb5_checksum(&checksum, &out); if (retval != 0) goto cleanup; - pa->contents = (krb5_octet *) out->data; - pa->length = out->length; - out_enc_padata[(*idx)++] = pa; - pa = NULL; + pa.contents = (krb5_octet *) out->data; + pa.length = out->length; + retval = add_pa_data_element(kdc_context, &pa, out_enc_padata, FALSE); out->data = NULL; - pa = malloc(sizeof(krb5_pa_data)); - if (pa == NULL) { - retval = ENOMEM; + if (retval) goto cleanup; - } - pa->magic = KV5M_PA_DATA; - pa->pa_type = KRB5_PADATA_FX_FAST; - pa->length = 0; - pa->contents = NULL; - out_enc_padata[(*idx)++] = pa; - pa = NULL; + pa.magic = KV5M_PA_DATA; + pa.pa_type = KRB5_PADATA_FX_FAST; + pa.length = 0; + pa.contents = NULL; + retval = add_pa_data_element(kdc_context, &pa, out_enc_padata, FALSE); cleanup: if (checksum.contents) krb5_free_checksum_contents(kdc_context, &checksum); if (out != NULL) krb5_free_data(kdc_context, out); - if (pa != NULL) - free(pa); return retval; } diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 258389508..4b81376f3 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -258,7 +258,8 @@ return_enc_padata(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, krb5_keyblock *reply_key, krb5_db_entry *server, - krb5_enc_kdc_rep_part *reply_encpart); + krb5_enc_kdc_rep_part *reply_encpart, +krb5_boolean is_referral); krb5_error_code sign_db_authdata (krb5_context context, @@ -401,7 +402,7 @@ krb5_error_code kdc_preauth_get_cookie(struct kdc_request_state *state, krb5_error_code kdc_handle_protected_negotiation( krb5_data *req_pkt, krb5_kdc_req *request, const krb5_keyblock *reply_key, - krb5_pa_data **out_enc_padata, int *idx); + krb5_pa_data ***out_enc_padata); krb5_error_code krb5int_get_domain_realm_mapping(krb5_context context, const char *host, char ***realmsp);