Skip to content

Commit

Permalink
Add "pa_type" configuration to ccaches
Browse files Browse the repository at this point in the history
* 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)
  • Loading branch information
nalind authored and greghudson committed Oct 16, 2012
1 parent ebb41db commit 4e89b0b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/include/k5-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
66 changes: 66 additions & 0 deletions src/lib/krb5/krb/get_in_tkt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/krb5/krb/init_creds_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/lib/krb5/krb/preauth2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 4e89b0b

Please sign in to comment.