summaryrefslogtreecommitdiffstats
path: root/src/tests/t_pkinit.py
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2013-07-18 20:46:35 -0400
committerGreg Hudson <ghudson@mit.edu>2013-07-18 20:46:35 -0400
commit2757800b5b0043b635634fad0551d07c112ab54a (patch)
tree6c68be79d6b2c888821bc95787b5428885490109 /src/tests/t_pkinit.py
parenta654a7d9d6145256ce1b01a3f4c80884a8ba93d6 (diff)
downloadkrb5-2757800b5b0043b635634fad0551d07c112ab54a.tar.gz
krb5-2757800b5b0043b635634fad0551d07c112ab54a.tar.xz
krb5-2757800b5b0043b635634fad0551d07c112ab54a.zip
Combine PKINIT test scripts
Diffstat (limited to 'src/tests/t_pkinit.py')
-rw-r--r--src/tests/t_pkinit.py333
1 files changed, 333 insertions, 0 deletions
diff --git a/src/tests/t_pkinit.py b/src/tests/t_pkinit.py
new file mode 100644
index 0000000000..e9915ebd49
--- /dev/null
+++ b/src/tests/t_pkinit.py
@@ -0,0 +1,333 @@
+#!/usr/bin/python
+from k5test import *
+
+# Skip this test if pkinit wasn't built.
+if not os.path.exists(os.path.join(plugins, 'preauth', 'pkinit.so')):
+ success('Warning: not testing pkinit because it is not built')
+ exit(0)
+
+# Check if soft-pkcs11.so is available.
+have_soft_pkcs11 = False
+try:
+ import ctypes
+ lib = ctypes.LibraryLoader(ctypes.CDLL).LoadLibrary('soft-pkcs11.so')
+ del lib
+ have_soft_pkcs11 = True
+except:
+ have_soft_pkcs11 = False
+
+# Construct a krb5.conf fragment configuring pkinit.
+certs = os.path.join(srctop, 'tests', 'dejagnu', 'pkinit-certs')
+ca_pem = os.path.join(certs, 'ca.pem')
+kdc_pem = os.path.join(certs, 'kdc.pem')
+user_pem = os.path.join(certs, 'user.pem')
+privkey_pem = os.path.join(certs, 'privkey.pem')
+privkey_enc_pem = os.path.join(certs, 'privkey-enc.pem')
+user_p12 = os.path.join(certs, 'user.p12')
+user_enc_p12 = os.path.join(certs, 'user-enc.p12')
+path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs')
+path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc')
+
+pkinit_krb5_conf = {
+ 'realms': {'$realm': {
+ 'pkinit_anchors': 'FILE:%s' % ca_pem,
+ 'pkinit_identity': 'FILE:%s,%s' % (kdc_pem, privkey_pem)}}}
+pkinit_kdc_conf = {
+ 'realms': {'$realm': {
+ 'default_principal_flags': '+preauth',
+ 'pkinit_eku_checking': 'none'}}}
+
+file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem)
+file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem)
+dir_identity = 'DIR:%s' % path
+dir_enc_identity = 'DIR:%s' % path_enc
+dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'),
+ os.path.join(path, 'user.key'))
+dir_file_enc_identity = 'FILE:%s,%s' % (os.path.join(path_enc, 'user.crt'),
+ os.path.join(path_enc, 'user.key'))
+p12_identity = 'PKCS12:%s' % user_p12
+p12_enc_identity = 'PKCS12:%s' % user_enc_p12
+p11_identity = 'PKCS11:soft-pkcs11.so'
+p11_token_identity = ('PKCS11:module_name=soft-pkcs11.so:'
+ 'slotid=1:token=SoftToken (token)')
+
+# Set up the DIR: identities. They go away as a side-effect of reinitializing
+# the realm testdir, so we don't have a specific cleanup method.
+def setup_dir_identities(realm):
+ os.mkdir(path)
+ os.mkdir(path_enc)
+ shutil.copy(privkey_pem, os.path.join(path, 'user.key'))
+ shutil.copy(privkey_enc_pem, os.path.join(path_enc, 'user.key'))
+ shutil.copy(user_pem, os.path.join(path, 'user.crt'))
+ shutil.copy(user_pem, os.path.join(path_enc, 'user.crt'))
+
+# Sanity check - password-based preauth should still work.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+realm.run(['./responder',
+ '-r', 'password=%s' % password('user'),
+ 'user@%s' % realm.realm])
+realm.kinit('user@%s' % realm.realm,
+ password=password('user'))
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+restrictive_kdc_conf = {
+ 'realms': {'$realm' : {
+ 'restrict_anonymous_to_tgt': 'true' }}}
+
+# Test anonymous PKINIT.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, create_user=False)
+realm.addprinc('WELLKNOWN/ANONYMOUS')
+realm.kinit('@%s' % realm.realm, flags=['-n'])
+realm.klist('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS')
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# Now try again with anonymous restricted; kvno should fail.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=restrictive_kdc_conf,
+ create_user=False)
+realm.addprinc('WELLKNOWN/ANONYMOUS')
+realm.kinit('@%s' % realm.realm, flags=['-n'])
+# now try FAST
+realm.kinit('@%s' % realm.realm, flags=['-n', '-T', realm.ccache])
+realm.run([kvno, realm.host_princ], expected_code=1)
+realm.stop()
+
+# Run the basic test - PKINIT with FILE: identity, with no password on the key.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+realm.run(['./responder',
+ '-x',
+ 'pkinit={}',
+ '-X',
+ 'X509_user_identity=%s' % file_identity,
+ 'user@%s' % realm.realm])
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % file_identity])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# Run the basic test - PKINIT with FILE: identity, with a password on the key,
+# supplied by the prompter.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+# Expect failure if the responder does nothing, and we have no prompter.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % file_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % file_enc_identity,
+ 'user@%s' % realm.realm],
+ expected_code=2)
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % file_enc_identity],
+ password='encrypted')
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# Run the basic test - PKINIT with FILE: identity, with a password on the key,
+# supplied by the responder.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+# Supply the response in raw form.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % file_enc_identity,
+ '-r',
+ 'pkinit={"%s": "encrypted"}' % file_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % file_enc_identity,
+ 'user@%s' % realm.realm])
+# Supply the response through the convenience API.
+realm.run(['./responder',
+ '-X',
+ 'X509_user_identity=%s' % file_enc_identity,
+ '-p',
+ '%s=%s' % (file_enc_identity, 'encrypted'),
+ 'user@%s' % realm.realm])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with DIR: identity, with no password on the key.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+setup_dir_identities(realm)
+realm.run(['./responder',
+ '-x',
+ 'pkinit={}',
+ '-X',
+ 'X509_user_identity=%s' % dir_identity,
+ 'user@%s' % realm.realm])
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % dir_identity])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with DIR: identity, with a password on the key, supplied by the
+# prompter.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+setup_dir_identities(realm)
+# Expect failure if the responder does nothing, and we have no prompter.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' %
+ dir_file_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % dir_enc_identity,
+ 'user@%s' % realm.realm],
+ expected_code=2)
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % dir_enc_identity],
+ password='encrypted')
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with DIR: identity, with a password on the key, supplied by the
+# responder.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+setup_dir_identities(realm)
+# Supply the response in raw form.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' %
+ dir_file_enc_identity,
+ '-r',
+ 'pkinit={"%s": "encrypted"}' % dir_file_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % dir_enc_identity,
+ 'user@%s' % realm.realm])
+# Supply the response through the convenience API.
+realm.run(['./responder',
+ '-X',
+ 'X509_user_identity=%s' % dir_enc_identity,
+ '-p',
+ '%s=%s' % (dir_file_enc_identity, 'encrypted'),
+ 'user@%s' % realm.realm])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with PKCS12: identity, with no password on the bundle.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+realm.run(['./responder',
+ '-x',
+ 'pkinit={}',
+ '-X',
+ 'X509_user_identity=%s' % p12_identity,
+ 'user@%s' % realm.realm])
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % p12_identity])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with PKCS12: identity, with a password on the bundle, supplied by the
+# prompter.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+# Expect failure if the responder does nothing, and we have no prompter.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % p12_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % p12_enc_identity,
+ 'user@%s' % realm.realm],
+ expected_code=2)
+realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % p12_enc_identity],
+ password='encrypted')
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+# PKINIT with PKCS12: identity, with a password on the bundle, supplied by the
+# responder.
+realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+# Supply the response in raw form.
+realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % p12_enc_identity,
+ '-r',
+ 'pkinit={"%s": "encrypted"}' % p12_enc_identity,
+ '-X',
+ 'X509_user_identity=%s' % p12_enc_identity,
+ 'user@%s' % realm.realm])
+# Supply the response through the convenience API.
+realm.run(['./responder',
+ '-X',
+ 'X509_user_identity=%s' % p12_enc_identity,
+ '-p',
+ '%s=%s' % (p12_enc_identity, 'encrypted'),
+ 'user@%s' % realm.realm])
+realm.klist('user@%s' % realm.realm)
+realm.run([kvno, realm.host_princ])
+realm.stop()
+
+if have_soft_pkcs11:
+ os.environ['SOFTPKCS11RC'] = os.path.join(os.getcwd(), 'testdir',
+ 'soft-pkcs11.rc')
+
+ # PKINIT with PKCS11: identity, with a PIN supplied by the prompter.
+ realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+ conf = open(os.environ['SOFTPKCS11RC'], 'w')
+ conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem,
+ privkey_enc_pem))
+ conf.close()
+ # Expect failure if the responder does nothing, and there's no prompter
+ realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % p11_token_identity,
+ '-X',
+ 'X509_user_identity=%s' % p11_identity,
+ 'user@%s' % realm.realm],
+ expected_code=2)
+ realm.kinit('user@%s' % realm.realm,
+ flags=['-X', 'X509_user_identity=%s' % p11_identity],
+ password='encrypted')
+ realm.klist('user@%s' % realm.realm)
+ realm.run([kvno, realm.host_princ])
+ realm.stop()
+
+ # PKINIT with PKCS11: identity, with a PIN supplied by the responder.
+ realm = K5Realm(krb5_conf=pkinit_krb5_conf, kdc_conf=pkinit_kdc_conf,
+ get_creds=False)
+ conf = open(os.environ['SOFTPKCS11RC'], 'w')
+ conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem,
+ privkey_enc_pem))
+ conf.close()
+ # Supply the response in raw form.
+ realm.run(['./responder',
+ '-x',
+ 'pkinit={"%s": 0}' % p11_token_identity,
+ '-r',
+ 'pkinit={"%s": "encrypted"}' %
+ p11_token_identity,
+ '-X',
+ 'X509_user_identity=%s' % p11_identity,
+ 'user@%s' % realm.realm])
+ # Supply the response through the convenience API.
+ realm.run(['./responder',
+ '-X',
+ 'X509_user_identity=%s' % p11_identity,
+ '-p',
+ '%s=%s' % (p11_token_identity, 'encrypted'),
+ 'user@%s' % realm.realm])
+ realm.klist('user@%s' % realm.realm)
+ realm.run([kvno, realm.host_princ])
+ realm.stop()
+else:
+ output('soft-pkcs11.so not found: skipping tests with PKCS11 identities\n')
+
+success('Authenticated PKINIT')