krb5 commit: Add an input ccache get_init_creds option

Greg Hudson ghudson at MIT.EDU
Tue Oct 16 19:23:08 EDT 2012


https://github.com/krb5/krb5/commit/ebb41dbb797d7a922aaca9b3c09a3e05c45b5a72
commit ebb41dbb797d7a922aaca9b3c09a3e05c45b5a72
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date:   Mon Jul 23 15:02:37 2012 -0400

    Add an input ccache get_init_creds option
    
    Add a krb5_get_init_creds_opt_set_in_ccache() function.  An input
    ccache may hold configuration data which the client libraries can
    use to influence their decisions.
    
    ticket: 7413 (new)

 doc/appldev/refs/api/index.rst |    1 +
 src/clients/kinit/kinit.c      |   82 +++++++++++++++++++++++++++-------------
 src/include/k5-int.h           |    1 +
 src/include/krb5/krb5.hin      |   19 +++++++++
 src/lib/krb5/krb/gic_opt.c     |   15 +++++++
 src/lib/krb5/libkrb5.exports   |    1 +
 src/lib/krb5_32.def            |    1 +
 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


More information about the cvs-krb5 mailing list