krb5 commit: Add password option to cred store

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/f54b49d06cd2e468abb499df1b9d577054a4fb20
commit f54b49d06cd2e468abb499df1b9d577054a4fb20
Author: Simo Sorce <[email protected]>
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.
    
    [[email protected]: 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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.