summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-09-05 16:26:37 +0000
committerGreg Hudson <ghudson@mit.edu>2011-09-05 16:26:37 +0000
commitf784a37909b68b7dfc1eed8c3a0e014639c90e45 (patch)
treefab81e4348cffe5ff453522f76ee49d6f5528cb3
parent319c01a8f523843169b9e5342ac2d085ad67f8a2 (diff)
downloadkrb5-f784a37909b68b7dfc1eed8c3a0e014639c90e45.tar.gz
krb5-f784a37909b68b7dfc1eed8c3a0e014639c90e45.tar.xz
krb5-f784a37909b68b7dfc1eed8c3a0e014639c90e45.zip
Add new cache collection APIs
* krb5_cc_get_full_name retrieves the full type:name of a cache. * krb5_cc_switch makes a cache the primary cache. * krb5_cc_cache_match searches the collection for a client principal. * krb5_free_string releases a string (for the krb5_cc_get_full_name result). All of these are from Heimdal except for krb5_free_string (Heimdal uses krb5_xfree). ticket: 6954 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25155 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/include/k5-int.h1
-rw-r--r--src/include/krb5/krb5.hin69
-rw-r--r--src/lib/krb5/ccache/cc_dir.c25
-rw-r--r--src/lib/krb5/ccache/cc_file.c2
-rw-r--r--src/lib/krb5/ccache/cc_keyring.c2
-rw-r--r--src/lib/krb5/ccache/cc_memory.c1
-rw-r--r--src/lib/krb5/ccache/cc_mslsa.c1
-rw-r--r--src/lib/krb5/ccache/ccbase.c10
-rw-r--r--src/lib/krb5/ccache/cccursor.c44
-rw-r--r--src/lib/krb5/ccache/ccfns.c22
-rw-r--r--src/lib/krb5/krb/kfree.c6
-rw-r--r--src/lib/krb5/libkrb5.exports5
-rw-r--r--src/lib/krb5_32.def5
13 files changed, 193 insertions, 0 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index c153a7e51..0e82ce8a9 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2367,6 +2367,7 @@ struct _krb5_cc_ops {
krb5_timestamp *);
krb5_error_code (KRB5_CALLCONV *lock)(krb5_context, krb5_ccache);
krb5_error_code (KRB5_CALLCONV *unlock)(krb5_context, krb5_ccache);
+ krb5_error_code (KRB5_CALLCONV *switch_to)(krb5_context, krb5_ccache);
};
extern const krb5_cc_ops *krb5_cc_dfl_ops;
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index e594035bb..d1a7c83c6 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -2285,6 +2285,18 @@ typedef struct _krb5_cccol_cursor *krb5_cccol_cursor;
const char * KRB5_CALLCONV
krb5_cc_get_name(krb5_context context, krb5_ccache cache);
+/*
+ * Retrieve the full name of a credential cache.
+ *
+ * @param [in] context Library context
+ * @param [in] cache Credential cache handle
+ * @param [out] fullname_out Full name of cache
+ *
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_full_name(krb5_context context, krb5_ccache cache,
+ char **fullname_out);
+
#if KRB5_DEPRECATED
krb5_error_code KRB5_CALLCONV
krb5_cc_gen_new(krb5_context context, krb5_ccache *cache);
@@ -4393,6 +4405,54 @@ krb5_cc_set_config(krb5_context context, krb5_ccache id,
krb5_boolean KRB5_CALLCONV
krb5_is_config_principal(krb5_context context, krb5_const_principal principal);
+/**
+ * Make a credential cache the primary cache for its collection.
+ *
+ * @param [in] context Library context
+ * @param [in] cache Credential cache handle
+ *
+ * If the type of @a cache supports it, set @a cache to be the primary
+ * credential cache for the collection it belongs to.
+ *
+ * @retval
+ * 0 Success, or the type of @a cache doesn't support switching
+ * @return
+ * Kerberos error codes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_cc_switch(krb5_context context, krb5_ccache cache);
+
+/**
+ * Determine whether a credential cache type supports switching.
+ *
+ * @param [in] context Library context
+ * @param [in] type Credential cache type
+ *
+ * @retval @c TRUE if @a type supports switching
+ * @retval @a FALSE if it does not or is not a valid credential cache type.
+ */
+krb5_boolean KRB5_CALLCONV
+krb5_cc_support_switch(krb5_context context, const char *type);
+
+/**
+ * Find a credential cache with a specified client principal.
+ *
+ * @param [in] context Library context
+ * @param [in] client Client principal
+ * @param [out] cache_out Credential cache handle
+ *
+ * Find a cache within the collection whose default principal is @a client.
+ * Use @a krb5_cc_close to close @a ccache when it is no longer needed.
+ *
+ * @retval 0 Success
+ * @retval KRB5_CC_NOTFOUND
+ *
+ * @sa krb5_cccol_cursor_new
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_cc_cache_match(krb5_context context, krb5_principal client,
+ krb5_ccache *cache_out);
+
/* krb5_free.c */
/**
* Free the storage assigned to a principal.
@@ -4571,6 +4631,15 @@ void KRB5_CALLCONV
krb5_free_unparsed_name(krb5_context context, char *val);
/**
+ * Free a string allocated by a krb5 function.
+ *
+ * @param [in] context Library context
+ * @param [in] val String to be freed
+ */
+void KRB5_CALLCONV
+krb5_free_string(krb5_context context, char *val);
+
+/**
* Free an array of checksum types.
*
* @param [in] context Library context
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
index 1f32c389a..6cd192a71 100644
--- a/src/lib/krb5/ccache/cc_dir.c
+++ b/src/lib/krb5/ccache/cc_dir.c
@@ -672,6 +672,30 @@ dcc_unlock(krb5_context context, krb5_ccache cache)
return krb5_fcc_ops.unlock(context, data->fcc);
}
+static krb5_error_code KRB5_CALLCONV
+dcc_switch_to(krb5_context context, krb5_ccache cache)
+{
+ dcc_data *data = cache->data;
+ char *primary_path = NULL, *dirname = NULL, *filename = NULL;
+ krb5_error_code ret;
+
+ ret = split_path(context, data->residual + 1, &dirname, &filename);
+ if (ret)
+ return ret;
+
+ ret = primary_pathname(dirname, &primary_path);
+ if (ret)
+ goto cleanup;
+
+ ret = write_primary_file(primary_path, filename);
+
+cleanup:
+ free(primary_path);
+ free(dirname);
+ free(filename);
+ return ret;
+}
+
const krb5_cc_ops krb5_dcc_ops = {
0,
"DIR",
@@ -698,6 +722,7 @@ const krb5_cc_ops krb5_dcc_ops = {
NULL, /* wasdefault */
dcc_lock,
dcc_unlock,
+ dcc_switch_to,
};
#endif /* not _WIN32 */
diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c
index aee8a8396..459930932 100644
--- a/src/lib/krb5/ccache/cc_file.c
+++ b/src/lib/krb5/ccache/cc_file.c
@@ -2557,6 +2557,7 @@ const krb5_cc_ops krb5_fcc_ops = {
NULL, /* wasdefault */
krb5_fcc_lock,
krb5_fcc_unlock,
+ NULL, /* switch_to */
};
#if defined(_WIN32)
@@ -2626,4 +2627,5 @@ const krb5_cc_ops krb5_cc_file_ops = {
NULL, /* wasdefault */
krb5_fcc_lock,
krb5_fcc_unlock,
+ NULL, /* switch_to */
};
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index 2c77c3cda..fd1bcec38 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -2073,6 +2073,7 @@ const krb5_cc_ops krb5_krcc_ops = {
NULL, /* wasdefault */
krb5_krcc_lock,
krb5_krcc_unlock,
+ NULL, /* switch_to */
};
#else /* !USE_KEYRING_CCACHE */
@@ -2106,5 +2107,6 @@ const krb5_cc_ops krb5_krcc_ops = {
NULL,
NULL,
NULL,
+ NULL,
};
#endif /* USE_KEYRING_CCACHE */
diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
index 5ce6a0e6c..07d926144 100644
--- a/src/lib/krb5/ccache/cc_memory.c
+++ b/src/lib/krb5/ccache/cc_memory.c
@@ -827,4 +827,5 @@ const krb5_cc_ops krb5_mcc_ops = {
NULL, /* wasdefault */
krb5_mcc_lock,
krb5_mcc_unlock,
+ NULL, /* switch_to */
};
diff --git a/src/lib/krb5/ccache/cc_mslsa.c b/src/lib/krb5/ccache/cc_mslsa.c
index 9727b4fea..600478a15 100644
--- a/src/lib/krb5/ccache/cc_mslsa.c
+++ b/src/lib/krb5/ccache/cc_mslsa.c
@@ -2758,5 +2758,6 @@ const krb5_cc_ops krb5_lcc_ops = {
NULL,
NULL,
NULL,
+ NULL,
};
#endif /* _WIN32 */
diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c
index b330784c9..a1fd3aa83 100644
--- a/src/lib/krb5/ccache/ccbase.c
+++ b/src/lib/krb5/ccache/ccbase.c
@@ -418,6 +418,16 @@ krb5_cc_move(krb5_context context, krb5_ccache src, krb5_ccache dst)
return ret;
}
+krb5_boolean KRB5_CALLCONV
+krb5_cc_support_switch(krb5_context context, const char *type)
+{
+ const krb5_cc_ops *ops;
+ krb5_error_code err;
+
+ err = krb5int_cc_getops(context, type, &ops);
+ return (err ? FALSE : (ops->switch_to != NULL));
+}
+
krb5_error_code
k5_cc_mutex_init(k5_cc_mutex *m)
{
diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c
index 3d9bb7c8b..7bb074938 100644
--- a/src/lib/krb5/ccache/cccursor.c
+++ b/src/lib/krb5/ccache/cccursor.c
@@ -358,3 +358,47 @@ cccol_pertype_next(krb5_context context,
errout:
return ret;
}
+
+krb5_error_code
+krb5_cc_cache_match(krb5_context context, krb5_principal client,
+ krb5_ccache *cache_out)
+{
+ krb5_error_code ret;
+ krb5_cccol_cursor cursor;
+ krb5_ccache cache;
+ krb5_principal princ;
+ char *name;
+ krb5_boolean eq;
+
+ *cache_out = NULL;
+ ret = krb5_cccol_cursor_new(context, &cursor);
+ if (ret)
+ return ret;
+
+ while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 &&
+ cache != NULL) {
+ ret = krb5_cc_get_principal(context, cache, &princ);
+ if (ret == 0) {
+ eq = krb5_principal_compare(context, princ, client);
+ krb5_free_principal(context, princ);
+ if (eq)
+ break;
+ }
+ krb5_cc_close(context, cache);
+ }
+ krb5_cccol_cursor_free(context, &cursor);
+ if (ret)
+ return ret;
+ if (cache == NULL) {
+ ret = krb5_unparse_name(context, client, &name);
+ if (ret == 0) {
+ krb5_set_error_message(context, KRB5_CC_NOTFOUND,
+ _("Can't find client principal %s in "
+ "cache collection"), name);
+ krb5_free_unparsed_name(context, name);
+ }
+ ret = KRB5_CC_NOTFOUND;
+ } else
+ *cache_out = cache;
+ return ret;
+}
diff --git a/src/lib/krb5/ccache/ccfns.c b/src/lib/krb5/ccache/ccfns.c
index b92824d0a..70c607dfb 100644
--- a/src/lib/krb5/ccache/ccfns.c
+++ b/src/lib/krb5/ccache/ccfns.c
@@ -33,6 +33,20 @@ krb5_cc_get_name(krb5_context context, krb5_ccache cache)
}
krb5_error_code KRB5_CALLCONV
+krb5_cc_get_full_name(krb5_context context, krb5_ccache cache,
+ char **fullname_out)
+{
+ char *name;
+
+ *fullname_out = NULL;
+ if (asprintf(&name, "%s:%s", cache->ops->prefix,
+ cache->ops->get_name(context, cache)) < 0)
+ return ENOMEM;
+ *fullname_out = name;
+ return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
krb5_cc_gen_new(krb5_context context, krb5_ccache *cache)
{
TRACE_CC_GEN_NEW(context, cache);
@@ -323,3 +337,11 @@ out:
krb5_free_cred_contents(context, &mcred);
return ret;
}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_switch(krb5_context context, krb5_ccache cache)
+{
+ if (cache->ops->switch_to == NULL)
+ return 0;
+ return cache->ops->switch_to(context, cache);
+}
diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c
index 31e786cd8..72b685759 100644
--- a/src/lib/krb5/krb/kfree.c
+++ b/src/lib/krb5/krb/kfree.c
@@ -522,6 +522,12 @@ krb5_free_unparsed_name(krb5_context context, char *val)
}
void KRB5_CALLCONV
+krb5_free_string(krb5_context context, char *val)
+{
+ free(val);
+}
+
+void KRB5_CALLCONV
krb5_free_sam_challenge(krb5_context ctx, krb5_sam_challenge *sc)
{
if (!sc)
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 20bb6803d..a5b05b5fb 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -183,6 +183,7 @@ krb5_build_principal
krb5_build_principal_alloc_va
krb5_build_principal_ext
krb5_build_principal_va
+krb5_cc_cache_match
krb5_cc_close
krb5_cc_copy_creds
krb5_cc_default
@@ -194,6 +195,7 @@ krb5_cc_end_seq_get
krb5_cc_file_ops
krb5_cc_gen_new
krb5_cc_get_config
+krb5_cc_get_full_name
krb5_cc_get_name
krb5_cc_get_principal
krb5_cc_get_type
@@ -210,6 +212,8 @@ krb5_cc_set_default_name
krb5_cc_set_flags
krb5_cc_start_seq_get
krb5_cc_store_cred
+krb5_cc_support_switch
+krb5_cc_switch
krb5_cccol_cursor_free
krb5_cccol_cursor_new
krb5_cccol_cursor_next
@@ -322,6 +326,7 @@ krb5_free_sam_response
krb5_free_sam_response_2
krb5_free_sam_response_2_contents
krb5_free_sam_response_contents
+krb5_free_string
krb5_free_tgt_creds
krb5_free_ticket
krb5_free_tickets
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
index cff28772a..0afa6e499 100644
--- a/src/lib/krb5_32.def
+++ b/src/lib/krb5_32.def
@@ -412,3 +412,8 @@ EXPORTS
krb5_init_context_profile @386
krb5int_c_mandatory_cksumtype @387 ; PRIVATE GSSAPI
krb5int_arcfour_gsscrypt @388 ; PRIVATE GSSAPI
+ krb5_cc_cache_match @389
+ krb5_cc_get_full_name @390
+ krb5_cc_support_switch @391
+ krb5_cc_switch @392
+ krb5_free_string @393