167778
From 9b525f2406da57eb7a064fc56398a41e2680999a Mon Sep 17 00:00:00 2001
167778
From: Greg Hudson <ghudson@mit.edu>
167778
Date: Fri, 13 Jan 2017 20:45:48 -0500
167778
Subject: [PATCH] Simplify k5_preauth_tryagain()
167778
167778
When retrying pre-authentication for an error, try only the module for
167778
the selected preauth type, not all preauth types in the original
167778
method data.  Pass the error and its padata to k5_preauth_tryagain()
167778
explicitly, so that those fields of krb5_init_creds_context are only
167778
referenced in get_in_tkt.c.  Handle a degenerate case in
167778
init_creds_step_reply() to simplify the code in
167778
init_creds_step_request().
167778
167778
ticket: 8537
167778
(cherry picked from commit 27628e5d9d5e6fcfa73276106edbd8149d134dc0)
167778
---
167778
 src/include/k5-trace.h        |  7 ++--
167778
 src/lib/krb5/krb/get_in_tkt.c | 20 ++++-------
167778
 src/lib/krb5/krb/int-proto.h  |  3 +-
167778
 src/lib/krb5/krb/preauth2.c   | 64 +++++++++++++++++++----------------
167778
 4 files changed, 48 insertions(+), 46 deletions(-)
167778
167778
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
167778
index f44f162d3..814da3195 100644
167778
--- a/src/include/k5-trace.h
167778
+++ b/src/include/k5-trace.h
167778
@@ -287,8 +287,11 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
167778
 #define TRACE_PREAUTH_SKIP(c, name, patype)                           \
167778
     TRACE(c, "Skipping previously used preauth module {str} ({int})", \
167778
           name, (int) patype)
167778
-#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, padata)                 \
167778
-    TRACE(c, "Preauth tryagain input types: {patypes}", padata)
167778
+#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, patype, padata)                 \
167778
+    TRACE(c, "Preauth tryagain input types ({int}): {patypes}", patype, padata)
167778
+#define TRACE_PREAUTH_TRYAGAIN(c, name, patype, code)                   \
167778
+    TRACE(c, "Preauth module {str} ({int}) tryagain returned: {kerr}",  \
167778
+          name, (int)patype, code)
167778
 #define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata)                        \
167778
     TRACE(c, "Followup preauth for next request: {patypes}", padata)
167778
 #define TRACE_PREAUTH_WRONG_CONTEXT(c)                                  \
167778
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
167778
index da12204ac..988fca233 100644
167778
--- a/src/lib/krb5/krb/get_in_tkt.c
167778
+++ b/src/lib/krb5/krb/get_in_tkt.c
167778
@@ -1340,17 +1340,11 @@ init_creds_step_request(krb5_context context,
167778
         if (code != 0)
167778
             goto cleanup;
167778
     } else {
167778
-        if (ctx->preauth_to_use != NULL) {
167778
-            /*
167778
-             * Retry after an error other than PREAUTH_NEEDED,
167778
-             * using ctx->err_padata to figure out what to change.
167778
-             */
167778
-            code = k5_preauth_tryagain(context, ctx, ctx->preauth_to_use,
167778
-                                       &ctx->request->padata);
167778
-        } else {
167778
-            /* No preauth supplied, so can't query the plugins. */
167778
-            code = KRB5KRB_ERR_GENERIC;
167778
-        }
167778
+        /* Retry after an error other than PREAUTH_NEEDED, using error padata
167778
+         * to figure out what to change. */
167778
+        code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type,
167778
+                                   ctx->err_reply, ctx->err_padata,
167778
+                                   &ctx->request->padata);
167778
         if (code != 0) {
167778
             /* couldn't come up with anything better */
167778
             code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5;
167778
@@ -1535,10 +1529,10 @@ init_creds_step_reply(krb5_context context,
167778
             ctx->enc_pa_rep_permitted = TRUE;
167778
             code = restart_init_creds_loop(context, ctx, FALSE);
167778
         } else {
167778
-            if (retry) {
167778
+            if (retry && ctx->selected_preauth_type != KRB5_PADATA_NONE) {
167778
                 code = 0;
167778
             } else {
167778
-                /* error + no hints = give up */
167778
+                /* error + no hints (or no preauth mech) = give up */
167778
                 code = (krb5_error_code)reply_code + ERROR_TABLE_BASE_krb5;
167778
             }
167778
         }
167778
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
167778
index 628f0baa8..8903df232 100644
167778
--- a/src/lib/krb5/krb/int-proto.h
167778
+++ b/src/lib/krb5/krb/int-proto.h
167778
@@ -185,7 +185,8 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
167778
 
167778
 krb5_error_code
167778
 k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
167778
-                    krb5_pa_data **in_padata, krb5_pa_data ***padata_out);
167778
+                    krb5_preauthtype pa_type, krb5_error *err,
167778
+                    krb5_pa_data **err_padata, krb5_pa_data ***padata_out);
167778
 
167778
 void
167778
 k5_init_preauth_context(krb5_context context);
167778
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
167778
index cfe3dd5b0..354234a93 100644
167778
--- a/src/lib/krb5/krb/preauth2.c
167778
+++ b/src/lib/krb5/krb/preauth2.c
167778
@@ -911,49 +911,53 @@ add_s4u_x509_user_padata(krb5_context context, krb5_s4u_userid *userid,
167778
 }
167778
 
167778
 /*
167778
- * If one of the modules can adjust its AS_REQ data using the contents of the
167778
- * err_reply, return 0.  If it's the sort of correction which requires that we
167778
- * ask the user another question, we let the calling application deal with it.
167778
+ * If the module for pa_type can adjust its AS_REQ data using the contents of
167778
+ * err and err_padata, return 0 with *padata_out set to a padata list for the
167778
+ * next request.  If it's the sort of correction which requires that we ask the
167778
+ * user another question, we let the calling application deal with it.
167778
  */
167778
 krb5_error_code
167778
 k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
167778
-                    krb5_pa_data **in_padata, krb5_pa_data ***padata_out)
167778
+                    krb5_preauthtype pa_type, krb5_error *err,
167778
+                    krb5_pa_data **err_padata, krb5_pa_data ***padata_out)
167778
 {
167778
     krb5_error_code ret;
167778
     krb5_pa_data **mod_pa;
167778
     krb5_clpreauth_modreq modreq;
167778
     clpreauth_handle h;
167778
-    int i, count;
167778
+    int count;
167778
 
167778
     *padata_out = NULL;
167778
 
167778
-    TRACE_PREAUTH_TRYAGAIN_INPUT(context, in_padata);
167778
+    TRACE_PREAUTH_TRYAGAIN_INPUT(context, pa_type, err_padata);
167778
 
167778
-    for (i = 0; in_padata[i] != NULL; i++) {
167778
-        h = find_module(context, ctx, in_padata[i]->pa_type, &modreq);
167778
-        if (h == NULL)
167778
-            continue;
167778
-        mod_pa = NULL;
167778
-        ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
167778
-                                 (krb5_clpreauth_rock)ctx, ctx->request,
167778
-                                 ctx->inner_request_body,
167778
-                                 ctx->encoded_previous_request,
167778
-                                 in_padata[i]->pa_type,
167778
-                                 ctx->err_reply, ctx->err_padata,
167778
-                                 ctx->prompter, ctx->prompter_data, &mod_pa);
167778
-        if (ret == 0 && mod_pa != NULL) {
167778
-            for (count = 0; mod_pa[count] != NULL; count++);
167778
-            ret = copy_cookie(context, ctx->err_padata, &mod_pa, &count);
167778
-            if (ret) {
167778
-                krb5_free_pa_data(context, mod_pa);
167778
-                return ret;
167778
-            }
167778
-            TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
167778
-            *padata_out = mod_pa;
167778
-            return 0;
167778
-        }
167778
+    h = find_module(context, ctx, pa_type, &modreq);
167778
+    if (h == NULL)
167778
+        return KRB5KRB_ERR_GENERIC;
167778
+    mod_pa = NULL;
167778
+    ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
167778
+                             (krb5_clpreauth_rock)ctx, ctx->request,
167778
+                             ctx->inner_request_body,
167778
+                             ctx->encoded_previous_request, pa_type, err,
167778
+                             err_padata, ctx->prompter, ctx->prompter_data,
167778
+                             &mod_pa);
167778
+    TRACE_PREAUTH_TRYAGAIN(context, h->vt.name, pa_type, ret);
167778
+    if (!ret && mod_pa == NULL)
167778
+        ret = KRB5KRB_ERR_GENERIC;
167778
+    if (ret)
167778
+        return ret;
167778
+
167778
+
167778
+    for (count = 0; mod_pa[count] != NULL; count++);
167778
+    ret = copy_cookie(context, err_padata, &mod_pa, &count);
167778
+    if (ret) {
167778
+        krb5_free_pa_data(context, mod_pa);
167778
+        return ret;
167778
     }
167778
-    return KRB5KRB_ERR_GENERIC;
167778
+
167778
+    TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
167778
+    *padata_out = mod_pa;
167778
+    return 0;
167778
 }
167778
 
167778
 /* Compile the set of response items for in_padata by invoke each module's