aboutsummaryrefslogtreecommitdiff
path: root/src/tests/t_policy.py
blob: 1fa5106a0efd21c08fdae03e85e2b5f6a4c88146 (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/python
from k5test import *
import re

realm = K5Realm(create_host=False)

# Test password quality enforcement.
realm.run([kadminl, 'addpol', '-minlength', '6', '-minclasses', '2', 'pwpol'])
realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'pwpol', 'pwuser'])
out = realm.run([kadminl, 'cpw', '-pw', 'sh0rt', 'pwuser'], expected_code=1)
if 'Password is too short' not in out:
    fail('short password')
out = realm.run([kadminl, 'cpw', '-pw', 'longenough', 'pwuser'],
                expected_code=1)
if 'Password does not contain enough character classes' not in out:
    fail('insufficient character classes')
realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'])

# Test some password history enforcement.  Even with no history value,
# the current password should be denied.
out = realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'],
                expected_code=1)
if 'Cannot reuse password' not in out:
    fail('reuse of current password')
realm.run([kadminl, 'modpol', '-history', '2', 'pwpol'])
realm.run([kadminl, 'cpw', '-pw', 'an0therpw', 'pwuser'])
out = realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'],
                expected_code=1)
if 'Cannot reuse password' not in out:
    fail('reuse of old password')
realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'])
realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'])

# Test references to nonexistent policies.
realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'newpol', 'newuser'])
out = realm.run([kadminl, 'getprinc', 'newuser'])
if 'Policy: newpol [does not exist]\n' not in out:
    fail('getprinc output for principal referencing nonexistent policy')
realm.run([kadminl, 'modprinc', '-policy', 'newpol', 'pwuser'])
# pwuser should allow reuse of the current password since newpol doesn't exist.
realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'])

# Create newpol and verify that it is enforced.
realm.run([kadminl, 'addpol', '-minlength', '3', 'newpol'])
out = realm.run([kadminl, 'getprinc', 'pwuser'])
if 'Policy: newpol\n' not in out:
    fail('getprinc after creating policy (pwuser)')
out = realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'], expected_code=1)
if 'Password is too short' not in out:
    fail('short password after creating policy (pwuser)')
out = realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'],
                expected_code=1)
if 'Cannot reuse password' not in out:
    fail('reuse of current password after creating policy')

out = realm.run([kadminl, 'getprinc', 'newuser'])
if 'Policy: newpol\n' not in out:
    fail('getprinc after creating policy (newuser)')
out = realm.run([kadminl, 'cpw', '-pw', 'aa', 'newuser'], expected_code=1)
if 'Password is too short' not in out:
    fail('short password after creating policy (newuser)')

# Delete the policy and verify that it is no longer enforced.
realm.run([kadminl, 'delpol', 'newpol'])
out = realm.run([kadminl, 'getpol', 'newpol'], expected_code=1)
if 'Policy does not exist' not in out:
    fail('deletion of referenced policy')
realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'])

# Test basic password lockout support.

realm.run([kadminl, 'addpol', '-maxfailure', '2', '-failurecountinterval',
           '5m', 'lockout'])
realm.run([kadminl, 'modprinc', '+requires_preauth', '-policy', 'lockout',
           'user'])

# kinit twice with the wrong password.
output = realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1)
if 'Password incorrect while getting initial credentials' not in output:
    fail('Expected error message not seen in kinit output')
output = realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1)
if 'Password incorrect while getting initial credentials' not in output:
    fail('Expected error message not seen in kinit output')

# Now the account should be locked out.
output = realm.run([kinit, realm.user_princ], expected_code=1)
if 'Clients credentials have been revoked while getting initial credentials' \
        not in output:
    fail('Expected lockout error message not seen in kinit output')

# Check that modprinc -unlock allows a further attempt.
realm.run([kadminl, 'modprinc', '-unlock', 'user'])
realm.kinit(realm.user_princ, password('user'))

# Make sure a nonexistent policy reference doesn't prevent authentication.
realm.run([kadminl, 'delpol', 'lockout'])
realm.kinit(realm.user_princ, password('user'))

# Regression test for issue #7099: databases created prior to krb5 1.3 have
# multiple history keys, and kadmin prior to 1.7 didn't necessarily use the
# first one to create history entries.

realm.stop()
realm = K5Realm(start_kdc=False)
# Create a history principal with two keys.
realm.run(['./hist', 'make'])
realm.run([kadminl, 'addpol', '-history', '2', 'pol'])
realm.run([kadminl, 'modprinc', '-policy', 'pol', 'user'])
realm.run([kadminl, 'cpw', '-pw', 'pw2', 'user'])
# Swap the keys, simulating older kadmin having chosen the second entry.
realm.run(['./hist', 'swap'])
# Make sure we can read the history entry.
out = realm.run([kadminl, 'cpw', '-pw', password('user'), 'user'],
                expected_code=1)
if 'Cannot reuse password' not in out:
    fail('Expected error not seen in output')

# Test key/salt constraints.

realm.stop()
krb5_conf1 = {'libdefaults': {'supported_enctypes': 'aes256-cts'}}
realm = K5Realm(krb5_conf=krb5_conf1, create_host=False, get_creds=False)

# Add policy.
realm.run([kadminl, 'addpol', '-allowedkeysalts', 'aes256-cts', 'ak'])
realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server'])

# Test with one-enctype allowed_keysalts.
realm.run([kadminl, 'modprinc', '-policy', 'ak', 'server'])
out = realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server'],
                expected_code=1)
if not 'Invalid key/salt tuples' in out:
    fail('allowed_keysalts policy not applied properly')
realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server'])

# Now test a multi-enctype allowed_keysalts.  Test that subsets are allowed,
# the the complete set is allowed, that order doesn't matter, and that
# enctypes outside the set are not allowed.

# Test modpol.
realm.run([kadminl, 'modpol', '-allowedkeysalts', 'aes256-cts,rc4-hmac', 'ak'])
out = realm.run([kadminl, 'getpol', 'ak'])
if not 'Allowed key/salt types: aes256-cts,rc4-hmac' in out:
    fail('getpol does not implement allowedkeysalts?')

# Test subsets and full set.
realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac', 'server'])
realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server'])
realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,rc4-hmac', 'server'])
realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts', 'server'])

# Check that the order we got is the one from the policy.
out = realm.run([kadminl, 'getprinc', '-terse', 'server'])
if not '2\t1\t6\t18\t0\t1\t6\t23\t0' in out:
    fail('allowed_keysalts policy did not preserve order')

# Test partially intersecting sets.
out = realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes128-cts',
                 'server'], expected_code=1)
if not 'Invalid key/salt tuples' in out:
    fail('allowed_keysalts policy not applied properly')
out = realm.run([kadminl, 'cpw', '-randkey', '-e',
                 'rc4-hmac,aes256-cts,aes128-cts', 'server'], expected_code=1)
if not 'Invalid key/salt tuples' in out:
    fail('allowed_keysalts policy not applied properly')

# Test reset of allowedkeysalts.
realm.run([kadminl, 'modpol', '-allowedkeysalts', '-', 'ak'])
out = realm.run([kadminl, 'getpol', 'ak'])
if 'Allowed key/salt types' in out:
    fail('failed to clear allowedkeysalts')
realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server'])

success('Policy tests')