2 # Unix SMB/CIFS implementation.
3 # Copyright (C) Stefan Metzmacher 2020
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 sys
.path
.insert(0, "bin/python")
23 os
.environ
["PYTHONUNBUFFERED"] = "1"
25 from samba
.tests
import DynamicTestCase
26 from samba
.tests
.krb5
.kdc_base_test
import KDCBaseTest
27 import samba
.tests
.krb5
.kcrypto
as kcrypto
28 import samba
.tests
.krb5
.rfc4120_pyasn1
as krb5_asn1
29 from samba
.tests
.krb5
.rfc4120_constants
import (
31 KDC_ERR_PREAUTH_REQUIRED
,
38 global_asn1_print
= False
39 global_hexdump
= False
42 class AsReqBaseTest(KDCBaseTest
):
43 def _run_as_req_enc_timestamp(self
, client_creds
):
44 client_account
= client_creds
.get_username()
45 client_as_etypes
= self
.get_default_enctypes()
46 client_kvno
= client_creds
.get_kvno()
47 krbtgt_creds
= self
.get_krbtgt_creds(require_strongest_key
=True)
48 krbtgt_account
= krbtgt_creds
.get_username()
49 realm
= krbtgt_creds
.get_realm()
51 cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
52 names
=[client_account
])
53 sname
= self
.PrincipalName_create(name_type
=NT_SRV_INST
,
54 names
=[krbtgt_account
, realm
])
56 expected_crealm
= realm
57 expected_cname
= cname
58 expected_srealm
= realm
59 expected_sname
= sname
60 expected_salt
= client_creds
.get_salt()
62 till
= self
.get_KerberosTime(offset
=36000)
64 initial_etypes
= client_as_etypes
65 initial_kdc_options
= krb5_asn1
.KDCOptions('forwardable')
66 initial_error_mode
= KDC_ERR_PREAUTH_REQUIRED
68 rep
, kdc_exchange_dict
= self
._test
_as
_exchange
(cname
,
83 etype_info2
= kdc_exchange_dict
['preauth_etype_info2']
84 self
.assertIsNotNone(etype_info2
)
86 preauth_key
= self
.PasswordKey_from_etype_info2(client_creds
,
90 (patime
, pausec
) = self
.get_KerberosTimeWithUsec()
91 pa_ts
= self
.PA_ENC_TS_ENC_create(patime
, pausec
)
92 pa_ts
= self
.der_encode(pa_ts
, asn1Spec
=krb5_asn1
.PA_ENC_TS_ENC())
94 enc_pa_ts_usage
= KU_PA_ENC_TIMESTAMP
95 pa_ts
= self
.EncryptedData_create(preauth_key
, enc_pa_ts_usage
, pa_ts
)
96 pa_ts
= self
.der_encode(pa_ts
, asn1Spec
=krb5_asn1
.EncryptedData())
98 pa_ts
= self
.PA_DATA_create(PADATA_ENC_TIMESTAMP
, pa_ts
)
100 preauth_padata
= [pa_ts
]
101 preauth_etypes
= client_as_etypes
102 preauth_kdc_options
= krb5_asn1
.KDCOptions('forwardable')
103 preauth_error_mode
= 0 # AS-REP
105 krbtgt_decryption_key
= (
106 self
.TicketDecryptionKey_from_creds(krbtgt_creds
))
108 as_rep
, kdc_exchange_dict
= self
._test
_as
_exchange
(
123 preauth_key
=preauth_key
,
124 ticket_decryption_key
=krbtgt_decryption_key
,
126 self
.assertIsNotNone(as_rep
)
132 class AsReqKerberosTests(AsReqBaseTest
):
135 def setUpDynamicTestCases(cls
):
136 for (name
, idx
) in cls
.etype_test_permutation_name_idx():
137 for pac
in [None, True, False]:
138 tname
= "%s_pac_%s" % (name
, pac
)
140 cls
.generate_dynamic_test("test_as_req_no_preauth", tname
, *targs
)
143 super(AsReqKerberosTests
, self
).setUp()
144 self
.do_asn1_print
= global_asn1_print
145 self
.do_hexdump
= global_hexdump
147 def _test_as_req_nopreauth(self
,
150 initial_kdc_options
=None):
151 client_creds
= self
.get_client_creds()
152 client_account
= client_creds
.get_username()
153 client_as_etypes
= self
.get_default_enctypes()
154 krbtgt_creds
= self
.get_krbtgt_creds(require_keys
=False)
155 krbtgt_account
= krbtgt_creds
.get_username()
156 realm
= krbtgt_creds
.get_realm()
158 cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
159 names
=[client_account
])
160 sname
= self
.PrincipalName_create(name_type
=NT_SRV_INST
,
161 names
=[krbtgt_account
, realm
])
163 expected_crealm
= realm
164 expected_cname
= cname
165 expected_srealm
= realm
166 expected_sname
= sname
167 expected_salt
= client_creds
.get_salt()
169 if any(etype
in client_as_etypes
and etype
in initial_etypes
170 for etype
in (kcrypto
.Enctype
.AES256
,
171 kcrypto
.Enctype
.AES128
,
172 kcrypto
.Enctype
.RC4
)):
173 expected_error_mode
= KDC_ERR_PREAUTH_REQUIRED
175 expected_error_mode
= KDC_ERR_ETYPE_NOSUPP
177 kdc_exchange_dict
= self
.as_exchange_dict(
178 expected_crealm
=expected_crealm
,
179 expected_cname
=expected_cname
,
180 expected_srealm
=expected_srealm
,
181 expected_sname
=expected_sname
,
182 generate_padata_fn
=None,
183 check_error_fn
=self
.generic_check_kdc_error
,
185 expected_error_mode
=expected_error_mode
,
186 client_as_etypes
=client_as_etypes
,
187 expected_salt
=expected_salt
,
188 kdc_options
=str(initial_kdc_options
),
191 self
._generic
_kdc
_exchange
(kdc_exchange_dict
,
195 etypes
=initial_etypes
)
197 def _test_as_req_no_preauth_with_args(self
, etype_idx
, pac
):
198 name
, etypes
= self
.etype_test_permutation_by_idx(etype_idx
)
199 self
._test
_as
_req
_nopreauth
(
201 initial_etypes
=etypes
,
202 initial_kdc_options
=krb5_asn1
.KDCOptions('forwardable'))
204 def test_as_req_enc_timestamp(self
):
205 client_creds
= self
.get_client_creds()
206 self
._run
_as
_req
_enc
_timestamp
(client_creds
)
208 def test_as_req_enc_timestamp_mac(self
):
209 client_creds
= self
.get_mach_creds()
210 self
._run
_as
_req
_enc
_timestamp
(client_creds
)
212 def test_as_req_enc_timestamp_rc4(self
):
213 client_creds
= self
.get_client_creds()
214 self
._run
_as
_req
_enc
_timestamp
(
216 etypes
={kcrypto
.Enctype
.RC4
})
218 def test_as_req_enc_timestamp_mac_rc4(self
):
219 client_creds
= self
.get_mach_creds()
220 self
._run
_as
_req
_enc
_timestamp
(
222 etypes
={kcrypto
.Enctype
.RC4
})
224 def test_as_req_enc_timestamp_rc4_dummy(self
):
225 client_creds
= self
.get_client_creds()
226 self
._run
_as
_req
_enc
_timestamp
(
228 etypes
={kcrypto
.Enctype
.RC4
,
231 def test_as_req_enc_timestamp_mac_rc4_dummy(self
):
232 client_creds
= self
.get_mach_creds()
233 self
._run
_as
_req
_enc
_timestamp
(
235 etypes
={kcrypto
.Enctype
.RC4
,
238 def test_as_req_enc_timestamp_aes128_rc4(self
):
239 client_creds
= self
.get_client_creds()
240 self
._run
_as
_req
_enc
_timestamp
(
242 etypes
={kcrypto
.Enctype
.AES128
,
243 kcrypto
.Enctype
.RC4
})
245 def test_as_req_enc_timestamp_mac_aes128_rc4(self
):
246 client_creds
= self
.get_mach_creds()
247 self
._run
_as
_req
_enc
_timestamp
(
249 etypes
={kcrypto
.Enctype
.AES128
,
250 kcrypto
.Enctype
.RC4
})
253 if __name__
== "__main__":
254 global_asn1_print
= False
255 global_hexdump
= False