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