krb5/krb5-1.14-Support-KDC_ERR_MORE_PREAUTH_DATA_REQUIRED.patch

143 lines
6.4 KiB
Diff
Raw Normal View History

From 95c3cab051aa1b8b4f7eb309bf135e8f51665baa Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccallum@redhat.com>
Date: Sun, 25 Jan 2015 16:53:49 -0500
Subject: [PATCH] Support KDC_ERR_MORE_PREAUTH_DATA_REQUIRED
Add support for multi-hop preauth mechs.
In the KDC, allow kdcpreauth modules to return
KDC_ERR_MORE_PREAUTH_DATA_REQUIRED as defined in RFC 6113.
In libkrb5, treat this code like KDC_ERR_PREAUTH_REQUIRED. clpreauth
modules can use the modreq parameter to distinguish between the first
and subsequent KDC messages. We assume that the error padata will
include an element of the preauth mech's type, or at least of a type
recognized by the clpreauth module.
Also reset the list of previously attempted preauth types for both
kinds of errors. That list is really only appropriate for retrying
after a failed preauth attempt, which we don't currently do. Add an
intermediate variable for the reply code to avoid a long conditional
expression.
[ghudson@mit.edu: adjust get_in_tkt.c logic to avoid needing a helper
function; clarify commit message]
ticket: 8063 (new)
---
doc/plugindev/clpreauth.rst | 6 +++---
src/include/k5-int.h | 1 +
src/kdc/kdc_preauth.c | 2 ++
src/lib/krb5/error_tables/krb5_err.et | 2 +-
src/lib/krb5/krb/get_in_tkt.c | 13 ++++++++-----
5 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/doc/plugindev/clpreauth.rst b/doc/plugindev/clpreauth.rst
index c3e7298..38aa52e 100644
--- a/doc/plugindev/clpreauth.rst
+++ b/doc/plugindev/clpreauth.rst
@@ -21,9 +21,9 @@ A clpreauth module is generally responsible for:
just returns ``PA_REAL``, indicating that it implements a normal
preauthentication type.
-* Examining the padata information included in the preauth_required
- error and producing padata values for the next AS request. This is
- done with the **process** method.
+* Examining the padata information included in a PREAUTH_REQUIRED or
+ MORE_PREAUTH_DATA_REQUIRED error and producing padata values for the
+ next AS request. This is done with the **process** method.
* Examining the padata information included in a successful ticket
reply, possibly verifying the KDC identity and computing a reply
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index a1ea25a..4868e7d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -391,6 +391,7 @@ typedef unsigned char u_char;
not find a KDC */
#define KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE 86 /* The KDC did not respond
to the IAKERB proxy */
+#define KDC_ERR_MORE_PREAUTH_DATA_REQUIRED 91 /* RFC 6113 */
#define KRB_ERR_MAX 127 /* err table base max offset for protocol err codes */
/*
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 50cc252..dd83844 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -1000,6 +1000,8 @@ finish_check_padata(struct padata_state *state, krb5_error_code code)
case KRB5KDC_ERR_DISCARD:
/* pkinit alg-agility */
case KRB5KDC_ERR_NO_ACCEPTABLE_KDF:
+ /* rfc 6113 */
+ case KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED:
(*oldrespond)(oldarg, code);
return;
default:
diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et
index 5c6f10b..7ba7c1e 100644
--- a/src/lib/krb5/error_tables/krb5_err.et
+++ b/src/lib/krb5/error_tables/krb5_err.et
@@ -132,7 +132,7 @@ error_code KRB5PLACEHOLD_87, "KRB5 error code 87"
error_code KRB5PLACEHOLD_88, "KRB5 error code 88"
error_code KRB5PLACEHOLD_89, "KRB5 error code 89"
error_code KRB5PLACEHOLD_90, "KRB5 error code 90"
-error_code KRB5PLACEHOLD_91, "KRB5 error code 91"
+error_code KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, "More preauthentication data is required"
error_code KRB5PLACEHOLD_92, "KRB5 error code 92"
error_code KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION, "An unsupported critical FAST option was requested"
error_code KRB5PLACEHOLD_94, "KRB5 error code 94"
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index f9bc027..fa8afcc 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -1239,7 +1239,8 @@ init_creds_step_request(krb5_context context,
clear_cc_config_out_data(context, ctx);
if (ctx->err_reply == NULL) {
- /* either our first attempt, or retrying after PREAUTH_NEEDED */
+ /* Either our first attempt, or retrying after KDC_ERR_PREAUTH_REQUIRED
+ * or KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
code = k5_preauth(context, ctx, ctx->preauth_to_use,
ctx->preauth_required, &ctx->request->padata,
&ctx->selected_preauth_type);
@@ -1408,6 +1409,7 @@ init_creds_step_reply(krb5_context context,
krb5_preauthtype kdc_pa_type;
krb5_boolean retry = FALSE;
int canon_flag = 0;
+ uint32_t reply_code;
krb5_keyblock *strengthen_key = NULL;
krb5_keyblock encrypting_key;
krb5_boolean fast_avail;
@@ -1431,6 +1433,7 @@ init_creds_step_reply(krb5_context context,
&retry);
if (code != 0)
goto cleanup;
+ reply_code = ctx->err_reply->error;
if (negotiation_requests_restart(context, ctx, ctx->err_padata)) {
ctx->have_restarted = 1;
k5_preauth_request_context_fini(context);
@@ -1441,9 +1444,10 @@ init_creds_step_reply(krb5_context context,
ctx->err_reply = NULL;
krb5_free_pa_data(context, ctx->err_padata);
ctx->err_padata = NULL;
- } else if (ctx->err_reply->error == KDC_ERR_PREAUTH_REQUIRED &&
- retry) {
+ } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
+ reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
/* reset the list of preauth types to try */
+ k5_reset_preauth_types_tried(context);
krb5_free_pa_data(context, ctx->preauth_to_use);
ctx->preauth_to_use = ctx->err_padata;
ctx->err_padata = NULL;
@@ -1480,8 +1484,7 @@ init_creds_step_reply(krb5_context context,
code = 0;
} else {
/* error + no hints = give up */
- code = (krb5_error_code)ctx->err_reply->error +
- ERROR_TABLE_BASE_krb5;
+ code = (krb5_error_code)reply_code + ERROR_TABLE_BASE_krb5;
}
}