]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add password option to cred store
authorSimo Sorce <simo@redhat.com>
Wed, 16 Sep 2020 19:07:09 +0000 (15:07 -0400)
committerGreg Hudson <ghudson@mit.edu>
Wed, 18 Nov 2020 16:28:19 +0000 (11:28 -0500)
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@mit.edu: squashed commits; rewrote commit message]

ticket: 8962 (new)

src/lib/gssapi/krb5/acquire_cred.c
src/lib/gssapi/krb5/gssapiP_krb5.h
src/tests/gssapi/Makefile.in
src/tests/gssapi/t_credstore.c
src/tests/gssapi/t_credstore.py [new file with mode: 0644]
src/tests/gssapi/t_gssapi.py

index 519abae4362af1b5da05a9d3d7badef5107e0d5c..4270bdf179f1976d6964694b1acfa01be2d4c318 100644 (file)
@@ -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);
index f21a7de12deb315e3c26bca49e8d9a2dffab239b..3214eb9e1be021d768ccf7c47227de53b71c5f18 100644 (file)
@@ -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,
index 828c2b751bd73a7107622a9c6950f1757009a995..23f7d0e9bb05ed01b888f7caa62066f4ed02ed77 100644 (file)
@@ -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)
index 0278581ba6e2ddc51c837f033e68893064657173..1e3636991380aabd2a640f55b13cab5c97ecd9f3 100644 (file)
@@ -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 (file)
index 0000000..ebb79d8
--- /dev/null
@@ -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')
index ecf982604a938684c3951daf44eae0d0820d3bad..ff2e24870d9b4f819882775fadd1f2bee3682c45 100755 (executable)
@@ -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)