From: Greg Hudson Date: Fri, 31 Jul 2015 16:31:25 +0000 (-0400) Subject: Limit use of IAKERB X-Git-Tag: krb5-1.14-alpha1~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F303%2Fhead;p=thirdparty%2Fkrb5.git Limit use of IAKERB Add the GSS_C_MA_NOT_DFLT_MECH attribute to IAKERB, and filter out mechs with that attribute from the SPNEGO and gss_acquire_cred() default mechanisms. Add a -iakerb option to gss-server and pass it when performing IAKERB tests. Also add tests using the wrong password, to verify that gss_acquire_cred_with_password() fails with the wrong password when using SPNEGO. ticket: 8021 --- diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c index 3c116dec17..c0d0da35b9 100644 --- a/src/appl/gss-sample/gss-server.c +++ b/src/appl/gss-sample/gss-server.c @@ -98,6 +98,7 @@ int verbose = 0; * Arguments: * * service_name (r) the ASCII service name + * mech (r) the desired mechanism (or GSS_C_NO_OID) * server_creds (w) the GSS-API service credentials * * Returns: 0 on success, -1 on failure @@ -107,15 +108,19 @@ int verbose = 0; * The service name is imported with gss_import_name, and service * credentials are acquired with gss_acquire_cred. If either opertion * fails, an error message is displayed and -1 is returned; otherwise, - * 0 is returned. + * 0 is returned. If mech is given, credentials are acquired for the + * specified mechanism. */ static int -server_acquire_creds(char *service_name, gss_cred_id_t *server_creds) +server_acquire_creds(char *service_name, gss_OID mech, + gss_cred_id_t *server_creds) { gss_buffer_desc name_buf; gss_name_t server_name; OM_uint32 maj_stat, min_stat; + gss_OID_set_desc mechlist; + gss_OID_set mechs = GSS_C_NO_OID_SET; name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; @@ -126,8 +131,12 @@ server_acquire_creds(char *service_name, gss_cred_id_t *server_creds) return -1; } - maj_stat = gss_acquire_cred(&min_stat, server_name, 0, - GSS_C_NO_OID_SET, GSS_C_ACCEPT, + if (mech != GSS_C_NO_OID) { + mechlist.count = 1; + mechlist.elements = mech; + mechs = &mechlist; + } + maj_stat = gss_acquire_cred(&min_stat, server_name, 0, mechs, GSS_C_ACCEPT, server_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { display_status("acquiring credentials", maj_stat, min_stat); @@ -652,6 +661,7 @@ main(int argc, char **argv) { char *service_name; gss_cred_id_t server_creds; + gss_OID mech = GSS_C_NO_OID; OM_uint32 min_stat; u_short port = 4444; int once = 0; @@ -715,6 +725,8 @@ main(int argc, char **argv) fprintf(stderr, "failed to register keytab\n"); exit(1); } + } else if (strcmp(*argv, "-iakerb") == 0) { + mech = (gss_OID)gss_mech_iakerb; } else break; argc--; @@ -741,7 +753,7 @@ main(int argc, char **argv) service_name = *argv; - if (server_acquire_creds(service_name, &server_creds) < 0) + if (server_acquire_creds(service_name, mech, &server_creds) < 0) return -1; if (do_inetd) { diff --git a/src/appl/gss-sample/t_gss_sample.py b/src/appl/gss-sample/t_gss_sample.py index f6cd18cdaf..964e3ba08f 100755 --- a/src/appl/gss-sample/t_gss_sample.py +++ b/src/appl/gss-sample/t_gss_sample.py @@ -29,18 +29,23 @@ gss_client = os.path.join(appdir, 'gss-client') gss_server = os.path.join(appdir, 'gss-server') # Run a gss-server process and a gss-client process, with additional -# gss-client flags given by options. Verify that gss-client displayed -# the expected output for a successful negotiation, and that we -# obtained credentials for the host service. -def server_client_test(realm, options): +# gss-client flags given by options and additional gss-server flags +# given by server_options. Return the output of gss-client. +def run_client_server(realm, options, server_options, expected_code=0): portstr = str(realm.server_port()) - server = realm.start_server([gss_server, '-port', portstr, 'host'], - 'starting...') - output = realm.run([gss_client, '-port', portstr] + options + - [hostname, 'host', 'testmsg']) - if 'Signature verified.' not in output: - fail('Expected message not seen in gss-client output') + server_args = [gss_server, '-port', portstr] + server_options + ['host'] + server = realm.start_server(server_args, 'starting...') + out = realm.run([gss_client, '-port', portstr] + options + + [hostname, 'host', 'testmsg'], expected_code=expected_code) stop_daemon(server) + return out + +# Run a gss-server and gss-client process, and verify that gss-client +# displayed the expected output for a successful negotiation. +def server_client_test(realm, options, server_options): + out = run_client_server(realm, options, server_options) + if 'Signature verified.' not in out: + fail('Expected message not seen in gss-client output') # Make up a filename to hold user's initial credentials. def ccache_savefile(realm): @@ -55,27 +60,37 @@ def ccache_restore(realm): shutil.copyfile(ccache_savefile(realm), realm.ccache) # Perform a regular (TGS path) test of the server and client. -def tgs_test(realm, options): +def tgs_test(realm, options, server_options=[]): ccache_restore(realm) - server_client_test(realm, options) + server_client_test(realm, options, server_options) realm.klist(realm.user_princ, realm.host_princ) # Perform a test of the server and client with initial credentials # obtained through gss_acquire_cred_with_password(). -def pw_test(realm, options): +def pw_test(realm, options, server_options=[]): if os.path.exists(realm.ccache): os.remove(realm.ccache) - server_client_test(realm, options + ['-user', realm.user_princ, - '-pass', password('user')]) + options = options + ['-user', realm.user_princ, '-pass', password('user')] + server_client_test(realm, options, server_options) if os.path.exists(realm.ccache): fail('gss_acquire_cred_with_password created ccache') +# Perform a test using the wrong password, and make sure that failure +# occurs during the expected operation (gss_init_sec_context() for +# IAKERB, gss_aqcuire_cred_with_password() otherwise). +def wrong_pw_test(realm, options, server_options=[], iakerb=False): + options = options + ['-user', realm.user_princ, '-pass', 'wrongpw'] + out = run_client_server(realm, options, server_options, expected_code=1) + failed_op = 'initializing context' if iakerb else 'acquiring creds' + if 'GSS-API error ' + failed_op not in out: + fail('Expected error not seen in gss-client output') + # Perform a test of the server and client with initial credentials # obtained with the client keytab -def kt_test(realm, options): +def kt_test(realm, options, server_options=[]): if os.path.exists(realm.ccache): os.remove(realm.ccache) - server_client_test(realm, options) + server_client_test(realm, options, server_options) realm.klist(realm.user_princ, realm.host_princ) for realm in multipass_realms(): @@ -83,19 +98,24 @@ for realm in multipass_realms(): tgs_test(realm, ['-krb5']) tgs_test(realm, ['-spnego']) - tgs_test(realm, ['-iakerb']) + tgs_test(realm, ['-iakerb'], ['-iakerb']) # test default (i.e., krb5) mechanism with GSS_C_DCE_STYLE tgs_test(realm, ['-dce']) pw_test(realm, ['-krb5']) pw_test(realm, ['-spnego']) - pw_test(realm, ['-iakerb']) + pw_test(realm, ['-iakerb'], ['-iakerb']) pw_test(realm, ['-dce']) + wrong_pw_test(realm, ['-krb5']) + wrong_pw_test(realm, ['-spnego']) + wrong_pw_test(realm, ['-iakerb'], ['-iakerb'], True) + wrong_pw_test(realm, ['-dce']) + realm.extract_keytab(realm.user_princ, realm.client_keytab) kt_test(realm, ['-krb5']) kt_test(realm, ['-spnego']) - kt_test(realm, ['-iakerb']) + kt_test(realm, ['-iakerb'], ['-iakerb']) kt_test(realm, ['-dce']) success('GSS sample application') diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index aa5c4031b7..0be92e458e 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -749,6 +749,7 @@ krb5_gss_inquire_attrs_for_mech(OM_uint32 *minor_status, if (g_OID_equal(mech, gss_mech_iakerb)) { MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT); + MA_SUPPORTED(GSS_C_MA_NOT_DFLT_MECH); } else if (!g_OID_equal(mech, gss_mech_krb5)) { MA_SUPPORTED(GSS_C_MA_DEPRECATED); } diff --git a/src/lib/gssapi/mechglue/g_acquire_cred.c b/src/lib/gssapi/mechglue/g_acquire_cred.c index 22be5b4717..ff250deca4 100644 --- a/src/lib/gssapi/mechglue/g_acquire_cred.c +++ b/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -136,7 +136,7 @@ OM_uint32 * time_rec; OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; gss_OID_set mechs = GSS_C_NO_OID_SET; gss_OID_set_desc except_attrs; - gss_OID_desc attr_oids[1]; + gss_OID_desc attr_oids[2]; unsigned int i; gss_union_cred_t creds = NULL; @@ -158,7 +158,8 @@ OM_uint32 * time_rec; */ if (desired_mechs == GSS_C_NULL_OID_SET) { attr_oids[0] = *GSS_C_MA_DEPRECATED; - except_attrs.count = 1; + attr_oids[1] = *GSS_C_MA_NOT_DFLT_MECH; + except_attrs.count = 2; except_attrs.elements = attr_oids; major = gss_indicate_mechs_by_attrs(minor_status, GSS_C_NO_OID_SET, &except_attrs, GSS_C_NO_OID_SET, diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index 9a794abdc5..8ade2454ed 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -3013,10 +3013,11 @@ get_available_mechs(OM_uint32 *minor_status, OM_uint32 major_status = GSS_S_COMPLETE, tmpmin; gss_OID_set mechs, goodmechs; gss_OID_set_desc except_attrs; - gss_OID_desc attr_oids[1]; + gss_OID_desc attr_oids[2]; attr_oids[0] = *GSS_C_MA_DEPRECATED; - except_attrs.count = 1; + attr_oids[1] = *GSS_C_MA_NOT_DFLT_MECH; + except_attrs.count = 2; except_attrs.elements = attr_oids; major_status = gss_indicate_mechs_by_attrs(minor_status, GSS_C_NO_OID_SET,