From 632260bd1fccfb420f0827b59c85c329203eafc9 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 28 Oct 2012 11:31:37 -0400 Subject: [PATCH] Pass through module errors when preauthenticating If we are responding to a KDC_ERR_PREAUTH_REQUIRED and cannot preauthenticate, report the error from the first real preauth type we tried. k5_preauth() now accepts a boolean input indicating that it must succeed on a real preauth type, instead of returning a boolean saying whether or not it did. ticket: 7517 (new) --- src/lib/krb5/krb/get_in_tkt.c | 9 +++------ src/lib/krb5/krb/int-proto.h | 2 +- src/lib/krb5/krb/preauth2.c | 33 ++++++++++++++++++++++----------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 377773e1c2..3bf1b3a1c3 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -1219,7 +1219,6 @@ init_creds_step_request(krb5_context context, krb5_data *out) { krb5_error_code code; - krb5_boolean got_real; char random_buf[4]; krb5_data random_data; @@ -1267,9 +1266,7 @@ init_creds_step_request(krb5_context context, ctx->inner_request_body, ctx->encoded_previous_request, ctx->preauth_to_use, ctx->prompter, ctx->prompter_data, - &ctx->request->padata, &got_real); - if (code == 0 && !got_real && ctx->preauth_required) - code = KRB5_PREAUTH_FAILED; + ctx->preauth_required, &ctx->request->padata); if (code != 0) goto cleanup; } else { @@ -1419,7 +1416,7 @@ init_creds_step_reply(krb5_context context, int canon_flag = 0; krb5_keyblock *strengthen_key = NULL; krb5_keyblock encrypting_key; - krb5_boolean fast_avail, got_real; + krb5_boolean fast_avail; encrypting_key.length = 0; encrypting_key.contents = NULL; @@ -1535,7 +1532,7 @@ init_creds_step_reply(krb5_context context, code = k5_preauth(context, ctx->opte, &ctx->preauth_rock, ctx->request, ctx->inner_request_body, ctx->encoded_previous_request, ctx->reply->padata, ctx->prompter, ctx->prompter_data, - &kdc_padata, &got_real); + FALSE, &kdc_padata); if (code != 0) goto cleanup; diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h index 12bee33981..ca534cdcbf 100644 --- a/src/lib/krb5/krb/int-proto.h +++ b/src/lib/krb5/krb/int-proto.h @@ -208,7 +208,7 @@ k5_preauth(krb5_context context, krb5_gic_opt_ext *opte, krb5_clpreauth_rock rock, krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req, krb5_pa_data **in_padata, krb5_prompter_fct prompter, void *prompter_data, - krb5_pa_data ***padata_out, krb5_boolean *got_real_out); + krb5_boolean must_preauth, krb5_pa_data ***padata_out); krb5_error_code k5_preauth_tryagain(krb5_context context, krb5_gic_opt_ext *opte, diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index be560b2c46..a06233c27d 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -580,10 +580,11 @@ process_pa_data(krb5_context context, krb5_get_init_creds_opt *opt, krb5_clpreauth_rock rock, krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req, krb5_pa_data **in_pa_list, krb5_prompter_fct prompter, - void *prompter_data, krb5_pa_data ***out_pa_list, - int *out_pa_list_size, krb5_boolean *got_real_out) + void *prompter_data, krb5_boolean must_preauth, + krb5_pa_data ***out_pa_list, int *out_pa_list_size) { struct krb5_preauth_context_st *pctx = context->preauth_context; + struct errinfo save = EMPTY_ERRINFO; krb5_pa_data *pa, **pa_ptr, **mod_pa; krb5_error_code ret; clpreauth_handle h; @@ -620,20 +621,31 @@ process_pa_data(krb5_context context, krb5_get_init_creds_opt *opt, ret = grow_pa_list(out_pa_list, out_pa_list_size, mod_pa, i); if (ret) { krb5_free_pa_data(context, mod_pa); - return ret; + goto cleanup; } free(mod_pa); } if (ret == 0 && real) { - /* Record which real padata type we answered. */ + /* Stop now and record which real padata type we answered. */ if (rock->selected_preauth_type != NULL) *rock->selected_preauth_type = pa->pa_type; - *got_real_out = TRUE; - break; + goto cleanup; + } else if (real && save.code == 0) { + /* Save the first error we get from a real preauth type. */ + k5_save_ctx_error(context, ret, &save); } } } - return 0; + + if (must_preauth) { + /* No real preauth types succeeded and we needed to preauthenticate. */ + ret = (save.code != 0) ? k5_restore_ctx_error(context, &save) : + KRB5_PREAUTH_FAILED; + } + +cleanup: + k5_clear_error(&save); + return ret; } static inline krb5_data @@ -915,7 +927,7 @@ k5_preauth(krb5_context context, krb5_gic_opt_ext *opte, krb5_clpreauth_rock rock, krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req, krb5_pa_data **in_padata, krb5_prompter_fct prompter, void *prompter_data, - krb5_pa_data ***padata_out, krb5_boolean *got_real_out) + krb5_boolean must_preauth, krb5_pa_data ***padata_out) { int out_pa_list_size = 0; krb5_pa_data **out_pa_list = NULL; @@ -924,7 +936,6 @@ k5_preauth(krb5_context context, krb5_gic_opt_ext *opte, krb5_get_init_creds_opt *opt = (krb5_get_init_creds_opt *)opte; *padata_out = NULL; - *got_real_out = FALSE; if (in_padata == NULL) return 0; @@ -973,8 +984,8 @@ k5_preauth(krb5_context context, krb5_gic_opt_ext *opte, } ret = process_pa_data(context, opt, rock, req, req_body, prev_req, - in_padata, prompter, prompter_data, &out_pa_list, - &out_pa_list_size, got_real_out); + in_padata, prompter, prompter_data, must_preauth, + &out_pa_list, &out_pa_list_size); if (ret) goto error; -- 2.47.2