1*7f2fe78bSCy Schubertfrom k5test import * 2*7f2fe78bSCy Schubertimport random 3*7f2fe78bSCy Schubertimport re 4*7f2fe78bSCy Schubertimport struct 5*7f2fe78bSCy Schubert 6*7f2fe78bSCy Schubert# Convenience constants for use as expected enctypes. defetype is the 7*7f2fe78bSCy Schubert# default enctype for master keys. 8*7f2fe78bSCy Schubertaes256 = 'aes256-cts-hmac-sha1-96' 9*7f2fe78bSCy Schubertaes128 = 'aes128-cts-hmac-sha1-96' 10*7f2fe78bSCy Schubertdes3 = 'des3-cbc-sha1' 11*7f2fe78bSCy Schubertdefetype = aes256 12*7f2fe78bSCy Schubert 13*7f2fe78bSCy Schubertrealm = K5Realm(create_host=False, start_kadmind=True) 14*7f2fe78bSCy Schubertrealm.prep_kadmin() 15*7f2fe78bSCy Schubertstash_file = os.path.join(realm.testdir, 'stash') 16*7f2fe78bSCy Schubert 17*7f2fe78bSCy Schubert# Count the number of principals in the realm. 18*7f2fe78bSCy Schubertnprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) 19*7f2fe78bSCy Schubert 20*7f2fe78bSCy Schubert# List the currently active mkeys and compare against expected 21*7f2fe78bSCy Schubert# results. Each argument must be a sequence of four elements: an 22*7f2fe78bSCy Schubert# expected kvno, an expected enctype, whether the key is expected to 23*7f2fe78bSCy Schubert# have an activation time, and whether the key is expected to be 24*7f2fe78bSCy Schubert# currently active. 25*7f2fe78bSCy Schubertlist_mkeys_re = re.compile(r'^KVNO: (\d+), Enctype: (\S+), ' 26*7f2fe78bSCy Schubert r'(Active on: [^\*]+|No activate time set)( \*)?$') 27*7f2fe78bSCy Schubertdef check_mkey_list(*expected): 28*7f2fe78bSCy Schubert # Split the output of kdb5_util list_mkeys into lines and ignore the first. 29*7f2fe78bSCy Schubert outlines = realm.run([kdb5_util, 'list_mkeys']).splitlines()[1:] 30*7f2fe78bSCy Schubert if len(outlines) != len(expected): 31*7f2fe78bSCy Schubert fail('Unexpected number of list_mkeys output lines') 32*7f2fe78bSCy Schubert for line, ex in zip(outlines, expected): 33*7f2fe78bSCy Schubert m = list_mkeys_re.match(line) 34*7f2fe78bSCy Schubert if not m: 35*7f2fe78bSCy Schubert fail('Unrecognized list_mkeys output line') 36*7f2fe78bSCy Schubert kvno, enctype, act_time, active = m.groups() 37*7f2fe78bSCy Schubert exp_kvno, exp_enctype, exp_act_time_present, exp_active = ex 38*7f2fe78bSCy Schubert if kvno != str(exp_kvno): 39*7f2fe78bSCy Schubert fail('Unexpected master key version') 40*7f2fe78bSCy Schubert if enctype != exp_enctype: 41*7f2fe78bSCy Schubert fail('Unexpected master key enctype') 42*7f2fe78bSCy Schubert if act_time.startswith('Active on: ') != exp_act_time_present: 43*7f2fe78bSCy Schubert fail('Unexpected presence or absence of mkey activation time') 44*7f2fe78bSCy Schubert if (active == ' *') != exp_active: 45*7f2fe78bSCy Schubert fail('Master key unexpectedly active or inactive') 46*7f2fe78bSCy Schubert 47*7f2fe78bSCy Schubert 48*7f2fe78bSCy Schubert# Get the K/M principal. Verify that it has the expected mkvno. Each 49*7f2fe78bSCy Schubert# remaining argument must be a sequence of two elements: an expected 50*7f2fe78bSCy Schubert# key version and an expected enctype. 51*7f2fe78bSCy Schubertkeyline_re = re.compile(r'^Key: vno (\d+), (\S+)$') 52*7f2fe78bSCy Schubertdef check_master_dbent(expected_mkvno, *expected_keys): 53*7f2fe78bSCy Schubert outlines = realm.run([kadminl, 'getprinc', 'K/M']).splitlines() 54*7f2fe78bSCy Schubert mkeyline = [l for l in outlines if l.startswith('MKey: vno ')] 55*7f2fe78bSCy Schubert if len(mkeyline) != 1 or mkeyline[0] != ('MKey: vno %d' % expected_mkvno): 56*7f2fe78bSCy Schubert fail('Unexpected mkvno in K/M DB entry') 57*7f2fe78bSCy Schubert keylines = [l for l in outlines if l.startswith('Key: vno ')] 58*7f2fe78bSCy Schubert if len(keylines) != len(expected_keys): 59*7f2fe78bSCy Schubert fail('Unexpected number of key lines in K/M DB entry') 60*7f2fe78bSCy Schubert for line, ex in zip(keylines, expected_keys): 61*7f2fe78bSCy Schubert m = keyline_re.match(line) 62*7f2fe78bSCy Schubert if not m: 63*7f2fe78bSCy Schubert fail('Unrecognized key line in K/M DB entry') 64*7f2fe78bSCy Schubert kvno, enctype = m.groups() 65*7f2fe78bSCy Schubert exp_kvno, exp_enctype = ex 66*7f2fe78bSCy Schubert if kvno != str(exp_kvno): 67*7f2fe78bSCy Schubert fail('Unexpected key version in K/M DB entry') 68*7f2fe78bSCy Schubert if enctype != exp_enctype: 69*7f2fe78bSCy Schubert fail('Unexpected enctype in K/M DB entry') 70*7f2fe78bSCy Schubert 71*7f2fe78bSCy Schubert 72*7f2fe78bSCy Schubert# Check the stash file. Each argument must be a sequence of two 73*7f2fe78bSCy Schubert# elements: an expected key version and an expected enctype. 74*7f2fe78bSCy Schubertklist_re = re.compile(r'^\s*(\d+) K/M@KRBTEST.COM \((\S+)\)') 75*7f2fe78bSCy Schubertdef check_stash(*expected): 76*7f2fe78bSCy Schubert # Split the output of klist -e -k into lines and ignore the first three. 77*7f2fe78bSCy Schubert outlines = realm.run([klist, '-e', '-k', stash_file]).splitlines()[3:] 78*7f2fe78bSCy Schubert if len(outlines) != len(expected): 79*7f2fe78bSCy Schubert fail('Unexpected number of lines in stash file klist') 80*7f2fe78bSCy Schubert for line, ex in zip(outlines, expected): 81*7f2fe78bSCy Schubert m = klist_re.match(line) 82*7f2fe78bSCy Schubert if not m: 83*7f2fe78bSCy Schubert fail('Unrecognized stash file klist line') 84*7f2fe78bSCy Schubert kvno, enctype = m.groups() 85*7f2fe78bSCy Schubert exp_kvno, exp_enctype = ex 86*7f2fe78bSCy Schubert if kvno != str(exp_kvno): 87*7f2fe78bSCy Schubert fail('Unexpected stash file klist kvno') 88*7f2fe78bSCy Schubert if enctype != exp_enctype: 89*7f2fe78bSCy Schubert fail('Unexpected stash file klist enctype') 90*7f2fe78bSCy Schubert 91*7f2fe78bSCy Schubert 92*7f2fe78bSCy Schubert# Verify that the user principal has the expected mkvno. 93*7f2fe78bSCy Schubertdef check_mkvno(princ, expected_mkvno): 94*7f2fe78bSCy Schubert msg = 'MKey: vno %d\n' % expected_mkvno 95*7f2fe78bSCy Schubert realm.run([kadminl, 'getprinc', princ], expected_msg=msg) 96*7f2fe78bSCy Schubert 97*7f2fe78bSCy Schubert 98*7f2fe78bSCy Schubert# Change the password using either kadmin.local or kadmin, then check 99*7f2fe78bSCy Schubert# the mkvno of the principal against expected_mkvno and verify that 100*7f2fe78bSCy Schubert# the running KDC can access the new key. 101*7f2fe78bSCy Schubertdef change_password_check_mkvno(local, princ, password, expected_mkvno): 102*7f2fe78bSCy Schubert cmd = ['cpw', '-pw', password, princ] 103*7f2fe78bSCy Schubert if local: 104*7f2fe78bSCy Schubert realm.run([kadminl] + cmd) 105*7f2fe78bSCy Schubert else: 106*7f2fe78bSCy Schubert realm.run_kadmin(cmd) 107*7f2fe78bSCy Schubert check_mkvno(princ, expected_mkvno) 108*7f2fe78bSCy Schubert realm.kinit(princ, password) 109*7f2fe78bSCy Schubert 110*7f2fe78bSCy Schubert 111*7f2fe78bSCy Schubert# Add a master key with the specified options and a random password. 112*7f2fe78bSCy Schubertdef add_mkey(options): 113*7f2fe78bSCy Schubert pw = ''.join(random.choice(string.ascii_uppercase) for x in range(5)) 114*7f2fe78bSCy Schubert realm.run([kdb5_util, 'add_mkey'] + options, input=(pw + '\n' + pw + '\n')) 115*7f2fe78bSCy Schubert 116*7f2fe78bSCy Schubert 117*7f2fe78bSCy Schubert# Run kdb5_util update_princ_encryption (with the dry-run option if 118*7f2fe78bSCy Schubert# specified) and verify the output against the expected mkvno, number 119*7f2fe78bSCy Schubert# of updated principals, and number of already-current principals. 120*7f2fe78bSCy Schubertmkvno_re = {False: re.compile(r'^Principals whose keys are being re-encrypted ' 121*7f2fe78bSCy Schubert r'to master key vno (\d+) if necessary:$'), 122*7f2fe78bSCy Schubert True: re.compile(r'^Principals whose keys WOULD BE re-encrypted ' 123*7f2fe78bSCy Schubert r'to master key vno (\d+):$')} 124*7f2fe78bSCy Schubertcount_re = {False: re.compile(r'^(\d+) principals processed: (\d+) updated, ' 125*7f2fe78bSCy Schubert r'(\d+) already current$'), 126*7f2fe78bSCy Schubert True: re.compile(r'^(\d+) principals processed: (\d+) would be ' 127*7f2fe78bSCy Schubert r'updated, (\d+) already current$')} 128*7f2fe78bSCy Schubertdef update_princ_encryption(dry_run, expected_mkvno, expected_updated, 129*7f2fe78bSCy Schubert expected_current): 130*7f2fe78bSCy Schubert opts = ['-f', '-v'] 131*7f2fe78bSCy Schubert if dry_run: 132*7f2fe78bSCy Schubert opts += ['-n'] 133*7f2fe78bSCy Schubert out = realm.run([kdb5_util, 'update_princ_encryption'] + opts) 134*7f2fe78bSCy Schubert lines = out.splitlines() 135*7f2fe78bSCy Schubert # Parse the first line to get the target mkvno. 136*7f2fe78bSCy Schubert m = mkvno_re[dry_run].match(lines[0]) 137*7f2fe78bSCy Schubert if not m: 138*7f2fe78bSCy Schubert fail('Unexpected first line of update_princ_encryption output') 139*7f2fe78bSCy Schubert if m.group(1) != str(expected_mkvno): 140*7f2fe78bSCy Schubert fail('Unexpected master key version in update_princ_encryption output') 141*7f2fe78bSCy Schubert # Parse the last line to get the principal counts. 142*7f2fe78bSCy Schubert m = count_re[dry_run].match(lines[-1]) 143*7f2fe78bSCy Schubert if not m: 144*7f2fe78bSCy Schubert fail('Unexpected last line of update_princ_encryption output') 145*7f2fe78bSCy Schubert total, updated, current = m.groups() 146*7f2fe78bSCy Schubert if (total != str(expected_updated + expected_current) or 147*7f2fe78bSCy Schubert updated != str(expected_updated) or current != str(expected_current)): 148*7f2fe78bSCy Schubert fail('Unexpected counts from update_princ_encryption') 149*7f2fe78bSCy Schubert 150*7f2fe78bSCy Schubert 151*7f2fe78bSCy Schubert# Check the initial state of the realm. 152*7f2fe78bSCy Schubertmark('initial state') 153*7f2fe78bSCy Schubertcheck_mkey_list((1, defetype, True, True)) 154*7f2fe78bSCy Schubertcheck_master_dbent(1, (1, defetype)) 155*7f2fe78bSCy Schubertcheck_stash((1, defetype)) 156*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 1) 157*7f2fe78bSCy Schubert 158*7f2fe78bSCy Schubert# Check that stash will fail if a temp stash file is already present. 159*7f2fe78bSCy Schubertmark('temp stash collision') 160*7f2fe78bSCy Schubertcollisionfile = os.path.join(realm.testdir, 'stash_tmp') 161*7f2fe78bSCy Schubertf = open(collisionfile, 'w') 162*7f2fe78bSCy Schubertf.close() 163*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'stash'], expected_code=1, 164*7f2fe78bSCy Schubert expected_msg='Temporary stash file already exists') 165*7f2fe78bSCy Schubertos.unlink(collisionfile) 166*7f2fe78bSCy Schubert 167*7f2fe78bSCy Schubert# Add a new master key with no options. Verify that: 168*7f2fe78bSCy Schubert# 1. The new key appears in list_mkeys but has no activation time and 169*7f2fe78bSCy Schubert# is not active. 170*7f2fe78bSCy Schubert# 2. The new key appears in the K/M DB entry and is the current key to 171*7f2fe78bSCy Schubert# encrypt that entry. 172*7f2fe78bSCy Schubert# 3. The stash file is not modified (since we did not pass -s). 173*7f2fe78bSCy Schubert# 4. The old key is used for password changes. 174*7f2fe78bSCy Schubertmark('add_mkey (second master key)') 175*7f2fe78bSCy Schubertadd_mkey([]) 176*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, False, False), (1, defetype, True, True)) 177*7f2fe78bSCy Schubertcheck_master_dbent(2, (2, defetype), (1, defetype)) 178*7f2fe78bSCy Schubertchange_password_check_mkvno(True, realm.user_princ, 'abcd', 1) 179*7f2fe78bSCy Schubertchange_password_check_mkvno(False, realm.user_princ, 'user', 1) 180*7f2fe78bSCy Schubert 181*7f2fe78bSCy Schubert# Verify that use_mkey won't make all master keys inactive. 182*7f2fe78bSCy Schubertmark('use_mkey (no active keys)') 183*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '1', 'now+1day'], expected_code=1, 184*7f2fe78bSCy Schubert expected_msg='there must be one master key currently active') 185*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, False, False), (1, defetype, True, True)) 186*7f2fe78bSCy Schubert 187*7f2fe78bSCy Schubert# Make the new master key active. Verify that: 188*7f2fe78bSCy Schubert# 1. The new key has an activation time in list_mkeys and is active. 189*7f2fe78bSCy Schubert# 2. The new key is used for password changes. 190*7f2fe78bSCy Schubert# 3. The running KDC can access the new key. 191*7f2fe78bSCy Schubertmark('use_mkey') 192*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) 193*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, True, True), (1, defetype, True, False)) 194*7f2fe78bSCy Schubertchange_password_check_mkvno(True, realm.user_princ, 'abcd', 2) 195*7f2fe78bSCy Schubertchange_password_check_mkvno(False, realm.user_princ, 'user', 2) 196*7f2fe78bSCy Schubert 197*7f2fe78bSCy Schubert# Check purge_mkeys behavior with both master keys still in use. 198*7f2fe78bSCy Schubertmark('purge_mkeys (nothing to purge)') 199*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], 200*7f2fe78bSCy Schubert expected_msg='All keys in use, nothing purged.') 201*7f2fe78bSCy Schubert 202*7f2fe78bSCy Schubert# Do an update_princ_encryption dry run and for real. Verify that: 203*7f2fe78bSCy Schubert# 1. The target master key is 2 (the active mkvno). 204*7f2fe78bSCy Schubert# 2. nprincs - 2 principals were updated and one principal was 205*7f2fe78bSCy Schubert# skipped (K/M is not included in the output and user was updated 206*7f2fe78bSCy Schubert# above). 207*7f2fe78bSCy Schubert# 3. The dry run doesn't change user/admin's mkvno but the real update 208*7f2fe78bSCy Schubert# does. 209*7f2fe78bSCy Schubert# 4. The old stashed master key is sufficient to access the DB (via 210*7f2fe78bSCy Schubert# MKEY_AUX tl-data which keeps the current master key encrypted in 211*7f2fe78bSCy Schubert# each of the old master keys). 212*7f2fe78bSCy Schubertmark('update_princ_encryption') 213*7f2fe78bSCy Schubertupdate_princ_encryption(True, 2, nprincs - 2, 1) 214*7f2fe78bSCy Schubertcheck_mkvno(realm.admin_princ, 1) 215*7f2fe78bSCy Schubertupdate_princ_encryption(False, 2, nprincs - 2, 1) 216*7f2fe78bSCy Schubertcheck_mkvno(realm.admin_princ, 2) 217*7f2fe78bSCy Schubertrealm.stop_kdc() 218*7f2fe78bSCy Schubertrealm.start_kdc() 219*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, 'user') 220*7f2fe78bSCy Schubert 221*7f2fe78bSCy Schubert# Update all principals back to mkvno 1 and to mkvno 2 again, to 222*7f2fe78bSCy Schubert# verify that update_princ_encryption targets the active master key. 223*7f2fe78bSCy Schubertmark('update_princ_encryption (back and forth)') 224*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '2', 'now+1day']) 225*7f2fe78bSCy Schubertupdate_princ_encryption(False, 1, nprincs - 1, 0) 226*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 1) 227*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) 228*7f2fe78bSCy Schubertupdate_princ_encryption(False, 2, nprincs - 1, 0) 229*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 2) 230*7f2fe78bSCy Schubert 231*7f2fe78bSCy Schubert# Test the safety check for purging with an outdated stash file. 232*7f2fe78bSCy Schubertmark('purge_mkeys (outdated stash file)') 233*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'purge_mkeys', '-f'], expected_code=1, 234*7f2fe78bSCy Schubert expected_msg='stash file needs updating') 235*7f2fe78bSCy Schubert 236*7f2fe78bSCy Schubert# Update the master stash file and check it. Save a copy of the old 237*7f2fe78bSCy Schubert# one for a later test. 238*7f2fe78bSCy Schubertmark('update stash file') 239*7f2fe78bSCy Schubertshutil.copy(stash_file, stash_file + '.old') 240*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'stash']) 241*7f2fe78bSCy Schubertcheck_stash((2, defetype), (1, defetype)) 242*7f2fe78bSCy Schubert 243*7f2fe78bSCy Schubert# Do a purge_mkeys dry run and for real. Verify that: 244*7f2fe78bSCy Schubert# 1. Master key 1 is purged. 245*7f2fe78bSCy Schubert# 2. The dry run doesn't remove mkvno 1 but the real one does. 246*7f2fe78bSCy Schubert# 3. The old stash file is no longer sufficient to access the DB. 247*7f2fe78bSCy Schubert# 4. If the stash file is updated, it no longer contains mkvno 1. 248*7f2fe78bSCy Schubert# 5. use_mkey now gives an error if we refer to mkvno 1. 249*7f2fe78bSCy Schubert# 6. A second purge_mkeys gives the right message. 250*7f2fe78bSCy Schubertmark('purge_mkeys') 251*7f2fe78bSCy Schubertout = realm.run([kdb5_util, 'purge_mkeys', '-v', '-n', '-f']) 252*7f2fe78bSCy Schubertif 'KVNO: 1' not in out or '1 key(s) would be purged' not in out: 253*7f2fe78bSCy Schubert fail('Unexpected output from purge_mkeys dry-run') 254*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, True, True), (1, defetype, True, False)) 255*7f2fe78bSCy Schubertcheck_master_dbent(2, (2, defetype), (1, defetype)) 256*7f2fe78bSCy Schubertout = realm.run([kdb5_util, 'purge_mkeys', '-v', '-f']) 257*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, True, True)) 258*7f2fe78bSCy Schubertcheck_master_dbent(2, (2, defetype)) 259*7f2fe78bSCy Schubertos.rename(stash_file, stash_file + '.save') 260*7f2fe78bSCy Schubertos.rename(stash_file + '.old', stash_file) 261*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', 'user'], expected_code=1, 262*7f2fe78bSCy Schubert expected_msg='Unable to decrypt latest master key') 263*7f2fe78bSCy Schubertos.rename(stash_file + '.save', stash_file) 264*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'stash']) 265*7f2fe78bSCy Schubertcheck_stash((2, defetype)) 266*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '1'], expected_code=1, 267*7f2fe78bSCy Schubert expected_msg='1 is an invalid KVNO value') 268*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], 269*7f2fe78bSCy Schubert expected_msg='There is only one master key which can not be purged.') 270*7f2fe78bSCy Schubert 271*7f2fe78bSCy Schubert# Add a third master key with a specified enctype. Verify that: 272*7f2fe78bSCy Schubert# 1. The new master key receives the correct number. 273*7f2fe78bSCy Schubert# 2. The enctype argument is respected. 274*7f2fe78bSCy Schubert# 3. The new master key is stashed (by itself, at the moment). 275*7f2fe78bSCy Schubert# 4. We can roll over to the new master key and use it. 276*7f2fe78bSCy Schubertmark('add_mkey and update_princ_encryption (third master key)') 277*7f2fe78bSCy Schubertadd_mkey(['-s', '-e', aes128]) 278*7f2fe78bSCy Schubertcheck_mkey_list((3, aes128, False, False), (2, defetype, True, True)) 279*7f2fe78bSCy Schubertcheck_master_dbent(3, (3, aes128), (2, defetype)) 280*7f2fe78bSCy Schubertcheck_stash((3, aes128)) 281*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '3', 'now-1day']) 282*7f2fe78bSCy Schubertupdate_princ_encryption(False, 3, nprincs - 1, 0) 283*7f2fe78bSCy Schubertcheck_mkey_list((3, aes128, True, True), (2, defetype, True, False)) 284*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 3) 285*7f2fe78bSCy Schubert 286*7f2fe78bSCy Schubert# Regression test for #7994 (randkey does not update principal mkvno) 287*7f2fe78bSCy Schubert# and #7995 (-keepold does not re-encrypt old keys). 288*7f2fe78bSCy Schubertmark('#7994 and #7995 regression test') 289*7f2fe78bSCy Schubertadd_mkey(['-s']) 290*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '4', 'now-1day']) 291*7f2fe78bSCy Schubertrealm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.user_princ]) 292*7f2fe78bSCy Schubert# With #7994 unfixed, mkvno of user will still be 3. 293*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 4) 294*7f2fe78bSCy Schubert# With #7995 unfixed, old keys are still encrypted with mkvno 3. 295*7f2fe78bSCy Schubertupdate_princ_encryption(False, 4, nprincs - 2, 1) 296*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'purge_mkeys', '-f']) 297*7f2fe78bSCy Schubertout = realm.run([kadminl, 'xst', '-norandkey', realm.user_princ]) 298*7f2fe78bSCy Schubertif 'Decrypt integrity check failed' in out or 'added to keytab' not in out: 299*7f2fe78bSCy Schubert fail('Preserved old key data not updated to new master key') 300*7f2fe78bSCy Schubert 301*7f2fe78bSCy Schubertrealm.stop() 302*7f2fe78bSCy Schubert 303*7f2fe78bSCy Schubert# Load a dump file created with krb5 1.6, before the master key 304*7f2fe78bSCy Schubert# rollover changes were introduced. Write out an old-format stash 305*7f2fe78bSCy Schubert# file consistent with the dump's master password ("footes"). The K/M 306*7f2fe78bSCy Schubert# entry in this database will not have actkvno tl-data because it was 307*7f2fe78bSCy Schubert# created prior to master key rollover support. Verify that: 308*7f2fe78bSCy Schubert# 1. We can access the database using the old-format stash file. 309*7f2fe78bSCy Schubert# 2. list_mkeys displays the same list as for a post-1.7 KDB. 310*7f2fe78bSCy Schubertmark('pre-1.7 stash file') 311*7f2fe78bSCy Schubertdumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16') 312*7f2fe78bSCy Schubertos.remove(stash_file) 313*7f2fe78bSCy Schubertf = open(stash_file, 'wb') 314*7f2fe78bSCy Schubertf.write(struct.pack('=HL24s', 16, 24, 315*7f2fe78bSCy Schubert b'\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0' 316*7f2fe78bSCy Schubert b'\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86')) 317*7f2fe78bSCy Schubertf.close() 318*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'load', dumpfile]) 319*7f2fe78bSCy Schubertnprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) 320*7f2fe78bSCy Schubertcheck_mkvno('K/M', 1) 321*7f2fe78bSCy Schubertcheck_mkey_list((1, des3, True, True)) 322*7f2fe78bSCy Schubert 323*7f2fe78bSCy Schubert# Create a new master key and verify that, without actkvkno tl-data: 324*7f2fe78bSCy Schubert# 1. list_mkeys displays the same as for a post-1.7 KDB. 325*7f2fe78bSCy Schubert# 2. update_princ_encryption still targets mkvno 1. 326*7f2fe78bSCy Schubert# 3. libkadm5 still uses mkvno 1 for key changes. 327*7f2fe78bSCy Schubert# 4. use_mkey creates the same list as for a post-1.7 KDB. 328*7f2fe78bSCy Schubertmark('rollover from pre-1.7 KDB') 329*7f2fe78bSCy Schubertadd_mkey([]) 330*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, False, False), (1, des3, True, True)) 331*7f2fe78bSCy Schubertupdate_princ_encryption(False, 1, 0, nprincs - 1) 332*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', realm.user_princ]) 333*7f2fe78bSCy Schubertcheck_mkvno(realm.user_princ, 1) 334*7f2fe78bSCy Schubertrealm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) 335*7f2fe78bSCy Schubertcheck_mkey_list((2, defetype, True, True), (1, des3, True, False)) 336*7f2fe78bSCy Schubert 337*7f2fe78bSCy Schubert# Regression test for #8395. Purge the master key and verify that a 338*7f2fe78bSCy Schubert# master key fetch does not segfault. 339*7f2fe78bSCy Schubertmark('#8395 regression test') 340*7f2fe78bSCy Schubertrealm.run([kadminl, 'purgekeys', '-all', 'K/M']) 341*7f2fe78bSCy Schubertrealm.run([kadminl, 'getprinc', realm.user_princ], expected_code=1, 342*7f2fe78bSCy Schubert expected_msg='Cannot find master key record in database') 343*7f2fe78bSCy Schubert 344*7f2fe78bSCy Schubertsuccess('Master key rollover tests') 345