Blame SOURCES/Simplify-k5_preauth_tryagain.patch

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