summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2012-07-23 18:18:58 -0400
committerGreg Hudson <ghudson@mit.edu>2012-10-16 19:22:37 -0400
commit4e89b0b186ec90a6a06dd761d61ab45d82db599a (patch)
treeca59cffc6c705d7687753ea6e29416c011475dc3
parentebb41dbb797d7a922aaca9b3c09a3e05c45b5a72 (diff)
downloadkrb5-4e89b0b186ec90a6a06dd761d61ab45d82db599a.tar.gz
krb5-4e89b0b186ec90a6a06dd761d61ab45d82db599a.tar.xz
krb5-4e89b0b186ec90a6a06dd761d61ab45d82db599a.zip
Add "pa_type" configuration to ccaches
* When producing preauth data, keep track of the type of padata in the KDC's list of acceptable types which prompted the module to produce padata. * After obtaining credentials, store that value as a "pa_type" configuration item in the out_ccache. * Read that allowed preauth type from an in_ccache, if possible. * If we have an allowed preauth type, only call "real" modules that handle that value when filling in responder items and producing a client request. ticket: 7414 (new)
-rw-r--r--src/include/k5-int.h12
-rw-r--r--src/lib/krb5/krb/get_in_tkt.c66
-rw-r--r--src/lib/krb5/krb/init_creds_ctx.h2
-rw-r--r--src/lib/krb5/krb/preauth2.c17
4 files changed, 97 insertions, 0 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 169d6d3958..d5299c597e 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -282,6 +282,7 @@ typedef INT64_TYPE krb5_int64;
#define KRB5_CONF_FAST_AVAIL "fast_avail"
#define KRB5_CONF_PROXY_IMPERSONATOR "proxy_impersonator"
#define KRB5_CONF_REFRESH_TIME "refresh_time"
+#define KRB5_CONF_PA_TYPE "pa_type"
/* Error codes used in KRB_ERROR protocol messages.
Return values of library routines are based on a different error table
@@ -839,6 +840,17 @@ struct krb5_clpreauth_rock_st {
krb5_int32 pa_offset_usec;
enum { NO_OFFSET = 0, UNAUTH_OFFSET, AUTH_OFFSET } pa_offset_state;
struct krb5_responder_context_st rctx;
+
+ /*
+ * Configuration information read from an in_ccache, actually stored in the
+ * containing context structure, but needed by callbacks which currently
+ * only get a pointer to the rock
+ */
+
+ /* The allowed preauth type (number) that we might use, equal to
+ * KRB5_PADATA_NONE if none was set. */
+ krb5_preauthtype *allowed_preauth_type;
+ krb5_preauthtype *selected_preauth_type;
};
typedef struct _krb5_pa_enc_ts {
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 225f34f528..9929fdb8ed 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -830,6 +830,8 @@ krb5_init_creds_init(krb5_context context,
ctx->preauth_rock.client = client;
ctx->preauth_rock.prompter = prompter;
ctx->preauth_rock.prompter_data = data;
+ ctx->preauth_rock.allowed_preauth_type = &ctx->allowed_preauth_type;
+ ctx->preauth_rock.selected_preauth_type = &ctx->selected_preauth_type;
/* Initialise request parameters as per krb5_get_init_creds() */
ctx->request->kdc_options = context->kdc_default_options;
@@ -1088,6 +1090,53 @@ init_creds_validate_reply(krb5_context context,
return 0;
}
+static void
+read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_data config;
+ char *tmp, *p;
+
+ ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+ if (ctx->opte->opt_private->in_ccache == NULL)
+ return;
+ memset(&config, 0, sizeof(config));
+ if (krb5_cc_get_config(context, ctx->opte->opt_private->in_ccache,
+ ctx->request->server,
+ KRB5_CONF_PA_TYPE, &config) != 0)
+ return;
+ tmp = malloc(config.length + 1);
+ if (tmp == NULL) {
+ krb5_free_data_contents(context, &config);
+ return;
+ }
+ memcpy(tmp, config.data, config.length);
+ tmp[config.length] = '\0';
+ ctx->allowed_preauth_type = strtol(tmp, &p, 10);
+ if (p == NULL || *p != '\0')
+ ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+ free(tmp);
+ krb5_free_data_contents(context, &config);
+}
+
+static krb5_error_code
+save_selected_preauth_type(krb5_context context, krb5_ccache ccache,
+ krb5_init_creds_context ctx)
+{
+ krb5_data config_data;
+ char *tmp;
+ krb5_error_code code;
+
+ if (ctx->selected_preauth_type == KRB5_PADATA_NONE)
+ return 0;
+ if (asprintf(&tmp, "%ld", (long)ctx->selected_preauth_type) < 0)
+ return ENOMEM;
+ config_data = string2data(tmp);
+ code = krb5_cc_set_config(context, ccache, ctx->cred.server,
+ KRB5_CONF_PA_TYPE, &config_data);
+ free(tmp);
+ return code;
+}
+
static krb5_error_code
init_creds_step_request(krb5_context context,
krb5_init_creds_context ctx,
@@ -1123,6 +1172,11 @@ init_creds_step_request(krb5_context context,
if (code)
goto cleanup;
+ /* Read the allowed patype for this server principal from the in_ccache,
+ * if the application supplied one. */
+ read_allowed_preauth_type(context, ctx);
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
+
if (ctx->err_reply == NULL) {
/* either our first attempt, or retrying after PREAUTH_NEEDED */
code = krb5_do_preauth(context,
@@ -1396,6 +1450,15 @@ init_creds_step_reply(krb5_context context,
ctx->etype = ctx->reply->enc_part.enctype;
+ /*
+ * At this point, allow whichever preauth plugin that can handle the KDC's
+ * reply padata to do so, regardless of that data's padata type. We don't
+ * want to record the type of padata in the reply, so set the pointer for
+ * that data to NULL.
+ */
+ ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+ ctx->preauth_rock.selected_preauth_type = NULL;
+
code = krb5_do_preauth(context,
ctx->request,
ctx->inner_request_body,
@@ -1507,7 +1570,10 @@ init_creds_step_reply(krb5_context context,
config_data.length = strlen(config_data.data);
code = krb5_cc_set_config(context, out_ccache, ctx->cred.server,
KRB5_CONF_FAST_AVAIL, &config_data);
+ if (code != 0)
+ goto cc_cleanup;
}
+ code = save_selected_preauth_type(context, out_ccache, ctx);
cc_cleanup:
if (code !=0) {
const char *msg;
diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
index eb7b608c44..b4925ef697 100644
--- a/src/lib/krb5/krb/init_creds_ctx.h
+++ b/src/lib/krb5/krb/init_creds_ctx.h
@@ -47,6 +47,8 @@ struct _krb5_init_creds_context {
krb5_boolean sent_nontrivial_preauth;
krb5_boolean preauth_required;
struct krb5_responder_context_st rctx;
+ krb5_preauthtype selected_preauth_type;
+ krb5_preauthtype allowed_preauth_type;
};
krb5_error_code
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index 1ee53a6b72..dc8a31dd6d 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -536,6 +536,10 @@ run_preauth_plugins(krb5_context kcontext,
/* skip over those which don't match the flags (INFO vs REAL, mainly) */
if ((module->flags & module_required_flags) == 0)
continue;
+ if ((module->flags & PA_REAL) &&
+ *preauth_rock->allowed_preauth_type != KRB5_PADATA_NONE &&
+ in_padata->pa_type != *preauth_rock->allowed_preauth_type)
+ continue;
/* if it's a REAL module, try to call it only once per library call */
if (module_required_flags & PA_REAL) {
if (module->use_count > 0) {
@@ -570,6 +574,9 @@ run_preauth_plugins(krb5_context kcontext,
if (ret != 0)
return ret;
}
+ /* Record which pa_type we answered a call for. */
+ if (preauth_rock->selected_preauth_type != NULL)
+ *preauth_rock->selected_preauth_type = in_padata->pa_type;
break;
}
if (i >= kcontext->preauth_context->n_modules) {
@@ -821,6 +828,12 @@ krb5_do_preauth_tryagain(krb5_context kcontext,
if (module->pa_type != padata[i]->pa_type) {
continue;
}
+ if ((module->flags & PA_REAL) &&
+ *preauth_rock->allowed_preauth_type != KRB5_PADATA_NONE &&
+ padata[i]->pa_type != *preauth_rock->allowed_preauth_type) {
+ /* It's unlikely that we'll get here. */
+ continue;
+ }
if (module->client_tryagain == NULL) {
continue;
}
@@ -873,6 +886,10 @@ fill_response_items(krb5_context context, krb5_kdc_req *request,
prep_questions = module->client_prep_questions;
if (module->pa_type != pa->pa_type || prep_questions == NULL)
continue;
+ if ((module->flags & PA_REAL) &&
+ *rock->allowed_preauth_type != KRB5_PADATA_NONE &&
+ pa->pa_type != *rock->allowed_preauth_type)
+ continue;
ret = (*prep_questions)(context, module->moddata,
*module->modreq_p,
(krb5_get_init_creds_opt *)opte,