aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/appldev/refs/api/index.rst1
-rw-r--r--src/clients/kinit/kinit.c82
-rw-r--r--src/include/k5-int.h1
-rw-r--r--src/include/krb5/krb5.hin19
-rw-r--r--src/lib/krb5/krb/gic_opt.c15
-rw-r--r--src/lib/krb5/libkrb5.exports1
-rw-r--r--src/lib/krb5_32.def1
7 files changed, 94 insertions, 26 deletions
diff --git a/doc/appldev/refs/api/index.rst b/doc/appldev/refs/api/index.rst
index 26b7f86..cf06d3f 100644
--- a/doc/appldev/refs/api/index.rst
+++ b/doc/appldev/refs/api/index.rst
@@ -47,6 +47,7 @@ Frequently used public interfaces
krb5_get_init_creds_opt_set_fast_ccache_name.rst
krb5_get_init_creds_opt_set_fast_flags.rst
krb5_get_init_creds_opt_set_forwardable.rst
+ krb5_get_init_creds_opt_set_in_ccache.rst
krb5_get_init_creds_opt_set_out_ccache.rst
krb5_get_init_creds_opt_set_pa.rst
krb5_get_init_creds_opt_set_preauth_list.rst
diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c
index a315173..ac204c1 100644
--- a/src/clients/kinit/kinit.c
+++ b/src/clients/kinit/kinit.c
@@ -116,7 +116,8 @@ struct k_opts
char* principal_name;
char* service_name;
char* keytab_name;
- char* k5_cache_name;
+ char* k5_in_cache_name;
+ char* k5_out_cache_name;
char *armor_ccache;
action_type action;
@@ -132,7 +133,7 @@ struct k_opts
struct k5_data
{
krb5_context ctx;
- krb5_ccache cc;
+ krb5_ccache in_cc, out_cc;
krb5_principal me;
char* name;
krb5_boolean switch_to_cache;
@@ -286,8 +287,8 @@ parse_options(argc, argv, opts)
int errflg = 0;
int i;
- while ((i = GETOPT(argc, argv, "r:fpFPn54aAVl:s:c:kit:T:RS:vX:CE"))
- != -1) {
+ while ((i = GETOPT(argc, argv,
+ "r:fpFPn54aAVl:s:c:kit:T:RS:vX:CEI:")) != -1) {
switch (i) {
case 'V':
opts->verbose = 1;
@@ -376,12 +377,20 @@ parse_options(argc, argv, opts)
opts->action = VALIDATE;
break;
case 'c':
- if (opts->k5_cache_name)
+ if (opts->k5_out_cache_name)
{
fprintf(stderr, _("Only one -c option allowed\n"));
errflg++;
} else {
- opts->k5_cache_name = optarg;
+ opts->k5_out_cache_name = optarg;
+ }
+ break;
+ case 'I':
+ if (opts->k5_in_cache_name) {
+ fprintf(stderr, _("Only one -I option allowed\n"));
+ errflg++;
+ } else {
+ opts->k5_in_cache_name = optarg;
}
break;
case 'X':
@@ -467,16 +476,16 @@ k5_begin(opts, k5)
}
}
- if (opts->k5_cache_name) {
- code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc);
+ if (opts->k5_out_cache_name) {
+ code = krb5_cc_resolve(k5->ctx, opts->k5_out_cache_name, &k5->out_cc);
if (code != 0) {
com_err(progname, code, _("resolving ccache %s"),
- opts->k5_cache_name);
+ opts->k5_out_cache_name);
return 0;
}
if (opts->verbose) {
fprintf(stderr, _("Using specified cache: %s\n"),
- opts->k5_cache_name);
+ opts->k5_out_cache_name);
}
} else {
if ((code = krb5_cc_default(k5->ctx, &defcache))) {
@@ -486,7 +495,7 @@ k5_begin(opts, k5)
deftype = krb5_cc_get_type(k5->ctx, defcache);
if (k5->me != NULL && krb5_cc_support_switch(k5->ctx, deftype)) {
/* Use an existing cache for the specified principal if we can. */
- code = krb5_cc_cache_match(k5->ctx, k5->me, &k5->cc);
+ code = krb5_cc_cache_match(k5->ctx, k5->me, &k5->out_cc);
if (code != 0 && code != KRB5_CC_NOTFOUND) {
com_err(progname, code, _("while searching for ccache for %s"),
opts->principal_name);
@@ -494,7 +503,7 @@ k5_begin(opts, k5)
return 0;
}
if (code == KRB5_CC_NOTFOUND) {
- code = krb5_cc_new_unique(k5->ctx, deftype, NULL, &k5->cc);
+ code = krb5_cc_new_unique(k5->ctx, deftype, NULL, &k5->out_cc);
if (code) {
com_err(progname, code, _("while generating new ccache"));
krb5_cc_close(k5->ctx, defcache);
@@ -502,22 +511,34 @@ k5_begin(opts, k5)
}
if (opts->verbose) {
fprintf(stderr, _("Using new cache: %s\n"),
- krb5_cc_get_name(k5->ctx, k5->cc));
+ krb5_cc_get_name(k5->ctx, k5->out_cc));
}
} else if (opts->verbose) {
fprintf(stderr, _("Using existing cache: %s\n"),
- krb5_cc_get_name(k5->ctx, k5->cc));
+ krb5_cc_get_name(k5->ctx, k5->out_cc));
}
krb5_cc_close(k5->ctx, defcache);
k5->switch_to_cache = 1;
} else {
- k5->cc = defcache;
+ k5->out_cc = defcache;
if (opts->verbose) {
fprintf(stderr, _("Using default cache: %s\n"),
- krb5_cc_get_name(k5->ctx, k5->cc));
+ krb5_cc_get_name(k5->ctx, k5->out_cc));
}
}
}
+ if (opts->k5_in_cache_name) {
+ code = krb5_cc_resolve(k5->ctx, opts->k5_in_cache_name, &k5->in_cc);
+ if (code != 0) {
+ com_err(progname, code, _("resolving ccache %s"),
+ opts->k5_in_cache_name);
+ return 0;
+ }
+ if (opts->verbose) {
+ fprintf(stderr, _("Using specified input cache: %s\n"),
+ opts->k5_in_cache_name);
+ }
+ }
if (!k5->me) {
/* No principal name specified */
@@ -563,7 +584,7 @@ k5_begin(opts, k5)
}
} else {
/* Get default principal from cache if one exists */
- code = krb5_cc_get_principal(k5->ctx, k5->cc,
+ code = krb5_cc_get_principal(k5->ctx, k5->out_cc,
&k5->me);
if (code) {
char *name = get_name_from_os();
@@ -603,8 +624,10 @@ k5_end(k5)
krb5_free_unparsed_name(k5->ctx, k5->name);
if (k5->me)
krb5_free_principal(k5->ctx, k5->me);
- if (k5->cc)
- krb5_cc_close(k5->ctx, k5->cc);
+ if (k5->in_cc)
+ krb5_cc_close(k5->ctx, k5->in_cc);
+ if (k5->out_cc)
+ krb5_cc_close(k5->ctx, k5->out_cc);
if (k5->ctx)
krb5_free_context(k5->ctx);
errctx = NULL;
@@ -727,7 +750,14 @@ k5_kinit(opts, k5)
opts->pa_opts[i].value);
}
}
- code = krb5_get_init_creds_opt_set_out_ccache(k5->ctx, options, k5->cc);
+ if (k5->in_cc) {
+ code = krb5_get_init_creds_opt_set_in_ccache(k5->ctx, options,
+ k5->in_cc);
+ if (code)
+ goto cleanup;
+ }
+ code = krb5_get_init_creds_opt_set_out_ccache(k5->ctx, options,
+ k5->out_cc);
if (code)
goto cleanup;
@@ -747,11 +777,11 @@ k5_kinit(opts, k5)
options);
break;
case VALIDATE:
- code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
+ code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->out_cc,
opts->service_name);
break;
case RENEW:
- code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
+ code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->out_cc,
opts->service_name);
break;
}
@@ -780,17 +810,17 @@ k5_kinit(opts, k5)
}
if ((opts->action != INIT_PW) && (opts->action != INIT_KT)) {
- code = krb5_cc_initialize(k5->ctx, k5->cc, opts->canonicalize ?
+ code = krb5_cc_initialize(k5->ctx, k5->out_cc, opts->canonicalize ?
my_creds.client : k5->me);
if (code) {
com_err(progname, code, _("when initializing cache %s"),
- opts->k5_cache_name?opts->k5_cache_name:"");
+ opts->k5_out_cache_name?opts->k5_out_cache_name:"");
goto cleanup;
}
if (opts->verbose)
fprintf(stderr, _("Initialized cache\n"));
- code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);
+ code = krb5_cc_store_cred(k5->ctx, k5->out_cc, &my_creds);
if (code) {
com_err(progname, code, _("while storing credentials"));
goto cleanup;
@@ -801,7 +831,7 @@ k5_kinit(opts, k5)
notix = 0;
if (k5->switch_to_cache) {
- code = krb5_cc_switch(k5->ctx, k5->cc);
+ code = krb5_cc_switch(k5->ctx, k5->out_cc);
if (code) {
com_err(progname, code, _("while switching to new ccache"));
goto cleanup;
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 57a6277..169d6d3 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -1029,6 +1029,7 @@ typedef struct _krb5_gic_opt_private {
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;
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 3deb7a7..e515e8a 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -6820,6 +6820,25 @@ krb5_get_init_creds_opt_set_fast_ccache(krb5_context context,
krb5_ccache ccache);
/**
+ * Set an input credential cache in initial credential options.
+ *
+ * @param [in] context Library context
+ * @param [in] opt Options
+ * @param [in] ccache Credential cache handle
+ *
+ * If an input credential cache is set, then the krb5_get_init_creds family of
+ * APIs will read settings from it. Setting an input ccache is desirable when
+ * the application wishes to perform authentication in the same way (using the
+ * same preauthentication mechanisms, and making the same non-security-
+ * sensitive choices) as the previous authentication attempt, which stored
+ * information in the passed-in ccache.
+ */
+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);
+
+/**
* Set an output credential cache in initial credential options.
*
* @param [in] context Library context
diff --git a/src/lib/krb5/krb/gic_opt.c b/src/lib/krb5/krb/gic_opt.c
index 2580abd..5b0fc83 100644
--- a/src/lib/krb5/krb/gic_opt.c
+++ b/src/lib/krb5/krb/gic_opt.c
@@ -453,6 +453,21 @@ krb5_get_init_creds_opt_set_fast_ccache(krb5_context context,
return retval;
}
+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;
+
+ retval = krb5int_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;
+ return 0;
+}
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_out_ccache(krb5_context context,
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index c1acbce..2fbf5d4 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -369,6 +369,7 @@ krb5_get_init_creds_opt_set_fast_ccache
krb5_get_init_creds_opt_set_fast_ccache_name
krb5_get_init_creds_opt_set_fast_flags
krb5_get_init_creds_opt_set_forwardable
+krb5_get_init_creds_opt_set_in_ccache
krb5_get_init_creds_opt_set_out_ccache
krb5_get_init_creds_opt_set_pa
krb5_get_init_creds_opt_set_preauth_list
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index c31ba0f..c60da00 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -443,3 +443,4 @@ EXPORTS
krb5_responder_otp_set_answer @414
krb5_responder_otp_challenge_free @415
krb5_cc_move @416
+ krb5_get_init_creds_opt_set_in_ccache @417