aboutsummaryrefslogtreecommitdiff
path: root/src/tests/t_keytab.py
blob: a48740ba532ad00f95383f827b156ff89a22b024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python
from k5test import *

for realm in multipass_realms(create_user=False):
    # Test kinit with a keytab.
    realm.kinit(realm.host_princ, flags=['-k'])

realm = K5Realm(get_creds=False, start_kadmind=True)

# Test kinit with a partial keytab.
pkeytab = realm.keytab + '.partial'
realm.run([ktutil], input=('rkt %s\ndelent 1\nwkt %s\n' %
                           (realm.keytab, pkeytab)))
realm.kinit(realm.host_princ, flags=['-k', '-t', pkeytab])

# Test kinit with no keys for client in keytab.
realm.kinit(realm.user_princ, flags=['-k'], expected_code=1,
            expected_msg='no suitable keys')

# Test kinit and klist with client keytab defaults.
realm.extract_keytab(realm.user_princ, realm.client_keytab);
realm.run([kinit, '-k', '-i'])
realm.klist(realm.user_princ)
realm.run([kdestroy])
realm.kinit(realm.user_princ, flags=['-k', '-i'])
realm.klist(realm.user_princ)
out = realm.run([klist, '-k', '-i'])
if realm.client_keytab not in out or realm.user_princ not in out:
    fail('Expected output not seen from klist -k -i')

# Test implicit request for keytab (-i or -t without -k)
realm.run([kdestroy])
realm.kinit(realm.host_princ, flags=['-t', realm.keytab],
            expected_msg='keytab specified, forcing -k')
realm.klist(realm.host_princ)
realm.run([kdestroy])
realm.kinit(realm.user_princ, flags=['-i'],
            expected_msg='keytab specified, forcing -k')
realm.klist(realm.user_princ)

# Test extracting keys with multiple key versions present.
os.remove(realm.keytab)
realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.host_princ])
out = realm.run([kadminl, 'ktadd', '-norandkey', realm.host_princ])
if 'with kvno 1,' not in out or 'with kvno 2,' not in out:
    fail('Expected output not seen from kadmin.local ktadd -norandkey')
out = realm.run([klist, '-k', '-e'])
if ' 1 host/' not in out or ' 2 host/' not in out:
    fail('Expected output not seen from klist -k -e')

# Test again using kadmin over the network.
realm.prep_kadmin()
os.remove(realm.keytab)
out = realm.run_kadmin(['ktadd', '-norandkey', realm.host_princ])
if 'with kvno 1,' not in out or 'with kvno 2,' not in out:
    fail('Expected output not seen from kadmin.local ktadd -norandkey')
out = realm.run([klist, '-k', '-e'])
if ' 1 host/' not in out or ' 2 host/' not in out:
    fail('Expected output not seen from klist -k -e')

# Test handling of kvno values beyond 255.  Use kadmin over the
# network since we used to have an 8-bit limit on kvno marshalling.

# Test one key rotation, verifying that the expected new kvno appears
# in the keytab and in the principal entry.
def test_key_rotate(realm, princ, expected_kvno):
    realm.run_kadmin(['ktadd', '-k', realm.keytab, princ])
    realm.run([kadminl, 'ktrem', princ, 'old'])
    realm.kinit(princ, flags=['-k'])
    msg = '%d %s' % (expected_kvno, princ)
    out = realm.run([klist, '-k'], expected_msg=msg)
    msg = 'Key: vno %d,' % expected_kvno
    out = realm.run_kadmin(['getprinc', princ], expected_msg=msg)

princ = 'foo/bar@%s' % realm.realm
realm.addprinc(princ)
os.remove(realm.keytab)
realm.run([kadminl, 'modprinc', '-kvno', '253', princ])
test_key_rotate(realm, princ, 254)
test_key_rotate(realm, princ, 255)
test_key_rotate(realm, princ, 256)
test_key_rotate(realm, princ, 257)
realm.run([kadminl, 'modprinc', '-kvno', '32766', princ])
test_key_rotate(realm, princ, 32767)
test_key_rotate(realm, princ, 32768)
test_key_rotate(realm, princ, 32769)
realm.run([kadminl, 'modprinc', '-kvno', '65534', princ])
test_key_rotate(realm, princ, 65535)
test_key_rotate(realm, princ, 1)
test_key_rotate(realm, princ, 2)

# Test that klist -k can read a keytab entry without a 32-bit kvno and
# reports the 8-bit key version.
record = '\x00\x01'             # principal component count
record += '\x00\x0bKRBTEST.COM' # realm
record += '\x00\x04user'        # principal component
record += '\x00\x00\x00\x01'    # name type (NT-PRINCIPAL)
record += '\x54\xf7\x4d\x35'    # timestamp
record += '\x02'                # key version
record += '\x00\x12'            # enctype
record += '\x00\x20'            # key length
record += '\x00' * 32           # key bytes
f = open(realm.keytab, 'w')
f.write('\x05\x02\x00\x00\x00' + chr(len(record)))
f.write(record)
f.close()
msg = '   2 %s' % realm.user_princ
out = realm.run([klist, '-k'], expected_msg=msg)

# Make sure zero-fill isn't treated as a 32-bit kvno.
f = open(realm.keytab, 'w')
f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4))
f.write(record)
f.write('\x00\x00\x00\x00')
f.close()
msg = '   2 %s' % realm.user_princ
out = realm.run([klist, '-k'], expected_msg=msg)

# Make sure a hand-crafted 32-bit kvno is recognized.
f = open(realm.keytab, 'w')
f.write('\x05\x02\x00\x00\x00' + chr(len(record) + 4))
f.write(record)
f.write('\x00\x00\x00\x03')
f.close()
msg = '   3 %s' % realm.user_princ
out = realm.run([klist, '-k'], expected_msg=msg)

# Test parameter expansion in profile variables
realm.stop()
conf = {'libdefaults': {
        'default_keytab_name': 'testdir/%{null}abc%{uid}',
        'default_client_keytab_name': 'testdir/%{null}xyz%{uid}'}}
realm = K5Realm(krb5_conf=conf, create_kdb=False)
del realm.env['KRB5_KTNAME']
del realm.env['KRB5_CLIENT_KTNAME']
uidstr = str(os.getuid())
msg = 'FILE:testdir/abc%s' % uidstr
out = realm.run([klist, '-k'], expected_code=1, expected_msg=msg)
msg = 'FILE:testdir/xyz%s' % uidstr
out = realm.run([klist, '-ki'], expected_code=1, expected_msg=msg)

success('Keytab-related tests')