diff options
Diffstat (limited to 'src/tests/t_kdb.py')
-rwxr-xr-x | src/tests/t_kdb.py | 219 |
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: |