xref: /freebsd/crypto/krb5/src/tests/gssapi/t_gssapi.py (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubertfrom k5test import *
2*7f2fe78bSCy Schubert
3*7f2fe78bSCy Schubert# Test krb5 negotiation under SPNEGO for all enctype configurations.  Also
4*7f2fe78bSCy Schubert# test IOV wrap/unwrap with and without SPNEGO.
5*7f2fe78bSCy Schubertfor realm in multipass_realms():
6*7f2fe78bSCy Schubert    realm.run(['./t_spnego','p:' + realm.host_princ, realm.keytab])
7*7f2fe78bSCy Schubert    realm.run(['./t_iov', 'p:' + realm.host_princ])
8*7f2fe78bSCy Schubert    realm.run(['./t_iov', '-s', 'p:' + realm.host_princ])
9*7f2fe78bSCy Schubert    realm.run(['./t_pcontok', 'p:' + realm.host_princ])
10*7f2fe78bSCy Schubert
11*7f2fe78bSCy Schubertrealm = K5Realm()
12*7f2fe78bSCy Schubert
13*7f2fe78bSCy Schubert# Test gss_add_cred().
14*7f2fe78bSCy Schubertrealm.run(['./t_add_cred'])
15*7f2fe78bSCy Schubert
16*7f2fe78bSCy Schubert### Test acceptor name behavior.
17*7f2fe78bSCy Schubert
18*7f2fe78bSCy Schubert# Create some host-based principals and put most of them into the
19*7f2fe78bSCy Schubert# keytab.  Rename one principal so that the keytab name matches the
20*7f2fe78bSCy Schubert# key but not the client name.
21*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'service1/abraham'])
22*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'service1/barack'])
23*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'service2/calvin'])
24*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'service2/dwight'])
25*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-'])
26*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'http/localhost'])
27*7f2fe78bSCy Schubertrealm.run([kadminl, 'xst', 'service1/abraham'])
28*7f2fe78bSCy Schubertrealm.run([kadminl, 'xst', 'service1/barack'])
29*7f2fe78bSCy Schubertrealm.run([kadminl, 'xst', 'service2/calvin'])
30*7f2fe78bSCy Schubertrealm.run([kadminl, 'xst', 'http/localhost'])
31*7f2fe78bSCy Schubertrealm.run([kadminl, 'renprinc', 'service1/abraham', 'service1/andrew'])
32*7f2fe78bSCy Schubert
33*7f2fe78bSCy Schubert# Test with no default realm and no dots in the server name.
34*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'h:http@localhost'], expected_msg='http/localhost')
35*7f2fe78bSCy Schubertremove_default = {'libdefaults': {'default_realm': None}}
36*7f2fe78bSCy Schubertno_default = realm.special_env('no_default', False, krb5_conf=remove_default)
37*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'h:http@localhost'], expected_msg='http/localhost',
38*7f2fe78bSCy Schubert          env=no_default)
39*7f2fe78bSCy Schubert
40*7f2fe78bSCy Schubert# Test with no acceptor name, including client/keytab principal
41*7f2fe78bSCy Schubert# mismatch (non-fatal) and missing keytab entry (fatal).
42*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service1/andrew'],
43*7f2fe78bSCy Schubert          expected_msg='service1/abraham')
44*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service1/barack'], expected_msg='service1/barack')
45*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service2/calvin'], expected_msg='service2/calvin')
46*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service2/dwight'], expected_code=1,
47*7f2fe78bSCy Schubert          expected_msg=' not found in keytab')
48*7f2fe78bSCy Schubert
49*7f2fe78bSCy Schubert# Test with acceptor name containing service only, including
50*7f2fe78bSCy Schubert# client/keytab hostname mismatch (non-fatal) and service name
51*7f2fe78bSCy Schubert# mismatch (fatal).
52*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service1/andrew', 'h:service1'],
53*7f2fe78bSCy Schubert          expected_msg='service1/abraham')
54*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], expected_code=1,
55*7f2fe78bSCy Schubert          expected_msg=' not found in keytab')
56*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service2/calvin', 'h:service2'],
57*7f2fe78bSCy Schubert          expected_msg='service2/calvin')
58*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1,
59*7f2fe78bSCy Schubert          expected_msg=' found in keytab but does not match server principal')
60*7f2fe78bSCy Schubert# Regression test for #8892 (trailing @ in name).
61*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:service1/andrew', 'h:service1@'],
62*7f2fe78bSCy Schubert          expected_msg='service1/abraham')
63*7f2fe78bSCy Schubert
64*7f2fe78bSCy Schubert# Test with acceptor name containing service and host.  Use the
65*7f2fe78bSCy Schubert# client's un-canonicalized hostname as acceptor input to mirror what
66*7f2fe78bSCy Schubert# many servers do.
67*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:' + realm.host_princ,
68*7f2fe78bSCy Schubert           'h:host@%s' % socket.gethostname()], expected_msg=realm.host_princ)
69*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:host/-nomatch-',
70*7f2fe78bSCy Schubert           'h:host@%s' % socket.gethostname()], expected_code=1,
71*7f2fe78bSCy Schubert          expected_msg=' not found in keytab')
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert# If possible, test with an acceptor name requiring fallback to match
74*7f2fe78bSCy Schubert# against a keytab entry.
75*7f2fe78bSCy Schubertcanonname = canonicalize_hostname(hostname)
76*7f2fe78bSCy Schubertif canonname != hostname:
77*7f2fe78bSCy Schubert    os.rename(realm.keytab, realm.keytab + '.save')
78*7f2fe78bSCy Schubert    canonprinc = 'host/' + canonname
79*7f2fe78bSCy Schubert    realm.run([kadminl, 'addprinc', '-randkey', canonprinc])
80*7f2fe78bSCy Schubert    realm.extract_keytab(canonprinc, realm.keytab)
81*7f2fe78bSCy Schubert    # Use the canonical name for the initiator's target name, since
82*7f2fe78bSCy Schubert    # host/hostname exists in the KDB (but not the keytab).
83*7f2fe78bSCy Schubert    realm.run(['./t_accname', 'h:host@' + canonname, 'h:host@' + hostname])
84*7f2fe78bSCy Schubert    os.rename(realm.keytab + '.save', realm.keytab)
85*7f2fe78bSCy Schubertelse:
86*7f2fe78bSCy Schubert    skipped('GSS acceptor name fallback test',
87*7f2fe78bSCy Schubert            '%s does not canonicalize to a different name' % hostname)
88*7f2fe78bSCy Schubert
89*7f2fe78bSCy Schubert# Test krb5_gss_import_cred.
90*7f2fe78bSCy Schubertrealm.run(['./t_imp_cred', 'p:service1/barack'])
91*7f2fe78bSCy Schubertrealm.run(['./t_imp_cred', 'p:service1/barack', 'service1/barack'])
92*7f2fe78bSCy Schubertrealm.run(['./t_imp_cred', 'p:service1/andrew', 'service1/abraham'])
93*7f2fe78bSCy Schubertrealm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1,
94*7f2fe78bSCy Schubert          expected_msg=' not found in keytab')
95*7f2fe78bSCy Schubert
96*7f2fe78bSCy Schubert# Verify that we can't acquire acceptor creds without a keytab.
97*7f2fe78bSCy Schubertos.remove(realm.keytab)
98*7f2fe78bSCy Schubertout = realm.run(['./t_accname', 'p:abc'], expected_code=1)
99*7f2fe78bSCy Schubertif ('gss_acquire_cred: Keytab' not in out or
100*7f2fe78bSCy Schubert    'nonexistent or empty' not in out):
101*7f2fe78bSCy Schubert    fail('Expected error message not seen for nonexistent keytab')
102*7f2fe78bSCy Schubert
103*7f2fe78bSCy Schubertrealm.stop()
104*7f2fe78bSCy Schubert
105*7f2fe78bSCy Schubert# Re-run the last acceptor name test with ignore_acceptor_hostname set
106*7f2fe78bSCy Schubert# and the principal for the mismatching hostname in the keytab.
107*7f2fe78bSCy Schubertignore_conf = {'libdefaults': {'ignore_acceptor_hostname': 'true'}}
108*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=ignore_conf)
109*7f2fe78bSCy Schubertrealm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-'])
110*7f2fe78bSCy Schubertrealm.run([kadminl, 'xst', 'host/-nomatch-'])
111*7f2fe78bSCy Schubertrealm.run(['./t_accname', 'p:host/-nomatch-',
112*7f2fe78bSCy Schubert           'h:host@%s' % socket.gethostname()], expected_msg='host/-nomatch-')
113*7f2fe78bSCy Schubert
114*7f2fe78bSCy Schubertrealm.stop()
115*7f2fe78bSCy Schubert
116*7f2fe78bSCy Schubert# Make sure a GSSAPI acceptor can handle cross-realm tickets with a
117*7f2fe78bSCy Schubert# transited field.  (Regression test for #7639.)
118*7f2fe78bSCy Schubertr1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
119*7f2fe78bSCy Schubert                          create_user=False, create_host=False,
120*7f2fe78bSCy Schubert                          args=[{'realm': 'A.X', 'create_user': True},
121*7f2fe78bSCy Schubert                                {'realm': 'X'},
122*7f2fe78bSCy Schubert                                {'realm': 'B.X', 'create_host': True}])
123*7f2fe78bSCy Schubertos.rename(r3.keytab, r1.keytab)
124*7f2fe78bSCy Schubertr1.run(['./t_accname', 'p:' + r3.host_princ, 'h:host'])
125*7f2fe78bSCy Schubertr1.stop()
126*7f2fe78bSCy Schubertr2.stop()
127*7f2fe78bSCy Schubertr3.stop()
128*7f2fe78bSCy Schubert
129*7f2fe78bSCy Schubert### Test gss_inquire_cred behavior.
130*7f2fe78bSCy Schubert
131*7f2fe78bSCy Schubertrealm = K5Realm()
132*7f2fe78bSCy Schubert
133*7f2fe78bSCy Schubert# Test deferred resolution of the default ccache for initiator creds.
134*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred'], expected_msg=realm.user_princ)
135*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ)
136*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-s'], expected_msg=realm.user_princ)
137*7f2fe78bSCy Schubert
138*7f2fe78bSCy Schubert# Test picking a name from the keytab for acceptor creds.
139*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-a'], expected_msg=realm.host_princ)
140*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-k', '-a'], expected_msg=realm.host_princ)
141*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-s', '-a'], expected_msg=realm.host_princ)
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert# Test client keytab initiation (non-deferred) with a specified name.
144*7f2fe78bSCy Schubertrealm.extract_keytab(realm.user_princ, realm.client_keytab)
145*7f2fe78bSCy Schubertos.remove(realm.ccache)
146*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ)
147*7f2fe78bSCy Schubert
148*7f2fe78bSCy Schubert# Test deferred client keytab initiation and GSS_C_BOTH cred usage.
149*7f2fe78bSCy Schubertos.remove(realm.client_keytab)
150*7f2fe78bSCy Schubertos.remove(realm.ccache)
151*7f2fe78bSCy Schubertshutil.copyfile(realm.keytab, realm.client_keytab)
152*7f2fe78bSCy Schubertrealm.run(['./t_inq_cred', '-k', '-b'], expected_msg=realm.host_princ)
153*7f2fe78bSCy Schubert
154*7f2fe78bSCy Schubert# Test gss_export_name behavior.
155*7f2fe78bSCy Schubertrealm.run(['./t_export_name', 'u:x'], expected_msg=\
156*7f2fe78bSCy Schubert          '0401000B06092A864886F7120102020000000D78404B5242544553542E434F4D\n')
157*7f2fe78bSCy Schubertrealm.run(['./t_export_name', '-s', 'u:xyz'],
158*7f2fe78bSCy Schubert          expected_msg='0401000806062B06010505020000000378797A\n')
159*7f2fe78bSCy Schubertrealm.run(['./t_export_name', 'p:a@b'],
160*7f2fe78bSCy Schubert          expected_msg='0401000B06092A864886F71201020200000003614062\n')
161*7f2fe78bSCy Schubertrealm.run(['./t_export_name', '-s', 'p:a@b'],
162*7f2fe78bSCy Schubert          expected_msg='0401000806062B060105050200000003614062\n')
163*7f2fe78bSCy Schubert
164*7f2fe78bSCy Schubert# Test that composite-export tokens can be imported.
165*7f2fe78bSCy Schubertrealm.run(['./t_export_name', '-c', 'p:a@b'], expected_msg=
166*7f2fe78bSCy Schubert          '0402000B06092A864886F7120102020000000361406200000000\n')
167*7f2fe78bSCy Schubert
168*7f2fe78bSCy Schubert# Test gss_inquire_mechs_for_name behavior.
169*7f2fe78bSCy Schubertkrb5_mech = '{ 1 2 840 113554 1 2 2 }'
170*7f2fe78bSCy Schubertspnego_mech = '{ 1 3 6 1 5 5 2 }'
171*7f2fe78bSCy Schubertout = realm.run(['./t_inq_mechs_name', 'p:a@b'])
172*7f2fe78bSCy Schubertif krb5_mech not in out:
173*7f2fe78bSCy Schubert    fail('t_inq_mechs_name (principal)')
174*7f2fe78bSCy Schubertout = realm.run(['./t_inq_mechs_name', 'u:x'])
175*7f2fe78bSCy Schubertif krb5_mech not in out or spnego_mech not in out:
176*7f2fe78bSCy Schubert    fail('t_inq_mecs_name (user)')
177*7f2fe78bSCy Schubertout = realm.run(['./t_inq_mechs_name', 'h:host'])
178*7f2fe78bSCy Schubertif krb5_mech not in out or spnego_mech not in out:
179*7f2fe78bSCy Schubert    fail('t_inq_mecs_name (hostbased)')
180*7f2fe78bSCy Schubert
181*7f2fe78bSCy Schubert# Test that accept_sec_context can produce an error token and
182*7f2fe78bSCy Schubert# init_sec_context can interpret it.
183*7f2fe78bSCy Schubertrealm.run(['./t_err', 'p:' + realm.host_princ])
184*7f2fe78bSCy Schubertrealm.run(['./t_err', '--spnego', 'p:' + realm.host_princ])
185*7f2fe78bSCy Schubert
186*7f2fe78bSCy Schubert# Test the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option.
187*7f2fe78bSCy Schubertrealm.run(['./t_ciflags', 'p:' + realm.host_princ])
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy Schubert# Test that inquire_context works properly, even on incomplete
190*7f2fe78bSCy Schubert# contexts.
191*7f2fe78bSCy Schubertrealm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ])
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubertif runenv.sizeof_time_t <= 4:
194*7f2fe78bSCy Schubert    skip_rest('y2038 GSSAPI tests', 'platform has 32-bit time_t')
195*7f2fe78bSCy Schubert
196*7f2fe78bSCy Schubert# Test lifetime results, using a realm with a large maximum lifetime
197*7f2fe78bSCy Schubert# so that we can test ticket end dates after y2038.
198*7f2fe78bSCy Schubertrealm.stop()
199*7f2fe78bSCy Schubertconf = {'realms': {'$realm': {'max_life': '9000d'}}}
200*7f2fe78bSCy Schubertrealm = K5Realm(kdc_conf=conf, get_creds=False)
201*7f2fe78bSCy Schubert
202*7f2fe78bSCy Schubert# Check a lifetime string result against an expected number value (or None).
203*7f2fe78bSCy Schubert# Allow some variance due to time elapsed during the tests.
204*7f2fe78bSCy Schubertdef check_lifetime(msg, val, expected):
205*7f2fe78bSCy Schubert    if expected is None and val != 'indefinite':
206*7f2fe78bSCy Schubert        fail('%s: expected indefinite, got %s' % (msg, val))
207*7f2fe78bSCy Schubert    if expected is not None and val == 'indefinite':
208*7f2fe78bSCy Schubert        fail('%s: expected %d, got indefinite' % (msg, expected))
209*7f2fe78bSCy Schubert    if expected is not None and abs(int(val) - expected) > 100:
210*7f2fe78bSCy Schubert        fail('%s: expected %d, got %s' % (msg, expected, val))
211*7f2fe78bSCy Schubert
212*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d'])
213*7f2fe78bSCy Schubertout = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)])
214*7f2fe78bSCy Schubertln = out.split('\n')
215*7f2fe78bSCy Schubertcheck_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400)
216*7f2fe78bSCy Schubertcheck_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400)
217*7f2fe78bSCy Schubertcheck_lifetime('acred gss_acquire_cred', ln[2], None)
218*7f2fe78bSCy Schubertcheck_lifetime('acred gss_inquire_cred', ln[3], None)
219*7f2fe78bSCy Schubertcheck_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400)
220*7f2fe78bSCy Schubertcheck_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400)
221*7f2fe78bSCy Schubertcheck_lifetime('ictx gss_context_time', ln[6], 8000 * 86400)
222*7f2fe78bSCy Schubertcheck_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300)
223*7f2fe78bSCy Schubertcheck_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300)
224*7f2fe78bSCy Schubertcheck_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300)
225*7f2fe78bSCy Schubert
226*7f2fe78bSCy Schubertsuccess('GSSAPI tests')
227