|
|
665228 |
From 64c15ad2b8f4af57ffd998fc27f3781cc02bff29 Mon Sep 17 00:00:00 2001
|
|
|
665228 |
From: Greg Hudson <ghudson@mit.edu>
|
|
|
665228 |
Date: Mon, 16 Jan 2017 15:09:32 -0500
|
|
|
665228 |
Subject: [PATCH] Continue after KDC_ERR_PREAUTH_FAILED
|
|
|
665228 |
|
|
|
665228 |
If the KDC sends KDC_ERR_PREAUTH_FAILED, try another mechanism, or
|
|
|
665228 |
send an unauthenticated request if optimistic preauth failed.
|
|
|
665228 |
|
|
|
665228 |
ticket: 8537
|
|
|
665228 |
(cherry picked from commit 52d2de31bc4728dbc2f59c6033dcdab86da919e9)
|
|
|
665228 |
---
|
|
|
665228 |
src/lib/krb5/krb/get_in_tkt.c | 45 ++++++++++++++++++++++++++++-------
|
|
|
665228 |
1 file changed, 36 insertions(+), 9 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 8d0f964f9..c7d7bfe74 100644
|
|
|
665228 |
--- a/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
@@ -1308,6 +1308,7 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
krb5_error_code code;
|
|
|
665228 |
krb5_preauthtype pa_type;
|
|
|
665228 |
struct errinfo save = EMPTY_ERRINFO;
|
|
|
665228 |
+ uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error;
|
|
|
665228 |
|
|
|
665228 |
if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
|
|
|
665228 |
code = KRB5_GET_IN_TKT_LOOP;
|
|
|
665228 |
@@ -1358,8 +1359,10 @@ init_creds_step_request(krb5_context context,
|
|
|
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 |
- } else if (ctx->err_reply != NULL &&
|
|
|
665228 |
- ctx->err_reply->error != KDC_ERR_PREAUTH_REQUIRED) {
|
|
|
665228 |
+ } else if (rcode == KDC_ERR_PREAUTH_FAILED) {
|
|
|
665228 |
+ /* Report the KDC-side failure code if we can't try another mech. */
|
|
|
665228 |
+ code = KRB5KDC_ERR_PREAUTH_FAILED;
|
|
|
665228 |
+ } else if (rcode && rcode != 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 |
@@ -1380,7 +1383,7 @@ init_creds_step_request(krb5_context context,
|
|
|
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 |
+ * different mechanism after a 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 |
@@ -1480,6 +1483,18 @@ is_referral(krb5_context context, krb5_error *err, krb5_principal client)
|
|
|
665228 |
return !krb5_realm_compare(context, err->client, client);
|
|
|
665228 |
}
|
|
|
665228 |
|
|
|
665228 |
+/* Transfer error padata to method data in ctx and sort it according to
|
|
|
665228 |
+ * configuration. */
|
|
|
665228 |
+static krb5_error_code
|
|
|
665228 |
+accept_method_data(krb5_context context, krb5_init_creds_context ctx)
|
|
|
665228 |
+{
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->method_padata);
|
|
|
665228 |
+ ctx->method_padata = ctx->err_padata;
|
|
|
665228 |
+ ctx->err_padata = NULL;
|
|
|
665228 |
+ return sort_krb5_padata_sequence(context, &ctx->request->client->realm,
|
|
|
665228 |
+ ctx->method_padata);
|
|
|
665228 |
+}
|
|
|
665228 |
+
|
|
|
665228 |
static krb5_error_code
|
|
|
665228 |
init_creds_step_reply(krb5_context context,
|
|
|
665228 |
krb5_init_creds_context ctx,
|
|
|
665228 |
@@ -1538,14 +1553,26 @@ init_creds_step_reply(krb5_context context,
|
|
|
665228 |
ctx->restarted = FALSE;
|
|
|
665228 |
code = restart_init_creds_loop(context, ctx, FALSE);
|
|
|
665228 |
} else if (reply_code == KDC_ERR_PREAUTH_REQUIRED && retry) {
|
|
|
665228 |
- krb5_free_pa_data(context, ctx->method_padata);
|
|
|
665228 |
- ctx->method_padata = ctx->err_padata;
|
|
|
665228 |
- ctx->err_padata = NULL;
|
|
|
665228 |
note_req_timestamp(context, ctx, ctx->err_reply->stime,
|
|
|
665228 |
ctx->err_reply->susec);
|
|
|
665228 |
- code = sort_krb5_padata_sequence(context,
|
|
|
665228 |
- &ctx->request->client->realm,
|
|
|
665228 |
- ctx->method_padata);
|
|
|
665228 |
+ code = accept_method_data(context, ctx);
|
|
|
665228 |
+ } else if (reply_code == KDC_ERR_PREAUTH_FAILED && retry) {
|
|
|
665228 |
+ note_req_timestamp(context, ctx, ctx->err_reply->stime,
|
|
|
665228 |
+ ctx->err_reply->susec);
|
|
|
665228 |
+ if (ctx->method_padata == NULL) {
|
|
|
665228 |
+ /* Optimistic preauth failed on the KDC. Allow all mechanisms
|
|
|
665228 |
+ * to be tried again using method data. */
|
|
|
665228 |
+ k5_reset_preauth_types_tried(ctx);
|
|
|
665228 |
+ } else {
|
|
|
665228 |
+ /* Don't try again with the mechanism that failed. */
|
|
|
665228 |
+ code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type);
|
|
|
665228 |
+ if (code)
|
|
|
665228 |
+ goto cleanup;
|
|
|
665228 |
+ }
|
|
|
665228 |
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
|
|
|
665228 |
+ /* Accept or update method data if the KDC sent it. */
|
|
|
665228 |
+ if (ctx->err_padata != NULL)
|
|
|
665228 |
+ code = accept_method_data(context, ctx);
|
|
|
665228 |
} else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) {
|
|
|
665228 |
ctx->more_padata = ctx->err_padata;
|
|
|
665228 |
ctx->err_padata = NULL;
|