diff options
author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2012-09-17 18:16:51 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2012-10-17 15:24:52 -0400 |
commit | f6a42c26d14ca71eb942e2eca5e1c7b50715e250 (patch) | |
tree | 358fa77013513396bdd5f25d70b5408ac6acf1f7 /src/lib/krb5 | |
parent | 9364a03d0d099040552cb52590a67d3f455d3f25 (diff) | |
download | krb5-f6a42c26d14ca71eb942e2eca5e1c7b50715e250.tar.gz krb5-f6a42c26d14ca71eb942e2eca5e1c7b50715e250.tar.xz krb5-f6a42c26d14ca71eb942e2eca5e1c7b50715e250.zip |
Add "pa_config_data" configuration to ccaches
* Read a "pa_config_data" item from an in_ccache, if provided, and add a
callback which client preauth plugins can use to retrieve a string
value from it that's keyed by a string.
* Add a callback which client preauth plugins can use to provide string
key/value pairs to be stored in the ccache.
* Moves the definition of (struct krb5_clpreauth_rock_st) from k5-int.h
to init_creds_ctx.h to try to reduce the number of files that will
need to include k5-json.h to understand k5_json_value.
Diffstat (limited to 'src/lib/krb5')
-rw-r--r-- | src/lib/krb5/krb/get_in_tkt.c | 84 | ||||
-rw-r--r-- | src/lib/krb5/krb/init_creds_ctx.h | 53 | ||||
-rw-r--r-- | src/lib/krb5/krb/preauth2.c | 46 | ||||
-rw-r--r-- | src/lib/krb5/krb/preauth_sam2.c | 1 |
4 files changed, 183 insertions, 1 deletions
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 9929fdb8ed..c2cd9e8837 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -832,6 +832,8 @@ krb5_init_creds_init(krb5_context context, 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; + ctx->preauth_rock.cc_config_in = &ctx->cc_config_in; + ctx->preauth_rock.cc_config_out = &ctx->cc_config_out; /* Initialise request parameters as per krb5_get_init_creds() */ ctx->request->kdc_options = context->kdc_default_options; @@ -1138,6 +1140,77 @@ save_selected_preauth_type(krb5_context context, krb5_ccache ccache, } static krb5_error_code +clear_cc_config_out_data(krb5_context context, krb5_init_creds_context ctx) +{ + if (ctx->cc_config_out != NULL) + k5_json_release(ctx->cc_config_out); + ctx->cc_config_out = k5_json_object_create(); + if (ctx->cc_config_out == NULL) + return ENOMEM; + return 0; +} + +static krb5_error_code +read_cc_config_in_data(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_data config; + char *encoded; + krb5_error_code code; + int i; + + if (ctx->cc_config_in != NULL) + k5_json_release(ctx->cc_config_in); + ctx->cc_config_in = NULL; + + if (ctx->opte->opt_private->in_ccache == NULL) + return 0; + + memset(&config, 0, sizeof(config)); + code = krb5_cc_get_config(context, ctx->opte->opt_private->in_ccache, + ctx->request->server, + KRB5_CONF_PA_CONFIG_DATA, &config); + if (code) + return code; + + i = asprintf(&encoded, "%.*s", (int)config.length, config.data); + krb5_free_data_contents(context, &config); + if (i < 0) + return ENOMEM; + + ctx->cc_config_in = k5_json_decode(encoded); + free(encoded); + if (ctx->cc_config_in == NULL) + return ENOMEM; + if (k5_json_get_tid(ctx->cc_config_in) != K5_JSON_TID_OBJECT) { + k5_json_release(ctx->cc_config_in); + ctx->cc_config_in = NULL; + return EINVAL; + } + + return 0; +} + +static krb5_error_code +save_cc_config_out_data(krb5_context context, krb5_ccache ccache, + krb5_init_creds_context ctx) +{ + krb5_data config; + char *encoded; + krb5_error_code code; + + if (ctx->cc_config_out == NULL) + return 0; + encoded = k5_json_encode(ctx->cc_config_out); + if (encoded == NULL) + return ENOMEM; + config = string2data(encoded); + code = krb5_cc_set_config(context, ccache, ctx->cred.server, + KRB5_CONF_PA_CONFIG_DATA, &config); + free(encoded); + return code; +} + +static krb5_error_code init_creds_step_request(krb5_context context, krb5_init_creds_context ctx, krb5_data *out) @@ -1177,6 +1250,14 @@ init_creds_step_request(krb5_context context, read_allowed_preauth_type(context, ctx); ctx->selected_preauth_type = KRB5_PADATA_NONE; + /* + * Read cached preauth configuration data for this server principal from + * the in_ccache, if the application supplied one, and delete any that was + * stored by a previous (clearly failed) module. + */ + read_cc_config_in_data(context, ctx); + clear_cc_config_out_data(context, ctx); + if (ctx->err_reply == NULL) { /* either our first attempt, or retrying after PREAUTH_NEEDED */ code = krb5_do_preauth(context, @@ -1574,6 +1655,9 @@ init_creds_step_reply(krb5_context context, goto cc_cleanup; } code = save_selected_preauth_type(context, out_ccache, ctx); + if (code != 0) + goto cc_cleanup; + code = save_cc_config_out_data(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 b4925ef697..e893113a05 100644 --- a/src/lib/krb5/krb/init_creds_ctx.h +++ b/src/lib/krb5/krb/init_creds_ctx.h @@ -3,6 +3,57 @@ #ifndef KRB5_INIT_CREDS_CONTEXT #define KRB5_INIT_CREDS_CONTEXT 1 +#include "k5-json.h" + +#define CLIENT_ROCK_MAGIC 0x4352434b +/* + * This structure is passed into the clpreauth methods and passed back to + * clpreauth callbacks so that they can locate the requested information. It + * is opaque to the plugin code and can be expanded in the future as new types + * of requests are defined which may require other things to be passed through. + * All pointer fields are aliases and should not be freed. + */ +struct krb5_clpreauth_rock_st { + krb5_magic magic; + krb5_enctype *etype; + struct krb5int_fast_request_state *fast_state; + + /* + * These fields allow gak_fct to be called via the rock. The + * gak_fct and gak_data fields have an extra level of indirection + * since they can change in the init_creds context. + */ + krb5_keyblock *as_key; + krb5_gic_get_as_key_fct *gak_fct; + void **gak_data; + krb5_boolean *default_salt; + krb5_data *salt; + krb5_data *s2kparams; + krb5_principal client; + krb5_prompter_fct prompter; + void *prompter_data; + + /* Discovered offset of server time during preauth */ + krb5_timestamp pa_offset; + 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; + /* Preauth configuration data which can help us make some decisions. */ + k5_json_value *cc_config_in; + k5_json_value *cc_config_out; +}; + struct _krb5_init_creds_context { krb5_gic_opt_ext *opte; char *in_tkt_service; @@ -49,6 +100,8 @@ struct _krb5_init_creds_context { struct krb5_responder_context_st rctx; krb5_preauthtype selected_preauth_type; krb5_preauthtype allowed_preauth_type; + void *cc_config_in; + void *cc_config_out; }; krb5_error_code diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index dc8a31dd6d..9ce82d5a35 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -31,10 +31,12 @@ */ #include "k5-int.h" +#include "k5-json.h" #include "osconf.h" #include <krb5/preauth_plugin.h> #include "int-proto.h" #include "fast.h" +#include "init_creds_ctx.h" #if !defined(_WIN32) #include <unistd.h> @@ -436,6 +438,46 @@ need_as_key(krb5_context context, krb5_clpreauth_rock rock) NULL, NULL, *rock->gak_data, rock->rctx.items); } +static const char * +get_cc_config(krb5_context context, krb5_clpreauth_rock rock, const char *key) +{ + k5_json_value value; + + if (rock->cc_config_in == NULL || *rock->cc_config_in == NULL) + return NULL; + + value = k5_json_object_get(*rock->cc_config_in, key); + if (value == NULL) + return NULL; + + if (k5_json_get_tid(value) != K5_JSON_TID_STRING) + return NULL; + + return k5_json_string_utf8(value); +} + +static krb5_error_code +set_cc_config(krb5_context context, krb5_clpreauth_rock rock, + const char *key, const char *data) +{ + k5_json_value value; + int i; + + if (rock->cc_config_out == NULL || *rock->cc_config_out == NULL) + return ENOENT; + + value = k5_json_string_create(data); + if (value == NULL) + return ENOMEM; + + i = k5_json_object_set(*rock->cc_config_out, key, value); + k5_json_release(value); + if (i < 0) + return ENOMEM; + + return 0; +} + static struct krb5_clpreauth_callbacks_st callbacks = { 2, get_etype, @@ -445,7 +487,9 @@ static struct krb5_clpreauth_callbacks_st callbacks = { get_preauth_time, responder_ask_question, responder_get_answer, - need_as_key + need_as_key, + get_cc_config, + set_cc_config }; /* Tweak the request body, for now adding any enctypes which the module claims diff --git a/src/lib/krb5/krb/preauth_sam2.c b/src/lib/krb5/krb/preauth_sam2.c index 0190137e96..a5f6395978 100644 --- a/src/lib/krb5/krb/preauth_sam2.c +++ b/src/lib/krb5/krb/preauth_sam2.c @@ -28,6 +28,7 @@ #include <k5-int.h> #include <krb5/preauth_plugin.h> #include "int-proto.h" +#include "init_creds_ctx.h" static int sam2_flags(krb5_context context, krb5_preauthtype pa_type) |