Make get_preauth_hint_list respond via callback
authorGreg Hudson <ghudson@mit.edu>
Sat, 15 Oct 2011 15:03:17 +0000 (15:03 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sat, 15 Oct 2011 15:03:17 +0000 (15:03 +0000)
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
src/kdc/kdc_preauth.c
src/kdc/kdc_util.h

index 8419a8cfc993cc5579add571f8a84638a3d035ef..15263b3485fd16c2d954018cdaa0604586d58f78 100644 (file)
@@ -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);
index d0a081914ada40cd9dd32d4b8250a69c19e3eafd..13b51e3299248b24c9c9f2d8a4622efe9d58601a 100644 (file)
@@ -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);
 }
 
 /*
index e33f606b82a40665bbcf5fe9182f54d54ac1fef2..a31eec568dd7762d9d3ae1a1a5320f7c576b0e1a 100644 (file)
@@ -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