Blame SOURCES/Simplify-k5_preauth_tryagain.patch

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