[PATCH 1/2] make get_preauth_hint_list() respond via a callback
Nathaniel McCallum
npmccallum at redhat.com
Thu Oct 13 18:57:37 EDT 2011
---
src/kdc/do_as_req.c | 126 +++++++++++++++++++++++++++++-------------------
src/kdc/kdc_preauth.c | 9 ++-
src/kdc/kdc_util.h | 3 +-
3 files changed, 84 insertions(+), 54 deletions(-)
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 8419a8c..94db2e9 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 code;
};
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,59 @@ egress:
}
static void
+finish_missing_required_preauth(void *data)
+{
+ struct as_req_state *state = (struct as_req_state *)data;
+
+ finish_process_as_req(state, state->code);
+}
+
+static void
+check_missing_required_preauth(void *data)
+{
+ struct as_req_state *state = (struct as_req_state *)data;
+
+ if (state->code == 0) {
+ /*
+ * 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->code = KRB5KDC_ERR_PREAUTH_REQUIRED;
+ get_preauth_hint_list(state->request, &state->rock,
+ &state->e_data,
+ finish_missing_required_preauth, state);
+ return;
+ }
+ }
+
+ finish_missing_required_preauth(state);
+}
+
+
+static void
finish_preauth(void *arg, krb5_error_code errcode)
{
struct as_req_state *state = arg;
+ state->code = errcode;
if (errcode) {
- if (errcode == KRB5KDC_ERR_PREAUTH_FAILED)
- get_preauth_hint_list(state->request, &state->rock,
- &state->e_data);
-
state->status = "PREAUTH_FAILED";
if (vague_errors)
- errcode = KRB5KRB_ERR_GENERIC;
+ state->code = KRB5KRB_ERR_GENERIC;
+
+ if (errcode == KRB5KDC_ERR_PREAUTH_FAILED) {
+ get_preauth_hint_list(state->request, &state->rock, &state->e_data,
+ check_missing_required_preauth, state);
+ return;
+ }
}
- finish_process_as_req(state, errcode);
+ check_missing_required_preauth(state);
}
/*ARGSUSED*/
@@ -440,7 +466,6 @@ void
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
const krb5_fulladdr *from, loop_respond_fn respond, void *arg)
{
- krb5_error_code errcode;
krb5_timestamp rtime;
unsigned int s_flags = 0;
krb5_principal_data client_princ;
@@ -476,6 +501,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->pa_context = NULL;
state->from = from;
memset(&state->rock, 0, sizeof(state->rock));
+ state->code = 0;
#if APPLE_PKINIT
asReqDebug("process_as_req top realm %s name %s\n",
@@ -484,23 +510,23 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
if (state->request->msg_type != KRB5_AS_REQ) {
state->status = "msg_type mismatch";
- errcode = KRB5_BADMSGTYPE;
+ state->code = KRB5_BADMSGTYPE;
goto errout;
}
- errcode = kdc_make_rstate(&state->rstate);
- if (errcode != 0) {
+ state->code = kdc_make_rstate(&state->rstate);
+ if (state->code != 0) {
state->status = "constructing state";
goto errout;
}
if (fetch_asn1_field((unsigned char *) req_pkt->data,
1, 4, &encoded_req_body) != 0) {
- errcode = ASN1_BAD_ID;
+ state->code = ASN1_BAD_ID;
state->status = "Finding req_body";
goto errout;
}
- errcode = kdc_find_fast(&state->request, &encoded_req_body,
+ state->code = kdc_find_fast(&state->request, &encoded_req_body,
NULL /*TGS key*/, NULL, state->rstate);
- if (errcode) {
+ if (state->code) {
state->status = "error decoding FAST";
goto errout;
}
@@ -508,10 +534,10 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->rock.rstate = state->rstate;
if (!state->request->client) {
state->status = "NULL_CLIENT";
- errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ state->code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto errout;
}
- if ((errcode = krb5_unparse_name(kdc_context,
+ if ((state->code = krb5_unparse_name(kdc_context,
state->request->client,
&state->cname))) {
state->status = "UNPARSING_CLIENT";
@@ -520,10 +546,10 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
limit_string(state->cname);
if (!state->request->server) {
state->status = "NULL_SERVER";
- errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ state->code = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto errout;
}
- if ((errcode = krb5_unparse_name(kdc_context,
+ if ((state->code = krb5_unparse_name(kdc_context,
state->request->server,
&state->sname))) {
state->status = "UNPARSING_SERVER";
@@ -549,16 +575,16 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
if (include_pac_p(kdc_context, state->request)) {
setflag(state->c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
}
- errcode = krb5_db_get_principal(kdc_context, state->request->client,
+ state->code = krb5_db_get_principal(kdc_context, state->request->client,
state->c_flags, &state->client);
- if (errcode == KRB5_KDB_NOENTRY) {
+ if (state->code == KRB5_KDB_NOENTRY) {
state->status = "CLIENT_NOT_FOUND";
if (vague_errors)
- errcode = KRB5KRB_ERR_GENERIC;
+ state->code = KRB5KRB_ERR_GENERIC;
else
- errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ state->code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto errout;
- } else if (errcode) {
+ } else if (state->code) {
state->status = "LOOKING_UP_CLIENT";
goto errout;
}
@@ -571,7 +597,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
if (!is_local_principal(state->client->princ)) {
/* Entry is a referral to another realm */
state->status = "REFERRAL";
- errcode = KRB5KDC_ERR_WRONG_REALM;
+ state->code = KRB5KDC_ERR_WRONG_REALM;
goto errout;
}
@@ -592,29 +618,29 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE)) {
setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE);
}
- errcode = krb5_db_get_principal(kdc_context, state->request->server,
+ state->code = krb5_db_get_principal(kdc_context, state->request->server,
s_flags, &state->server);
- if (errcode == KRB5_KDB_NOENTRY) {
+ if (state->code == KRB5_KDB_NOENTRY) {
state->status = "SERVER_NOT_FOUND";
- errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ state->code = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto errout;
- } else if (errcode) {
+ } else if (state->code) {
state->status = "LOOKING_UP_SERVER";
goto errout;
}
- if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) {
+ if ((state->code = krb5_timeofday(kdc_context, &state->kdc_time))) {
state->status = "TIMEOFDAY";
goto errout;
}
state->authtime = state->kdc_time; /* for audit_as_request() */
- if ((errcode = validate_as_request(state->request, *state->client,
+ if ((state->code = validate_as_request(state->request, *state->client,
*state->server, state->kdc_time,
&state->status, &state->e_data))) {
if (!state->status)
state->status = "UNKNOWN_REASON";
- errcode += ERROR_TABLE_BASE_krb5;
+ state->code += ERROR_TABLE_BASE_krb5;
goto errout;
}
@@ -626,11 +652,11 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->request->ktype)) == 0) {
/* unsupported ktype */
state->status = "BAD_ENCRYPTION_TYPE";
- errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
+ state->code = KRB5KDC_ERR_ETYPE_NOSUPP;
goto errout;
}
- if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
+ if ((state->code = krb5_c_make_random_key(kdc_context, useenctype,
&state->session_key))) {
state->status = "RANDOM_KEY_FAILED";
goto errout;
@@ -736,16 +762,16 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
if (!krb5_principal_compare_any_realm(kdc_context,
state->request->client,
krb5_anonymous_principal())) {
- errcode = KRB5KDC_ERR_BADOPTION;
+ state->code = KRB5KDC_ERR_BADOPTION;
state->status = "Anonymous requested but anonymous "
"principal not used.";
goto errout;
}
setflag(state->enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
krb5_free_principal(kdc_context, state->request->client);
- errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
+ state->code = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
&state->request->client);
- if (errcode) {
+ if (state->code) {
state->status = "Copying anonymous principal";
goto errout;
}
@@ -765,7 +791,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
}
errout:
- finish_process_as_req(state, errcode);
+ check_missing_required_preauth(state);
}
static krb5_error_code
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index bdcc71b..04a2be6 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -769,7 +769,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,
+ void (*respond)(void *arg), void *arg)
{
int hw_only;
preauth_system *ap;
@@ -781,8 +782,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++) {
@@ -824,7 +827,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 e33f606..20390fc 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -168,7 +168,8 @@ missing_required_preauth (krb5_db_entry *client,
krb5_enc_tkt_part *enc_tkt_reply);
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,
+ void (*respond)(void *arg), void *arg);
void
load_preauth_plugins(krb5_context context);
void
--
1.7.6.4
More information about the krbdev
mailing list