krb5 commit: Add tests for S4U2Self with certificate

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/01319a310cf06e4139b65afb12f998dbea636103
commit 01319a310cf06e4139b65afb12f998dbea636103
Author: Isaac Boukris <[email protected]>
Date:   Thu Jan 17 11:36:46 2019 +0200

    Add tests for S4U2Self with certificate
    
    [[email protected]: fixed memory leaks in test KDB method]
    
    ticket: 8781

 src/plugins/kdb/test/kdb_test.c |   64 +++++++++++++++++++++++++++++++++-
 src/tests/gssapi/t_s4u.py       |   73 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 133 insertions(+), 4 deletions(-)

diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c
index 6df2d58..8118e66 100644
--- a/src/plugins/kdb/test/kdb_test.c
+++ b/src/plugins/kdb/test/kdb_test.c
@@ -423,6 +423,64 @@ cleanup:
     return ret;
 }
 
+static void
+lookup_princ_by_cert(krb5_context context, const krb5_data *client_cert,
+                     krb5_principal *princ)
+{
+    krb5_error_code ret;
+    char *cert_princ_name;
+
+    /* The test client sends a principal string instead of a cert. */
+    cert_princ_name = k5memdup0(client_cert->data, client_cert->length, &ret);
+    check(ret);
+
+    check(krb5_parse_name(context, cert_princ_name, princ));
+    free(cert_princ_name);
+}
+
+static krb5_error_code
+test_get_s4u_x509_principal(krb5_context context, const krb5_data *client_cert,
+                            krb5_const_principal princ, unsigned int flags,
+                            krb5_db_entry **entry)
+{
+    krb5_error_code ret;
+    krb5_principal cert_princ, canon_princ;
+    testhandle h = context->dal_handle->db_context;
+    krb5_boolean match;
+    char *canon, *princ_name;
+
+    lookup_princ_by_cert(context, client_cert, &cert_princ);
+
+    ret = test_get_principal(context, cert_princ, flags, entry);
+    krb5_free_principal(context, cert_princ);
+    if (ret || (flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY))
+        return ret;
+
+    if (!krb5_realm_compare(context, princ, (*entry)->princ))
+        abort();
+
+    if (princ->length == 0 ||
+        krb5_principal_compare(context, princ, (*entry)->princ))
+        return 0;
+
+    check(krb5_unparse_name_flags(context, princ,
+                                  KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+                                  &princ_name));
+    canon = get_string(h, "alias", princ_name, NULL);
+    krb5_free_unparsed_name(context, princ_name);
+    if (canon != NULL &&
+        ((flags & KRB5_KDB_FLAG_ALIAS_OK) ||
+         princ->type == KRB5_NT_ENTERPRISE_PRINCIPAL)) {
+        check(krb5_parse_name(context, canon, &canon_princ));
+        match = krb5_principal_compare(context, canon_princ, (*entry)->princ);
+        krb5_free_principal(context, canon_princ);
+        if (match)
+            return 0;
+    }
+
+    return KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+}
+
 static krb5_error_code
 test_fetch_master_key(krb5_context context, krb5_principal mname,
                       krb5_keyblock *key_out, krb5_kvno *kvno_out,
@@ -535,7 +593,7 @@ test_check_allowed_to_delegate(krb5_context context,
 
 kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_test, kdb_function_table) = {
     KRB5_KDB_DAL_MAJOR_VERSION,             /* major version number */
-    0,                                      /* minor version number 0 */
+    1,                                      /* minor version number */
     test_init,
     test_cleanup,
     test_open,
@@ -569,5 +627,7 @@ kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_test, kdb_function_table) = {
     NULL, /* check_policy_tgs */
     NULL, /* audit_as_req */
     NULL, /* refresh_config */
-    test_check_allowed_to_delegate
+    test_check_allowed_to_delegate,
+    NULL, /* free_principal_e_data */
+    test_get_s4u_x509_principal
 };
diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
index 7aff9af..63183aa 100755
--- a/src/tests/gssapi/t_s4u.py
+++ b/src/tests/gssapi/t_s4u.py
@@ -1,4 +1,6 @@
 from k5test import *
+from base64 import b64encode
+import shutil
 
 realm = K5Realm(create_host=False, get_creds=False)
 usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache')
@@ -159,7 +161,8 @@ for realm in multipass_realms(create_host=False, get_creds=False):
 mark('cross-realm S4U2Self')
 testprincs = {'krbtgt/SREALM': {'keys': 'aes128-cts'},
               'krbtgt/UREALM': {'keys': 'aes128-cts'},
-              'user': {'keys': 'aes128-cts', 'flags': '+preauth'}}
+              'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
+              'other': {'keys': 'aes128-cts'}}
 kdcconf1 = {'realms': {'$realm': {'database_module': 'test'}},
             'dbmodules': {'test': {'db_library': 'test',
                                    'princs': testprincs,
@@ -178,6 +181,8 @@ r1.start_kdc()
 r2.start_kdc()
 r1.extract_keytab(r1.user_princ, r1.keytab)
 r1.kinit(r1.user_princ, None, ['-k', '-t', r1.keytab])
+savefile = r1.ccache + '.save'
+shutil.copyfile(r1.ccache, savefile)
 
 # Include a regression test for #8741 by unsetting the default realm.
 remove_default = {'libdefaults': {'default_realm': None}}
@@ -193,7 +198,7 @@ msgs = ('Getting credentials user@UREALM -> user@SREALM',
 r1.run(['./t_s4u', 'p:' + r2.user_princ, '-', r1.keytab], env=no_default,
        expected_trace=msgs)
 
-# Test realm identification of enterprise principal names ([MS-S4U]
+# Test realm identification of enterprise principal names ([MS-SFU]
 # 3.1.5.1.1.1).  Attach a bogus realm to the enterprise name to verify
 # that we start at the server realm.
 mark('cross-realm S4U2Self with enterprise name')
@@ -209,6 +214,70 @@ msgs = ('Getting initial credentials for enterprise\\@abc@SREALM',
 r1.run(['./t_s4u', 'e:enterprise@abc@NOREALM', '-', r1.keytab],
        expected_trace=msgs)
 
+mark('S4U2Self using X509 certificate')
+
+# Encode name as a PEM certificate file (sort of) for use by kvno.
+def princ_cert(name):
+    enc = b64encode(name.encode('ascii')).decode('ascii')
+    return '-----BEGIN CERTIFICATE-----\n%s\n-----END y\n' % enc
+
+cert_path = os.path.join(r1.testdir, 'fake_cert')
+with open(cert_path, "w") as cert_file:
+    cert_file.write(princ_cert('other'))
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting initial credentials for @SREALM',
+        'Identified realm of client principal as SREALM',
+        'TGS reply is for other@SREALM',
+        'Getting credentials other@SREALM',
+        'Storing other@SREALM')
+r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs)
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting credentials other@SREALM',
+        'TGS reply is for other@SREALM',
+        'Storing other@SREALM')
+r1.run([kvno, '-I', 'other', '-F', cert_path, r1.user_princ],
+       expected_trace=msgs)
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting initial credentials for other@SREALM',
+        'Identified realm of client principal as SREALM',
+        'Getting credentials other@SREALM',
+        'TGS reply is for other@SREALM',
+        'Storing other@SREALM')
+r1.run([kvno, '-U', 'other', '-F', cert_path, r1.user_princ],
+       expected_trace=msgs)
+
+mark('cross-realm S4U2Self using X509 certificate')
+
+with open(cert_path, "w") as cert_file:
+    cert_file.write(princ_cert('user@UREALM'))
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting initial credentials for @SREALM',
+        'Identified realm of client principal as UREALM',
+        'TGS reply is for user@UREALM',
+        'Getting credentials user@UREALM',
+        'Storing user@UREALM')
+r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs)
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting credentials user@UREALM',
+        'TGS reply is for user@UREALM',
+        'Storing user@UREALM')
+r1.run([kvno, '-I', 'user@UREALM', '-F', cert_path, r1.user_princ],
+       expected_trace=msgs)
+
+shutil.copyfile(savefile, r1.ccache)
+msgs = ('Getting initial credentials for enterprise\\@abc@SREALM',
+        'Identified realm of client principal as UREALM',
+        'Getting credentials enterprise\\@abc@UREALM',
+        'TGS reply is for enterprise\\@abc@UREALM',
+        'Storing enterprise\\@abc@UREALM')
+r1.run([kvno, '-U', 'enterprise@abc', '-F', cert_path, r1.user_princ],
+       expected_trace=msgs)
+
 r1.stop()
 r2.stop()
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.