|
|
665228 |
From 129e5a5694783bb033532e5933b2eeefabc5a35d Mon Sep 17 00:00:00 2001
|
|
|
665228 |
From: Greg Hudson <ghudson@mit.edu>
|
|
|
665228 |
Date: Fri, 13 Jan 2017 15:35:48 -0500
|
|
|
665228 |
Subject: [PATCH] Preserve method data in get_in_tkt.c
|
|
|
665228 |
|
|
|
665228 |
To continue after preauth failures, we need a persistent field in
|
|
|
665228 |
krb5_init_creds_context containing the METHOD-DATA from a
|
|
|
665228 |
KDC_PREAUTH_REQUIRED or KDC_PREAUTH_FAILED error. If we overwrite
|
|
|
665228 |
this field with the padata in a KDC_MORE_PREAUTH_DATA_REQUIRED error,
|
|
|
665228 |
or conflate it with an optimistic padata list, we won't be able to
|
|
|
665228 |
correctly continue after a preauth failure.
|
|
|
665228 |
|
|
|
665228 |
In krb5_init_creds_context, split the preauth_to_use field into
|
|
|
665228 |
optimistic_padata, method_padata, and more_padata. Separately handle
|
|
|
665228 |
KDC_ERR_MORE_PREAUTH_DATA_REQUIRED in init_creds_step_request() and
|
|
|
665228 |
init_creds_step_reply(), and separately handle optimistic preauth in
|
|
|
665228 |
init_creds_step_request(). Do not call k5_preauth() if none of the
|
|
|
665228 |
padata lists are set.
|
|
|
665228 |
|
|
|
665228 |
Also stop clearing ctx->err_reply when processing a
|
|
|
665228 |
KDC_ERR_PREAUTH_REQUIRED response. Instead look for that error code
|
|
|
665228 |
in init_creds_step_request(). Eliminate the preauth_required field of
|
|
|
665228 |
krb5_init_creds_context as it can be inferred from whether we are
|
|
|
665228 |
performing optimistic preauth.
|
|
|
665228 |
|
|
|
665228 |
ticket: 8537
|
|
|
665228 |
(cherry picked from commit 97a9b0c4ef3fc7b20e6ae592201bcb132d58bbe5)
|
|
|
665228 |
---
|
|
|
665228 |
src/include/k5-trace.h | 11 +++++
|
|
|
665228 |
src/lib/krb5/krb/get_in_tkt.c | 71 +++++++++++++++++++++----------
|
|
|
665228 |
src/lib/krb5/krb/init_creds_ctx.h | 5 ++-
|
|
|
665228 |
3 files changed, 62 insertions(+), 25 deletions(-)
|
|
|
665228 |
|
|
|
665228 |
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
|
|
|
665228 |
index 814da3195..e60ee0b75 100644
|
|
|
665228 |
--- a/src/include/k5-trace.h
|
|
|
665228 |
+++ b/src/include/k5-trace.h
|
|
|
665228 |
@@ -213,8 +213,19 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
|
|
|
665228 |
TRACE(c, "Looked up etypes in keytab: {etypes}", etypes)
|
|
|
665228 |
#define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code) \
|
|
|
665228 |
TRACE(c, "Couldn't lookup etypes in keytab: {kerr}", code)
|
|
|
665228 |
+#define TRACE_INIT_CREDS_PREAUTH(c) \
|
|
|
665228 |
+ TRACE(c, "Preauthenticating using KDC method data")
|
|
|
665228 |
#define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code) \
|
|
|
665228 |
TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code)
|
|
|
665228 |
+#define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype) \
|
|
|
665228 |
+ TRACE(c, "Continuing preauth mech {int}", (int)patype)
|
|
|
665228 |
+#define TRACE_INIT_CREDS_PREAUTH_NONE(c) \
|
|
|
665228 |
+ TRACE(c, "Sending unauthenticated request")
|
|
|
665228 |
+#define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c) \
|
|
|
665228 |
+ TRACE(c, "Attempting optimistic preauth")
|
|
|
665228 |
+#define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code) \
|
|
|
665228 |
+ TRACE(c, "Recovering from KDC error {int} using preauth mech {int}", \
|
|
|
665228 |
+ (int)patype, (int)code)
|
|
|
665228 |
#define TRACE_INIT_CREDS_RESTART_FAST(c) \
|
|
|
665228 |
TRACE(c, "Restarting to upgrade to FAST")
|
|
|
665228 |
#define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c) \
|
|
|
665228 |
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
index bc903b6e9..8c7919e65 100644
|
|
|
665228 |
--- a/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
+++ b/src/lib/krb5/krb/get_in_tkt.c
|
|
|
665228 |
@@ -575,7 +575,9 @@ krb5_init_creds_free(krb5_context context,
|
|
|
665228 |
krb5_free_data(context, ctx->inner_request_body);
|
|
|
665228 |
krb5_free_data(context, ctx->encoded_previous_request);
|
|
|
665228 |
krb5int_fast_free_state(context, ctx->fast_state);
|
|
|
665228 |
- krb5_free_pa_data(context, ctx->preauth_to_use);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->optimistic_padata);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->method_padata);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->more_padata);
|
|
|
665228 |
krb5_free_data_contents(context, &ctx->salt);
|
|
|
665228 |
krb5_free_data_contents(context, &ctx->s2kparams);
|
|
|
665228 |
krb5_free_keyblock_contents(context, &ctx->as_key);
|
|
|
665228 |
@@ -827,10 +829,13 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
|
|
|
665228 |
{
|
|
|
665228 |
krb5_error_code code = 0;
|
|
|
665228 |
|
|
|
665228 |
- krb5_free_pa_data(context, ctx->preauth_to_use);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->optimistic_padata);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->method_padata);
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->more_padata);
|
|
|
665228 |
krb5_free_pa_data(context, ctx->err_padata);
|
|
|
665228 |
krb5_free_error(context, ctx->err_reply);
|
|
|
665228 |
- ctx->preauth_to_use = ctx->err_padata = NULL;
|
|
|
665228 |
+ ctx->optimistic_padata = ctx->method_padata = ctx->more_padata = NULL;
|
|
|
665228 |
+ ctx->err_padata = NULL;
|
|
|
665228 |
ctx->err_reply = NULL;
|
|
|
665228 |
ctx->selected_preauth_type = KRB5_PADATA_NONE;
|
|
|
665228 |
|
|
|
665228 |
@@ -849,7 +854,7 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
|
|
|
665228 |
if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
|
|
|
665228 |
code = make_preauth_list(context, ctx->opt->preauth_list,
|
|
|
665228 |
ctx->opt->preauth_list_length,
|
|
|
665228 |
- &ctx->preauth_to_use);
|
|
|
665228 |
+ &ctx->optimistic_padata);
|
|
|
665228 |
if (code)
|
|
|
665228 |
goto cleanup;
|
|
|
665228 |
}
|
|
|
665228 |
@@ -1301,6 +1306,7 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
krb5_data *out)
|
|
|
665228 |
{
|
|
|
665228 |
krb5_error_code code;
|
|
|
665228 |
+ krb5_preauthtype pa_type;
|
|
|
665228 |
|
|
|
665228 |
if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
|
|
|
665228 |
code = KRB5_GET_IN_TKT_LOOP;
|
|
|
665228 |
@@ -1331,17 +1337,36 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
read_cc_config_in_data(context, ctx);
|
|
|
665228 |
clear_cc_config_out_data(context, ctx);
|
|
|
665228 |
|
|
|
665228 |
- if (ctx->err_reply == NULL) {
|
|
|
665228 |
- /* Either our first attempt, or retrying after KDC_ERR_PREAUTH_REQUIRED
|
|
|
665228 |
- * or KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
|
|
|
665228 |
- code = k5_preauth(context, ctx, ctx->preauth_to_use,
|
|
|
665228 |
- ctx->preauth_required, &ctx->request->padata,
|
|
|
665228 |
- &ctx->selected_preauth_type);
|
|
|
665228 |
+ ctx->request->padata = NULL;
|
|
|
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 |
+ &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 |
- } else {
|
|
|
665228 |
- /* Retry after an error other than PREAUTH_NEEDED, using error padata
|
|
|
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 |
+ 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 |
@@ -1351,6 +1376,8 @@ init_creds_step_request(krb5_context context,
|
|
|
665228 |
goto cleanup;
|
|
|
665228 |
}
|
|
|
665228 |
}
|
|
|
665228 |
+ if (ctx->request->padata == NULL)
|
|
|
665228 |
+ TRACE_INIT_CREDS_PREAUTH_NONE(context);
|
|
|
665228 |
|
|
|
665228 |
/* Remember when we sent this request (after any preauth delay). */
|
|
|
665228 |
ctx->request_time = time(NULL);
|
|
|
665228 |
@@ -1467,8 +1494,9 @@ init_creds_step_reply(krb5_context context,
|
|
|
665228 |
ctx->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL;
|
|
|
665228 |
|
|
|
665228 |
if (ctx->err_reply != NULL) {
|
|
|
665228 |
+ krb5_free_pa_data(context, ctx->more_padata);
|
|
|
665228 |
krb5_free_pa_data(context, ctx->err_padata);
|
|
|
665228 |
- ctx->err_padata = NULL;
|
|
|
665228 |
+ ctx->more_padata = ctx->err_padata = NULL;
|
|
|
665228 |
code = krb5int_fast_process_error(context, ctx->fast_state,
|
|
|
665228 |
&ctx->err_reply, &ctx->err_padata,
|
|
|
665228 |
&retry);
|
|
|
665228 |
@@ -1494,21 +1522,18 @@ init_creds_step_reply(krb5_context context,
|
|
|
665228 |
* FAST upgrade. */
|
|
|
665228 |
ctx->restarted = FALSE;
|
|
|
665228 |
code = restart_init_creds_loop(context, ctx, FALSE);
|
|
|
665228 |
- } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
|
|
|
665228 |
- reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
|
|
|
665228 |
- krb5_free_pa_data(context, ctx->preauth_to_use);
|
|
|
665228 |
- ctx->preauth_to_use = ctx->err_padata;
|
|
|
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 |
- /* This will trigger a new call to k5_preauth(). */
|
|
|
665228 |
- krb5_free_error(context, ctx->err_reply);
|
|
|
665228 |
- ctx->err_reply = NULL;
|
|
|
665228 |
code = sort_krb5_padata_sequence(context,
|
|
|
665228 |
&ctx->request->client->realm,
|
|
|
665228 |
- ctx->preauth_to_use);
|
|
|
665228 |
- ctx->preauth_required = TRUE;
|
|
|
665228 |
-
|
|
|
665228 |
+ ctx->method_padata);
|
|
|
665228 |
+ } else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) {
|
|
|
665228 |
+ ctx->more_padata = ctx->err_padata;
|
|
|
665228 |
+ ctx->err_padata = NULL;
|
|
|
665228 |
} else if (canon_flag && is_referral(context, ctx->err_reply,
|
|
|
665228 |
ctx->request->client)) {
|
|
|
665228 |
TRACE_INIT_CREDS_REFERRAL(context, &ctx->err_reply->client->realm);
|
|
|
665228 |
diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
|
|
|
665228 |
index 8c8b7494b..fe769685b 100644
|
|
|
665228 |
--- a/src/lib/krb5/krb/init_creds_ctx.h
|
|
|
665228 |
+++ b/src/lib/krb5/krb/init_creds_ctx.h
|
|
|
665228 |
@@ -50,7 +50,9 @@ struct _krb5_init_creds_context {
|
|
|
665228 |
krb5_data *inner_request_body; /**< For preauth */
|
|
|
665228 |
krb5_data *encoded_previous_request;
|
|
|
665228 |
struct krb5int_fast_request_state *fast_state;
|
|
|
665228 |
- krb5_pa_data **preauth_to_use;
|
|
|
665228 |
+ krb5_pa_data **optimistic_padata; /* from gic options */
|
|
|
665228 |
+ krb5_pa_data **method_padata; /* from PREAUTH_REQUIRED or PREAUTH_FAILED */
|
|
|
665228 |
+ krb5_pa_data **more_padata; /* from MORE_PREAUTH_DATA_REQUIRED */
|
|
|
665228 |
krb5_boolean default_salt;
|
|
|
665228 |
krb5_data salt;
|
|
|
665228 |
krb5_data s2kparams;
|
|
|
665228 |
@@ -58,7 +60,6 @@ struct _krb5_init_creds_context {
|
|
|
665228 |
krb5_enctype etype;
|
|
|
665228 |
krb5_boolean enc_pa_rep_permitted;
|
|
|
665228 |
krb5_boolean restarted;
|
|
|
665228 |
- krb5_boolean preauth_required;
|
|
|
665228 |
struct krb5_responder_context_st rctx;
|
|
|
665228 |
krb5_preauthtype selected_preauth_type;
|
|
|
665228 |
krb5_preauthtype allowed_preauth_type;
|