Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/tests/t_crossrealm.py
34878 views
1
# Copyright (C) 2011 by the Massachusetts Institute of Technology.
2
# All rights reserved.
3
#
4
# Export of this software from the United States of America may
5
# require a specific license from the United States Government.
6
# It is the responsibility of any person or organization contemplating
7
# export to obtain such a license before exporting.
8
#
9
# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10
# distribute this software and its documentation for any purpose and
11
# without fee is hereby granted, provided that the above copyright
12
# notice appear in all copies and that both that copyright notice and
13
# this permission notice appear in supporting documentation, and that
14
# the name of M.I.T. not be used in advertising or publicity pertaining
15
# to distribution of the software without specific, written prior
16
# permission. Furthermore if you modify this software you must label
17
# your software as modified software and not distribute it in such a
18
# fashion that it might be confused with the original M.I.T. software.
19
# M.I.T. makes no representations about the suitability of
20
# this software for any purpose. It is provided "as is" without express
21
# or implied warranty.
22
23
from k5test import *
24
25
def test_kvno(r, princ, test, env=None):
26
r.run([kvno, princ], env=env, expected_msg=princ)
27
28
29
def stop(*realms):
30
for r in realms:
31
r.stop()
32
33
34
# Verify that the princs appear as the service principals in the klist
35
# output for the realm r, in order.
36
def check_klist(r, princs):
37
out = r.run([klist])
38
count = 0
39
seen_header = False
40
for l in out.split('\n'):
41
if l.startswith('Valid starting'):
42
seen_header = True
43
continue
44
if not seen_header or l == '':
45
continue
46
if count >= len(princs):
47
fail('too many entries in klist output')
48
svcprinc = l.split()[4]
49
if svcprinc != princs[count]:
50
fail('saw service princ %s in klist output, expected %s' %
51
(svcprinc, princs[count]))
52
count += 1
53
if count != len(princs):
54
fail('not enough entries in klist output')
55
56
57
def tgt(r1, r2):
58
return 'krbtgt/%s@%s' % (r1.realm, r2.realm)
59
60
61
# Basic two-realm test with cross TGTs in both directions.
62
mark('two realms')
63
r1, r2 = cross_realms(2)
64
test_kvno(r1, r2.host_princ, 'basic r1->r2')
65
check_klist(r1, (tgt(r1, r1), tgt(r2, r1), r2.host_princ))
66
test_kvno(r2, r1.host_princ, 'basic r2->r1')
67
check_klist(r2, (tgt(r2, r2), tgt(r1, r2), r1.host_princ))
68
stop(r1, r2)
69
70
# Test the KDC domain walk for hierarchically arranged realms. The
71
# client in A.X will ask for a cross TGT to B.X, but A.X's KDC only
72
# has a TGT for the intermediate realm X, so it will return that
73
# instead. The client will use that to get a TGT for B.X.
74
mark('hierarchical realms')
75
r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
76
args=({'realm': 'A.X'}, {'realm': 'X'},
77
{'realm': 'B.X'}))
78
test_kvno(r1, r3.host_princ, 'KDC domain walk')
79
check_klist(r1, (tgt(r1, r1), r3.host_princ))
80
81
# Test start_realm in this setup.
82
r1.run([kvno, '--out-cache', r1.ccache, r2.krbtgt_princ])
83
r1.run([klist, '-C'], expected_msg='config: start_realm = X')
84
msgs = ('Requesting TGT krbtgt/B.X@X using TGT krbtgt/X@X',
85
'Received TGT for service realm: krbtgt/B.X@X')
86
r1.run([kvno, r3.host_princ], expected_trace=msgs)
87
88
stop(r1, r2, r3)
89
90
# Test client capaths. The client in A will ask for a cross TGT to D,
91
# but A's KDC won't have it and won't know an intermediate to return.
92
# The client will walk its A->D capaths to get TGTs for B, then C,
93
# then D. The KDCs for C and D need capaths settings to avoid failing
94
# transited checks, including a capaths for A->C.
95
mark('client capaths')
96
capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}}}
97
r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)),
98
args=({'realm': 'A'},
99
{'realm': 'B'},
100
{'realm': 'C', 'krb5_conf': capaths},
101
{'realm': 'D', 'krb5_conf': capaths}))
102
r1client = r1.special_env('client', False, krb5_conf=capaths)
103
test_kvno(r1, r4.host_princ, 'client capaths', r1client)
104
check_klist(r1, (tgt(r1, r1), tgt(r2, r1), tgt(r3, r2), tgt(r4, r3),
105
r4.host_princ))
106
stop(r1, r2, r3, r4)
107
108
# Test KDC capaths. The KDCs for A and B have appropriate capaths
109
# settings to determine intermediate TGTs to return, but the client
110
# has no idea.
111
mark('kdc capaths')
112
capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}, 'B': {'D': 'C'}}}
113
r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)),
114
args=({'realm': 'A', 'krb5_conf': capaths},
115
{'realm': 'B', 'krb5_conf': capaths},
116
{'realm': 'C', 'krb5_conf': capaths},
117
{'realm': 'D', 'krb5_conf': capaths}))
118
r1client = r1.special_env('client', False, krb5_conf={'capaths': None})
119
test_kvno(r1, r4.host_princ, 'KDC capaths', r1client)
120
check_klist(r1, (tgt(r1, r1), r4.host_princ))
121
stop(r1, r2, r3, r4)
122
123
# A capaths value of '.' should enforce direct cross-realm, with no
124
# intermediate.
125
mark('direct cross-realm enforcement')
126
capaths = {'capaths': {'A.X': {'B.X': '.'}}}
127
r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
128
args=({'realm': 'A.X', 'krb5_conf': capaths},
129
{'realm': 'X'}, {'realm': 'B.X'}))
130
r1.run([kvno, r3.host_princ], expected_code=1,
131
expected_msg='Server krbtgt/[email protected] not found in Kerberos database')
132
stop(r1, r2, r3)
133
134
# Test transited error. The KDC for C does not recognize B as an
135
# intermediate realm for A->C, so it refuses to issue a service
136
# ticket.
137
mark('transited error (three realms)')
138
capaths = {'capaths': {'A': {'C': 'B'}}}
139
r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
140
args=({'realm': 'A', 'krb5_conf': capaths},
141
{'realm': 'B'}, {'realm': 'C'}))
142
r1.run([kvno, r3.host_princ], expected_code=1,
143
expected_msg='KDC policy rejects request')
144
check_klist(r1, (tgt(r1, r1), tgt(r3, r2)))
145
stop(r1, r2, r3)
146
147
# Test server transited checking. The KDC for C recognizes B as an
148
# intermediate realm for A->C, but the server environment does not.
149
# The server should honor the ticket if the transited-policy-checked
150
# flag is set, but not if it isn't. (It is only possible for our KDC
151
# to issue a ticket without the transited-policy-checked flag with
152
# reject_bad_transit=false.)
153
mark('server transited checking')
154
capaths = {'capaths': {'A': {'C': 'B'}}}
155
noreject = {'realms': {'$realm': {'reject_bad_transit': 'false'}}}
156
r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)),
157
args=({'realm': 'A', 'krb5_conf': capaths},
158
{'realm': 'B'},
159
{'realm': 'C', 'krb5_conf': capaths,
160
'kdc_conf': noreject}))
161
r3server = r3.special_env('server', False, krb5_conf={'capaths': None})
162
# Process a ticket with the transited-policy-checked flag set.
163
shutil.copy(r1.ccache, r1.ccache + '.copy')
164
r1.run(['./gcred', 'principal', r3.host_princ])
165
os.rename(r1.ccache, r3.ccache)
166
r3.run(['./rdreq', r3.host_princ], env=r3server, expected_msg='0 success')
167
# Try again with the transited-policy-checked flag unset.
168
os.rename(r1.ccache + '.copy', r1.ccache)
169
r1.run(['./gcred', '-t', 'principal', r3.host_princ])
170
os.rename(r1.ccache, r3.ccache)
171
r3.run(['./rdreq', r3.host_princ], env=r3server,
172
expected_msg='43 Illegal cross-realm ticket')
173
stop(r1, r2, r3)
174
175
# Test a four-realm scenario. This test used to result in an "Illegal
176
# cross-realm ticket" error as the KDC for D would refuse to process
177
# the cross-realm ticket from C. Now that we honor the
178
# transited-policy-checked flag in krb5_rd_req(), it instead issues a
179
# policy error as in the three-realm scenario.
180
mark('transited error (four realms)')
181
capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}, 'B': {'D': 'C'}}}
182
r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)),
183
args=({'realm': 'A', 'krb5_conf': capaths},
184
{'realm': 'B', 'krb5_conf': capaths},
185
{'realm': 'C', 'krb5_conf': capaths},
186
{'realm': 'D'}))
187
r1.run([kvno, r4.host_princ], expected_code=1,
188
expected_msg='KDC policy rejects request')
189
check_klist(r1, (tgt(r1, r1), tgt(r4, r3)))
190
stop(r1, r2, r3, r4)
191
192
success('Cross-realm tests')
193
194