|
|
665228 |
From 0cd770449a733a8b3a853531a562c91883ccac27 Mon Sep 17 00:00:00 2001
|
|
|
665228 |
From: Greg Hudson <ghudson@mit.edu>
|
|
|
665228 |
Date: Sat, 14 Jan 2017 13:55:22 -0500
|
|
|
665228 |
Subject: [PATCH] Continue preauth after client-side failures
|
|
|
665228 |
|
|
|
665228 |
If the module for the selected preauth mechanism fails when processing
|
|
|
665228 |
a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error, or fails a tryagain
|
|
|
665228 |
operation, try again with a different preauth mech using the cached
|
|
|
665228 |
method data.
|
|
|
665228 |
|
|
|
665228 |
If optimistic preauth fails on the client side, send an
|
|
|
665228 |
unauthenticated request, allowing the mechanisms we tried
|
|
|
665228 |
optimistically to be tried again.
|
|
|
665228 |
|
|
|
665228 |
ticket: 8537
|
|
|
665228 |
(cherry picked from commit 644840a207917661a6ccf706e7830bec273e23b3)
|
|
|
665228 |
---
|
|
|
665228 |
src/lib/krb5/krb/get_in_tkt.c | 49 +++++++++++++++++++++++------------
|
|
|
665228 |
1 file changed, 32 insertions(+), 17 deletions(-)
|
|
|
665228 |
|
|
|
665228 |
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
index 8c7919e65..8d0f964f9 100644
|
|
|
665228 |
--- a/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
@@ -1307,6 +1307,7 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
{
|
|
|
665228 |
krb5_error_code code;
|
|
|
665228 |
krb5_preauthtype pa_type;
|
|
|
665228 |
+ struct errinfo save = EMPTY_ERRINFO;
|
|
|
665228 |
|
|
|
665228 |
if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
|
|
|
665228 |
code = KRB5_GET_IN_TKT_LOOP;
|
|
|
665228 |
@@ -1341,38 +1342,51 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
if (ctx->optimistic_padata != NULL) {
|
|
|
665228 |
/* Our first attempt, using an optimistic padata list. */
|
|
|
665228 |
TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(context);
|
|
|
665228 |
- code = k5_preauth(context, ctx, ctx->optimistic_padata, FALSE,
|
|
|
665228 |
+ code = k5_preauth(context, ctx, ctx->optimistic_padata, TRUE,
|
|
|
665228 |
&ctx->request->padata, &ctx->selected_preauth_type);
|
|
|
665228 |
krb5_free_pa_data(context, ctx->optimistic_padata);
|
|
|
665228 |
ctx->optimistic_padata = NULL;
|
|
|
665228 |
- if (code != 0)
|
|
|
665228 |
- goto cleanup;
|
|
|
665228 |
+ if (code) {
|
|
|
665228 |
+ /* Make an unauthenticated request, and possibly try again using
|
|
|
665228 |
+ * the same mechanisms as we tried optimistically. */
|
|
|
665228 |
+ k5_reset_preauth_types_tried(ctx);
|
|
|
665228 |
+ krb5_clear_error_message(context);
|
|
|
665228 |
+ code = 0;
|
|
|
665228 |
+ }
|
|
|
665228 |
} if (ctx->more_padata != NULL) {
|
|
|
665228 |
/* Continuing after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
|
|
|
665228 |
TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type);
|
|
|
665228 |
code = k5_preauth(context, ctx, ctx->more_padata, TRUE,
|
|
|
665228 |
&ctx->request->padata, &pa_type);
|
|
|
665228 |
- if (code != 0)
|
|
|
665228 |
- goto cleanup;
|
|
|
665228 |
} else if (ctx->err_reply != NULL &&
|
|
|
665228 |
- ctx->err_reply->error == KDC_ERR_PREAUTH_REQUIRED) {
|
|
|
665228 |
- /* Continuing after KDC_ERR_PREAUTH_REQUIRED, using method data. */
|
|
|
665228 |
- TRACE_INIT_CREDS_PREAUTH(context);
|
|
|
665228 |
- code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
|
|
|
665228 |
- &ctx->request->padata, &ctx->selected_preauth_type);
|
|
|
665228 |
- if (code != 0)
|
|
|
665228 |
- goto cleanup;
|
|
|
665228 |
- } else if (ctx->err_reply != NULL) {
|
|
|
665228 |
- /* Retry after an error other than PREAUTH_REQUIRED, using error padata
|
|
|
665228 |
- * to figure out what to change. */
|
|
|
665228 |
+ ctx->err_reply->error != KDC_ERR_PREAUTH_REQUIRED) {
|
|
|
665228 |
+ /* Retrying after an error (possibly mechanism-specific), using error
|
|
|
665228 |
+ * padata to figure out what to change. */
|
|
|
665228 |
TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error,
|
|
|
665228 |
ctx->selected_preauth_type);
|
|
|
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 |
+ if (code) {
|
|
|
665228 |
+ krb5_clear_error_message(context);
|
|
|
665228 |
code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5;
|
|
|
665228 |
+ }
|
|
|
665228 |
+ }
|
|
|
665228 |
+ if (code) {
|
|
|
665228 |
+ /* See if we can try a different preauth mech before giving up. */
|
|
|
665228 |
+ k5_save_ctx_error(context, code, &save);
|
|
|
665228 |
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
|
|
|
665228 |
+ }
|
|
|
665228 |
+
|
|
|
665228 |
+ if (ctx->request->padata == NULL && ctx->method_padata != NULL) {
|
|
|
665228 |
+ /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a
|
|
|
665228 |
+ * different mechanism after a client-side failure. */
|
|
|
665228 |
+ TRACE_INIT_CREDS_PREAUTH(context);
|
|
|
665228 |
+ code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
|
|
|
665228 |
+ &ctx->request->padata, &ctx->selected_preauth_type);
|
|
|
665228 |
+ if (code) {
|
|
|
665228 |
+ if (save.code != 0)
|
|
|
665228 |
+ code = k5_restore_ctx_error(context, &save);
|
|
|
665228 |
goto cleanup;
|
|
|
665228 |
}
|
|
|
665228 |
}
|
|
|
665228 |
@@ -1413,6 +1427,7 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
cleanup:
|
|
|
665228 |
krb5_free_pa_data(context, ctx->request->padata);
|
|
|
665228 |
ctx->request->padata = NULL;
|
|
|
665228 |
+ k5_clear_error(&save);
|
|
|
665228 |
return code;
|
|
|
665228 |
}
|
|
|
665228 |
|