1*7f2fe78bSCy Schubertfrom k5test import * 2*7f2fe78bSCy Schubertimport re 3*7f2fe78bSCy Schubert 4*7f2fe78bSCy Schubertrealm = K5Realm(create_host=False, start_kadmind=True) 5*7f2fe78bSCy Schubert 6*7f2fe78bSCy Schubert# Test password quality enforcement. 7*7f2fe78bSCy Schubertmark('password quality') 8*7f2fe78bSCy Schubertrealm.run([kadminl, 'addpol', '-minlength', '6', '-minclasses', '2', 'pwpol']) 9*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', '-policy', 'pwpol', 'pwuser']) 10*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'sh0rt', 'pwuser'], expected_code=1, 11*7f2fe78bSCy Schubert expected_msg='Password is too short') 12*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'longenough', 'pwuser'], expected_code=1, 13*7f2fe78bSCy Schubert expected_msg='Password does not contain enough character classes') 14*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) 15*7f2fe78bSCy Schubert 16*7f2fe78bSCy Schubert# Test some password history enforcement. Even with no history value, 17*7f2fe78bSCy Schubert# the current password should be denied. 18*7f2fe78bSCy Schubertmark('password history') 19*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, 20*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 21*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '2', 'pwpol']) 22*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'an0therpw', 'pwuser']) 23*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, 24*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 25*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) 26*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) 27*7f2fe78bSCy Schubert 28*7f2fe78bSCy Schubert# Regression test for #929 (kadmind crash with more historical 29*7f2fe78bSCy Schubert# passwords in a principal entry than current policy history setting). 30*7f2fe78bSCy Schubertmark('password history (policy value reduced below current array size)') 31*7f2fe78bSCy Schubertrealm.run([kadminl, 'addpol', '-history', '5', 'histpol']) 32*7f2fe78bSCy Schubertrealm.addprinc('histprinc', 'first') 33*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) 34*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'second', 'histprinc']) 35*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'third', 'histprinc']) 36*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'fourth', 'histprinc']) 37*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '3', 'histpol']) 38*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'fifth', 'histprinc']) 39*7f2fe78bSCy Schubertrealm.run([kadminl, 'delprinc', 'histprinc']) 40*7f2fe78bSCy Schubert 41*7f2fe78bSCy Schubert# Regression test for #2841 (heap buffer overflow when policy history 42*7f2fe78bSCy Schubert# value is reduced to match the number of historical passwords for a 43*7f2fe78bSCy Schubert# principal). 44*7f2fe78bSCy Schubertmark('password history (policy value reduced to current array size)') 45*7f2fe78bSCy Schubertdef histfail(*pwlist): 46*7f2fe78bSCy Schubert for pw in pwlist: 47*7f2fe78bSCy Schubert realm.run([kadminl, 'cpw', '-pw', pw, 'histprinc'], expected_code=1, 48*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 49*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '3', 'histpol']) 50*7f2fe78bSCy Schubertrealm.addprinc('histprinc', '1111') 51*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) 52*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) 53*7f2fe78bSCy Schuberthistfail('2222', '1111') 54*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '2', 'histpol']) 55*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) 56*7f2fe78bSCy Schubert 57*7f2fe78bSCy Schubert# Test that the history array is properly resized if the policy 58*7f2fe78bSCy Schubert# history value is increased after the array is filled. 59*7f2fe78bSCy Schubertmark('password history (policy value increase)') 60*7f2fe78bSCy Schubertrealm.run([kadminl, 'delprinc', 'histprinc']) 61*7f2fe78bSCy Schubertrealm.addprinc('histprinc', '1111') 62*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) 63*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) 64*7f2fe78bSCy Schuberthistfail('2222', '1111') 65*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc'], expected_code=1, 66*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 67*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '1111', 'histprinc'], expected_code=1, 68*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 69*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '3', 'histpol']) 70*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) 71*7f2fe78bSCy Schuberthistfail('3333', '2222', '1111') 72*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '4', 'histpol']) 73*7f2fe78bSCy Schuberthistfail('3333', '2222', '1111') 74*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '4444', 'histprinc']) 75*7f2fe78bSCy Schuberthistfail('4444', '3333', '2222', '1111') 76*7f2fe78bSCy Schubert 77*7f2fe78bSCy Schubert# Test that when the policy history value is reduced, all currently 78*7f2fe78bSCy Schubert# known old passwords still fail until the next password change, after 79*7f2fe78bSCy Schubert# which the new number of old passwords fails (but no more). 80*7f2fe78bSCy Schubertmark('password history (policy value reduction)') 81*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '3', 'histpol']) 82*7f2fe78bSCy Schuberthistfail('4444', '3333', '2222', '1111') 83*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '5555', 'histprinc']) 84*7f2fe78bSCy Schuberthistfail('5555', '3333', '3333') 85*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) 86*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-history', '2', 'histpol']) 87*7f2fe78bSCy Schuberthistfail('2222', '5555', '4444') 88*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) 89*7f2fe78bSCy Schubert 90*7f2fe78bSCy Schubert# Test references to nonexistent policies. 91*7f2fe78bSCy Schubertmark('nonexistent policy references') 92*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', '-policy', 'newpol', 'newuser']) 93*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', 'newuser'], 94*7f2fe78bSCy Schubert expected_msg='Policy: newpol [does not exist]\n') 95*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'newpol', 'pwuser']) 96*7f2fe78bSCy Schubert# pwuser should allow reuse of the current password since newpol doesn't exist. 97*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) 98*7f2fe78bSCy Schubert# Regression test for #8427 (min_life check with nonexistent policy). 99*7f2fe78bSCy Schubertrealm.run([kadmin, '-p', 'pwuser', '-w', '3rdpassword', 'cpw', '-pw', 100*7f2fe78bSCy Schubert '3rdpassword', 'pwuser']) 101*7f2fe78bSCy Schubert 102*7f2fe78bSCy Schubert# Create newpol and verify that it is enforced. 103*7f2fe78bSCy Schubertmark('create referenced policy') 104*7f2fe78bSCy Schubertrealm.run([kadminl, 'addpol', '-minlength', '3', 'newpol']) 105*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', 'pwuser'], expected_msg='Policy: newpol\n') 106*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'], expected_code=1, 107*7f2fe78bSCy Schubert expected_msg='Password is too short') 108*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'], expected_code=1, 109*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 110*7f2fe78bSCy Schubert 111*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', 'newuser'], expected_msg='Policy: newpol\n') 112*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'aa', 'newuser'], expected_code=1, 113*7f2fe78bSCy Schubert expected_msg='Password is too short') 114*7f2fe78bSCy Schubert 115*7f2fe78bSCy Schubert# Delete the policy and verify that it is no longer enforced. 116*7f2fe78bSCy Schubertmark('delete referenced policy') 117*7f2fe78bSCy Schubertrealm.run([kadminl, 'delpol', 'newpol']) 118*7f2fe78bSCy Schubertrealm.run([kadminl, 'getpol', 'newpol'], expected_code=1, 119*7f2fe78bSCy Schubert expected_msg='Policy does not exist') 120*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser']) 121*7f2fe78bSCy Schubert 122*7f2fe78bSCy Schubert# Test basic password lockout support. 123*7f2fe78bSCy Schubertmark('password lockout') 124*7f2fe78bSCy Schubertrealm.stop() 125*7f2fe78bSCy Schubertfor realm in multidb_realms(create_host=False): 126*7f2fe78bSCy Schubert realm.run([kadminl, 'addpol', '-maxfailure', '2', '-failurecountinterval', 127*7f2fe78bSCy Schubert '5m', 'lockout']) 128*7f2fe78bSCy Schubert realm.run([kadminl, 'modprinc', '+requires_preauth', '-policy', 'lockout', 129*7f2fe78bSCy Schubert 'user']) 130*7f2fe78bSCy Schubert 131*7f2fe78bSCy Schubert # kinit twice with the wrong password. 132*7f2fe78bSCy Schubert msg = 'Password incorrect while getting initial credentials' 133*7f2fe78bSCy Schubert realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, 134*7f2fe78bSCy Schubert expected_msg=msg) 135*7f2fe78bSCy Schubert realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, 136*7f2fe78bSCy Schubert expected_msg=msg) 137*7f2fe78bSCy Schubert 138*7f2fe78bSCy Schubert # Now the account should be locked out. 139*7f2fe78bSCy Schubert msg = 'credentials have been revoked while getting initial credentials' 140*7f2fe78bSCy Schubert realm.run([kinit, realm.user_princ], expected_code=1, expected_msg=msg) 141*7f2fe78bSCy Schubert 142*7f2fe78bSCy Schubert # Check that modprinc -unlock allows a further attempt. 143*7f2fe78bSCy Schubert realm.run([kadminl, 'modprinc', '-unlock', 'user']) 144*7f2fe78bSCy Schubert realm.kinit(realm.user_princ, password('user')) 145*7f2fe78bSCy Schubert 146*7f2fe78bSCy Schubert # Make sure a nonexistent policy reference doesn't prevent authentication. 147*7f2fe78bSCy Schubert realm.run([kadminl, 'delpol', 'lockout']) 148*7f2fe78bSCy Schubert realm.kinit(realm.user_princ, password('user')) 149*7f2fe78bSCy Schubert 150*7f2fe78bSCy Schubert# Regression test for issue #7099: databases created prior to krb5 1.3 have 151*7f2fe78bSCy Schubert# multiple history keys, and kadmin prior to 1.7 didn't necessarily use the 152*7f2fe78bSCy Schubert# first one to create history entries. 153*7f2fe78bSCy Schubertmark('#7099 regression test') 154*7f2fe78bSCy Schubertrealm = K5Realm(start_kdc=False) 155*7f2fe78bSCy Schubert# Create a history principal with two keys. 156*7f2fe78bSCy Schubertrealm.run(['./hist', 'make']) 157*7f2fe78bSCy Schubertrealm.run([kadminl, 'addpol', '-history', '2', 'pol']) 158*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'pol', 'user']) 159*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', 'pw2', 'user']) 160*7f2fe78bSCy Schubert# Swap the keys, simulating older kadmin having chosen the second entry. 161*7f2fe78bSCy Schubertrealm.run(['./hist', 'swap']) 162*7f2fe78bSCy Schubert# Make sure we can read the history entry. 163*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-pw', password('user'), 'user'], expected_code=1, 164*7f2fe78bSCy Schubert expected_msg='Cannot reuse password') 165*7f2fe78bSCy Schubert 166*7f2fe78bSCy Schubert# Test key/salt constraints. 167*7f2fe78bSCy Schubertmark('allowedkeysalts') 168*7f2fe78bSCy Schubert 169*7f2fe78bSCy Schubertrealm.stop() 170*7f2fe78bSCy Schubertkrb5_conf1 = {'libdefaults': {'supported_enctypes': 'aes256-cts'}} 171*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=krb5_conf1, create_host=False, get_creds=False) 172*7f2fe78bSCy Schubert 173*7f2fe78bSCy Schubert# Add policy. 174*7f2fe78bSCy Schubertrealm.run([kadminl, 'addpol', '-allowedkeysalts', 'aes256-cts', 'ak']) 175*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) 176*7f2fe78bSCy Schubert 177*7f2fe78bSCy Schubert# Test with one-enctype allowed_keysalts. 178*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-policy', 'ak', 'server']) 179*7f2fe78bSCy Schubertout = realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server'], 180*7f2fe78bSCy Schubert expected_code=1) 181*7f2fe78bSCy Schubertif not 'Invalid key/salt tuples' in out: 182*7f2fe78bSCy Schubert fail('allowed_keysalts policy not applied properly') 183*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server']) 184*7f2fe78bSCy Schubert 185*7f2fe78bSCy Schubert# Now test a multi-enctype allowed_keysalts. Test that subsets are allowed, 186*7f2fe78bSCy Schubert# the the complete set is allowed, that order doesn't matter, and that 187*7f2fe78bSCy Schubert# enctypes outside the set are not allowed. 188*7f2fe78bSCy Schubert 189*7f2fe78bSCy Schubert# Test modpol. 190*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-allowedkeysalts', 'aes256-cts,rc4-hmac', 'ak']) 191*7f2fe78bSCy Schubertrealm.run([kadminl, 'getpol', 'ak'], 192*7f2fe78bSCy Schubert expected_msg='Allowed key/salt types: aes256-cts,rc4-hmac') 193*7f2fe78bSCy Schubert 194*7f2fe78bSCy Schubert# Test subsets and full set. 195*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac', 'server']) 196*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server']) 197*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,rc4-hmac', 'server']) 198*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts', 'server']) 199*7f2fe78bSCy Schubert 200*7f2fe78bSCy Schubert# Check that the order we got is the one from the policy. 201*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', '-terse', 'server'], 202*7f2fe78bSCy Schubert expected_msg='2\t1\t6\t18\t0\t1\t6\t23\t0') 203*7f2fe78bSCy Schubert 204*7f2fe78bSCy Schubert# Test partially intersecting sets. 205*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes128-cts', 'server'], 206*7f2fe78bSCy Schubert expected_code=1, expected_msg='Invalid key/salt tuples') 207*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts,aes128-cts', 208*7f2fe78bSCy Schubert 'server'], expected_code=1, expected_msg='Invalid key/salt tuples') 209*7f2fe78bSCy Schubert 210*7f2fe78bSCy Schubert# Test reset of allowedkeysalts. 211*7f2fe78bSCy Schubertrealm.run([kadminl, 'modpol', '-allowedkeysalts', '-', 'ak']) 212*7f2fe78bSCy Schubertout = realm.run([kadminl, 'getpol', 'ak']) 213*7f2fe78bSCy Schubertif 'Allowed key/salt types' in out: 214*7f2fe78bSCy Schubert fail('failed to clear allowedkeysalts') 215*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server']) 216*7f2fe78bSCy Schubert 217*7f2fe78bSCy Schubertsuccess('Policy tests') 218