From 5f8d6146a69b3afe6bf8a83d40e811c8a6d8f96b Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sat, 15 Oct 2011 15:03:17 +0000 Subject: [PATCH] Make get_preauth_hint_list respond via callback From npmccallum@redhat.com with changes. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25347 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/do_as_req.c | 64 ++++++++++++++++++++++++++----------------- src/kdc/kdc_preauth.c | 9 ++++-- src/kdc/kdc_util.h | 4 ++- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 8419a8cfc..15263b348 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -124,6 +124,8 @@ struct as_req_state { char *sname, *cname; void *pa_context; const krb5_fulladdr *from; + + krb5_error_code preauth_err; }; static void @@ -147,20 +149,6 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) if (errcode) goto egress; - /* - * Final check before handing out ticket: If the client requires - * preauthentication, verify that the proper kind of - * preauthentication was carried out. - */ - state->status = missing_required_preauth(state->client, - state->server, - &state->enc_tkt_reply); - if (state->status) { - errcode = KRB5KDC_ERR_PREAUTH_REQUIRED; - get_preauth_hint_list(state->request, &state->rock, &state->e_data); - goto egress; - } - if ((errcode = validate_forwardable(state->request, *state->client, *state->server, state->kdc_time, &state->status))) { @@ -418,21 +406,46 @@ egress: } static void -finish_preauth(void *arg, krb5_error_code errcode) +finish_missing_required_preauth(void *arg) { - struct as_req_state *state = arg; + struct as_req_state *state = (struct as_req_state *)arg; - if (errcode) { - if (errcode == KRB5KDC_ERR_PREAUTH_FAILED) - get_preauth_hint_list(state->request, &state->rock, - &state->e_data); + finish_process_as_req(state, state->preauth_err); +} - state->status = "PREAUTH_FAILED"; +static void +finish_preauth(void *arg, krb5_error_code code) +{ + struct as_req_state *state = arg; + krb5_error_code real_code = code; + + if (code) { if (vague_errors) - errcode = KRB5KRB_ERR_GENERIC; + code = KRB5KRB_ERR_GENERIC; + state->status = "PREAUTH_FAILED"; + if (real_code == KRB5KDC_ERR_PREAUTH_FAILED) { + state->preauth_err = code; + get_preauth_hint_list(state->request, &state->rock, &state->e_data, + finish_missing_required_preauth, state); + return; + } + } else { + /* + * Final check before handing out ticket: If the client requires + * preauthentication, verify that the proper kind of + * preauthentication was carried out. + */ + state->status = missing_required_preauth(state->client, state->server, + &state->enc_tkt_reply); + if (state->status) { + state->preauth_err = KRB5KDC_ERR_PREAUTH_REQUIRED; + get_preauth_hint_list(state->request, &state->rock, &state->e_data, + finish_missing_required_preauth, state); + return; + } } - finish_process_as_req(state, errcode); + finish_process_as_req(state, code); } /*ARGSUSED*/ @@ -761,8 +774,9 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, state->request, &state->enc_tkt_reply, &state->pa_context, &state->e_data, &state->typed_e_data, finish_preauth, state); - return; - } + } else + finish_preauth(state, 0); + return; errout: finish_process_as_req(state, errcode); diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index d0a081914..13b51e329 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -746,7 +746,8 @@ const char *missing_required_preauth(krb5_db_entry *client, void get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, - krb5_pa_data ***e_data_out) + krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond, + void *arg) { int hw_only; preauth_system *ap; @@ -758,8 +759,10 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, hw_only = isflagset(rock->client->attributes, KRB5_KDB_REQUIRES_HW_AUTH); /* Allocate two extra entries for the cookie and the terminator. */ pa_data = calloc(n_preauth_systems + 2, sizeof(krb5_pa_data *)); - if (pa_data == 0) + if (pa_data == 0) { + (*respond)(arg); return; + } pa = pa_data; for (ap = preauth_systems; ap->type != -1; ap++) { @@ -801,7 +804,7 @@ get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, errout: krb5_free_pa_data(kdc_context, pa_data); - return; + (*respond)(arg); } /* diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index e33f606b8..a31eec568 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -166,9 +166,11 @@ const char * missing_required_preauth (krb5_db_entry *client, krb5_db_entry *server, krb5_enc_tkt_part *enc_tkt_reply); +typedef void (*kdc_hint_respond_fn)(void *arg); void get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, - krb5_pa_data ***e_data_out); + krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond, + void *arg); void load_preauth_plugins(krb5_context context); void -- 2.26.2