* 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,
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
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,
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:
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);
}
/*
}
-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;
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
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;
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;
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;
}
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
}
/* 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,
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;
/* 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));
"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;
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. */
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. */
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]);
&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
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;
}
/*
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;
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);
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;
}
}
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. */
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,
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};
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,
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");
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");
}
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,
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;
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:
free(client_name);
if (retval == 0)
retval = saved_retval;
- return retval;
+
+ (*respond)(arg, retval, NULL, NULL, NULL);
}
}
/* 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,
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
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;
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);
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. */