From: Simo Sorce Date: Wed, 16 Sep 2020 19:07:09 +0000 (-0400) Subject: Add password option to cred store X-Git-Tag: krb5-1.19-beta1~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f54b49d06cd2e468abb499df1b9d577054a4fb20;p=thirdparty%2Fkrb5.git 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@mit.edu: squashed commits; rewrote commit message] ticket: 8962 (new) --- diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c index 519abae436..4270bdf179 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 f21a7de12d..3214eb9e1b 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 828c2b751b..23f7d0e9bb 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 0278581ba6..1e36369913 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 0000000000..ebb79d846d --- /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 ecf982604a..ff2e24870d 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)