3 for realm in multipass_realms(create_user=False):
4 # Test kinit with a keytab.
5 realm.kinit(realm.host_princ, flags=['-k'])
7 realm = K5Realm(get_creds=False, start_kadmind=True)
9 # Test kinit with a partial keytab.
10 mark('partial keytab')
11 pkeytab = realm.keytab + '.partial'
12 realm.run([ktutil], input=('rkt %s\ndelent 1\nwkt %s\n' %
13 (realm.keytab, pkeytab)))
14 realm.kinit(realm.host_princ, flags=['-k', '-t', pkeytab])
16 # Test kinit with no keys for client in keytab.
17 mark('no keys for client')
18 realm.kinit(realm.user_princ, flags=['-k'], expected_code=1,
19 expected_msg='no suitable keys')
21 # Test kinit and klist with client keytab defaults.
23 realm.extract_keytab(realm.user_princ, realm.client_keytab);
24 realm.run([kinit, '-k', '-i'])
25 realm.klist(realm.user_princ)
27 realm.kinit(realm.user_princ, flags=['-k', '-i'])
28 realm.klist(realm.user_princ)
29 out = realm.run([klist, '-k', '-i'])
30 if realm.client_keytab not in out or realm.user_princ not in out:
31 fail('Expected output not seen from klist -k -i')
33 # Test implicit request for keytab (-i or -t without -k)
36 realm.kinit(realm.host_princ, flags=['-t', realm.keytab],
37 expected_msg='keytab specified, forcing -k')
38 realm.klist(realm.host_princ)
40 realm.kinit(realm.user_princ, flags=['-i'],
41 expected_msg='keytab specified, forcing -k')
42 realm.klist(realm.user_princ)
44 # Test default principal for -k. This operation requires
45 # canonicalization against the keytab in krb5_get_init_creds_keytab()
46 # as the krb5_sname_to_principal() result won't have a realm. Try
47 # with and without without fallback processing since the code paths
49 mark('default principal for -k')
50 realm.run([kinit, '-k'])
51 realm.klist(realm.host_princ)
52 no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}}
53 no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf)
54 realm.run([kinit, '-k'], env=no_canon)
55 realm.klist(realm.host_princ)
57 # Test extracting keys with multiple key versions present.
58 mark('multi-kvno extract')
59 os.remove(realm.keytab)
60 realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.host_princ])
61 out = realm.run([kadminl, 'ktadd', '-norandkey', realm.host_princ])
62 if 'with kvno 1,' not in out or 'with kvno 2,' not in out:
63 fail('Expected output not seen from kadmin.local ktadd -norandkey')
64 out = realm.run([klist, '-k', '-e'])
65 if ' 1 host/' not in out or ' 2 host/' not in out:
66 fail('Expected output not seen from klist -k -e')
68 # Test again using kadmin over the network.
69 mark('multi-kvno extract (via kadmin)')
71 os.remove(realm.keytab)
72 out = realm.run_kadmin(['ktadd', '-norandkey', realm.host_princ])
73 if 'with kvno 1,' not in out or 'with kvno 2,' not in out:
74 fail('Expected output not seen from kadmin.local ktadd -norandkey')
75 out = realm.run([klist, '-k', '-e'])
76 if ' 1 host/' not in out or ' 2 host/' not in out:
77 fail('Expected output not seen from klist -k -e')
79 # Test handling of kvno values beyond 255. Use kadmin over the
80 # network since we used to have an 8-bit limit on kvno marshalling.
82 # Test one key rotation, verifying that the expected new kvno appears
83 # in the keytab and in the principal entry.
84 def test_key_rotate(realm, princ, expected_kvno):
85 realm.run_kadmin(['ktadd', '-k', realm.keytab, princ])
86 realm.run([kadminl, 'ktrem', princ, 'old'])
87 realm.kinit(princ, flags=['-k'])
88 msg = '%d %s' % (expected_kvno, princ)
89 out = realm.run([klist, '-k'], expected_msg=msg)
90 msg = 'Key: vno %d,' % expected_kvno
91 out = realm.run_kadmin(['getprinc', princ], expected_msg=msg)
93 mark('key rotation across boundaries')
94 princ = 'foo/bar@%s' % realm.realm
96 os.remove(realm.keytab)
97 realm.run([kadminl, 'modprinc', '-kvno', '253', princ])
98 test_key_rotate(realm, princ, 254)
99 test_key_rotate(realm, princ, 255)
100 test_key_rotate(realm, princ, 256)
101 test_key_rotate(realm, princ, 257)
102 realm.run([kadminl, 'modprinc', '-kvno', '32766', princ])
103 test_key_rotate(realm, princ, 32767)
104 test_key_rotate(realm, princ, 32768)
105 test_key_rotate(realm, princ, 32769)
106 realm.run([kadminl, 'modprinc', '-kvno', '65534', princ])
107 test_key_rotate(realm, princ, 65535)
108 test_key_rotate(realm, princ, 1)
109 test_key_rotate(realm, princ, 2)
113 # Test that klist -k can read a keytab entry without a 32-bit kvno and
114 # reports the 8-bit key version.
115 record = b'\x00\x01' # principal component count
116 record += b'\x00\x0bKRBTEST.COM' # realm
117 record += b'\x00\x04user' # principal component
118 record += b'\x00\x00\x00\x01' # name type (NT-PRINCIPAL)
119 record += b'\x54\xf7\x4d\x35' # timestamp
120 record += b'\x02' # key version
121 record += b'\x00\x12' # enctype
122 record += b'\x00\x20' # key length
123 record += b'\x00' * 32 # key bytes
124 f = open(realm.keytab, 'wb')
125 f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record)]))
128 msg = ' 2 %s' % realm.user_princ
129 out = realm.run([klist, '-k'], expected_msg=msg)
131 # Make sure zero-fill isn't treated as a 32-bit kvno.
132 f = open(realm.keytab, 'wb')
133 f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4]))
135 f.write(b'\x00\x00\x00\x00')
137 msg = ' 2 %s' % realm.user_princ
138 out = realm.run([klist, '-k'], expected_msg=msg)
140 # Make sure a hand-crafted 32-bit kvno is recognized.
141 f = open(realm.keytab, 'wb')
142 f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4]))
144 f.write(b'\x00\x00\x00\x03')
146 msg = ' 3 %s' % realm.user_princ
147 out = realm.run([klist, '-k'], expected_msg=msg)
149 # Test parameter expansion in profile variables
150 mark('parameter expansion')
152 conf = {'libdefaults': {
153 'default_keytab_name': 'testdir/%{null}abc%{uid}',
154 'default_client_keytab_name': 'testdir/%{null}xyz%{uid}'}}
155 realm = K5Realm(krb5_conf=conf, create_kdb=False)
156 del realm.env['KRB5_KTNAME']
157 del realm.env['KRB5_CLIENT_KTNAME']
158 uidstr = str(os.getuid())
159 msg = 'FILE:testdir/abc%s' % uidstr
160 out = realm.run([klist, '-k'], expected_code=1, expected_msg=msg)
161 msg = 'FILE:testdir/xyz%s' % uidstr
162 out = realm.run([klist, '-ki'], expected_code=1, expected_msg=msg)
164 conf = {'libdefaults': {'allow_weak_crypto': 'true'}}
165 realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf)
167 realm.run([kadminl, 'ank', '-pw', 'pw', 'default'])
168 realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp'])
169 realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth',
172 # Extract one of the explicit salt values from the database.
173 out = realm.run([kdb5_util, 'tabdump', 'keyinfo'])
174 salt_dict = {f[0]: f[5] for f in [l.split('\t') for l in out.splitlines()]}
175 exp_salt = bytes.fromhex(salt_dict['exp@KRBTEST.COM']).decode('ascii')
177 # Create a keytab using ktutil addent with the specified options and
178 # password "pw". Test that we can use it to get initial tickets.
179 # Remove the keytab afterwards.
180 def test_addent(realm, princ, opts):
181 realm.run([ktutil], input=('addent -password -p %s -k 1 %s\npw\nwkt %s\n' %
182 (princ, opts, realm.keytab)))
183 realm.kinit(princ, flags=['-k'])
184 os.remove(realm.keytab)
186 mark('ktutil addent')
188 # Test with default salt.
189 test_addent(realm, 'default', '-e aes128-cts')
190 test_addent(realm, 'default', '-e aes256-cts')
192 # Test with a salt specified to ktutil addent.
193 test_addent(realm, 'exp', '-e aes256-cts -s %s' % exp_salt)
195 # Test etype-info fetching.
196 test_addent(realm, 'default', '-f')
197 test_addent(realm, 'default', '-f -e aes128-cts')
198 test_addent(realm, 'exp', '-f')
199 test_addent(realm, 'pexp', '-f')
201 # Regression test for #8914: INT32_MIN length can cause backwards seek
202 mark('invalid record length')
203 f = open(realm.keytab, 'wb')
204 f.write(b'\x05\x02\x80\x00\x00\x00')
206 msg = 'Bad format in keytab while scanning keytab'
207 realm.run([klist, '-k'], expected_code=1, expected_msg=msg)
209 success('Keytab-related tests')