summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2014-03-01 00:35:50 -0500
committerGreg Hudson <ghudson@mit.edu>2014-03-05 16:48:50 -0500
commitc724843cb90cfed71d54eab94b68b0583c1d6dc5 (patch)
tree5060aeaa8f07f514ffa665152fe96b02be0824b2
parent06817686bfdef99523f300464bcbb0c8b037a27d (diff)
downloadkrb5-c724843cb90cfed71d54eab94b68b0583c1d6dc5.tar.gz
krb5-c724843cb90cfed71d54eab94b68b0583c1d6dc5.tar.xz
krb5-c724843cb90cfed71d54eab94b68b0583c1d6dc5.zip
Improve extended gic option support
The current extended gic option facility violates strict aliasing, is not nestable (gic_opt_to_opte cannot be used on an extended options structure casted back to krb5_get_init_creds_options), and requires callers to use error-prone conversion functions. Rewrite this code to use a new structure private to gic_opt.c, which contains a krb5_get_init_creds_opt structure as its first member. We can cast between the extended structure and its first element without violating strict aliasing (C99 6.7.2.1 paragraph 13 and the aggregate type clause of 6.5 paragraph 7). Define internal accessor functions for the extended option fields. Replace all uses of krb5_gic_opt_ext in callers with krb5_get_init_creds_opt and the new accessors. Bring krb5_get_init_creds_opt_set_pa back into gic_opt.c (reverting faa810c5b59fa33d9f7db837c5bb88df5436bb30) so that all of the code which accesses the extended options structure can be in one file. ticket: 6034
-rw-r--r--src/lib/krb5/krb/Makefile.in3
-rw-r--r--src/lib/krb5/krb/deps11
-rw-r--r--src/lib/krb5/krb/fast.c15
-rw-r--r--src/lib/krb5/krb/fast.h2
-rw-r--r--src/lib/krb5/krb/get_in_tkt.c102
-rw-r--r--src/lib/krb5/krb/gic_opt.c439
-rw-r--r--src/lib/krb5/krb/gic_opt_set_pa.c99
-rw-r--r--src/lib/krb5/krb/gic_pwd.c53
-rw-r--r--src/lib/krb5/krb/init_creds_ctx.h3
-rw-r--r--src/lib/krb5/krb/int-proto.h118
-rw-r--r--src/lib/krb5/krb/preauth2.c22
11 files changed, 316 insertions, 551 deletions
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index 91010ba22..62f0b90f6 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -79,7 +79,6 @@ STLIBOBJS= \
preauth_otp.o \
preauth_pkinit.o \
preauth_sam2.o \
- gic_opt_set_pa.o \
princ_comp.o \
privsafe.o \
random_str.o \
@@ -189,7 +188,6 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \
$(OUTPRE)preauth_otp.$(OBJEXT) \
$(OUTPRE)preauth_pkinit.$(OBJEXT) \
$(OUTPRE)preauth_sam2.$(OBJEXT) \
- $(OUTPRE)gic_opt_set_pa.$(OBJEXT) \
$(OUTPRE)princ_comp.$(OBJEXT) \
$(OUTPRE)privsafe.$(OBJEXT) \
$(OUTPRE)random_str.$(OBJEXT) \
@@ -299,7 +297,6 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/preauth_otp.c \
$(srcdir)/preauth_pkinit.c \
$(srcdir)/preauth_sam2.c \
- $(srcdir)/gic_opt_set_pa.c \
$(srcdir)/princ_comp.c \
$(srcdir)/privsafe.c \
$(srcdir)/random_str.c \
diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
index db9c4ec41..d08d53371 100644
--- a/src/lib/krb5/krb/deps
+++ b/src/lib/krb5/krb/deps
@@ -783,17 +783,6 @@ preauth_sam2.so preauth_sam2.po $(OUTPRE)preauth_sam2.$(OBJEXT): \
$(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
init_creds_ctx.h int-proto.h preauth_sam2.c
-gic_opt_set_pa.so gic_opt_set_pa.po $(OUTPRE)gic_opt_set_pa.$(OBJEXT): \
- $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
- $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
- gic_opt_set_pa.c int-proto.h
princ_comp.so princ_comp.po $(OUTPRE)princ_comp.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c
index 56e61a63a..8d622681e 100644
--- a/src/lib/krb5/krb/fast.c
+++ b/src/lib/krb5/krb/fast.c
@@ -171,21 +171,21 @@ krb5int_fast_prep_req_body(krb5_context context,
krb5_error_code
krb5int_fast_as_armor(krb5_context context,
struct krb5int_fast_request_state *state,
- krb5_gic_opt_ext *opte,
- krb5_kdc_req *request)
+ krb5_get_init_creds_opt *opt, krb5_kdc_req *request)
{
krb5_error_code retval = 0;
krb5_ccache ccache = NULL;
krb5_principal target_principal = NULL;
krb5_data *target_realm;
+ const char *ccname = k5_gic_opt_get_fast_ccache_name(opt);
+ krb5_flags fast_flags;
krb5_clear_error_message(context);
target_realm = &request->server->realm;
- if (opte->opt_private->fast_ccache_name) {
- TRACE_FAST_ARMOR_CCACHE(context, opte->opt_private->fast_ccache_name);
+ if (ccname != NULL) {
+ TRACE_FAST_ARMOR_CCACHE(context, ccname);
state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL;
- retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name,
- &ccache);
+ retval = krb5_cc_resolve(context, ccname, &ccache);
if (retval == 0) {
retval = krb5int_tgtname(context, target_realm, target_realm,
&target_principal);
@@ -202,7 +202,8 @@ krb5int_fast_as_armor(krb5_context context,
krb5_free_data_contents(context, &config_data);
retval = 0;
}
- if (opte->opt_private->fast_flags & KRB5_FAST_REQUIRED) {
+ fast_flags = k5_gic_opt_get_fast_flags(opt);
+ if (fast_flags & KRB5_FAST_REQUIRED) {
TRACE_FAST_REQUIRED(context);
state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
}
diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h
index 88456741a..684e25d0d 100644
--- a/src/lib/krb5/krb/fast.h
+++ b/src/lib/krb5/krb/fast.h
@@ -83,7 +83,7 @@ krb5int_fast_free_state(krb5_context context,
krb5_error_code
krb5int_fast_as_armor(krb5_context context,
struct krb5int_fast_request_state *state,
- krb5_gic_opt_ext *opte, krb5_kdc_req *request);
+ krb5_get_init_creds_opt *opt, krb5_kdc_req *request);
krb5_error_code
krb5int_fast_reply_key(krb5_context context,
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index d7b2bd9eb..ebd28440d 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -485,10 +485,6 @@ krb5_init_creds_free(krb5_context context,
if (ctx == NULL)
return;
- if (ctx->opte != NULL && gic_opt_is_shadowed(ctx->opte)) {
- krb5_get_init_creds_opt_free(context,
- (krb5_get_init_creds_opt *)ctx->opte);
- }
k5_response_items_free(ctx->rctx.items);
free(ctx->in_tkt_service);
zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length);
@@ -749,11 +745,11 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
krb5_free_data(context, ctx->outer_request_body);
ctx->outer_request_body = NULL;
}
- if (ctx->opte &&
- (ctx->opte->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)) {
- if ((code = make_preauth_list(context, ctx->opte->preauth_list,
- ctx->opte->preauth_list_length,
- &ctx->preauth_to_use)))
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
+ code = make_preauth_list(context, ctx->opt->preauth_list,
+ ctx->opt->preauth_list_length,
+ &ctx->preauth_to_use);
+ if (code)
goto cleanup;
}
@@ -766,18 +762,18 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
if (code != 0)
goto cleanup;
- code = krb5int_fast_as_armor(context, ctx->fast_state,
- ctx->opte, ctx->request);
+ code = krb5int_fast_as_armor(context, ctx->fast_state, ctx->opt,
+ ctx->request);
if (code != 0)
goto cleanup;
if (krb5int_upgrade_to_fast_p(context, ctx->fast_state, padata)) {
- code = krb5int_fast_as_armor(context, ctx->fast_state,
- ctx->opte, ctx->request);
+ code = krb5int_fast_as_armor(context, ctx->fast_state, ctx->opt,
+ ctx->request);
if (code != 0)
goto cleanup;
}
/* give the preauth plugins a chance to prep the request body */
- k5_preauth_prepare_request(context, ctx->opte, ctx->request);
+ k5_preauth_prepare_request(context, ctx->opt, ctx->request);
code = krb5int_fast_prep_req_body(context, ctx->fast_state,
ctx->request,
@@ -794,15 +790,13 @@ krb5_init_creds_init(krb5_context context,
krb5_prompter_fct prompter,
void *data,
krb5_deltat start_time,
- krb5_get_init_creds_opt *options,
+ krb5_get_init_creds_opt *opt,
krb5_init_creds_context *pctx)
{
krb5_error_code code;
krb5_init_creds_context ctx;
int tmp;
char *str = NULL;
- krb5_gic_opt_ext *opte;
- krb5_get_init_creds_opt local_opts;
TRACE_INIT_CREDS(context, client);
@@ -825,34 +819,23 @@ krb5_init_creds_init(krb5_context context,
ctx->start_time = start_time;
- if (options == NULL) {
- /*
- * We initialize a non-extended options because that way the shadowed
- * flag will be sent and they will be freed when the init_creds context
- * is freed. The options will be extended and copied off the stack into
- * storage by opt_to_opte.
- */
- krb5_get_init_creds_opt_init(&local_opts);
- options = &local_opts;
+ if (opt == NULL) {
+ ctx->opt = &ctx->opt_storage;
+ krb5_get_init_creds_opt_init(ctx->opt);
+ } else {
+ ctx->opt = opt;
}
- code = k5_gic_opt_to_opte(context, options, &ctx->opte, 1,
- "krb5_init_creds_init");
- if (code != 0)
- goto cleanup;
-
code = k5_response_items_new(&ctx->rctx.items);
if (code != 0)
goto cleanup;
- opte = ctx->opte;
-
/* Initialise request parameters as per krb5_get_init_creds() */
ctx->request->kdc_options = context->kdc_default_options;
/* forwardable */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
- tmp = opte->forwardable;
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
+ tmp = ctx->opt->forwardable;
else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm,
KRB5_CONF_FORWARDABLE, &tmp) == 0)
;
@@ -862,8 +845,8 @@ krb5_init_creds_init(krb5_context context,
ctx->request->kdc_options |= KDC_OPT_FORWARDABLE;
/* proxiable */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
- tmp = opte->proxiable;
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
+ tmp = ctx->opt->proxiable;
else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm,
KRB5_CONF_PROXIABLE, &tmp) == 0)
;
@@ -873,7 +856,7 @@ krb5_init_creds_init(krb5_context context,
ctx->request->kdc_options |= KDC_OPT_PROXIABLE;
/* canonicalize */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_CANONICALIZE)
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_CANONICALIZE)
tmp = 1;
else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm,
KRB5_CONF_CANONICALIZE, &tmp) == 0)
@@ -888,8 +871,8 @@ krb5_init_creds_init(krb5_context context,
ctx->request->kdc_options |= KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED;
/* ticket lifetime */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)
- ctx->tkt_life = options->tkt_life;
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)
+ ctx->tkt_life = ctx->opt->tkt_life;
else if (krb5int_libdefault_string(context, &ctx->request->client->realm,
KRB5_CONF_TICKET_LIFETIME, &str) == 0) {
code = krb5_string_to_deltat(str, &ctx->tkt_life);
@@ -901,8 +884,8 @@ krb5_init_creds_init(krb5_context context,
ctx->tkt_life = 24 * 60 * 60; /* previously hardcoded in kinit */
/* renewable lifetime */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)
- ctx->renew_life = options->renew_life;
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE)
+ ctx->renew_life = ctx->opt->renew_life;
else if (krb5int_libdefault_string(context, &ctx->request->client->realm,
KRB5_CONF_RENEW_LIFETIME, &str) == 0) {
code = krb5_string_to_deltat(str, &ctx->renew_life);
@@ -917,13 +900,14 @@ krb5_init_creds_init(krb5_context context,
ctx->request->kdc_options |= KDC_OPT_RENEWABLE;
/* enctypes */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
ctx->request->ktype =
- k5memdup(opte->etype_list,
- opte->etype_list_length * sizeof(krb5_enctype), &code);
+ k5memdup(ctx->opt->etype_list,
+ ctx->opt->etype_list_length * sizeof(krb5_enctype),
+ &code);
if (code != 0)
goto cleanup;
- ctx->request->nktypes = opte->etype_list_length;
+ ctx->request->nktypes = ctx->opt->etype_list_length;
} else if (krb5_get_default_in_tkt_ktypes(context,
&ctx->request->ktype) == 0) {
ctx->request->nktypes = k5_count_etypes(ctx->request->ktype);
@@ -942,8 +926,8 @@ krb5_init_creds_init(krb5_context context,
ctx->etype = ctx->request->ktype[0];
/* addresses */
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) {
- code = krb5_copy_addresses(context, opte->address_list,
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) {
+ code = krb5_copy_addresses(context, ctx->opt->address_list,
&ctx->request->addresses);
if (code != 0)
goto cleanup;
@@ -957,8 +941,8 @@ krb5_init_creds_init(krb5_context context,
goto cleanup;
}
- if (opte->flags & KRB5_GET_INIT_CREDS_OPT_SALT) {
- code = krb5int_copy_data_contents(context, opte->salt, &ctx->salt);
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_SALT) {
+ code = krb5int_copy_data_contents(context, ctx->opt->salt, &ctx->salt);
if (code != 0)
goto cleanup;
ctx->default_salt = FALSE;
@@ -968,7 +952,7 @@ krb5_init_creds_init(krb5_context context,
}
/* Anonymous. */
- if(opte->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) {
+ if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) {
ctx->request->kdc_options |= KDC_OPT_REQUEST_ANONYMOUS;
/* Remap @REALM to WELLKNOWN/ANONYMOUS@REALM. */
if (client->length == 1 && client->data[0].length ==0) {
@@ -1108,13 +1092,13 @@ read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
krb5_error_code ret;
krb5_data config;
char *tmp, *p;
+ krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
ctx->allowed_preauth_type = KRB5_PADATA_NONE;
- if (ctx->opte->opt_private->in_ccache == NULL)
+ if (in_ccache == NULL)
return;
memset(&config, 0, sizeof(config));
- if (krb5_cc_get_config(context, ctx->opte->opt_private->in_ccache,
- ctx->request->server,
+ if (krb5_cc_get_config(context, in_ccache, ctx->request->server,
KRB5_CC_CONF_PA_TYPE, &config) != 0)
return;
tmp = k5memdup0(config.data, config.length, &ret);
@@ -1162,16 +1146,16 @@ read_cc_config_in_data(krb5_context context, krb5_init_creds_context ctx)
char *encoded;
krb5_error_code code;
int i;
+ krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
k5_json_release(ctx->cc_config_in);
ctx->cc_config_in = NULL;
- if (ctx->opte->opt_private->in_ccache == NULL)
+ if (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,
+ code = krb5_cc_get_config(context, in_ccache, ctx->request->server,
KRB5_CC_CONF_PA_CONFIG_DATA, &config);
if (code)
return code;
@@ -1438,6 +1422,7 @@ init_creds_step_reply(krb5_context context,
krb5_keyblock *strengthen_key = NULL;
krb5_keyblock encrypting_key;
krb5_boolean fast_avail;
+ krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt);
encrypting_key.length = 0;
encrypting_key.contents = NULL;
@@ -1631,8 +1616,7 @@ init_creds_step_reply(krb5_context context,
code = stash_as_reply(context, ctx->reply, &ctx->cred, NULL);
if (code != 0)
goto cleanup;
- if (ctx->opte && ctx->opte->opt_private->out_ccache) {
- krb5_ccache out_ccache = ctx->opte->opt_private->out_ccache;
+ if (out_ccache != NULL) {
krb5_data config_data;
code = krb5_cc_initialize(context, out_ccache, ctx->cred.client);
if (code != 0)
diff --git a/src/lib/krb5/krb/gic_opt.c b/src/lib/krb5/krb/gic_opt.c
index 40a51d7c0..55f915264 100644
--- a/src/lib/krb5/krb/gic_opt.c
+++ b/src/lib/krb5/krb/gic_opt.c
@@ -3,17 +3,29 @@
#include "int-proto.h"
#include <krb5/clpreauth_plugin.h>
-static void
-init_common(krb5_get_init_creds_opt *opt)
-{
- opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
-}
+#define GIC_OPT_EXTENDED 0x80000000
+#define GIC_OPT_SHALLOW_COPY 0x40000000
+
+#define DEFAULT_FLAGS KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT
+
+struct extended_options {
+ krb5_get_init_creds_opt opt;
+ int num_preauth_data;
+ krb5_gic_opt_pa_data *preauth_data;
+ char *fast_ccache_name;
+ krb5_ccache in_ccache;
+ krb5_ccache out_ccache;
+ krb5_flags fast_flags;
+ krb5_expire_callback_func expire_cb;
+ void *expire_data;
+ krb5_responder_fn responder;
+ void *responder_data;
+};
void KRB5_CALLCONV
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
{
- opt->flags = 0;
- init_common(opt);
+ opt->flags = DEFAULT_FLAGS;
}
void KRB5_CALLCONV
@@ -101,81 +113,22 @@ krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt,
opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
}
-/* Forward prototype */
-static void
-free_gic_opt_ext_preauth_data(krb5_context context,
- krb5_gic_opt_ext *opte);
-
-static krb5_error_code
-gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte)
-{
- if (NULL == opte || !gic_opt_is_extended(opte))
- return EINVAL;
-
- opte->opt_private = calloc(1, sizeof(*opte->opt_private));
- if (NULL == opte->opt_private) {
- return ENOMEM;
- }
- /* Allocate any private stuff */
- opte->opt_private->num_preauth_data = 0;
- opte->opt_private->preauth_data = NULL;
- return 0;
-}
-
-static krb5_error_code
-gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
-{
- if (NULL == opte || !gic_opt_is_extended(opte))
- return EINVAL;
-
- /* Free up any private stuff */
- if (opte->opt_private->preauth_data != NULL)
- free_gic_opt_ext_preauth_data(context, opte);
- if (opte->opt_private->fast_ccache_name)
- free(opte->opt_private->fast_ccache_name);
- free(opte->opt_private);
- opte->opt_private = NULL;
- return 0;
-}
-
-static krb5_gic_opt_ext *
-gic_opte_alloc(krb5_context context)
-{
- krb5_gic_opt_ext *opte;
- krb5_error_code code;
-
- opte = calloc(1, sizeof(*opte));
- if (NULL == opte)
- return NULL;
- opte->flags = GIC_OPT_EXTENDED;
-
- code = gic_opte_private_alloc(context, opte);
- if (code) {
- free(opte);
- return NULL;
- }
- return(opte);
-}
-
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_alloc(krb5_context context,
krb5_get_init_creds_opt **opt)
{
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte;
if (NULL == opt)
return EINVAL;
*opt = NULL;
- /*
- * We return a new extended structure cast as a krb5_get_init_creds_opt
- */
- opte = gic_opte_alloc(context);
- if (NULL == opte)
+ /* Return an extended structure cast as a krb5_get_init_creds_opt. */
+ opte = calloc(1, sizeof(*opte));
+ if (opte == NULL)
return ENOMEM;
-
- *opt = (krb5_get_init_creds_opt *) opte;
- init_common(*opt);
+ opte->opt.flags = DEFAULT_FLAGS | GIC_OPT_EXTENDED;
+ *opt = (krb5_get_init_creds_opt *)opte;
return 0;
}
@@ -183,111 +136,54 @@ void KRB5_CALLCONV
krb5_get_init_creds_opt_free(krb5_context context,
krb5_get_init_creds_opt *opt)
{
- krb5_gic_opt_ext *opte;
-
- if (NULL == opt)
- return;
+ struct extended_options *opte = (struct extended_options *)opt;
+ int i;
- /* Don't touch it if we didn't allocate it */
- if (!gic_opt_is_extended(opt))
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
return;
-
- opte = (krb5_gic_opt_ext *)opt;
- if (opte->opt_private)
- gic_opte_private_free(context, opte);
-
+ assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
+ for (i = 0; i < opte->num_preauth_data; i++) {
+ free(opte->preauth_data[i].attr);
+ free(opte->preauth_data[i].value);
+ }
+ free(opte->preauth_data);
+ free(opte->fast_ccache_name);
free(opte);
}
-static krb5_error_code
-gic_opte_copy(krb5_context context,
- krb5_get_init_creds_opt *opt,
- krb5_gic_opt_ext **opte)
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_set_pa(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ const char *attr,
+ const char *value)
{
- krb5_gic_opt_ext *oe;
-
- oe = gic_opte_alloc(context);
- if (NULL == oe)
- return ENOMEM;
+ struct extended_options *opte = (struct extended_options *)opt;
+ krb5_gic_opt_pa_data *t, *pa;
- if (opt) {
- oe->flags = opt->flags;
- oe->tkt_life = opt->tkt_life;
- oe->renew_life = opt->renew_life;
- oe->forwardable = opt->forwardable;
- oe->proxiable = opt->proxiable;
- oe->etype_list = opt->etype_list;
- oe->etype_list_length = opt->etype_list_length;
- oe->address_list = opt->address_list;
- oe->preauth_list = opt->preauth_list;
- oe->preauth_list_length = opt->preauth_list_length;
- oe->salt = opt->salt;
- }
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
- /*
- * Fix the flags -- the EXTENDED flag would have been
- * overwritten by the copy if there was one. The
- * SHADOWED flag is necessary to ensure that the
- * krb5_gic_opt_ext structure that was allocated
- * here will be freed by the library because the
- * application is unaware of its existence.
- */
- oe->flags |= (GIC_OPT_EXTENDED | GIC_OPT_SHADOWED);
-
- *opte = oe;
- return 0;
-}
+ /* Allocate space for another option. */
+ t = realloc(opte->preauth_data, (opte->num_preauth_data + 1) * sizeof(*t));
+ if (t == NULL)
+ return ENOMEM;
+ opte->preauth_data = t;
-/*
- * Convert a krb5_get_init_creds_opt pointer to a pointer to
- * an extended, krb5_gic_opt_ext pointer. If the original
- * pointer already points to an extended structure, then simply
- * return the original pointer. Otherwise, if 'force' is non-zero,
- * allocate an extended structure and copy the original over it.
- * If the original pointer did not point to an extended structure
- * and 'force' is zero, then return an error. This is used in
- * cases where the original *should* be an extended structure.
- */
-krb5_error_code
-k5_gic_opt_to_opte(krb5_context context, krb5_get_init_creds_opt *opt,
- krb5_gic_opt_ext **opte, unsigned int force,
- const char *where)
-{
- if (!gic_opt_is_extended(opt)) {
- if (force) {
- return gic_opte_copy(context, opt, opte);
- } else {
- krb5_set_error_message(context, EINVAL,
- _("%s: attempt to convert non-extended "
- "krb5_get_init_creds_opt"), where);
- return EINVAL;
- }
+ /* Copy the option into the new slot. */
+ pa = &opte->preauth_data[opte->num_preauth_data];
+ pa->attr = strdup(attr);
+ if (pa->attr == NULL)
+ return ENOMEM;
+ pa->value = strdup(value);
+ if (pa->value == NULL) {
+ free(pa->attr);
+ return ENOMEM;
}
- /* If it is already extended, just return it */
- *opte = (krb5_gic_opt_ext *)opt;
- return 0;
-}
+ opte->num_preauth_data++;
-static void
-free_gic_opt_ext_preauth_data(krb5_context context,
- krb5_gic_opt_ext *opte)
-{
- int i;
-
- if (NULL == opte || !gic_opt_is_extended(opte))
- return;
- if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data)
- return;
-
- for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
- if (opte->opt_private->preauth_data[i].attr != NULL)
- free(opte->opt_private->preauth_data[i].attr);
- if (opte->opt_private->preauth_data[i].value != NULL)
- free(opte->opt_private->preauth_data[i].value);
- }
- free(opte->opt_private->preauth_data);
- opte->opt_private->preauth_data = NULL;
- opte->opt_private->num_preauth_data = 0;
+ /* Give preauth modules a chance to look at the option now. */
+ return krb5_preauth_supply_preauth_data(context, opt, attr, value);
}
/*
@@ -304,41 +200,36 @@ krb5_get_init_creds_opt_get_pa(krb5_context context,
int *num_preauth_data,
krb5_gic_opt_pa_data **preauth_data)
{
- krb5_error_code retval;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
krb5_gic_opt_pa_data *p = NULL;
int i;
size_t allocsize;
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_get_pa");
- if (retval)
- return retval;
-
if (num_preauth_data == NULL || preauth_data == NULL)
return EINVAL;
-
*num_preauth_data = 0;
*preauth_data = NULL;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
- if (opte->opt_private->num_preauth_data == 0)
+ if (opte->num_preauth_data == 0)
return 0;
allocsize =
- opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
+ opte->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
p = malloc(allocsize);
if (p == NULL)
return ENOMEM;
/* Init these to make cleanup easier */
- for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ for (i = 0; i < opte->num_preauth_data; i++) {
p[i].attr = NULL;
p[i].value = NULL;
}
- for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
- p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
- p[i].value = strdup(opte->opt_private->preauth_data[i].value);
+ for (i = 0; i < opte->num_preauth_data; i++) {
+ p[i].attr = strdup(opte->preauth_data[i].attr);
+ p[i].value = strdup(opte->preauth_data[i].value);
if (p[i].attr == NULL || p[i].value == NULL)
goto cleanup;
}
@@ -346,7 +237,7 @@ krb5_get_init_creds_opt_get_pa(krb5_context context,
*preauth_data = p;
return 0;
cleanup:
- for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ for (i = 0; i < opte->num_preauth_data; i++) {
if (p[i].attr != NULL)
free(p[i].attr);
if (p[i].value != NULL)
@@ -384,20 +275,16 @@ krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *ccache_name)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
-
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_fast_ccache_name");
- if (retval)
- return retval;
- if (opte->opt_private->fast_ccache_name) {
- free(opte->opt_private->fast_ccache_name);
- }
- opte->opt_private->fast_ccache_name = strdup(ccache_name);
- if (opte->opt_private->fast_ccache_name == NULL)
- retval = ENOMEM;
- return retval;
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
+ free(opte->fast_ccache_name);
+ opte->fast_ccache_name = strdup(ccache_name);
+ if (opte->fast_ccache_name == NULL)
+ return ENOMEM;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -423,52 +310,73 @@ krb5_get_init_creds_opt_set_fast_ccache(krb5_context context,
return retval;
}
+const char *
+k5_gic_opt_get_fast_ccache_name(krb5_get_init_creds_opt *opt)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return NULL;
+ return opte->fast_ccache_name;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_in_ccache(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_ccache ccache)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_in_ccache");
- if (retval)
- return retval;
- opte->opt_private->in_ccache = ccache;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ opte->in_ccache = ccache;
return 0;
}
+krb5_ccache
+k5_gic_opt_get_in_ccache(krb5_get_init_creds_opt *opt)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return NULL;
+ return opte->in_ccache;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_out_ccache(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_ccache ccache)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_out_ccache");
- if (retval)
- return retval;
- opte->opt_private->out_ccache = ccache;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ opte->out_ccache = ccache;
return 0;
}
+krb5_ccache
+k5_gic_opt_get_out_ccache(krb5_get_init_creds_opt *opt)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return NULL;
+ return opte->out_ccache;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_fast_flags(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_flags flags)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_fast_flags");
- if (retval)
- return retval;
- opte->opt_private->fast_flags = flags;
- return retval;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ opte->fast_flags = flags;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -476,18 +384,25 @@ krb5_get_init_creds_opt_get_fast_flags(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_flags *out_flags)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
if (out_flags == NULL)
return EINVAL;
*out_flags = 0;
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_get_fast_flags");
- if (retval)
- return retval;
- *out_flags = opte->opt_private->fast_flags;
- return retval;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ *out_flags = opte->fast_flags;
+ return 0;
+}
+
+krb5_flags
+k5_gic_opt_get_fast_flags(krb5_get_init_creds_opt *opt)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return 0;
+ return opte->fast_flags;
}
krb5_error_code KRB5_CALLCONV
@@ -496,16 +411,27 @@ krb5_get_init_creds_opt_set_expire_callback(krb5_context context,
krb5_expire_callback_func cb,
void *data)
{
- krb5_error_code retval = 0;
- krb5_gic_opt_ext *opte;
-
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_expire_callback");
- if (retval)
- return retval;
- opte->opt_private->expire_cb = cb;
- opte->opt_private->expire_data = data;
- return retval;
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ opte->expire_cb = cb;
+ opte->expire_data = data;
+ return 0;
+}
+
+void
+k5_gic_opt_get_expire_cb(krb5_get_init_creds_opt *opt,
+ krb5_expire_callback_func *cb_out, void **data_out)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ *cb_out = NULL;
+ *data_out = NULL;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return;
+ *cb_out = opte->expire_cb;
+ *data_out = opte->expire_data;
}
krb5_error_code KRB5_CALLCONV
@@ -513,14 +439,41 @@ krb5_get_init_creds_opt_set_responder(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_responder_fn responder, void *data)
{
- krb5_error_code ret;
- krb5_gic_opt_ext *opte;
+ struct extended_options *opte = (struct extended_options *)opt;
- ret = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_responder");
- if (ret)
- return ret;
- opte->opt_private->responder = responder;
- opte->opt_private->responder_data = data;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return EINVAL;
+ opte->responder = responder;
+ opte->responder_data = data;
return 0;
}
+
+void
+k5_gic_opt_get_responder(krb5_get_init_creds_opt *opt,
+ krb5_responder_fn *responder_out, void **data_out)
+{
+ struct extended_options *opte = (struct extended_options *)opt;
+
+ *responder_out = NULL;
+ *data_out = NULL;
+ if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
+ return;
+ *responder_out = opte->responder;
+ *data_out = opte->responder_data;
+}
+
+krb5_get_init_creds_opt *
+k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt)
+{
+ struct extended_options *opte;
+
+ opte = calloc(1, sizeof(*opte));
+ if (opt == NULL)
+ opte->opt.flags = DEFAULT_FLAGS;
+ else if (opt->flags & GIC_OPT_EXTENDED)
+ *opte = *(struct extended_options *)opt;
+ else
+ opte->opt = *opt;
+ opte->opt.flags |= GIC_OPT_SHALLOW_COPY;
+ return (krb5_get_init_creds_opt *)opte;
+}
diff --git a/src/lib/krb5/krb/gic_opt_set_pa.c b/src/lib/krb5/krb/gic_opt_set_pa.c
deleted file mode 100644
index d44780599..000000000
--- a/src/lib/krb5/krb/gic_opt_set_pa.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright 1995, 2003, 2008 by the Massachusetts Institute of Technology. All
- * Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * krb5_get_init_creds_opt_set_pa()
- * krb5_preauth_supply_preauth_data()
- */
-
-#include "k5-int.h"
-#include "int-proto.h"
-
-static krb5_error_code
-add_gic_opt_ext_preauth_data(krb5_context context,
- krb5_gic_opt_ext *opte,
- const char *attr,
- const char *value)
-{
- size_t newsize;
- int i;
- krb5_gic_opt_pa_data *newpad;
-
- newsize = opte->opt_private->num_preauth_data + 1;
- newsize = newsize * sizeof(*opte->opt_private->preauth_data);
- if (opte->opt_private->preauth_data == NULL)
- newpad = malloc(newsize);
- else
- newpad = realloc(opte->opt_private->preauth_data, newsize);
- if (newpad == NULL)
- return ENOMEM;
- opte->opt_private->preauth_data = newpad;
-
- i = opte->opt_private->num_preauth_data;
- newpad[i].attr = strdup(attr);
- if (newpad[i].attr == NULL)
- return ENOMEM;
- newpad[i].value = strdup(value);
- if (newpad[i].value == NULL) {
- free(newpad[i].attr);
- return ENOMEM;
- }
- opte->opt_private->num_preauth_data += 1;
- return 0;
-}
-
-/*
- * This function allows the caller to supply options to preauth
- * plugins. Preauth plugin modules are given a chance to look
- * at each option at the time this function is called in ordre
- * to check the validity of the option.
- * The 'opt' pointer supplied to this function must have been
- * obtained using krb5_get_init_creds_opt_alloc()
- */
-krb5_error_code KRB5_CALLCONV
-krb5_get_init_creds_opt_set_pa(krb5_context context,
- krb5_get_init_creds_opt *opt,
- const char *attr,
- const char *value)
-{
- krb5_error_code retval;
- krb5_gic_opt_ext *opte;
-
- retval = k5_gic_opt_to_opte(context, opt, &opte, 0,
- "krb5_get_init_creds_opt_set_pa");
- if (retval)
- return retval;
-
- /*
- * Copy the option into the extended get_init_creds_opt structure
- */
- retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
- if (retval)
- return retval;
-
- /*
- * Give the plugins a chance to look at the option now.
- */
- retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
- return retval;
-}
diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
index 6aec7c3a7..e95673fe4 100644
--- a/src/lib/krb5/krb/gic_pwd.c
+++ b/src/lib/krb5/krb/gic_pwd.c
@@ -178,21 +178,19 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
const char *in_tkt_service, krb5_kdc_rep *as_reply)
{
krb5_error_code ret;
+ krb5_expire_callback_func expire_cb;
+ void *expire_data;
krb5_timestamp pw_exp, acct_exp, now;
krb5_boolean is_last_req;
krb5_deltat delta;
- krb5_gic_opt_ext *opte;
char ts[256], banner[1024];
get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req);
- ret = k5_gic_opt_to_opte(context, options, &opte, 0, "");
- if (ret == 0 && opte->opt_private->expire_cb != NULL) {
- krb5_expire_callback_func cb = opte->opt_private->expire_cb;
- void *cb_data = opte->opt_private->expire_data;
-
+ k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data);
+ if (expire_cb != NULL) {
/* Invoke the expire callback and don't send prompter warnings. */
- (*cb)(context, cb_data, pw_exp, acct_exp, is_last_req);
+ (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req);
return;
}
@@ -249,31 +247,20 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
* resulting ticket or how it is stored. Set lifetime and flags appropriate
* for a ticket which we will use immediately and then discard.
*
- * storage1 and storage2 will be used to hold the temporary options. The
- * caller must not free the result, as it will contain aliases into the
- * application options.
+ * The caller should free the result with free().
*/
-static krb5_get_init_creds_opt *
-make_chpw_options(krb5_get_init_creds_opt *in, krb5_gic_opt_ext *storage1,
- gic_opt_private *storage2)
+static krb5_error_code
+make_chpw_options(krb5_context context, krb5_get_init_creds_opt *in,
+ krb5_get_init_creds_opt **out)
{
- krb5_gic_opt_ext *in_ext;
krb5_get_init_creds_opt *opt;
- /* Copy the application's options to storage. */
- if (in == NULL) {
- storage1->flags = 0;
- } else if (gic_opt_is_extended(in)) {
- in_ext = (krb5_gic_opt_ext *)in;
- *storage1 = *in_ext;
- *storage2 = *in_ext->opt_private;
- storage1->opt_private = storage2;
- } else {
- *(krb5_get_init_creds_opt *)storage1 = *in;
- }
+ *out = NULL;
+ opt = k5_gic_opt_shallow_copy(in);
+ if (opt == NULL)
+ return ENOMEM;
/* Get a non-forwardable, non-proxiable, short-lifetime ticket. */
- opt = (krb5_get_init_creds_opt *)storage1;
krb5_get_init_creds_opt_set_tkt_life(opt, 5 * 60);
krb5_get_init_creds_opt_set_renew_life(opt, 0);
krb5_get_init_creds_opt_set_forwardable(opt, 0);
@@ -284,10 +271,10 @@ make_chpw_options(krb5_get_init_creds_opt *in, krb5_gic_opt_ext *storage1,
opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
/* The output ccache should only be used for the actual ticket. */
- if (gic_opt_is_extended(opt))
- storage2->out_ccache = NULL;
+ krb5_get_init_creds_opt_set_out_ccache(context, opt, NULL);
- return opt;
+ *out = opt;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -307,8 +294,6 @@ krb5_get_init_creds_password(krb5_context context,
int tries;
krb5_creds chpw_creds;
krb5_get_init_creds_opt *chpw_opts = NULL;
- krb5_gic_opt_ext storage1;
- gic_opt_private storage2;
struct gak_password gakpw;
krb5_data pw0, pw1;
char banner[1024], pw0array[1024], pw1array[1024];
@@ -395,7 +380,9 @@ krb5_get_init_creds_password(krb5_context context,
/* ok, we have an expired password. Give the user a few chances
to change it */
- chpw_opts = make_chpw_options(options, &storage1, &storage2);
+ ret = make_chpw_options(context, options, &chpw_opts);
+ if (ret)
+ goto cleanup;
ret = k5_get_init_creds(context, &chpw_creds, client, prompter, data,
start_time, "kadmin/changepw", chpw_opts,
krb5_get_as_key_password, &gakpw, &use_master,
@@ -511,7 +498,7 @@ cleanup:
if (ret == 0)
warn_pw_expiry(context, options, prompter, data, in_tkt_service,
as_reply);
-
+ free(chpw_opts);
zapfree(gakpw.storage.data, gakpw.storage.length);
memset(pw0array, 0, sizeof(pw0array));
memset(pw1array, 0, sizeof(pw1array));
diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
index 4dbb0e92a..6ecf0966c 100644
--- a/src/lib/krb5/krb/init_creds_ctx.h
+++ b/src/lib/krb5/krb/init_creds_ctx.h
@@ -16,7 +16,8 @@ struct gak_password {
};
struct _krb5_init_creds_context {
- krb5_gic_opt_ext *opte;
+ krb5_get_init_creds_opt *opt;
+ krb5_get_init_creds_opt opt_storage;
char *in_tkt_service;
krb5_prompter_fct prompter;
void *prompter_data;
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 3a139b520..db6fa95ea 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -37,84 +37,6 @@ typedef krb5_error_code
krb5_keyblock *as_key, void *gak_data,
k5_response_items *ritems);
-/*
- * Extending the krb5_get_init_creds_opt structure. The original
- * krb5_get_init_creds_opt structure is defined publicly. The new extended
- * version is private. The original interface assumed a pre-allocated
- * structure which was passed to krb5_get_init_creds_init(). The new interface
- * assumes that the caller will call krb5_get_init_creds_alloc() and
- * krb5_get_init_creds_free().
- *
- * Callers MUST NOT call krb5_get_init_creds_init() after allocating an opts
- * structure using krb5_get_init_creds_alloc(). To do so will introduce memory
- * leaks. Unfortunately, there is no way to enforce this behavior.
- *
- * Two private flags are added for backward compatibility. GIC_OPT_EXTENDED
- * says that the structure was allocated with the new
- * krb5_get_init_creds_opt_alloc() function. GIC_OPT_SHADOWED is set to
- * indicate that the extended structure is a shadow copy of an original
- * krb5_get_init_creds_opt structure. If GIC_OPT_SHADOWED is set after a call
- * to k5_gic_opt_to_opte(), the resulting extended structure should be freed
- * (using krb5_get_init_creds_free). Otherwise, the original structure was
- * already extended and there is no need to free it.
- */
-
-#define GIC_OPT_EXTENDED 0x80000000
-#define GIC_OPT_SHADOWED 0x40000000
-
-#define gic_opt_is_extended(s) ((s) != NULL && ((s)->flags & GIC_OPT_EXTENDED))
-#define gic_opt_is_shadowed(s) ((s) != NULL && ((s)->flags & GIC_OPT_SHADOWED))
-
-typedef struct gic_opt_private_st {
- int num_preauth_data;
- krb5_gic_opt_pa_data *preauth_data;
- char * fast_ccache_name;
- krb5_ccache in_ccache;
- krb5_ccache out_ccache;
- krb5_flags fast_flags;
- krb5_expire_callback_func expire_cb;
- void *expire_data;
- krb5_responder_fn responder;
- void *responder_data;
-} gic_opt_private;
-
-/*
- * On the Mac, ensure that the layout of krb5_gic_opt_ext matches that
- * of krb5_get_init_creds_opt.
- */
-#if TARGET_OS_MAC
-# pragma pack(push,2)
-#endif
-
-typedef struct _krb5_gic_opt_ext {
- krb5_flags flags;
- krb5_deltat tkt_life;
- krb5_deltat renew_life;
- int forwardable;
- int proxiable;
- krb5_enctype *etype_list;
- int etype_list_length;
- krb5_address **address_list;
- krb5_preauthtype *preauth_list;
- int preauth_list_length;
- krb5_data *salt;
- /*
- * Do not change anything above this point in this structure.
- * It is identical to the public krb5_get_init_creds_opt structure.
- * New members must be added below.
- */
- gic_opt_private *opt_private;
-} krb5_gic_opt_ext;
-
-#if TARGET_OS_MAC
-# pragma pack(pop)
-#endif
-
-krb5_error_code
-k5_gic_opt_to_opte(krb5_context context, krb5_get_init_creds_opt *opt,
- krb5_gic_opt_ext **opte, unsigned int force,
- const char *where);
-
krb5_error_code
krb5int_tgtname(krb5_context context, const krb5_data *, const krb5_data *,
krb5_principal *);
@@ -137,9 +59,8 @@ krb5_error_code krb5_ser_authdata_context_init (krb5_context);
krb5_error_code
krb5_preauth_supply_preauth_data(krb5_context context,
- krb5_gic_opt_ext *opte,
- const char *attr,
- const char *value);
+ krb5_get_init_creds_opt *opt,
+ const char *attr, const char *value);
krb5_error_code
clpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver,
@@ -278,7 +199,7 @@ void
k5_reset_preauth_types_tried(krb5_context context);
void
-k5_preauth_prepare_request(krb5_context context, krb5_gic_opt_ext *opte,
+k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
krb5_kdc_req *request);
void
@@ -368,4 +289,37 @@ k5_count_etypes(const krb5_enctype *list);
krb5_error_code
k5_copy_etypes(const krb5_enctype *old_list, krb5_enctype **new_list);
+krb5_ccache
+k5_gic_opt_get_in_ccache(krb5_get_init_creds_opt *opt);
+
+krb5_ccache
+k5_gic_opt_get_out_ccache(krb5_get_init_creds_opt *opt);
+
+const char *
+k5_gic_opt_get_fast_ccache_name(krb5_get_init_creds_opt *opt);
+
+krb5_flags
+k5_gic_opt_get_fast_flags(krb5_get_init_creds_opt *opt);
+
+void
+k5_gic_opt_get_expire_cb(krb5_get_init_creds_opt *opt,
+ krb5_expire_callback_func *cb_out, void **data_out);
+
+void
+k5_gic_opt_get_responder(krb5_get_init_creds_opt *opt,
+ krb5_responder_fn *responder_out, void **data_out);
+
+/*
+ * Make a shallow copy of opt, with all pointer fields aliased, or NULL on an
+ * out-of-memory failure. The caller must free the result with free, and must
+ * not use it with the following functions:
+ *
+ * krb5_get_init_creds_opt_free
+ * krb5_get_init_creds_opt_set_pa
+ * krb5_get_init_creds_opt_set_fast_ccache
+ * krb5_get_init_creds_opt_set_fast_ccache_name
+ */
+krb5_get_init_creds_opt *
+k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt);
+
#endif /* KRB5_INT_FUNC_PROTO__ */
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index f1b364dd9..cda91b908 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -492,7 +492,7 @@ static struct krb5_clpreauth_callbacks_st callbacks = {
* to add support for to the list, but in the future perhaps doing more
* involved things. */
void
-k5_preauth_prepare_request(krb5_context context, krb5_gic_opt_ext *opte,
+k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
krb5_kdc_req *req)
{
struct krb5_preauth_context_st *pctx = context->preauth_context;
@@ -502,7 +502,7 @@ k5_preauth_prepare_request(krb5_context context, krb5_gic_opt_ext *opte,
if (pctx == NULL)
return;
/* Don't modify the enctype list if it's specified in the gic opts. */
- if (opte != NULL && (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))
+ if (opt != NULL && (opt->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))
return;
for (hp = pctx->handles; *hp != NULL; hp++) {
h = *hp;
@@ -586,7 +586,6 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
krb5_preauthtype *out_type)
{
struct krb5_preauth_context_st *pctx = context->preauth_context;
- krb5_get_init_creds_opt *opt = (krb5_get_init_creds_opt *)ctx->opte;
struct errinfo save = EMPTY_ERRINFO;
krb5_pa_data *pa, **pa_ptr, **mod_pa;
krb5_error_code ret = 0;
@@ -614,7 +613,7 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
if (real && already_tried(context, pa->pa_type))
continue;
mod_pa = NULL;
- ret = clpreauth_process(context, h, opt, &callbacks,
+ ret = clpreauth_process(context, h, ctx->opt, &callbacks,
(krb5_clpreauth_rock)ctx, ctx->request,
ctx->inner_request_body,
ctx->encoded_previous_request, pa,
@@ -863,7 +862,6 @@ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
struct krb5_preauth_context_st *pctx = context->preauth_context;
krb5_error_code ret;
krb5_pa_data **mod_pa;
- krb5_get_init_creds_opt *opt = (krb5_get_init_creds_opt *)ctx->opte;
clpreauth_handle h;
int i;
@@ -878,7 +876,7 @@ k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
if (h == NULL)
continue;
mod_pa = NULL;
- ret = clpreauth_tryagain(context, h, opt, &callbacks,
+ ret = clpreauth_tryagain(context, h, ctx->opt, &callbacks,
(krb5_clpreauth_rock)ctx, ctx->request,
ctx->inner_request_body,
ctx->encoded_previous_request,
@@ -901,7 +899,6 @@ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
krb5_pa_data **in_padata)
{
struct krb5_preauth_context_st *pctx = context->preauth_context;
- krb5_get_init_creds_opt *opt = (krb5_get_init_creds_opt *)ctx->opte;
krb5_error_code ret;
krb5_pa_data *pa;
clpreauth_handle h;
@@ -915,7 +912,7 @@ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
h = find_module(pctx->handles, pa->pa_type);
if (h == NULL)
continue;
- ret = clpreauth_prep_questions(context, h, opt, &callbacks,
+ ret = clpreauth_prep_questions(context, h, ctx->opt, &callbacks,
(krb5_clpreauth_rock)ctx,
ctx->request, ctx->inner_request_body,
ctx->encoded_previous_request, pa);
@@ -933,8 +930,8 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
int out_pa_list_size = 0;
krb5_pa_data **out_pa_list = NULL;
krb5_error_code ret;
- krb5_responder_fn responder = ctx->opte->opt_private->responder;
- void *responder_data = ctx->opte->opt_private->responder_data;
+ krb5_responder_fn responder;
+ void *responder_data;
*padata_out = NULL;
*pa_type_out = KRB5_PADATA_NONE;
@@ -978,6 +975,7 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
goto error;
/* Call the responder to answer response items. */
+ k5_gic_opt_get_responder(ctx->opt, &responder, &responder_data);
if (responder != NULL && !k5_response_items_empty(ctx->rctx.items)) {
ret = (*responder)(context, responder_data, &ctx->rctx);
if (ret)
@@ -1003,11 +1001,11 @@ error:
* has just been set
*/
krb5_error_code
-krb5_preauth_supply_preauth_data(krb5_context context, krb5_gic_opt_ext *opte,
+krb5_preauth_supply_preauth_data(krb5_context context,
+ krb5_get_init_creds_opt *opt,
const char *attr, const char *value)
{
struct krb5_preauth_context_st *pctx = context->preauth_context;
- krb5_get_init_creds_opt *opt = (krb5_get_init_creds_opt *)opte;
clpreauth_handle *hp, h;
krb5_error_code ret;
const char *emsg = NULL;