summaryrefslogtreecommitdiff
path: root/src/tests/t_kdb.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/t_kdb.py')
-rwxr-xr-xsrc/tests/t_kdb.py219
1 files changed, 111 insertions, 108 deletions
diff --git a/src/tests/t_kdb.py b/src/tests/t_kdb.py
index 185225afa5a3..217f2cdc3bdc 100755
--- a/src/tests/t_kdb.py
+++ b/src/tests/t_kdb.py
@@ -16,22 +16,27 @@ if (not os.path.exists(os.path.join(plugins, 'kdb', 'kldap.so')) and
if 'SLAPD' not in os.environ and not which('slapd'):
skip_rest('LDAP KDB tests', 'slapd not found')
+slapadd = which('slapadd')
+if not slapadd:
+ skip_rest('LDAP KDB tests', 'slapadd not found')
+
ldapdir = os.path.abspath('ldap')
dbdir = os.path.join(ldapdir, 'ldap')
-slapd_conf = os.path.join(ldapdir, 'slapd.conf')
+slapd_conf = os.path.join(ldapdir, 'slapd.d')
slapd_out = os.path.join(ldapdir, 'slapd.out')
slapd_pidfile = os.path.join(ldapdir, 'pid')
ldap_pwfile = os.path.join(ldapdir, 'pw')
ldap_sock = os.path.join(ldapdir, 'sock')
ldap_uri = 'ldapi://%s/' % ldap_sock.replace(os.path.sep, '%2F')
schema = os.path.join(srctop, 'plugins', 'kdb', 'ldap', 'libkdb_ldap',
- 'kerberos.schema')
+ 'kerberos.openldap.ldif')
top_dn = 'cn=krb5'
admin_dn = 'cn=admin,cn=krb5'
admin_pw = 'admin'
shutil.rmtree(ldapdir, True)
os.mkdir(ldapdir)
+os.mkdir(slapd_conf)
os.mkdir(dbdir)
if 'SLAPD' in os.environ:
@@ -44,32 +49,61 @@ else:
slapd = os.path.join(ldapdir, 'slapd')
shutil.copy(system_slapd, slapd)
-# Find the core schema file if we can.
+def slap_add(ldif):
+ proc = subprocess.Popen([slapadd, '-b', 'cn=config', '-F', slapd_conf],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ (out, dummy) = proc.communicate(ldif)
+ output(out)
+ return proc.wait()
+
+
+# Configure the pid file and some authorization rules we will need for
+# SASL testing.
+if slap_add('dn: cn=config\n'
+ 'objectClass: olcGlobal\n'
+ 'olcPidFile: %s\n'
+ 'olcAuthzRegexp: '
+ '".*uidNumber=%d,cn=peercred,cn=external,cn=auth" "%s"\n'
+ 'olcAuthzRegexp: "uid=digestuser,cn=digest-md5,cn=auth" "%s"\n' %
+ (slapd_pidfile, os.geteuid(), admin_dn, admin_dn)) != 0:
+ skip_rest('LDAP KDB tests', 'slapd basic configuration failed')
+
+# Find a working writable database type, trying mdb (added in OpenLDAP
+# 2.4.27) and bdb (deprecated and sometimes not built due to licensing
+# incompatibilities).
+for dbtype in ('mdb', 'bdb'):
+ # Try to load the module. This could fail if OpenLDAP is built
+ # without module support, so ignore errors.
+ slap_add('dn: cn=module,cn=config\n'
+ 'objectClass: olcModuleList\n'
+ 'olcModuleLoad: back_%s\n' % dbtype)
+
+ dbclass = 'olc%sConfig' % dbtype.capitalize()
+ if slap_add('dn: olcDatabase=%s,cn=config\n'
+ 'objectClass: olcDatabaseConfig\n'
+ 'objectClass: %s\n'
+ 'olcSuffix: %s\n'
+ 'olcRootDN: %s\n'
+ 'olcRootPW: %s\n'
+ 'olcDbDirectory: %s\n' %
+ (dbtype, dbclass, top_dn, admin_dn, admin_pw, dbdir)) == 0:
+ break
+else:
+ skip_rest('LDAP KDB tests', 'could not find working slapd db type')
+
+if slap_add('include: file://%s\n' % schema) != 0:
+ skip_rest('LDAP KDB tests', 'failed to load Kerberos schema')
+
+# Load the core schema if we can.
ldap_homes = ['/etc/ldap', '/etc/openldap', '/usr/local/etc/openldap',
'/usr/local/etc/ldap']
-local_schema_path = '/schema/core.schema'
+local_schema_path = '/schema/core.ldif'
core_schema = next((i for i in imap(lambda x:x+local_schema_path, ldap_homes)
if os.path.isfile(i)), None)
-
-# Make a slapd config file. This is deprecated in OpenLDAP 2.3 and
-# later, but it's easier than using LDIF and slapadd. Include some
-# authz-regexp entries for SASL authentication tests. Load the core
-# schema if we found it, for use in the DIGEST-MD5 test.
-file = open(slapd_conf, 'w')
-file.write('pidfile %s\n' % slapd_pidfile)
-file.write('include %s\n' % schema)
if core_schema:
- file.write('include %s\n' % core_schema)
-file.write('moduleload back_bdb\n')
-file.write('database bdb\n')
-file.write('suffix %s\n' % top_dn)
-file.write('rootdn %s\n' % admin_dn)
-file.write('rootpw %s\n' % admin_pw)
-file.write('directory %s\n' % dbdir)
-file.write('authz-regexp .*uidNumber=%d,cn=peercred,cn=external,cn=auth %s\n' %
- (os.geteuid(), admin_dn))
-file.write('authz-regexp uid=digestuser,cn=digest-md5,cn=auth %s\n' % admin_dn)
-file.close()
+ if slap_add('include: file://%s\n' % core_schema) != 0:
+ core_schema = None
slapd_pid = -1
def kill_slapd():
@@ -80,7 +114,7 @@ def kill_slapd():
atexit.register(kill_slapd)
out = open(slapd_out, 'w')
-subprocess.call([slapd, '-h', ldap_uri, '-f', slapd_conf], stdout=out,
+subprocess.call([slapd, '-h', ldap_uri, '-F', slapd_conf], stdout=out,
stderr=out)
out.close()
pidf = open(slapd_pidfile, 'r')
@@ -167,47 +201,31 @@ if out != 'KRBTEST.COM\n':
# because we're sticking a krbPrincipalAux objectclass onto a subtree
# krbContainer, but it works and it avoids having to load core.schema
# in the test LDAP server.
-out = realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'],
- expected_code=1)
-if 'DN is out of the realm subtree' not in out:
- fail('Unexpected kadmin.local output for out-of-realm dn')
+realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'],
+ expected_code=1, expected_msg='DN is out of the realm subtree')
realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'princ1'])
-out = realm.run([kadminl, 'getprinc', 'princ1'])
-if 'Principal: princ1' not in out:
- fail('Unexpected kadmin.local output after creating princ1')
-out = realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5',
- 'again'], expected_code=1)
-if 'ldap object is already kerberized' not in out:
- fail('Unexpected kadmin.local output trying to re-kerberize DN')
+realm.run([kadminl, 'getprinc', 'princ1'], expected_msg='Principal: princ1')
+realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'again'],
+ expected_code=1, expected_msg='ldap object is already kerberized')
# Check that we can't set linkdn on a non-standalone object.
-out = realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t1,cn=krb5', 'princ1'],
- expected_code=1)
-if 'link information can not be set' not in out:
- fail('Unexpected kadmin.local output trying to set linkdn on princ1')
+realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t1,cn=krb5', 'princ1'],
+ expected_code=1, expected_msg='link information can not be set')
# Create a principal with a specified linkdn.
-out = realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=krb5', 'princ2'],
- expected_code=1)
-if 'DN is out of the realm subtree' not in out:
- fail('Unexpected kadmin.local output for out-of-realm linkdn')
+realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=krb5', 'princ2'],
+ expected_code=1, expected_msg='DN is out of the realm subtree')
realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=t1,cn=krb5', 'princ2'])
# Check that we can't reset linkdn.
-out = realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t2,cn=krb5', 'princ2'],
- expected_code=1)
-if 'kerberos principal is already linked' not in out:
- fail('Unexpected kadmin.local output for re-specified linkdn')
+realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t2,cn=krb5', 'princ2'],
+ expected_code=1, expected_msg='kerberos principal is already linked')
# Create a principal with a specified containerdn.
-out = realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5',
- 'princ3'], expected_code=1)
-if 'DN is out of the realm subtree' not in out:
- fail('Unexpected kadmin.local output for out-of-realm containerdn')
+realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5', 'princ3'],
+ expected_code=1, expected_msg='DN is out of the realm subtree')
realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=t1,cn=krb5',
'princ3'])
-out = realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5',
- 'princ3'], expected_code=1)
-if 'containerdn option not supported' not in out:
- fail('Unexpected kadmin.local output trying to reset containerdn')
+realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5', 'princ3'],
+ expected_code=1, expected_msg='containerdn option not supported')
# Create and modify a ticket policy.
kldaputil(['create_policy', '-maxtktlife', '3hour', '-maxrenewlife', '6hour',
@@ -255,9 +273,8 @@ if out:
kldaputil(['create_policy', 'tktpol2'])
# Try to create a password policy conflicting with a ticket policy.
-out = realm.run([kadminl, 'addpol', 'tktpol2'], expected_code=1)
-if 'Already exists while creating policy "tktpol2"' not in out:
- fail('Expected error not seen in kadmin.local output')
+realm.run([kadminl, 'addpol', 'tktpol2'], expected_code=1,
+ expected_msg='Already exists while creating policy "tktpol2"')
# Try to create a ticket policy conflicting with a password policy.
realm.run([kadminl, 'addpol', 'pwpol'])
@@ -266,16 +283,13 @@ if 'Already exists while creating policy object' not in out:
fail('Expected error not seen in kdb5_ldap_util output')
# Try to use a password policy as a ticket policy.
-out = realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=pwpol', 'princ4'],
- expected_code=1)
-if 'Object class violation' not in out:
- fail('Expected error not seem in kadmin.local output')
+realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=pwpol', 'princ4'],
+ expected_code=1, expected_msg='Object class violation')
# Use a ticket policy as a password policy (CVE-2014-5353). This
# works with a warning; use kadmin.local -q so the warning is shown.
-out = realm.run([kadminl, '-q', 'modprinc -policy tktpol2 princ4'])
-if 'WARNING: policy "tktpol2" does not exist' not in out:
- fail('Expected error not seen in kadmin.local output')
+realm.run([kadminl, '-q', 'modprinc -policy tktpol2 princ4'],
+ expected_msg='WARNING: policy "tktpol2" does not exist')
# Do some basic tests with a KDC against the LDAP module, exercising the
# db_args processing code.
@@ -298,9 +312,8 @@ if 'krbPrincipalAuthInd: otp' not in out:
if 'krbPrincipalAuthInd: radius' not in out:
fail('Expected krbPrincipalAuthInd value not in output')
-out = realm.run([kadminl, 'getstrs', 'authind'])
-if 'require_auth: otp radius' not in out:
- fail('Expected auth indicators value not in output')
+realm.run([kadminl, 'getstrs', 'authind'],
+ expected_msg='require_auth: otp radius')
# Test service principal aliases.
realm.addprinc('canon', password('canon'))
@@ -311,14 +324,11 @@ ldap_modify('dn: krbPrincipalName=canon@KRBTEST.COM,cn=t1,cn=krb5\n'
'-\n'
'add: krbCanonicalName\n'
'krbCanonicalName: canon@KRBTEST.COM\n')
-out = realm.run([kadminl, 'getprinc', 'alias'])
-if 'Principal: canon@KRBTEST.COM\n' not in out:
- fail('Could not fetch canon through alias')
-out = realm.run([kadminl, 'getprinc', 'canon'])
-if 'Principal: canon@KRBTEST.COM\n' not in out:
- fail('Could not fetch canon through canon')
-realm.run([kvno, 'alias'])
-realm.run([kvno, 'canon'])
+realm.run([kadminl, 'getprinc', 'alias'],
+ expected_msg='Principal: canon@KRBTEST.COM\n')
+realm.run([kadminl, 'getprinc', 'canon'],
+ expected_msg='Principal: canon@KRBTEST.COM\n')
+realm.run([kvno, 'alias', 'canon'])
out = realm.run([klist])
if 'alias@KRBTEST.COM\n' not in out or 'canon@KRBTEST.COM' not in out:
fail('After fetching alias and canon, klist is missing one or both')
@@ -334,9 +344,8 @@ ldap_modify('dn: krbPrincipalName=krbtgt/KRBTEST.COM@KRBTEST.COM,'
'-\n'
'add: krbCanonicalName\n'
'krbCanonicalName: krbtgt/KRBTEST.COM@KRBTEST.COM\n')
-out = realm.run([kadminl, 'getprinc', 'tgtalias'])
-if 'Principal: krbtgt/KRBTEST.COM@KRBTEST.COM' not in out:
- fail('Could not fetch krbtgt through tgtalias')
+realm.run([kadminl, 'getprinc', 'tgtalias'],
+ expected_msg='Principal: krbtgt/KRBTEST.COM@KRBTEST.COM')
realm.kinit(realm.user_princ, password('user'))
realm.run([kvno, 'tgtalias'])
realm.klist(realm.user_princ, 'tgtalias@KRBTEST.COM')
@@ -352,9 +361,8 @@ realm.klist(realm.user_princ, 'alias@KRBTEST.COM')
# Test client principal aliases, with and without preauth.
realm.kinit('canon', password('canon'))
-out = realm.kinit('alias', password('canon'), expected_code=1)
-if 'not found in Kerberos database' not in out:
- fail('Wrong error message for kinit to alias without -C flag')
+realm.kinit('alias', password('canon'), expected_code=1,
+ expected_msg='not found in Kerberos database')
realm.kinit('alias', password('canon'), ['-C'])
realm.run([kvno, 'alias'])
realm.klist('canon@KRBTEST.COM', 'alias@KRBTEST.COM')
@@ -413,31 +421,24 @@ realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts,aes128-cts',
'kvnoprinc'])
realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e',
'aes256-cts,aes128-cts', 'kvnoprinc'])
-out = realm.run([kadminl, 'getprinc', 'kvnoprinc'])
-if 'Number of keys: 4' not in out:
- fail('After cpw -keepold, wrong number of keys')
+realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 4')
realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e',
'aes256-cts,aes128-cts', 'kvnoprinc'])
-out = realm.run([kadminl, 'getprinc', 'kvnoprinc'])
-if 'Number of keys: 6' not in out:
- fail('After cpw -keepold, wrong number of keys')
+realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 6')
# Regression test for #8041 (NULL dereference on keyless principals).
realm.run([kadminl, 'addprinc', '-nokey', 'keylessprinc'])
-out = realm.run([kadminl, 'getprinc', 'keylessprinc'])
-if 'Number of keys: 0' not in out:
- fail('Failed to create a principal with no keys')
+realm.run([kadminl, 'getprinc', 'keylessprinc'],
+ expected_msg='Number of keys: 0')
realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,aes128-cts',
'keylessprinc'])
realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e',
'aes256-cts,aes128-cts', 'keylessprinc'])
-out = realm.run([kadminl, 'getprinc', 'keylessprinc'])
-if 'Number of keys: 4' not in out:
- fail('Failed to add keys to keylessprinc')
+realm.run([kadminl, 'getprinc', 'keylessprinc'],
+ expected_msg='Number of keys: 4')
realm.run([kadminl, 'purgekeys', '-all', 'keylessprinc'])
-out = realm.run([kadminl, 'getprinc', 'keylessprinc'])
-if 'Number of keys: 0' not in out:
- fail('After purgekeys -all, keys remain')
+realm.run([kadminl, 'getprinc', 'keylessprinc'],
+ expected_msg='Number of keys: 0')
# Test for 8354 (old password history entries when -keepold is used)
realm.run([kadminl, 'addpol', '-history', '2', 'keepoldpasspol'])
@@ -446,14 +447,20 @@ realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa',
for p in ('bbbb', 'cccc', 'aaaa'):
realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc'])
+if runenv.sizeof_time_t <= 4:
+ skipped('y2038 LDAP test', 'platform has 32-bit time_t')
+else:
+ # Test storage of timestamps after y2038.
+ realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user'])
+ realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n')
+
realm.stop()
# Briefly test dump and load.
dumpfile = os.path.join(realm.testdir, 'dump')
realm.run([kdb5_util, 'dump', dumpfile])
-out = realm.run([kdb5_util, 'load', dumpfile], expected_code=1)
-if 'KDB module requires -update argument' not in out:
- fail('Unexpected error from kdb5_util load without -update')
+realm.run([kdb5_util, 'load', dumpfile], expected_code=1,
+ expected_msg='KDB module requires -update argument')
realm.run([kdb5_util, 'load', '-update', dumpfile])
# Destroy the realm.
@@ -501,14 +508,10 @@ realm.addprinc(realm.user_princ, password('user'))
realm.kinit(realm.user_princ, password('user'))
realm.stop()
# Exercise DB options, which should cause binding to fail.
-out = realm.run([kadminl, '-x', 'sasl_authcid=ab', 'getprinc', 'user'],
- expected_code=1)
-if 'Cannot bind to LDAP server' not in out:
- fail('Expected error not seen in kadmin.local output')
-out = realm.run([kadminl, '-x', 'bindpwd=wrong', 'getprinc', 'user'],
- expected_code=1)
-if 'Cannot bind to LDAP server' not in out:
- fail('Expected error not seen in kadmin.local output')
+realm.run([kadminl, '-x', 'sasl_authcid=ab', 'getprinc', 'user'],
+ expected_code=1, expected_msg='Cannot bind to LDAP server')
+realm.run([kadminl, '-x', 'bindpwd=wrong', 'getprinc', 'user'],
+ expected_code=1, expected_msg='Cannot bind to LDAP server')
realm.run([kdb5_ldap_util, 'destroy', '-f'])
# We could still use tests to exercise: