krb5 commit: Add password option to cred store

Greg Hudson ghudson at mit.edu
Wed Nov 18 12:06:05 EST 2020


https://github.com/krb5/krb5/commit/f54b49d06cd2e468abb499df1b9d577054a4fb20
commit f54b49d06cd2e468abb499df1b9d577054a4fb20
Author: Simo Sorce <simo at redhat.com>
Date:   Wed Sep 16 15:07:09 2020 -0400

    Add password option to cred store
    
    Add an option for initial creds acquisition via password to
    gss_acquire_cred_from(), storing credentials in a new MEMORY ccache.
    
    Move existing cred store tests from t_gssapi.py to t_credstore.py and
    add new ones for password acquisition.
    
    [ghudson at mit.edu: squashed commits; rewrote commit message]
    
    ticket: 8962 (new)

 src/lib/gssapi/krb5/acquire_cred.c |   26 ++++++++++++++++++-
 src/lib/gssapi/krb5/gssapiP_krb5.h |    1 +
 src/tests/gssapi/Makefile.in       |    1 +
 src/tests/gssapi/t_credstore.c     |    6 +++-
 src/tests/gssapi/t_credstore.py    |   50 ++++++++++++++++++++++++++++++++++++
 src/tests/gssapi/t_gssapi.py       |   21 ---------------
 6 files changed, 81 insertions(+), 24 deletions(-)

diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 519abae..4270bdf 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -1182,6 +1182,8 @@ acquire_cred_from(OM_uint32 *minor_status, const gss_name_t desired_name,
     krb5_keytab keytab = NULL;
     krb5_ccache ccache = NULL;
     const char *rcname, *value;
+    gss_buffer_desc pwbuf;
+    gss_buffer_t password = NULL;
     OM_uint32 ret;
 
     code = gss_krb5int_initialize_library();
@@ -1241,7 +1243,29 @@ acquire_cred_from(OM_uint32 *minor_status, const gss_name_t desired_name,
     if (GSS_ERROR(ret))
         goto out;
 
-    ret = acquire_cred_context(context, minor_status, desired_name, NULL,
+    ret = kg_value_from_cred_store(cred_store, KRB5_CS_PASSWORD_URN, &value);
+    if (GSS_ERROR(ret))
+        goto out;
+
+    if (value) {
+        /* We must be acquiring an initiator cred with an explicit name.  A
+         * password is mutually exclusive with a client keytab or ccache. */
+        if (desired_name == GSS_C_NO_NAME) {
+            ret = GSS_S_BAD_NAME;
+            goto out;
+        }
+        if (cred_usage == GSS_C_ACCEPT || desired_name == GSS_C_NO_NAME ||
+            ccache != NULL || client_keytab != NULL) {
+            *minor_status = (OM_uint32)G_BAD_USAGE;
+            ret = GSS_S_FAILURE;
+            goto out;
+        }
+        pwbuf.length = strlen(value);
+        pwbuf.value = (void *)value;
+        password = &pwbuf;
+    }
+
+    ret = acquire_cred_context(context, minor_status, desired_name, password,
                                time_req, cred_usage, ccache, client_keytab,
                                keytab, rcname, iakerb, output_cred_handle,
                                time_rec);
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index f21a7de..3214eb9 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -1296,6 +1296,7 @@ data_to_gss(krb5_data *input_k5data, gss_buffer_t output_buffer)
 #define KRB5_CS_KEYTAB_URN "keytab"
 #define KRB5_CS_CCACHE_URN "ccache"
 #define KRB5_CS_RCACHE_URN "rcache"
+#define KRB5_CS_PASSWORD_URN "password"
 
 OM_uint32
 kg_value_from_cred_store(gss_const_key_value_set_t cred_store,
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 828c2b7..23f7d0e 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -50,6 +50,7 @@ check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \
 	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
 	$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
+	$(RUNPYTEST) $(srcdir)/t_credstore.py $(PYTESTFLAGS)
 	$(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS)
 	$(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS)
 	$(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS)
diff --git a/src/tests/gssapi/t_credstore.c b/src/tests/gssapi/t_credstore.c
index 0278581..1e36369 100644
--- a/src/tests/gssapi/t_credstore.c
+++ b/src/tests/gssapi/t_credstore.c
@@ -42,7 +42,7 @@ main(int argc, char *argv[])
 {
     OM_uint32 minor, major;
     gss_key_value_set_desc store;
-    gss_name_t name;
+    gss_name_t name = GSS_C_NO_NAME;
     gss_cred_usage_t cred_usage = GSS_C_BOTH;
     gss_OID_set mechs = GSS_C_NO_OID_SET;
     gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
@@ -71,7 +71,9 @@ main(int argc, char *argv[])
     /* Get the principal name. */
     if (*argv == NULL)
         usage();
-    name = import_name(*argv++);
+    if (**argv != '\0')
+        name = import_name(*argv);
+    argv++;
 
     /* Put any remaining arguments into the store. */
     store.elements = calloc(argc, sizeof(struct gss_key_value_element_struct));
diff --git a/src/tests/gssapi/t_credstore.py b/src/tests/gssapi/t_credstore.py
new file mode 100644
index 0000000..ebb79d8
--- /dev/null
+++ b/src/tests/gssapi/t_credstore.py
@@ -0,0 +1,50 @@
+from k5test import *
+
+realm = K5Realm()
+
+mark('gss_store_cred_into() and ccache/keytab')
+storagecache = 'FILE:' + os.path.join(realm.testdir, 'user_store')
+servicekeytab = os.path.join(realm.testdir, 'kt')
+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),
+        'Retrieving %s from FILE:%s' % (service_cs, servicekeytab))
+realm.run(['./t_credstore', '-s', 'p:' + service_cs, 'ccache', storagecache,
+           'keytab', servicekeytab], expected_trace=msgs)
+
+mark('rcache')
+# t_credstore -r should produce a replay error normally, but not with
+# rcache set to "none:".
+output = realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ],
+                   expected_code=1)
+if 'gss_accept_sec_context(2): Request is a replay' not in output:
+    fail('Expected replay error not seen in t_credstore output')
+realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ,
+           'rcache', 'none:'])
+
+# Test password feature.
+mark('password')
+# Must be used with a desired name.
+realm.run(['./t_credstore', '-i', '', 'password', 'pw'],
+          expected_code=1, expected_msg='An invalid name was supplied')
+# Must not be used with a client keytab.
+realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ,
+           'password', 'pw', 'client_keytab', servicekeytab],
+          expected_code=1, expected_msg='Credential usage type is unknown')
+# Must not be used with a ccache.
+realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ,
+           'password', 'pw', 'ccache', storagecache],
+          expected_code=1, expected_msg='Credential usage type is unknown')
+# Must be acquiring initiator credentials.
+realm.run(['./t_credstore', '-a', 'u:' + realm.user_princ, 'password', 'pw'],
+          expected_code=1, expected_msg='Credential usage type is unknown')
+msgs = ('Getting initial credentials for %s' % realm.user_princ,
+        'Storing %s -> %s in MEMORY:' % (realm.user_princ, realm.krbtgt_princ),
+        'Destroying ccache MEMORY:')
+realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password',
+           password('user')], expected_trace=msgs)
+
+success('Credential store tests')
diff --git a/src/tests/gssapi/t_gssapi.py b/src/tests/gssapi/t_gssapi.py
index ecf9826..ff2e248 100755
--- a/src/tests/gssapi/t_gssapi.py
+++ b/src/tests/gssapi/t_gssapi.py
@@ -67,27 +67,6 @@ realm.run(['./t_imp_cred', 'p:service1/andrew', 'service1/abraham'])
 realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1,
           expected_msg=' not found in keytab')
 
-# Test credential store extension.
-tmpccname = 'FILE:' + os.path.join(realm.testdir, 'def_cache')
-realm.env['KRB5CCNAME'] = tmpccname
-storagecache = 'FILE:' + os.path.join(realm.testdir, 'user_store')
-servicekeytab = os.path.join(realm.testdir, 'kt')
-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])
-realm.run(['./t_credstore', '-s', 'p:' + service_cs, 'ccache', storagecache,
-           'keytab', servicekeytab])
-
-# Test rcache feature of cred stores.  t_credstore -r should produce a
-# replay error normally, but not with rcache set to "none:".
-output = realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ],
-                   expected_code=1)
-if 'gss_accept_sec_context(2): Request is a replay' not in output:
-    fail('Expected replay error not seen in t_credstore output')
-realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ,
-           'rcache', 'none:'])
-
 # Verify that we can't acquire acceptor creds without a keytab.
 os.remove(realm.keytab)
 output = realm.run(['./t_accname', 'p:abc'], expected_code=1)


More information about the cvs-krb5 mailing list