krb5 commit: Limit use of IAKERB

Greg Hudson ghudson at mit.edu
Mon Aug 10 13:38:01 EDT 2015


https://github.com/krb5/krb5/commit/608a65570aa868d6e03423b5de3b8f82c0bff60b
commit 608a65570aa868d6e03423b5de3b8f82c0bff60b
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Jul 31 12:31:25 2015 -0400

    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

 src/appl/gss-sample/gss-server.c         |   22 ++++++++--
 src/appl/gss-sample/t_gss_sample.py      |   60 ++++++++++++++++++++----------
 src/lib/gssapi/krb5/gssapi_krb5.c        |    1 +
 src/lib/gssapi/mechglue/g_acquire_cred.c |    5 +-
 src/lib/gssapi/spnego/spnego_mech.c      |    5 +-
 5 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c
index 3c116de..c0d0da3 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 f6cd18c..964e3ba 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 aa5c403..0be92e4 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 22be5b4..ff250de 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 9a794ab..8ade245 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,


More information about the cvs-krb5 mailing list