krb5 commit: Improve gss_store_cred() behavior
Greg Hudson
ghudson at mit.edu
Mon Sep 13 23:55:07 EDT 2021
https://github.com/krb5/krb5/commit/3f5a348287646d65700854650fe668b9c4249013
commit 3f5a348287646d65700854650fe668b9c4249013
Author: Greg Hudson <ghudson at mit.edu>
Date: Fri Sep 3 11:36:01 2021 -0400
Improve gss_store_cred() behavior
Select an output credential cache using similar logic to kinit. Do
not require the target cache to be initialized.
Try to use the per-thread cache set by gss_krb5_ccache_name() if no
output cache was specified via a cred store.
When the destination is a collection, honor the default_cred flag by
switching the primary cache to the selected output cache. When the
destination is not a collection, ignore the default_cred flag.
(Previously the default_cred flag was mandatory for gss_store_cred()
even though it is an advisory flag, and ignored for
gss_store_cred_into() even if no ccache was specified in the cred
store.)
Honor the overwrite_cred flag by refusing to replace an initialized
cache if it is not set. Stop using gss_acquire_cred() for this
purpose as it could go out and fetch credentials from a client keytab.
Perform atomic replacement of the target cache when possible, using
krb5_cc_move().
Add a test harness for calling gss_store_cred() or
gss_store_cred_into() and a suite of tests. Fix a broken trace log
message for krb5_cc_move() and update the expected trace logs for an
existing t_credstore.py test.
ticket: 8010
.gitignore | 1 +
doc/appdev/gssapi.rst | 15 +++-
src/include/k5-trace.h | 2 +-
src/lib/gssapi/krb5/store_cred.c | 145 +++++++++++++++++--------------------
src/tests/gssapi/Makefile.in | 14 +++--
src/tests/gssapi/t_credstore.py | 4 +-
src/tests/gssapi/t_store_cred.c | 114 ++++++++++++++++++++++++++++++
src/tests/gssapi/t_store_cred.py | 80 +++++++++++++++++++++
8 files changed, 285 insertions(+), 90 deletions(-)
diff --git a/.gitignore b/.gitignore
index 45c8bba..a1ba832 100644
--- a/.gitignore
+++ b/.gitignore
@@ -470,6 +470,7 @@ local.properties
/src/tests/gssapi/t_saslname
/src/tests/gssapi/t_spnego
/src/tests/gssapi/t_srcattrs
+/src/tests/gssapi/t_store_cred
/src/tests/gssapi/t_inq_ctx
/src/tests/hammer/kdc5_hammer
diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst
index d26c9fe..339fd6c 100644
--- a/doc/appdev/gssapi.rst
+++ b/doc/appdev/gssapi.rst
@@ -252,10 +252,8 @@ The following options are supported by the krb5 mechanism:
* **ccache**: For acquiring initiator credentials, the name of the
:ref:`credential cache <ccache_definition>` to which the handle will
- refer. For storing credentials, the name of the cache where the
- credentials should be stored. If a collection name is given, the
- primary cache of the collection will be used; this behavior may
- change in future releases to select a cache from the collection.
+ refer. For storing credentials, the name of the cache or collection
+ where the credentials will be stored (see below).
* **client_keytab**: For acquiring initiator credentials, the name of
the :ref:`keytab <keytab_definition>` which will be used, if
@@ -285,6 +283,15 @@ The following options are supported by the krb5 mechanism:
the empty string. If the empty string is given, any ``host``
service principal in the keytab may be used. (New in release 1.19.)
+In release 1.20 or later, if a collection name is specified for
+**cache** in a call to gss_store_cred_into(), an existing cache for
+the client principal within the collection will be selected, or a new
+cache will be created within the collection. If *overwrite_cred* is
+false and the selected credential cache already exists, a
+**GSS_S_DUPLICATE_ELEMENT** error will be returned. If *default_cred*
+is true, the primary cache of the collection will be switched to the
+selected cache.
+
Importing and exporting credentials
-----------------------------------
diff --git a/src/include/k5-trace.h b/src/include/k5-trace.h
index 79b5a7a..7bf0c45 100644
--- a/src/include/k5-trace.h
+++ b/src/include/k5-trace.h
@@ -119,7 +119,7 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
TRACE(c, "Initializing {ccache} with default princ {princ}", \
cache, princ)
#define TRACE_CC_MOVE(c, src, dst) \
- TRACE(c, "Moving contents of ccache {src} to {dst}", src, dst)
+ TRACE(c, "Moving ccache {ccache} to {ccache}", src, dst)
#define TRACE_CC_NEW_UNIQUE(c, type) \
TRACE(c, "Resolving unique ccache of type {str}", type)
#define TRACE_CC_REMOVE(c, cache, creds) \
diff --git a/src/lib/gssapi/krb5/store_cred.c b/src/lib/gssapi/krb5/store_cred.c
index 96eb1c9..1e168bc 100644
--- a/src/lib/gssapi/krb5/store_cred.c
+++ b/src/lib/gssapi/krb5/store_cred.c
@@ -27,36 +27,6 @@
#include "k5-int.h"
#include "gssapiP_krb5.h"
-static int
-has_unexpired_creds(krb5_gss_cred_id_t kcred,
- const gss_OID desired_mech,
- int default_cred,
- gss_const_key_value_set_t cred_store)
-{
- OM_uint32 major_status, minor;
- gss_name_t cred_name;
- gss_OID_set_desc desired_mechs;
- gss_cred_id_t tmp_cred = GSS_C_NO_CREDENTIAL;
- OM_uint32 time_rec;
-
- desired_mechs.count = 1;
- desired_mechs.elements = (gss_OID)desired_mech;
-
- if (default_cred)
- cred_name = GSS_C_NO_NAME;
- else
- cred_name = (gss_name_t)kcred->name;
-
- major_status = krb5_gss_acquire_cred_from(&minor, cred_name, 0,
- &desired_mechs, GSS_C_INITIATE,
- cred_store, &tmp_cred, NULL,
- &time_rec);
-
- krb5_gss_release_cred(&minor, &tmp_cred);
-
- return (GSS_ERROR(major_status) || time_rec);
-}
-
static OM_uint32
copy_initiator_creds(OM_uint32 *minor_status,
gss_cred_id_t input_cred_handle,
@@ -66,26 +36,19 @@ copy_initiator_creds(OM_uint32 *minor_status,
gss_const_key_value_set_t cred_store)
{
OM_uint32 major_status;
- krb5_error_code code;
+ krb5_error_code ret;
krb5_gss_cred_id_t kcred = NULL;
krb5_context context = NULL;
- krb5_ccache ccache = NULL;
- const char *ccache_name;
+ krb5_ccache cache = NULL, defcache = NULL, mcc = NULL;
+ krb5_principal princ = NULL;
+ krb5_boolean switch_to_cache = FALSE;
+ const char *ccache_name, *deftype;
*minor_status = 0;
- if (!default_cred && cred_store == GSS_C_NO_CRED_STORE) {
- *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP;
- major_status = GSS_S_FAILURE;
- goto cleanup;
- }
-
- code = krb5_gss_init_context(&context);
- if (code != 0) {
- *minor_status = code;
- major_status = GSS_S_FAILURE;
- goto cleanup;
- }
+ ret = krb5_gss_init_context(&context);
+ if (ret)
+ goto kerr_cleanup;
major_status = krb5_gss_validate_cred_1(minor_status,
input_cred_handle,
@@ -101,52 +64,69 @@ copy_initiator_creds(OM_uint32 *minor_status,
goto cleanup;
}
- if (!overwrite_cred &&
- has_unexpired_creds(kcred, desired_mech, default_cred, cred_store)) {
- major_status = GSS_S_DUPLICATE_ELEMENT;
- goto cleanup;
- }
-
major_status = kg_value_from_cred_store(cred_store,
KRB5_CS_CCACHE_URN, &ccache_name);
if (GSS_ERROR(major_status))
goto cleanup;
if (ccache_name != NULL) {
- code = krb5_cc_resolve(context, ccache_name, &ccache);
- if (code != 0) {
- *minor_status = code;
- major_status = GSS_S_FAILURE;
+ ret = krb5_cc_set_default_name(context, ccache_name);
+ if (ret)
+ goto kerr_cleanup;
+ } else {
+ major_status = kg_sync_ccache_name(context, minor_status);
+ if (major_status != GSS_S_COMPLETE)
goto cleanup;
- }
- code = krb5_cc_initialize(context, ccache,
- kcred->name->princ);
- if (code != 0) {
- *minor_status = code;
- major_status = GSS_S_FAILURE;
- goto cleanup;
- }
}
- if (ccache == NULL) {
- if (!default_cred) {
- *minor_status = G_STORE_NON_DEFAULT_CRED_NOSUPP;
- major_status = GSS_S_FAILURE;
+ /* Resolve the default ccache and get its type. */
+ ret = krb5_cc_default(context, &defcache);
+ if (ret)
+ goto kerr_cleanup;
+ deftype = krb5_cc_get_type(context, defcache);
+
+ if (krb5_cc_support_switch(context, deftype)) {
+ /* Use an existing or new cache within the collection. */
+ ret = krb5_cc_cache_match(context, kcred->name->princ, &cache);
+ if (!ret && !overwrite_cred) {
+ major_status = GSS_S_DUPLICATE_ELEMENT;
goto cleanup;
}
- code = krb5int_cc_default(context, &ccache);
- if (code != 0) {
- *minor_status = code;
- major_status = GSS_S_FAILURE;
+ if (ret == KRB5_CC_NOTFOUND)
+ ret = krb5_cc_new_unique(context, deftype, NULL, &cache);
+ if (ret)
+ goto kerr_cleanup;
+ switch_to_cache = default_cred;
+ } else {
+ /* Use the default cache. */
+ cache = defcache;
+ defcache = NULL;
+ ret = krb5_cc_get_principal(context, cache, &princ);
+ krb5_free_principal(context, princ);
+ if (!ret && !overwrite_cred) {
+ major_status = GSS_S_DUPLICATE_ELEMENT;
goto cleanup;
}
}
- code = krb5_cc_copy_creds(context, kcred->ccache, ccache);
- if (code != 0) {
- *minor_status = code;
- major_status = GSS_S_FAILURE;
- goto cleanup;
+ ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc);
+ if (ret)
+ goto kerr_cleanup;
+ ret = krb5_cc_initialize(context, mcc, kcred->name->princ);
+ if (ret)
+ goto kerr_cleanup;
+ ret = krb5_cc_copy_creds(context, kcred->ccache, mcc);
+ if (ret)
+ goto kerr_cleanup;
+ ret = krb5_cc_move(context, mcc, cache);
+ if (ret)
+ goto kerr_cleanup;
+ mcc = NULL;
+
+ if (switch_to_cache) {
+ ret = krb5_cc_switch(context, cache);
+ if (ret)
+ goto kerr_cleanup;
}
*minor_status = 0;
@@ -155,11 +135,20 @@ copy_initiator_creds(OM_uint32 *minor_status,
cleanup:
if (kcred != NULL)
k5_mutex_unlock(&kcred->lock);
- if (ccache != NULL)
- krb5_cc_close(context, ccache);
+ if (defcache != NULL)
+ krb5_cc_close(context, defcache);
+ if (cache != NULL)
+ krb5_cc_close(context, cache);
+ if (mcc != NULL)
+ krb5_cc_destroy(context, mcc);
krb5_free_context(context);
return major_status;
+
+kerr_cleanup:
+ *minor_status = ret;
+ major_status = GSS_S_FAILURE;
+ goto cleanup;
}
OM_uint32 KRB5_CALLCONV
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 23f7d0e..4cac8cb 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -19,7 +19,7 @@ SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \
$(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \
$(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \
$(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \
- $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c
+ $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c $(srcdir)/t_store_cred.c
OBJS= ccinit.o ccrefresh.o common.o reload.o t_accname.o t_add_cred.o \
t_bindings.o t_ccselect.o t_ciflags.o t_context.o t_credstore.o \
@@ -27,7 +27,7 @@ OBJS= ccinit.o ccrefresh.o common.o reload.o t_accname.o t_add_cred.o \
t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o t_inq_ctx.o \
t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o t_oid.o \
t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \
- t_spnego.o t_srcattrs.o
+ t_spnego.o t_srcattrs.o t_store_cred.o
COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
@@ -36,7 +36,7 @@ all: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect t_ciflags \
t_context t_credstore t_enctypes t_err t_export_cred t_export_name \
t_gssexts t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx \
t_inq_mechs_name t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf \
- t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs
+ t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs t_store_cred
check-unix: t_oid reload
$(RUN_TEST) ./t_invalid
@@ -48,8 +48,10 @@ check-unix: t_oid reload
check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \
t_ciflags t_context t_credstore t_enctypes t_err t_export_cred \
t_export_name t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov \
- t_lifetime t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs
+ t_lifetime t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs \
+ t_store_cred
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_store_cred.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_credstore.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS)
$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
@@ -124,6 +126,8 @@ t_spnego: t_spnego.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_spnego.o $(COMMON_LIBS)
t_srcattrs: t_srcattrs.o $(COMMON_DEPS)
$(CC_LINK) -o $@ t_srcattrs.o $(COMMON_LIBS)
+t_store_cred: t_store_cred.o $(COMMON_DEPS)
+ $(CC_LINK) -o $@ t_store_cred.o $(COMMON_LIBS)
clean:
$(RM) ccinit ccrefresh reload t_accname t_add_cred t_bindings
@@ -131,4 +135,4 @@ clean:
$(RM) t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name
$(RM) t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime
$(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5
- $(RM) t_saslname t_spnego t_srcattrs
+ $(RM) t_saslname t_spnego t_srcattrs t_store_cred
diff --git a/src/tests/gssapi/t_credstore.py b/src/tests/gssapi/t_credstore.py
index f666e5e..ec59dd8 100644
--- a/src/tests/gssapi/t_credstore.py
+++ b/src/tests/gssapi/t_credstore.py
@@ -9,8 +9,8 @@ service_cs = 'service/cs@%s' % realm.realm
realm.addprinc(service_cs)
realm.extract_keytab(service_cs, servicekeytab)
realm.kinit(service_cs, None, ['-k', '-t', servicekeytab])
-msgs = ('Storing %s -> %s in %s' % (service_cs, realm.krbtgt_princ,
- storagecache),
+msgs = ('Storing %s -> %s in MEMORY:' % (service_cs, realm.krbtgt_princ),
+ 'Moving ccache MEMORY:',
'Retrieving %s from FILE:%s' % (service_cs, servicekeytab))
realm.run(['./t_credstore', '-s', 'p:' + service_cs, 'ccache', storagecache,
'keytab', servicekeytab], expected_trace=msgs)
diff --git a/src/tests/gssapi/t_store_cred.c b/src/tests/gssapi/t_store_cred.c
new file mode 100644
index 0000000..b053e52
--- /dev/null
+++ b/src/tests/gssapi/t_store_cred.c
@@ -0,0 +1,114 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/gssapi/t_store_cred.c - gss_store_cred() test harness */
+/*
+ * Copyright (C) 2021 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Usage: t_store_cred [-d] [-i] [-o] src_ccname [dest_ccname]
+ *
+ * Acquires creds from src_ccname using gss_acquire_cred_from() and then stores
+ * them, using gss_store_cred_into() if -i is specified or gss_store_cred()
+ * otherwise. If dest_ccname is specified with -i, it is included in the cred
+ * store for the store operation; if it is specified without -i, it is set with
+ * gss_krb5_ccache_name() before the store operation. If -d and/or -o are
+ * specified they set the default_cred and overwrite_cred flags to true
+ * respectively.
+ */
+
+#include "k5-platform.h"
+#include <gssapi/gssapi_ext.h>
+#include "common.h"
+
+int
+main(int argc, char *argv[])
+{
+ OM_uint32 major, minor;
+ gss_key_value_set_desc store;
+ gss_key_value_element_desc elem;
+ gss_cred_id_t cred;
+ krb5_boolean def = FALSE, into = FALSE, overwrite = FALSE;
+ const char *src_ccname, *dest_ccname;
+ int c;
+
+ /* Parse arguments. */
+ while ((c = getopt(argc, argv, "dio")) != -1) {
+ switch (c) {
+ case 'd':
+ def = TRUE;
+ break;
+ case 'i':
+ into = TRUE;
+ break;
+ case 'o':
+ overwrite = TRUE;
+ break;
+ default:
+ abort();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ assert(argc == 1 || argc == 2);
+ src_ccname = argv[0];
+ dest_ccname = argv[1];
+
+ elem.key = "ccache";
+ elem.value = src_ccname;
+ store.count = 1;
+ store.elements = &elem;
+ major = gss_acquire_cred_from(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
+ &mechset_krb5, GSS_C_INITIATE, &store, &cred,
+ NULL, NULL);
+ check_gsserr("acquire_cred", major, minor);
+
+ if (into) {
+ if (dest_ccname != NULL) {
+ elem.key = "ccache";
+ elem.value = dest_ccname;
+ store.count = 1;
+ } else {
+ store.count = 0;
+ }
+ major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, &mech_krb5,
+ overwrite, def, &store, NULL, NULL);
+ check_gsserr("store_cred_into", major, minor);
+ } else {
+ if (dest_ccname != NULL) {
+ major = gss_krb5_ccache_name(&minor, dest_ccname, NULL);
+ check_gsserr("ccache_name", major, minor);
+ }
+ major = gss_store_cred(&minor, cred, GSS_C_INITIATE, &mech_krb5,
+ overwrite, def, NULL, NULL);
+ check_gsserr("store_cred", major, minor);
+ }
+
+ gss_release_cred(&minor, &cred);
+ return 0;
+}
diff --git a/src/tests/gssapi/t_store_cred.py b/src/tests/gssapi/t_store_cred.py
new file mode 100644
index 0000000..00e80cf
--- /dev/null
+++ b/src/tests/gssapi/t_store_cred.py
@@ -0,0 +1,80 @@
+from k5test import *
+
+realm = K5Realm(create_user=False)
+
+alice = 'alice@' + realm.realm
+bob = 'bob@' + realm.realm
+cc_alice = realm.ccache + '.alice'
+cc_bob = realm.ccache + '.bob'
+realm.addprinc(alice)
+realm.addprinc(bob)
+realm.extract_keytab(alice, realm.keytab)
+realm.extract_keytab(bob, realm.keytab)
+realm.kinit(alice, flags=['-k', '-c', cc_alice])
+realm.kinit(bob, flags=['-k', '-c', cc_bob])
+
+mark('FILE, default output ccache')
+realm.run(['./t_store_cred', cc_alice])
+realm.klist(alice)
+# Overwriting should fail by default, whether or not the principal matches.
+realm.run(['./t_store_cred', cc_alice], expected_code=1,
+ expected_msg='The requested credential element already exists')
+realm.run(['./t_store_cred', cc_bob], expected_code=1,
+ expected_msg='The requested credential element already exists')
+# Overwriting should succeed with overwrite_cred set.
+realm.run(['./t_store_cred', '-o', cc_bob])
+realm.klist(bob)
+# default_cred has no effect without a collection.
+realm.run(['./t_store_cred', '-d', '-o', cc_alice])
+realm.klist(alice)
+
+mark('FILE, gss_krb5_ccache_name()')
+cc_alternate = realm.ccache + '.alternate'
+realm.run(['./t_store_cred', cc_alice, cc_alternate])
+realm.klist(alice, ccache=cc_alternate)
+realm.run(['./t_store_cred', cc_bob, cc_alternate], expected_code=1,
+ expected_msg='The requested credential element already exists')
+
+mark('FILE, gss_store_cred_into()')
+os.remove(cc_alternate)
+realm.run(['./t_store_cred', '-i', cc_alice, cc_alternate])
+realm.klist(alice, ccache=cc_alternate)
+realm.run(['./t_store_cred', '-i', cc_bob, cc_alternate], expected_code=1,
+ expected_msg='The requested credential element already exists')
+
+mark('DIR, gss_krb5_ccache_name()')
+cc_dir = 'DIR:' + os.path.join(realm.testdir, 'cc')
+realm.run(['./t_store_cred', cc_alice, cc_dir])
+realm.run([klist, '-c', cc_dir], expected_code=1,
+ expected_msg='No credentials cache found')
+realm.run([klist, '-l', '-c', cc_dir], expected_msg=alice)
+realm.run(['./t_store_cred', cc_alice, cc_dir], expected_code=1,
+ expected_msg='The requested credential element already exists')
+realm.run(['./t_store_cred', '-o', cc_alice, cc_dir])
+realm.run([klist, '-c', cc_dir], expected_code=1,
+ expected_msg='No credentials cache found')
+realm.run([klist, '-l', cc_dir], expected_msg=alice)
+realm.run(['./t_store_cred', '-d', cc_bob, cc_dir])
+# The k5test klist method does not currently work with a collection name.
+realm.run([klist, cc_dir], expected_msg=bob)
+realm.run([klist, '-l', cc_dir], expected_msg=alice)
+realm.run(['./t_store_cred', '-o', '-d', cc_alice, cc_dir])
+realm.run([klist, cc_dir], expected_msg=alice)
+realm.run([kdestroy, '-A', '-c', cc_dir])
+
+mark('DIR, gss_store_cred_into()')
+realm.run(['./t_store_cred', '-i', cc_alice, cc_dir])
+realm.run(['./t_store_cred', '-i', '-d', cc_bob, cc_dir])
+realm.run([klist, cc_dir], expected_msg=bob)
+realm.run([klist, '-l', cc_dir], expected_msg=alice)
+realm.run([kdestroy, '-A', '-c', cc_dir])
+
+mark('DIR, default output ccache')
+realm.ccache = cc_dir
+realm.env['KRB5CCNAME'] = cc_dir
+realm.run(['./t_store_cred', '-i', cc_alice, cc_dir])
+realm.run(['./t_store_cred', '-i', '-d', cc_bob, cc_dir])
+realm.run([klist], expected_msg=bob)
+realm.run([klist, '-l'], expected_msg=alice)
+
+success('gss_store_cred() tests')
More information about the cvs-krb5
mailing list