From 1329c7742c951596efbf06186828a14155194993 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 3 Oct 2011 19:14:05 +0000 Subject: [PATCH] Make kdcpreauth verify respond via callback From npmccallum@redhat.com with changes. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25294 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/krb5/preauth_plugin.h | 13 +- src/kdc/kdc_preauth.c | 367 +++++++++++------- src/kdc/kdc_preauth_ec.c | 12 +- .../preauth/cksum_body/cksum_body_main.c | 46 ++- src/plugins/preauth/pkinit/pkinit_srv.c | 46 ++- .../preauth/securid_sam2/securid_sam2_main.c | 13 +- src/plugins/preauth/wpse/wpse_main.c | 34 +- 7 files changed, 317 insertions(+), 214 deletions(-) diff --git a/src/include/krb5/preauth_plugin.h b/src/include/krb5/preauth_plugin.h index d376098b3..c620d6cdb 100644 --- a/src/include/krb5/preauth_plugin.h +++ b/src/include/krb5/preauth_plugin.h @@ -419,7 +419,13 @@ typedef krb5_error_code * per-request module data for consumption by the return_fn or free_modreq_fn * below. */ -typedef krb5_error_code +typedef void +(*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code, + krb5_kdcpreauth_modreq modreq, + krb5_data *e_data, + krb5_authdata **authz_data); + +typedef void (*krb5_kdcpreauth_verify_fn)(krb5_context context, struct _krb5_db_entry_new *client, krb5_data *req_pkt, krb5_kdc_req *request, @@ -427,9 +433,8 @@ typedef krb5_error_code krb5_pa_data *data, krb5_kdcpreauth_get_data_fn get_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data_out, - krb5_authdata ***authz_data_out); + krb5_kdcpreauth_verify_respond_fn respond, + void *arg); /* * Optional: generate preauthentication response data to send to the client as diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 5e1312656..ec10e170e 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -104,14 +104,14 @@ typedef struct preauth_system_st { krb5_kdcpreauth_free_modreq_fn free_modreq; } preauth_system; -static krb5_error_code +static void verify_enc_timestamp(krb5_context, krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, krb5_kdcpreauth_get_data_fn get_entry_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, krb5_data **e_data, - krb5_authdata ***authz_data); + krb5_kdcpreauth_verify_respond_fn respond, + void *arg); static krb5_error_code get_enc_ts(krb5_context context, krb5_kdc_req *request, @@ -933,161 +933,79 @@ add_authorization_data(krb5_enc_tkt_part *enc_tkt_part, krb5_authdata **ad) return 0; } -/* - * This routine is called to verify the preauthentication information - * for a V5 request. - * - * Returns 0 if the pre-authentication is valid, non-zero to indicate - * an error code of some sort. - */ +struct padata_state { + kdc_preauth_respond_fn respond; + void *arg; + kdc_realm_t *realm; -void -check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, - krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, - void **padata_context, krb5_data *e_data, - kdc_preauth_respond_fn respond, void *arg) -{ - krb5_error_code retval = 0; - krb5_pa_data **padata; - preauth_system *pa_sys; krb5_kdcpreauth_modreq *modreq_ptr; - krb5_data *pa_e_data = NULL, *tmp_e_data = NULL; - int pa_ok = 0, pa_found = 0; - krb5_error_code saved_retval = 0; - int use_saved_retval = 0; - const char *emsg; - krb5_authdata **tmp_authz_data = NULL; + krb5_pa_data **padata; + int pa_found; + krb5_context context; + krb5_db_entry *client; + krb5_data *req_pkt; + krb5_kdc_req *request; + krb5_enc_tkt_part *enc_tkt_reply; + void **padata_context; + krb5_data *e_data; - if (request->padata == 0) { - (*respond)(arg, 0); - return; - } + preauth_system *pa_sys; + krb5_data *pa_e_data; + int pa_ok; + krb5_error_code saved_code; +}; - if (make_padata_context(context, padata_context) != 0) { - (*respond)(arg, KRB5KRB_ERR_GENERIC); - return; - } +static void +finish_check_padata(struct padata_state *state, krb5_error_code code) +{ + kdc_preauth_respond_fn oldrespond; + void *oldarg; -#ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, "checking padata"); -#endif - for (padata = request->padata; *padata; padata++) { -#ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*padata)->pa_type); -#endif - if (find_pa_system((*padata)->pa_type, &pa_sys)) - continue; - if (find_modreq(pa_sys, *padata_context, &modreq_ptr)) - continue; -#ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", pa_sys->name); -#endif - if (pa_sys->verify_padata == 0) - continue; - pa_found++; - retval = pa_sys->verify_padata(context, client, req_pkt, request, - enc_tkt_reply, *padata, - get_entry_data, pa_sys->moddata, - modreq_ptr, &tmp_e_data, - &tmp_authz_data); - if (retval) { - emsg = krb5_get_error_message (context, retval); - krb5_klog_syslog (LOG_INFO, "preauth (%s) verify failure: %s", - pa_sys->name, emsg); - krb5_free_error_message (context, emsg); - /* Ignore authorization data returned from modules that fail */ - if (tmp_authz_data != NULL) { - krb5_free_authdata(context, tmp_authz_data); - tmp_authz_data = NULL; - } - if (pa_sys->flags & PA_REQUIRED) { - /* free up any previous edata we might have been saving */ - if (pa_e_data != NULL) - krb5_free_data(context, pa_e_data); - pa_e_data = tmp_e_data; - tmp_e_data = NULL; - use_saved_retval = 0; /* Make sure we use the current retval */ - pa_ok = 0; - break; - } - /* - * We'll return edata from either the first PA_REQUIRED module - * that fails, or the first non-PA_REQUIRED module that fails. - * Hang on to edata from the first non-PA_REQUIRED module. - * If we've already got one saved, simply discard this one. - */ - if (tmp_e_data != NULL) { - if (pa_e_data == NULL) { - /* save the first error code and e-data */ - pa_e_data = tmp_e_data; - tmp_e_data = NULL; - saved_retval = retval; - use_saved_retval = 1; - } else { - /* discard this extra e-data from non-PA_REQUIRED module */ - krb5_free_data(context, tmp_e_data); - tmp_e_data = NULL; - } - } - } else { -#ifdef DEBUG - krb5_klog_syslog (LOG_DEBUG, ".. .. ok"); -#endif - /* Ignore any edata returned on success */ - if (tmp_e_data != NULL) { - krb5_free_data(context, tmp_e_data); - tmp_e_data = NULL; - } - /* Add any authorization data to the ticket */ - if (tmp_authz_data != NULL) { - add_authorization_data(enc_tkt_reply, tmp_authz_data); - free(tmp_authz_data); - tmp_authz_data = NULL; - } - pa_ok = 1; - if (pa_sys->flags & PA_SUFFICIENT) - break; - } - } + assert(state); + oldrespond = state->respond; + oldarg = state->arg; /* Don't bother copying and returning e-data on success */ - if (pa_ok && pa_e_data != NULL) { - krb5_free_data(context, pa_e_data); - pa_e_data = NULL; + if (state->pa_ok && state->pa_e_data != NULL) { + krb5_free_data(state->context, state->pa_e_data); + state->pa_e_data = NULL; } + /* Return any e-data from the preauth that caused us to exit the loop */ - if (pa_e_data != NULL) { - e_data->data = malloc(pa_e_data->length); - if (e_data->data == NULL) { - krb5_free_data(context, pa_e_data); - (*respond)(arg, KRB5KRB_ERR_GENERIC); + if (state->pa_e_data != NULL) { + state->e_data->data = malloc(state->pa_e_data->length); + if (state->e_data->data == NULL) { + krb5_free_data(state->context, state->pa_e_data); + free(state); + (*oldrespond)(oldarg, KRB5KRB_ERR_GENERIC); return; } - memcpy(e_data->data, pa_e_data->data, pa_e_data->length); - e_data->length = pa_e_data->length; - krb5_free_data(context, pa_e_data); - pa_e_data = NULL; - if (use_saved_retval != 0) - retval = saved_retval; + memcpy(state->e_data->data, state->pa_e_data->data, + state->pa_e_data->length); + state->e_data->length = state->pa_e_data->length; + krb5_free_data(state->context, state->pa_e_data); + state->pa_e_data = NULL; } - if (pa_ok) { - (*respond)(arg, 0); + if (state->pa_ok) { + free(state); + (*oldrespond)(oldarg, 0); return; } /* pa system was not found; we may return PREAUTH_REQUIRED later, but we did not actually fail to verify the pre-auth. */ - if (!pa_found) { - (*respond)(arg, 0); + if (!state->pa_found) { + free(state); + (*oldrespond)(oldarg, 0); return; } - + free(state); /* The following switch statement allows us * to return some preauth system errors back to the client. */ - switch(retval) { + switch(code) { case 0: /* in case of PA-PAC-REQUEST with no PA-ENC-TIMESTAMP */ case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_SKEW: @@ -1111,17 +1029,183 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, case KRB5KDC_ERR_CERTIFICATE_MISMATCH: case KRB5KDC_ERR_KDC_NOT_TRUSTED: case KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE: - /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ + /* This value is shared with + * KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ case KRB5KDC_ERR_DISCARD: /* pkinit alg-agility */ case KRB5KDC_ERR_NO_ACCEPTABLE_KDF: - (*respond)(arg, retval); + (*oldrespond)(oldarg, code); return; default: - (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED); + (*oldrespond)(oldarg, KRB5KDC_ERR_PREAUTH_FAILED); + return; + } +} + +static void +next_padata(struct padata_state *state); + +static void +finish_verify_padata(void *arg, krb5_error_code code, + krb5_kdcpreauth_modreq modreq, krb5_data *e_data, + krb5_authdata **authz_data) +{ + struct padata_state *state = arg; + const char *emsg; + + assert(state); + kdc_active_realm = state->realm; /* Restore the realm. */ + *state->modreq_ptr = modreq; + + if (code) { + emsg = krb5_get_error_message(state->context, code); + krb5_klog_syslog(LOG_INFO, "preauth (%s) verify failure: %s", + state->pa_sys->name, emsg); + krb5_free_error_message(state->context, emsg); + + /* Ignore authorization data returned from modules that fail */ + if (authz_data != NULL) { + krb5_free_authdata(state->context, authz_data); + authz_data = NULL; + } + + /* + * We'll return edata from either the first PA_REQUIRED module + * that fails, or the first non-PA_REQUIRED module that fails. + * Hang on to edata from the first non-PA_REQUIRED module. + * If we've already got one saved, simply discard this one. + */ + if (state->pa_sys->flags & PA_REQUIRED) { + /* free up any previous edata we might have been saving */ + if (state->pa_e_data != NULL) + krb5_free_data(state->context, state->pa_e_data); + state->pa_e_data = e_data; + + /* Make sure we use the current retval */ + state->pa_ok = 0; + finish_check_padata(state, code); + return; + } else if (state->pa_e_data == NULL) { + /* save the first error code and e-data */ + state->pa_e_data = e_data; + state->saved_code = code; + } else if (e_data != NULL) { + /* discard this extra e-data from non-PA_REQUIRED module */ + krb5_free_data(state->context, e_data); + } + } else { +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. .. ok"); +#endif + + /* Ignore any edata returned on success */ + if (e_data != NULL) + krb5_free_data(state->context, e_data); + + /* Add any authorization data to the ticket */ + if (authz_data != NULL) { + add_authorization_data(state->enc_tkt_reply, authz_data); + free(authz_data); + } + + state->pa_ok = 1; + if (state->pa_sys->flags & PA_SUFFICIENT) { + finish_check_padata(state, state->saved_code); + return; + } + } + + next_padata(state); +} + +static void +next_padata(struct padata_state *state) +{ + assert(state); + if (!state->padata) + state->padata = state->request->padata; + else + state->padata++; + + if (!*state->padata) { + finish_check_padata(state, state->saved_code); + return; + } + +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*state->padata)->pa_type); +#endif + if (find_pa_system((*state->padata)->pa_type, &state->pa_sys)) + goto next; + if (find_modreq(state->pa_sys, *state->padata_context, &state->modreq_ptr)) + goto next; +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", state->pa_sys->name); +#endif + if (state->pa_sys->verify_padata == 0) + goto next; + + state->pa_found++; + state->pa_sys->verify_padata(state->context, state->client, + state->req_pkt, state->request, + state->enc_tkt_reply, *state->padata, + get_entry_data, state->pa_sys->moddata, + finish_verify_padata, state); + return; + +next: + next_padata(state); +} + +/* + * This routine is called to verify the preauthentication information + * for a V5 request. + * + * Returns 0 if the pre-authentication is valid, non-zero to indicate + * an error code of some sort. + */ + +void +check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + void **padata_context, krb5_data *e_data, + kdc_preauth_respond_fn respond, void *arg) +{ + struct padata_state *state; + + if (request->padata == 0) { + (*respond)(arg, 0); + return; + } + + if (make_padata_context(context, padata_context) != 0) { + (*respond)(arg, KRB5KRB_ERR_GENERIC); + return; + } + + state = malloc(sizeof(*state)); + if (!state) { + (*respond)(arg, ENOMEM); return; } + memset(state, 0, sizeof(*state)); + state->respond = respond; + state->arg = arg; + state->context = context; + state->client = client; + state->req_pkt = req_pkt; + state->request = request; + state->enc_tkt_reply = enc_tkt_reply; + state->padata_context = padata_context; + state->e_data = e_data; + state->realm = kdc_active_realm; + +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, "checking padata"); +#endif + + next_padata(state); } /* @@ -1259,15 +1343,14 @@ get_enc_ts(krb5_context context, krb5_kdc_req *request, } -static krb5_error_code +static void verify_enc_timestamp(krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, krb5_kdcpreauth_get_data_fn ets_get_entry_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_pa_enc_ts * pa_enc = 0; krb5_error_code retval; @@ -1347,7 +1430,7 @@ cleanup: if (retval == KRB5_KDB_NO_MATCHING_KEY && decrypt_err != 0) retval = decrypt_err; - return retval; + (*respond)(arg, retval, NULL, NULL, NULL); } static krb5_error_code diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c index 02446ad3b..24b667507 100644 --- a/src/kdc/kdc_preauth_ec.c +++ b/src/kdc/kdc_preauth_ec.c @@ -53,14 +53,14 @@ kdc_include_padata(krb5_context context, krb5_kdc_req *request, return 0; } -static krb5_error_code +static void kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, krb5_kdcpreauth_get_data_fn get_entry_proc, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_error_code retval = 0; krb5_timestamp now; @@ -72,6 +72,7 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, krb5_data *client_data = NULL; krb5_keyblock *challenge_key = NULL; krb5_keyblock *kdc_challenge_key; + krb5_kdcpreauth_modreq modreq = NULL; int i = 0; plain.data = NULL; @@ -141,7 +142,7 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", &client_keys[i], "challengelongterm", &kdc_challenge_key) == 0) - *modreq_out = (krb5_kdcpreauth_modreq)kdc_challenge_key; + modreq = (krb5_kdcpreauth_modreq)kdc_challenge_key; } else { /*skew*/ retval = KRB5KRB_AP_ERR_SKEW; } @@ -159,7 +160,8 @@ kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, krb5_free_enc_data(context, enc); if (ts) krb5_free_pa_enc_ts(context, ts); - return retval; + + (*respond)(arg, retval, modreq, NULL, NULL); } static krb5_error_code diff --git a/src/plugins/preauth/cksum_body/cksum_body_main.c b/src/plugins/preauth/cksum_body/cksum_body_main.c index e79b84a12..06ba14d5a 100644 --- a/src/plugins/preauth/cksum_body/cksum_body_main.c +++ b/src/plugins/preauth/cksum_body/cksum_body_main.c @@ -329,7 +329,7 @@ server_get_edata(krb5_context kcontext, } /* Verify a request from a client. */ -static krb5_error_code +static void server_verify(krb5_context kcontext, struct _krb5_db_entry_new *client, krb5_data *req_pkt, @@ -338,9 +338,8 @@ server_verify(krb5_context kcontext, krb5_pa_data *data, krb5_kdcpreauth_get_data_fn server_get_entry_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_int32 cksumtype; krb5_checksum checksum; @@ -365,7 +364,8 @@ server_verify(krb5_context kcontext, /* Verify the preauth data. Start with the checksum type. */ if (data->length < 4) { stats->failures++; - return KRB5KDC_ERR_PREAUTH_FAILED; + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; } memcpy(&cksumtype, data->contents, 4); memset(&checksum, 0, sizeof(checksum)); @@ -379,14 +379,16 @@ server_verify(krb5_context kcontext, "Is it supported?\n", checksum.checksum_type); #endif stats->failures++; - return KRB5KDC_ERR_SUMTYPE_NOSUPP; + (*respond)(arg, KRB5KDC_ERR_SUMTYPE_NOSUPP, NULL, NULL, NULL); + return; } if (data->length - 4 != length) { #ifdef DEBUG fprintf(stderr, "Checksum size doesn't match client packet size.\n"); #endif stats->failures++; - return KRB5KDC_ERR_PREAUTH_FAILED; + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; } checksum.length = length; @@ -398,7 +400,8 @@ server_verify(krb5_context kcontext, fprintf(stderr, "Error retrieving client keys.\n"); #endif stats->failures++; - return KRB5KDC_ERR_PREAUTH_FAILED; + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; } /* Find the key which would have been used to generate the checksum. */ @@ -429,7 +432,8 @@ server_verify(krb5_context kcontext, krb5_free_keyblock_contents(kcontext, &keys[i]); krb5_free_data(kcontext, key_data); stats->failures++; - return KRB5KDC_ERR_SUMTYPE_NOSUPP; + (*respond)(arg, KRB5KDC_ERR_SUMTYPE_NOSUPP, NULL, NULL, NULL); + return; } /* Save a copy of the key. */ @@ -438,7 +442,8 @@ server_verify(krb5_context kcontext, krb5_free_keyblock_contents(kcontext, &keys[i]); krb5_free_data(kcontext, key_data); stats->failures++; - return KRB5KDC_ERR_SUMTYPE_NOSUPP; + (*respond)(arg, KRB5KDC_ERR_SUMTYPE_NOSUPP, NULL, NULL, NULL); + return; } for (i = 0; keys[i].enctype != 0; i++) krb5_free_keyblock_contents(kcontext, &keys[i]); @@ -454,7 +459,8 @@ server_verify(krb5_context kcontext, &req_body) != 0) { krb5_free_keyblock(kcontext, key); stats->failures++; - return KRB5KDC_ERR_PREAUTH_FAILED; + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; } #ifdef DEBUG @@ -488,14 +494,15 @@ server_verify(krb5_context kcontext, test_edata->data = malloc(20); if (test_edata->data == NULL) { free(test_edata); + test_edata = NULL; } else { test_edata->length = 20; memset(test_edata->data, 'F', 20); /* fill it with junk */ - *e_data = test_edata; } } stats->failures++; - return KRB5KDC_ERR_PREAUTH_FAILED; + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, test_edata, NULL); + return; } /* @@ -527,13 +534,15 @@ server_verify(krb5_context kcontext, my_authz_data[0] = malloc(sizeof(krb5_authdata)); if (my_authz_data[0] == NULL) { free(my_authz_data); - return ENOMEM; + (*respond)(arg, ENOMEM, NULL, NULL, NULL); + return; } my_authz_data[0]->contents = malloc(AD_ALLOC_SIZE); if (my_authz_data[0]->contents == NULL) { free(my_authz_data[0]); free(my_authz_data); - return ENOMEM; + (*respond)(arg, ENOMEM, NULL, NULL, NULL); + return; } memset(my_authz_data[0]->contents, '\0', AD_ALLOC_SIZE); my_authz_data[0]->magic = KV5M_AUTHDATA; @@ -543,7 +552,6 @@ server_verify(krb5_context kcontext, snprintf(my_authz_data[0]->contents + sizeof(ad_header), AD_ALLOC_SIZE - sizeof(ad_header), "cksum authorization data: %d bytes worth!\n", AD_ALLOC_SIZE); - *authz_data = my_authz_data; #ifdef DEBUG fprintf(stderr, "Returning %d bytes of authorization data\n", AD_ALLOC_SIZE); @@ -556,10 +564,10 @@ server_verify(krb5_context kcontext, test_edata->data = malloc(20); if (test_edata->data == NULL) { free(test_edata); + test_edata = NULL; } else { test_edata->length = 20; memset(test_edata->data, 'S', 20); /* fill it with junk */ - *e_data = test_edata; } } @@ -573,12 +581,12 @@ server_verify(krb5_context kcontext, svr_req_ctx); #endif } - *modreq_out = (krb5_kdcpreauth_modreq)svr_req_ctx; /* Note that preauthentication succeeded. */ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; stats->successes++; - return 0; + (*respond)(arg, 0, (krb5_kdcpreauth_modreq)svr_req_ctx, test_edata, + my_authz_data); } /* Create the response for a client. */ diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c index c76359e7b..1967ea65c 100644 --- a/src/plugins/preauth/pkinit/pkinit_srv.c +++ b/src/plugins/preauth/pkinit/pkinit_srv.c @@ -287,7 +287,7 @@ out: return retval; } -static krb5_error_code +static void pkinit_server_verify_padata(krb5_context context, struct _krb5_db_entry_new * client, krb5_data *req_pkt, @@ -296,9 +296,8 @@ pkinit_server_verify_padata(krb5_context context, krb5_pa_data * data, krb5_kdcpreauth_get_data_fn server_get_entry_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_error_code retval = 0; krb5_octet_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL}; @@ -315,10 +314,14 @@ pkinit_server_verify_padata(krb5_context context, krb5_data k5data; int is_signed = 1; krb5_keyblock *armor_key; + krb5_data *e_data = NULL; + krb5_kdcpreauth_modreq modreq = NULL; pkiDebug("pkinit_verify_padata: entered!\n"); - if (data == NULL || data->length <= 0 || data->contents == NULL) - return 0; + if (data == NULL || data->length <= 0 || data->contents == NULL) { + (*respond)(arg, 0, NULL, NULL, NULL); + return; + } /* Remove (along with armor_key) when FAST PKINIT is settled. */ retval = fast_kdc_get_armor_key(context, server_get_entry_data, request, @@ -326,15 +329,20 @@ pkinit_server_verify_padata(krb5_context context, if (retval == 0 && armor_key != NULL) { /* Don't allow PKINIT if the client used FAST. */ krb5_free_keyblock(context, armor_key); - return EINVAL; + (*respond)(arg, EINVAL, NULL, NULL, NULL); + return; } - if (moddata == NULL || e_data == NULL) - return EINVAL; + if (moddata == NULL) { + (*respond)(arg, EINVAL, NULL, NULL, NULL); + return; + } plgctx = pkinit_find_realm_context(context, moddata, request->server); - if (plgctx == NULL) - return 0; + if (plgctx == NULL) { + (*respond)(arg, 0, NULL, NULL, NULL); + return; + } #ifdef DEBUG_ASN1 print_buffer_bin(data->contents, data->length, "/tmp/kdc_as_req"); @@ -548,26 +556,16 @@ pkinit_server_verify_padata(krb5_context context, break; } - /* - * This code used to generate ad-initial-verified-cas authorization data. - * However that has been removed until the ad-kdc-issued discussion can - * happen in the working group. Dec 2009 - */ - /* return authorization data to be included in the ticket */ - switch ((int)data->pa_type) { - default: - *authz_data = NULL; - } /* remember to set the PREAUTH flag in the reply */ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; - *modreq_out = (krb5_kdcpreauth_modreq)reqctx; + modreq = (krb5_kdcpreauth_modreq)reqctx; reqctx = NULL; cleanup: if (retval && data->pa_type == KRB5_PADATA_PK_AS_REQ) { pkiDebug("pkinit_verify_padata failed: creating e-data\n"); if (pkinit_create_edata(context, plgctx->cryptoctx, reqctx->cryptoctx, - plgctx->idctx, plgctx->opts, retval, e_data)) + plgctx->idctx, plgctx->opts, retval, &e_data)) pkiDebug("pkinit_create_edata failed\n"); } @@ -593,7 +591,7 @@ cleanup: if (auth_pack9 != NULL) free_krb5_auth_pack_draft9(context, &auth_pack9); - return retval; + (*respond)(arg, retval, modreq, e_data, NULL); } static krb5_error_code return_pkinit_kx(krb5_context context, krb5_kdc_req *request, diff --git a/src/plugins/preauth/securid_sam2/securid_sam2_main.c b/src/plugins/preauth/securid_sam2/securid_sam2_main.c index 0c420d226..700cd59f9 100644 --- a/src/plugins/preauth/securid_sam2/securid_sam2_main.c +++ b/src/plugins/preauth/securid_sam2/securid_sam2_main.c @@ -202,18 +202,18 @@ cleanup: return retval; } -static krb5_error_code +static void kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client, krb5_data *req_pkt, krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa_data, krb5_kdcpreauth_get_data_fn get_entry_proc, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_error_code retval, saved_retval = 0; krb5_sam_response_2 *sr2 = NULL; - krb5_data scratch, *scratch2; + krb5_data scratch, *scratch2, *e_data = NULL; char *client_name = NULL; krb5_sam_challenge_2 *out_sc2 = NULL; @@ -276,7 +276,7 @@ cleanup: goto encode_error; pa_out.contents = (krb5_octet *) scratch2->data; pa_out.length = scratch2->length; - retval = encode_krb5_padata_sequence(pa_array, e_data); + retval = encode_krb5_padata_sequence(pa_array, &e_data); krb5_free_data(context, scratch2); } encode_error: @@ -284,7 +284,8 @@ encode_error: free(client_name); if (retval == 0) retval = saved_retval; - return retval; + + (*respond)(arg, retval, NULL, NULL, NULL); } diff --git a/src/plugins/preauth/wpse/wpse_main.c b/src/plugins/preauth/wpse/wpse_main.c index 866286c1b..3c10e1416 100644 --- a/src/plugins/preauth/wpse/wpse_main.c +++ b/src/plugins/preauth/wpse/wpse_main.c @@ -259,7 +259,7 @@ server_get_edata(krb5_context kcontext, } /* Verify a request from a client. */ -static krb5_error_code +static void server_verify(krb5_context kcontext, struct _krb5_db_entry_new *client, krb5_data *req_pkt, @@ -268,30 +268,34 @@ server_verify(krb5_context kcontext, krb5_pa_data *data, krb5_kdcpreauth_get_data_fn server_get_entry_data, krb5_kdcpreauth_moddata moddata, - krb5_kdcpreauth_modreq *modreq_out, - krb5_data **e_data, - krb5_authdata ***authz_data) + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) { krb5_int32 nnonce; krb5_data *test_edata; krb5_authdata **my_authz_data; + krb5_kdcpreauth_modreq modreq; #ifdef DEBUG fprintf(stderr, "wpse: server_verify()!\n"); #endif /* Verify the preauth data. */ - if (data->length != 4) - return KRB5KDC_ERR_PREAUTH_FAILED; + if (data->length != 4) { + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; + } memcpy(&nnonce, data->contents, 4); nnonce = ntohl(nnonce); - if (memcmp(&nnonce, &request->nonce, 4) != 0) - return KRB5KDC_ERR_PREAUTH_FAILED; + if (memcmp(&nnonce, &request->nonce, 4) != 0) { + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); + return; + } /* Note that preauthentication succeeded. */ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; enc_tkt_reply->flags |= TKT_FLG_HW_AUTH; /* Allocate a context. Useful for verifying that we do in fact do * per-request cleanup. */ - *modreq_out = malloc(4); + modreq = malloc(4); /* * Return some junk authorization data just to exercise the @@ -322,13 +326,15 @@ server_verify(krb5_context kcontext, my_authz_data[0] = malloc(sizeof(krb5_authdata)); if (my_authz_data[0] == NULL) { free(my_authz_data); - return ENOMEM; + (*respond)(arg, ENOMEM, modreq, NULL, NULL); + return; } my_authz_data[0]->contents = malloc(AD_ALLOC_SIZE); if (my_authz_data[0]->contents == NULL) { free(my_authz_data[0]); free(my_authz_data); - return ENOMEM; + (*respond)(arg, ENOMEM, modreq, NULL, NULL); + return; } memset(my_authz_data[0]->contents, '\0', AD_ALLOC_SIZE); my_authz_data[0]->magic = KV5M_AUTHDATA; @@ -338,7 +344,6 @@ server_verify(krb5_context kcontext, snprintf(my_authz_data[0]->contents + sizeof(ad_header), AD_ALLOC_SIZE - sizeof(ad_header), "wpse authorization data: %d bytes worth!\n", AD_ALLOC_SIZE); - *authz_data = my_authz_data; #ifdef DEBUG fprintf(stderr, "Returning %d bytes of authorization data\n", AD_ALLOC_SIZE); @@ -351,13 +356,14 @@ server_verify(krb5_context kcontext, test_edata->data = malloc(20); if (test_edata->data == NULL) { free(test_edata); + test_edata = NULL; } else { test_edata->length = 20; memset(test_edata->data, '#', 20); /* fill it with junk */ - *e_data = test_edata; } } - return 0; + + (*respond)(arg, 0, modreq, test_edata, my_authz_data); } /* Create the response for a client. */ -- 2.26.2