xref: /freebsd/crypto/krb5/src/tests/t_policy.py (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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