2 # Unix SMB/CIFS implementation.
3 # Copyright (C) Stefan Metzmacher 2020
4 # Copyright (C) 2020 Catalyst.Net Ltd
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 sys.path.insert(0, "bin/python")
24 os.environ["PYTHONUNBUFFERED"] = "1"
31 from samba.dcerpc import krb5pac, security
32 from samba.tests.krb5.raw_testcase import Krb5EncryptionKey, ZeroedChecksumKey
33 from samba.tests.krb5.kdc_base_test import KDCBaseTest
34 from samba.tests.krb5.rfc4120_constants import (
37 AES256_CTS_HMAC_SHA1_96,
39 FX_FAST_ARMOR_AP_REQUEST,
40 KDC_ERR_BAD_INTEGRITY,
43 KDC_ERR_S_PRINCIPAL_UNKNOWN,
47 KDC_ERR_PREAUTH_FAILED,
48 KDC_ERR_PREAUTH_REQUIRED,
50 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
53 KU_TGS_REQ_AUTH_DAT_SESSION,
54 KU_TGS_REQ_AUTH_DAT_SUBKEY,
60 PADATA_REQ_ENC_PA_REP,
62 import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
63 import samba.tests.krb5.kcrypto as kcrypto
65 global_asn1_print = False
66 global_hexdump = False
69 class FAST_Tests(KDCBaseTest):
72 self.do_asn1_print = global_asn1_print
73 self.do_hexdump = global_hexdump
75 def test_simple(self):
76 self._run_test_sequence([
78 'rep_type': KRB_AS_REP,
79 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
83 'rep_type': KRB_AS_REP,
84 'expected_error_mode': 0,
86 'gen_padata_fn': self.generate_enc_timestamp_padata
90 def test_simple_as_req_self(self):
91 self._run_test_sequence([
93 'rep_type': KRB_AS_REP,
94 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
99 'rep_type': KRB_AS_REP,
100 'expected_error_mode': 0,
102 'gen_padata_fn': self.generate_enc_timestamp_padata,
105 ], client_account=self.AccountType.COMPUTER)
107 def test_simple_as_req_self_no_auth_data(self):
108 self._run_test_sequence(
111 'rep_type': KRB_AS_REP,
112 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
117 'rep_type': KRB_AS_REP,
118 'expected_error_mode': 0,
120 'gen_padata_fn': self.generate_enc_timestamp_padata,
125 client_account=self.AccountType.COMPUTER,
126 client_opts={'no_auth_data_required': True})
128 def test_simple_as_req_self_pac_request_false(self):
129 self._run_test_sequence([
131 'rep_type': KRB_AS_REP,
132 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
137 'rep_type': KRB_AS_REP,
138 'expected_error_mode': 0,
140 'gen_padata_fn': self.generate_enc_timestamp_padata,
142 'pac_request': False,
145 ], client_account=self.AccountType.COMPUTER)
147 def test_simple_as_req_self_pac_request_none(self):
148 self._run_test_sequence([
150 'rep_type': KRB_AS_REP,
151 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
156 'rep_type': KRB_AS_REP,
157 'expected_error_mode': 0,
159 'gen_padata_fn': self.generate_enc_timestamp_padata,
164 ], client_account=self.AccountType.COMPUTER)
166 def test_simple_as_req_self_pac_request_true(self):
167 self._run_test_sequence([
169 'rep_type': KRB_AS_REP,
170 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
175 'rep_type': KRB_AS_REP,
176 'expected_error_mode': 0,
178 'gen_padata_fn': self.generate_enc_timestamp_padata,
183 ], client_account=self.AccountType.COMPUTER)
185 def test_simple_tgs(self):
186 self._run_test_sequence([
188 'rep_type': KRB_TGS_REP,
189 'expected_error_mode': 0,
191 'gen_tgt_fn': self.get_user_tgt
195 def test_fast_rodc_issued_armor(self):
196 self._run_test_sequence([
198 'rep_type': KRB_AS_REP,
199 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
201 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
202 'gen_armor_tgt_fn': self.get_rodc_issued_mach_tgt,
205 'rep_type': KRB_AS_REP,
206 # Test that RODC-issued armor tickets are permitted.
207 'expected_error_mode': 0,
209 'gen_padata_fn': self.generate_enc_challenge_padata,
210 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
211 'gen_armor_tgt_fn': self.get_rodc_issued_mach_tgt,
215 'allowed_replication_mock': True,
216 'revealed_to_mock_rodc': True,
219 def test_fast_tgs_rodc_issued_armor(self):
220 self._run_test_sequence([
222 'rep_type': KRB_TGS_REP,
223 # Test that RODC-issued armor tickets are not permitted.
224 'expected_error_mode': 0,
226 'gen_tgt_fn': self.get_user_tgt,
227 'gen_armor_tgt_fn': self.get_rodc_issued_mach_tgt,
228 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
232 'allowed_replication_mock': True,
233 'revealed_to_mock_rodc': True,
236 def test_simple_enc_pa_rep(self):
237 self._run_test_sequence([
239 'rep_type': KRB_AS_REP,
240 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
244 'rep_type': KRB_AS_REP,
245 'expected_error_mode': 0,
247 'gen_padata_fn': self.generate_enc_pa_rep_timestamp_padata,
248 'expected_flags': 'enc-pa-rep'
252 # Currently we only send PADATA-REQ-ENC-PA-REP for AS-REQ requests.
253 def test_simple_tgs_enc_pa_rep(self):
254 self._run_test_sequence([
256 'rep_type': KRB_TGS_REP,
257 'expected_error_mode': 0,
259 'gen_tgt_fn': self.get_user_tgt,
260 'gen_padata_fn': self.generate_enc_pa_rep_padata,
261 'expected_flags': 'enc-pa-rep'
265 def test_simple_no_sname(self):
266 expected_sname = self.get_krbtgt_sname()
268 self._run_test_sequence([
270 'rep_type': KRB_AS_REP,
271 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
274 'expected_sname': expected_sname,
275 'expect_edata': False
279 def test_simple_tgs_no_sname(self):
280 expected_sname = self.get_krbtgt_sname()
282 self._run_test_sequence([
284 'rep_type': KRB_TGS_REP,
285 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
287 'gen_tgt_fn': self.get_user_tgt,
289 'expected_sname': expected_sname,
290 'expect_edata': False
294 def test_fast_no_sname(self):
295 expected_sname = self.get_krbtgt_sname()
297 self._run_test_sequence([
299 'rep_type': KRB_AS_REP,
300 'expected_error_mode': (KDC_ERR_GENERIC,
301 KDC_ERR_S_PRINCIPAL_UNKNOWN),
303 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
304 'gen_armor_tgt_fn': self.get_mach_tgt,
306 'expected_sname': expected_sname,
307 'strict_edata_checking': False
311 def test_fast_tgs_no_sname(self):
312 expected_sname = self.get_krbtgt_sname()
314 self._run_test_sequence([
316 'rep_type': KRB_TGS_REP,
317 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
319 'gen_tgt_fn': self.get_user_tgt,
322 'expected_sname': expected_sname,
323 'strict_edata_checking': False
327 def test_fast_inner_no_sname(self):
328 expected_sname = self.get_krbtgt_sname()
330 self._run_test_sequence([
332 'rep_type': KRB_AS_REP,
333 'expected_error_mode': (KDC_ERR_GENERIC,
334 KDC_ERR_S_PRINCIPAL_UNKNOWN),
336 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
337 'gen_armor_tgt_fn': self.get_mach_tgt,
339 'sname': None # should be ignored
341 'expected_sname': expected_sname,
342 'strict_edata_checking': False
346 def test_fast_tgs_inner_no_sname(self):
347 expected_sname = self.get_krbtgt_sname()
349 self._run_test_sequence([
351 'rep_type': KRB_TGS_REP,
352 'expected_error_mode': (KDC_ERR_GENERIC,
353 KDC_ERR_S_PRINCIPAL_UNKNOWN),
355 'gen_tgt_fn': self.get_user_tgt,
358 'sname': None # should be ignored
360 'expected_sname': expected_sname,
361 'strict_edata_checking': False
365 def test_simple_tgs_wrong_principal(self):
366 self._run_test_sequence([
368 'rep_type': KRB_TGS_REP,
369 'expected_error_mode': 0,
371 'gen_tgt_fn': self.get_mach_tgt
375 def test_simple_tgs_service_ticket(self):
376 self._run_test_sequence([
378 'rep_type': KRB_TGS_REP,
379 'expected_error_mode': (KDC_ERR_NOT_US,
382 'gen_tgt_fn': self.get_user_service_ticket,
383 'expect_edata': False
387 def test_simple_tgs_service_ticket_mach(self):
388 self._run_test_sequence([
390 'rep_type': KRB_TGS_REP,
391 'expected_error_mode': (KDC_ERR_NOT_US,
394 'gen_tgt_fn': self.get_mach_service_ticket,
395 'expect_edata': False
399 def test_fast_no_claims(self):
400 self._run_test_sequence([
402 'rep_type': KRB_AS_REP,
403 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
405 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
406 'gen_armor_tgt_fn': self.get_mach_tgt,
410 'rep_type': KRB_AS_REP,
411 'expected_error_mode': 0,
413 'gen_padata_fn': self.generate_enc_challenge_padata,
414 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
415 'gen_armor_tgt_fn': self.get_mach_tgt,
420 def test_fast_tgs_no_claims(self):
421 self._run_test_sequence([
423 'rep_type': KRB_TGS_REP,
424 'expected_error_mode': 0,
426 'gen_tgt_fn': self.get_user_tgt,
432 def test_fast_no_claims_or_canon(self):
433 self._run_test_sequence([
435 'rep_type': KRB_AS_REP,
436 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
438 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
439 'gen_armor_tgt_fn': self.get_mach_tgt,
444 'rep_type': KRB_AS_REP,
445 'expected_error_mode': 0,
447 'gen_padata_fn': self.generate_enc_challenge_padata,
448 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
449 'gen_armor_tgt_fn': self.get_mach_tgt,
455 def test_fast_tgs_no_claims_or_canon(self):
456 self._run_test_sequence([
458 'rep_type': KRB_TGS_REP,
459 'expected_error_mode': 0,
461 'gen_tgt_fn': self.get_user_tgt,
468 def test_fast_no_canon(self):
469 self._run_test_sequence([
471 'rep_type': KRB_AS_REP,
472 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
474 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
475 'gen_armor_tgt_fn': self.get_mach_tgt,
479 'rep_type': KRB_AS_REP,
480 'expected_error_mode': 0,
482 'gen_padata_fn': self.generate_enc_challenge_padata,
483 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
484 'gen_armor_tgt_fn': self.get_mach_tgt,
489 def test_fast_tgs_no_canon(self):
490 self._run_test_sequence([
492 'rep_type': KRB_TGS_REP,
493 'expected_error_mode': 0,
495 'gen_tgt_fn': self.get_user_tgt,
501 def test_simple_tgs_no_etypes(self):
502 self._run_test_sequence([
504 'rep_type': KRB_TGS_REP,
505 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
507 'gen_tgt_fn': self.get_mach_tgt,
509 'expect_edata': False
513 def test_fast_tgs_no_etypes(self):
514 self._run_test_sequence([
516 'rep_type': KRB_TGS_REP,
517 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
519 'gen_tgt_fn': self.get_mach_tgt,
522 'strict_edata_checking': False
526 def test_simple_no_etypes(self):
527 self._run_test_sequence([
529 'rep_type': KRB_AS_REP,
530 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
536 def test_simple_fast_no_etypes(self):
537 self._run_test_sequence([
539 'rep_type': KRB_AS_REP,
540 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
542 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
543 'gen_armor_tgt_fn': self.get_mach_tgt,
545 'strict_edata_checking': False
549 def test_empty_fast(self):
550 # Add an empty PA-FX-FAST in the initial AS-REQ. This should get
551 # rejected with a Generic error.
552 self._run_test_sequence([
554 'rep_type': KRB_AS_REP,
555 'expected_error_mode': (KDC_ERR_GENERIC,
556 KDC_ERR_PREAUTH_FAILED),
558 'gen_fast_fn': self.generate_empty_fast,
560 'gen_armor_tgt_fn': self.get_mach_tgt,
561 'expect_edata': False
565 # Expected to fail against Windows - Windows does not produce an error.
566 def test_fast_unknown_critical_option(self):
567 self._run_test_sequence([
569 'rep_type': KRB_AS_REP,
570 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
572 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
573 'gen_armor_tgt_fn': self.get_mach_tgt
576 'rep_type': KRB_AS_REP,
577 'expected_error_mode': KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
579 'gen_padata_fn': self.generate_enc_challenge_padata,
580 'fast_options': '001', # unsupported critical option
581 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
582 'gen_armor_tgt_fn': self.get_mach_tgt
586 def test_unarmored_as_req(self):
587 self._run_test_sequence([
589 'rep_type': KRB_AS_REP,
590 'expected_error_mode': (KDC_ERR_GENERIC,
591 KDC_ERR_PREAUTH_FAILED),
593 'fast_armor': None, # no armor,
594 'gen_armor_tgt_fn': self.get_mach_tgt,
595 'expect_edata': False
599 def test_fast_invalid_armor_type(self):
600 self._run_test_sequence([
602 'rep_type': KRB_AS_REP,
603 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
605 'fast_armor': 0, # invalid armor type
606 'gen_armor_tgt_fn': self.get_mach_tgt
610 def test_fast_invalid_armor_type2(self):
611 self._run_test_sequence([
613 'rep_type': KRB_AS_REP,
614 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
616 'fast_armor': 2, # invalid armor type
617 'gen_armor_tgt_fn': self.get_mach_tgt
621 def test_fast_encrypted_challenge(self):
622 self._run_test_sequence([
624 'rep_type': KRB_AS_REP,
625 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
627 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
628 'gen_armor_tgt_fn': self.get_mach_tgt
631 'rep_type': KRB_AS_REP,
632 'expected_error_mode': 0,
634 'gen_padata_fn': self.generate_enc_challenge_padata,
635 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
636 'gen_armor_tgt_fn': self.get_mach_tgt
640 def test_fast_encrypted_challenge_as_req_self(self):
641 self._run_test_sequence([
643 'rep_type': KRB_AS_REP,
644 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
646 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
647 'gen_armor_tgt_fn': self.get_mach_tgt,
651 'rep_type': KRB_AS_REP,
652 'expected_error_mode': 0,
654 'gen_padata_fn': self.generate_enc_challenge_padata,
655 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
656 'gen_armor_tgt_fn': self.get_mach_tgt,
659 ], client_account=self.AccountType.COMPUTER)
661 def test_fast_encrypted_challenge_wrong_key(self):
662 self._run_test_sequence([
664 'rep_type': KRB_AS_REP,
665 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
667 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
668 'gen_armor_tgt_fn': self.get_mach_tgt
671 'rep_type': KRB_AS_REP,
672 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
674 'gen_padata_fn': self.generate_enc_challenge_padata_wrong_key,
675 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
676 'gen_armor_tgt_fn': self.get_mach_tgt
680 def test_fast_encrypted_challenge_wrong_key_kdc(self):
681 self._run_test_sequence([
683 'rep_type': KRB_AS_REP,
684 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
686 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
687 'gen_armor_tgt_fn': self.get_mach_tgt
690 'rep_type': KRB_AS_REP,
691 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
694 self.generate_enc_challenge_padata_wrong_key_kdc,
695 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
696 'gen_armor_tgt_fn': self.get_mach_tgt
700 def test_fast_encrypted_challenge_no_fast(self):
701 self._run_test_sequence([
703 'rep_type': KRB_AS_REP,
704 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
708 'rep_type': KRB_AS_REP,
709 'expected_error_mode': (KDC_ERR_PREAUTH_FAILED,
710 KDC_ERR_PREAUTH_REQUIRED),
712 'gen_padata_fn': self.generate_enc_challenge_padata_wrong_key
716 # Expected to fail against Windows - Windows does not produce an error.
717 def test_fast_encrypted_challenge_clock_skew(self):
718 # The KDC is supposed to confirm that the timestamp is within its
719 # current clock skew, and return KRB_APP_ERR_SKEW if it is not (RFC6113
720 # 5.4.6). However, this test fails against Windows, which accepts a
721 # skewed timestamp in the encrypted challenge.
722 self._run_test_sequence([
724 'rep_type': KRB_AS_REP,
725 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
727 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
728 'gen_armor_tgt_fn': self.get_mach_tgt
731 'rep_type': KRB_AS_REP,
732 'expected_error_mode': KDC_ERR_SKEW,
734 'gen_padata_fn': functools.partial(
735 self.generate_enc_challenge_padata,
737 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
738 'gen_armor_tgt_fn': self.get_mach_tgt
742 def test_fast_invalid_tgt(self):
743 # The armor ticket 'sname' field is required to identify the target
744 # realm TGS (RFC6113 5.4.1.1). However, this test fails against
745 # Windows, which will still accept a service ticket identifying a
746 # different server principal.
747 self._run_test_sequence([
749 'rep_type': KRB_AS_REP,
750 'expected_error_mode': (KDC_ERR_POLICY,
751 KDC_ERR_S_PRINCIPAL_UNKNOWN),
753 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
754 'gen_armor_tgt_fn': self.get_user_service_ticket
755 # ticket not identifying TGS of current
760 # Similarly, this test fails against Windows, which accepts a service
761 # ticket identifying a different server principal.
762 def test_fast_invalid_tgt_mach(self):
763 self._run_test_sequence([
765 'rep_type': KRB_AS_REP,
766 'expected_error_mode': (KDC_ERR_POLICY,
767 KDC_ERR_S_PRINCIPAL_UNKNOWN),
769 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
770 'gen_armor_tgt_fn': self.get_mach_service_ticket
771 # ticket not identifying TGS of current
776 def test_fast_invalid_checksum_tgt(self):
777 # The armor ticket 'sname' field is required to identify the target
778 # realm TGS (RFC6113 5.4.1.1). However, this test fails against
779 # Windows, which will still accept a service ticket identifying a
780 # different server principal even if the ticket checksum is invalid.
781 self._run_test_sequence([
783 'rep_type': KRB_AS_REP,
784 'expected_error_mode': (KDC_ERR_POLICY,
785 KDC_ERR_S_PRINCIPAL_UNKNOWN),
787 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
788 'gen_armor_tgt_fn': self.get_service_ticket_invalid_checksum
792 def test_fast_enc_timestamp(self):
793 # Provide ENC-TIMESTAMP as FAST padata when we should be providing
794 # ENCRYPTED-CHALLENGE - ensure that we get PREAUTH_REQUIRED.
795 self._run_test_sequence([
797 'rep_type': KRB_AS_REP,
798 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
800 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
801 'gen_armor_tgt_fn': self.get_mach_tgt
804 'rep_type': KRB_AS_REP,
805 'expected_error_mode': (KDC_ERR_PREAUTH_REQUIRED,
808 'gen_padata_fn': self.generate_enc_timestamp_padata,
809 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
810 'gen_armor_tgt_fn': self.get_mach_tgt
815 self._run_test_sequence([
817 'rep_type': KRB_AS_REP,
818 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
820 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
821 'gen_armor_tgt_fn': self.get_mach_tgt
824 'rep_type': KRB_AS_REP,
825 'expected_error_mode': 0,
827 'gen_padata_fn': self.generate_enc_challenge_padata,
828 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
829 'gen_armor_tgt_fn': self.get_mach_tgt
833 def test_fast_tgs(self):
834 self._run_test_sequence([
836 'rep_type': KRB_TGS_REP,
837 'expected_error_mode': 0,
839 'gen_tgt_fn': self.get_user_tgt,
844 def test_fast_tgs_armor(self):
845 self._run_test_sequence([
847 'rep_type': KRB_TGS_REP,
848 'expected_error_mode': 0,
850 'gen_tgt_fn': self.get_user_tgt,
851 'gen_armor_tgt_fn': self.get_mach_tgt,
852 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
856 def test_fast_session_key(self):
857 # Ensure that specified APOptions are ignored.
858 self._run_test_sequence([
860 'rep_type': KRB_AS_REP,
861 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
863 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
864 'gen_armor_tgt_fn': self.get_mach_tgt,
865 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
868 'rep_type': KRB_AS_REP,
869 'expected_error_mode': 0,
871 'gen_padata_fn': self.generate_enc_challenge_padata,
872 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
873 'gen_armor_tgt_fn': self.get_mach_tgt,
874 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
878 def test_fast_tgs_armor_session_key(self):
879 # Ensure that specified APOptions are ignored.
880 self._run_test_sequence([
882 'rep_type': KRB_TGS_REP,
883 'expected_error_mode': 0,
885 'gen_tgt_fn': self.get_user_tgt,
886 'gen_armor_tgt_fn': self.get_mach_tgt,
887 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
888 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
892 def test_fast_enc_pa_rep(self):
893 self._run_test_sequence([
895 'rep_type': KRB_AS_REP,
896 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
898 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
899 'gen_armor_tgt_fn': self.get_mach_tgt,
900 'expected_flags': 'enc-pa-rep'
903 'rep_type': KRB_AS_REP,
904 'expected_error_mode': 0,
906 'gen_padata_fn': self.generate_enc_pa_rep_challenge_padata,
907 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
908 'gen_armor_tgt_fn': self.get_mach_tgt,
909 'expected_flags': 'enc-pa-rep'
913 # Currently we only send PADATA-REQ-ENC-PA-REP for AS-REQ requests.
914 def test_fast_tgs_enc_pa_rep(self):
915 self._run_test_sequence([
917 'rep_type': KRB_TGS_REP,
918 'expected_error_mode': 0,
920 'gen_tgt_fn': self.get_user_tgt,
922 'gen_padata_fn': self.generate_enc_pa_rep_padata,
923 'expected_flags': 'enc-pa-rep'
927 # Currently we only send PADATA-REQ-ENC-PA-REP for AS-REQ requests.
928 def test_fast_tgs_armor_enc_pa_rep(self):
929 self._run_test_sequence([
931 'rep_type': KRB_TGS_REP,
932 'expected_error_mode': 0,
934 'gen_tgt_fn': self.get_user_tgt,
935 'gen_armor_tgt_fn': self.get_mach_tgt,
936 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
937 'gen_padata_fn': self.generate_enc_pa_rep_padata,
938 'expected_flags': 'enc-pa-rep'
942 def test_fast_outer_wrong_realm(self):
943 self._run_test_sequence([
945 'rep_type': KRB_AS_REP,
946 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
948 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
949 'gen_armor_tgt_fn': self.get_mach_tgt,
951 'realm': 'TEST' # should be ignored
955 'rep_type': KRB_AS_REP,
956 'expected_error_mode': 0,
958 'gen_padata_fn': self.generate_enc_challenge_padata,
959 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
960 'gen_armor_tgt_fn': self.get_mach_tgt,
962 'realm': 'TEST' # should be ignored
967 def test_fast_tgs_outer_wrong_realm(self):
968 self._run_test_sequence([
970 'rep_type': KRB_TGS_REP,
971 'expected_error_mode': 0,
973 'gen_tgt_fn': self.get_user_tgt,
976 'realm': 'TEST' # should be ignored
981 def test_fast_outer_wrong_nonce(self):
982 self._run_test_sequence([
984 'rep_type': KRB_AS_REP,
985 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
987 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
988 'gen_armor_tgt_fn': self.get_mach_tgt,
990 'nonce': '123' # should be ignored
994 'rep_type': KRB_AS_REP,
995 'expected_error_mode': 0,
997 'gen_padata_fn': self.generate_enc_challenge_padata,
998 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
999 'gen_armor_tgt_fn': self.get_mach_tgt,
1001 'nonce': '123' # should be ignored
1006 def test_fast_tgs_outer_wrong_nonce(self):
1007 self._run_test_sequence([
1009 'rep_type': KRB_TGS_REP,
1010 'expected_error_mode': 0,
1012 'gen_tgt_fn': self.get_user_tgt,
1015 'nonce': '123' # should be ignored
1020 def test_fast_outer_wrong_flags(self):
1021 self._run_test_sequence([
1023 'rep_type': KRB_AS_REP,
1024 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1026 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1027 'gen_armor_tgt_fn': self.get_mach_tgt,
1029 'kdc-options': '11111111111111111' # should be ignored
1033 'rep_type': KRB_AS_REP,
1034 'expected_error_mode': 0,
1036 'gen_padata_fn': self.generate_enc_challenge_padata,
1037 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1038 'gen_armor_tgt_fn': self.get_mach_tgt,
1040 'kdc-options': '11111111111111111' # should be ignored
1045 def test_fast_tgs_outer_wrong_flags(self):
1046 self._run_test_sequence([
1048 'rep_type': KRB_TGS_REP,
1049 'expected_error_mode': 0,
1051 'gen_tgt_fn': self.get_user_tgt,
1054 'kdc-options': '11111111111111111' # should be ignored
1059 def test_fast_outer_no_sname(self):
1060 self._run_test_sequence([
1062 'rep_type': KRB_AS_REP,
1063 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1065 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1066 'gen_armor_tgt_fn': self.get_mach_tgt,
1068 'sname': None # should be ignored
1072 'rep_type': KRB_AS_REP,
1073 'expected_error_mode': 0,
1075 'gen_padata_fn': self.generate_enc_challenge_padata,
1076 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1077 'gen_armor_tgt_fn': self.get_mach_tgt,
1079 'sname': None # should be ignored
1084 def test_fast_tgs_outer_no_sname(self):
1085 self._run_test_sequence([
1087 'rep_type': KRB_TGS_REP,
1088 'expected_error_mode': 0,
1090 'gen_tgt_fn': self.get_user_tgt,
1093 'sname': None # should be ignored
1098 def test_fast_outer_wrong_till(self):
1099 self._run_test_sequence([
1101 'rep_type': KRB_AS_REP,
1102 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1104 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1105 'gen_armor_tgt_fn': self.get_mach_tgt,
1107 'till': '15000101000000Z' # should be ignored
1111 'rep_type': KRB_AS_REP,
1112 'expected_error_mode': 0,
1114 'gen_padata_fn': self.generate_enc_challenge_padata,
1115 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1116 'gen_armor_tgt_fn': self.get_mach_tgt,
1118 'till': '15000101000000Z' # should be ignored
1123 def test_fast_tgs_outer_wrong_till(self):
1124 self._run_test_sequence([
1126 'rep_type': KRB_TGS_REP,
1127 'expected_error_mode': 0,
1129 'gen_tgt_fn': self.get_user_tgt,
1132 'till': '15000101000000Z' # should be ignored
1137 def test_fast_authdata_fast_used(self):
1138 self._run_test_sequence([
1140 'rep_type': KRB_TGS_REP,
1141 'expected_error_mode': 0,
1143 'gen_authdata_fn': self.generate_fast_used_auth_data,
1144 'gen_tgt_fn': self.get_user_tgt,
1149 def test_fast_authdata_fast_not_used(self):
1150 # The AD-fx-fast-used authdata type can be included in the
1151 # authenticator or the TGT authentication data to indicate that FAST
1152 # must be used. The KDC must return KRB_APP_ERR_MODIFIED if it receives
1153 # this authdata type in a request not using FAST (RFC6113 5.4.2).
1154 self._run_test_sequence([
1155 # This request works without FAST.
1157 'rep_type': KRB_TGS_REP,
1158 'expected_error_mode': 0,
1160 'gen_tgt_fn': self.get_user_tgt
1162 # Add the 'FAST used' auth data and it now fails.
1164 'rep_type': KRB_TGS_REP,
1165 'expected_error_mode': (KDC_ERR_MODIFIED,
1168 'gen_authdata_fn': self.generate_fast_used_auth_data,
1169 'gen_tgt_fn': self.get_user_tgt,
1170 'expect_edata': False
1174 def test_fast_ad_fx_fast_armor(self):
1175 expected_sname = self.get_krbtgt_sname()
1177 # If the authenticator or TGT authentication data contains the
1178 # AD-fx-fast-armor authdata type, the KDC must reject the request
1179 # (RFC6113 5.4.1.1).
1180 self._run_test_sequence([
1181 # This request works.
1183 'rep_type': KRB_TGS_REP,
1184 'expected_error_mode': 0,
1186 'gen_tgt_fn': self.get_user_tgt,
1189 # Add the 'FAST armor' auth data and it now fails.
1191 'rep_type': KRB_TGS_REP,
1192 'expected_error_mode': (KDC_ERR_GENERIC,
1193 KDC_ERR_BAD_INTEGRITY),
1195 'gen_authdata_fn': self.generate_fast_armor_auth_data,
1196 'gen_tgt_fn': self.get_user_tgt,
1198 'expected_sname': expected_sname,
1199 'expect_edata': False
1203 def test_fast_ad_fx_fast_armor2(self):
1204 # Show that we can still use the AD-fx-fast-armor authorization data in
1205 # FAST armor tickets.
1206 self._run_test_sequence([
1208 'rep_type': KRB_AS_REP,
1209 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1211 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1212 'gen_armor_tgt_fn': self.get_mach_tgt
1215 'rep_type': KRB_AS_REP,
1216 'expected_error_mode': 0,
1218 'gen_padata_fn': self.generate_enc_challenge_padata,
1219 'gen_authdata_fn': self.generate_fast_armor_auth_data,
1220 # include the auth data in the FAST armor.
1221 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1222 'gen_armor_tgt_fn': self.get_mach_tgt
1226 def test_fast_ad_fx_fast_armor_ticket(self):
1227 expected_sname = self.get_krbtgt_sname()
1229 # If the authenticator or TGT authentication data contains the
1230 # AD-fx-fast-armor authdata type, the KDC must reject the request
1232 self._run_test_sequence([
1233 # This request works.
1235 'rep_type': KRB_TGS_REP,
1236 'expected_error_mode': 0,
1238 'gen_tgt_fn': self.get_user_tgt,
1241 # Add AD-fx-fast-armor authdata element to user TGT. This request
1244 'rep_type': KRB_TGS_REP,
1245 'expected_error_mode': (KDC_ERR_GENERIC,
1246 KDC_ERR_BAD_INTEGRITY),
1248 'gen_tgt_fn': self.gen_tgt_fast_armor_auth_data,
1250 'expected_sname': expected_sname,
1251 'expect_edata': False
1255 def test_fast_ad_fx_fast_armor_enc_auth_data(self):
1256 # If the authenticator or TGT authentication data contains the
1257 # AD-fx-fast-armor authdata type, the KDC must reject the request
1258 # (RFC6113 5.4.2). However, the KDC should not reject a request that
1259 # contains this authdata type in enc-authorization-data.
1260 self._run_test_sequence([
1261 # This request works.
1263 'rep_type': KRB_TGS_REP,
1264 'expected_error_mode': 0,
1266 'gen_tgt_fn': self.get_user_tgt,
1269 # Add AD-fx-fast-armor authdata element to
1270 # enc-authorization-data. This request also works.
1272 'rep_type': KRB_TGS_REP,
1273 'expected_error_mode': 0,
1275 'gen_enc_authdata_fn': self.generate_fast_armor_auth_data,
1276 'gen_tgt_fn': self.get_user_tgt,
1281 def test_fast_ad_fx_fast_armor_ticket2(self):
1282 self._run_test_sequence([
1283 # Show that we can still use the modified ticket as armor.
1285 'rep_type': KRB_AS_REP,
1286 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1288 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1289 'gen_armor_tgt_fn': self.get_mach_tgt
1292 'rep_type': KRB_AS_REP,
1293 'expected_error_mode': 0,
1295 'gen_padata_fn': self.generate_enc_challenge_padata,
1296 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1297 'gen_armor_tgt_fn': self.gen_tgt_fast_armor_auth_data
1301 def test_fast_tgs_service_ticket(self):
1302 # Try to use a non-TGT ticket to establish an armor key, which fails
1304 self._run_test_sequence([
1306 'rep_type': KRB_TGS_REP,
1307 'expected_error_mode': (KDC_ERR_NOT_US,
1310 'gen_tgt_fn': self.get_user_service_ticket, # fails
1315 def test_fast_tgs_service_ticket_mach(self):
1316 self._run_test_sequence([
1318 'rep_type': KRB_TGS_REP,
1319 'expected_error_mode': (KDC_ERR_NOT_US, # fails
1322 'gen_tgt_fn': self.get_mach_service_ticket,
1327 def test_simple_tgs_no_subkey(self):
1328 self._run_test_sequence([
1330 'rep_type': KRB_TGS_REP,
1331 'expected_error_mode': 0,
1333 'gen_tgt_fn': self.get_user_tgt,
1334 'include_subkey': False
1338 def test_fast_tgs_no_subkey(self):
1339 expected_sname = self.get_krbtgt_sname()
1341 # Show that omitting the subkey in the TGS-REQ authenticator fails
1343 self._run_test_sequence([
1345 'rep_type': KRB_TGS_REP,
1346 'expected_error_mode': (KDC_ERR_GENERIC,
1347 KDC_ERR_PREAUTH_FAILED),
1349 'gen_tgt_fn': self.get_user_tgt,
1351 'include_subkey': False,
1352 'expected_sname': expected_sname,
1353 'expect_edata': False
1357 def test_fast_hide_client_names(self):
1358 self._run_test_sequence([
1360 'rep_type': KRB_AS_REP,
1361 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1363 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1364 'gen_armor_tgt_fn': self.get_mach_tgt,
1365 'fast_options': str(krb5_asn1.FastOptions(
1366 'hide-client-names')),
1367 'expected_anon': True
1370 'rep_type': KRB_AS_REP,
1371 'expected_error_mode': 0,
1373 'gen_padata_fn': self.generate_enc_challenge_padata,
1374 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1375 'gen_armor_tgt_fn': self.get_mach_tgt,
1376 'fast_options': str(krb5_asn1.FastOptions(
1377 'hide-client-names')),
1378 'expected_anon': True
1382 def test_fast_tgs_hide_client_names(self):
1383 self._run_test_sequence([
1385 'rep_type': KRB_TGS_REP,
1386 'expected_error_mode': 0,
1388 'gen_tgt_fn': self.get_user_tgt,
1390 'fast_options': str(krb5_asn1.FastOptions(
1391 'hide-client-names')),
1392 'expected_anon': True
1396 def test_fast_encrypted_challenge_replay(self):
1397 # The KDC is supposed to check that encrypted challenges are not
1398 # replays (RFC6113 5.4.6), but timestamps may be reused; an encrypted
1399 # challenge is only considered a replay if the ciphertext is identical
1400 # to a previous challenge. Windows does not perform this check.
1402 self._run_test_sequence([
1404 'rep_type': KRB_AS_REP,
1405 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1407 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1408 'gen_armor_tgt_fn': self.get_mach_tgt
1411 'rep_type': KRB_AS_REP,
1412 'expected_error_mode': 0,
1414 'gen_padata_fn': self.generate_enc_challenge_padata_replay,
1415 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1416 'gen_armor_tgt_fn': self.get_mach_tgt,
1421 def generate_enc_timestamp_padata(self,
1425 key = kdc_exchange_dict['preauth_key']
1427 padata = self.get_enc_timestamp_pa_data_from_key(key)
1428 return [padata], req_body
1430 def generate_enc_challenge_padata(self,
1435 armor_key = kdc_exchange_dict['armor_key']
1436 key = kdc_exchange_dict['preauth_key']
1438 client_challenge_key = (
1439 self.generate_client_challenge_key(armor_key, key))
1440 padata = self.get_challenge_pa_data(client_challenge_key, skew=skew)
1441 return [padata], req_body
1443 def generate_enc_challenge_padata_wrong_key_kdc(self,
1447 armor_key = kdc_exchange_dict['armor_key']
1448 key = kdc_exchange_dict['preauth_key']
1450 kdc_challenge_key = (
1451 self.generate_kdc_challenge_key(armor_key, key))
1452 padata = self.get_challenge_pa_data(kdc_challenge_key)
1453 return [padata], req_body
1455 def generate_enc_challenge_padata_wrong_key(self,
1459 key = kdc_exchange_dict['preauth_key']
1461 padata = self.get_challenge_pa_data(key)
1462 return [padata], req_body
1464 def generate_enc_challenge_padata_replay(self,
1468 padata = callback_dict.get('replay_padata')
1471 armor_key = kdc_exchange_dict['armor_key']
1472 key = kdc_exchange_dict['preauth_key']
1474 client_challenge_key = (
1475 self.generate_client_challenge_key(armor_key, key))
1476 padata = self.get_challenge_pa_data(client_challenge_key)
1477 callback_dict['replay_padata'] = padata
1479 return [padata], req_body
1481 def generate_empty_fast(self,
1489 fast_padata = self.PA_DATA_create(PADATA_FX_FAST, b'')
1493 def _run_test_sequence(self, test_sequence,
1494 client_account=KDCBaseTest.AccountType.USER,
1497 if self.strict_checking:
1498 self.check_kdc_fast_support()
1500 kdc_options_default = str(krb5_asn1.KDCOptions('forwardable,'
1503 client_creds = self.get_cached_creds(account_type=client_account,
1505 target_creds = self.get_service_creds()
1506 krbtgt_creds = self.get_krbtgt_creds()
1508 client_username = client_creds.get_username()
1509 client_realm = client_creds.get_realm()
1510 client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
1511 names=[client_username])
1513 krbtgt_username = krbtgt_creds.get_username()
1514 krbtgt_realm = krbtgt_creds.get_realm()
1515 krbtgt_sname = self.PrincipalName_create(
1516 name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm])
1517 krbtgt_decryption_key = self.TicketDecryptionKey_from_creds(
1519 krbtgt_etypes = krbtgt_creds.tgs_supported_enctypes
1521 target_username = target_creds.get_username()[:-1]
1522 target_realm = target_creds.get_realm()
1523 target_service = 'host'
1524 target_sname = self.PrincipalName_create(
1525 name_type=NT_SRV_HST, names=[target_service, target_username])
1526 target_decryption_key = self.TicketDecryptionKey_from_creds(
1528 target_etypes = target_creds.tgs_supported_enctypes
1530 client_decryption_key = self.TicketDecryptionKey_from_creds(
1532 client_etypes = client_creds.tgs_supported_enctypes
1535 preauth_etype_info2 = None
1537 for kdc_dict in test_sequence:
1538 rep_type = kdc_dict.pop('rep_type')
1539 self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP))
1541 expected_error_mode = kdc_dict.pop('expected_error_mode')
1542 if expected_error_mode == 0:
1543 expected_error_mode = ()
1544 elif not isinstance(expected_error_mode, collections.abc.Container):
1545 expected_error_mode = (expected_error_mode,)
1546 for error in expected_error_mode:
1547 self.assertIn(error, range(240))
1549 use_fast = kdc_dict.pop('use_fast')
1550 self.assertIs(type(use_fast), bool)
1553 self.assertIn('fast_armor', kdc_dict)
1554 fast_armor_type = kdc_dict.pop('fast_armor')
1556 if fast_armor_type is not None:
1557 self.assertIn('gen_armor_tgt_fn', kdc_dict)
1558 elif KDC_ERR_GENERIC not in expected_error_mode:
1559 self.assertNotIn('gen_armor_tgt_fn', kdc_dict)
1561 gen_armor_tgt_fn = kdc_dict.pop('gen_armor_tgt_fn', None)
1562 if gen_armor_tgt_fn is not None:
1563 armor_tgt = gen_armor_tgt_fn(armor_opts)
1567 fast_options = kdc_dict.pop('fast_options', '')
1569 fast_armor_type = None
1572 self.assertNotIn('fast_options', kdc_dict)
1575 if rep_type == KRB_TGS_REP:
1576 gen_tgt_fn = kdc_dict.pop('gen_tgt_fn')
1577 tgt = gen_tgt_fn(opts=client_opts)
1579 self.assertNotIn('gen_tgt_fn', kdc_dict)
1582 if len(expected_error_mode) != 0:
1583 check_error_fn = self.generic_check_kdc_error
1586 check_error_fn = None
1587 check_rep_fn = self.generic_check_kdc_rep
1589 etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96,
1592 cname = client_cname if rep_type == KRB_AS_REP else None
1593 crealm = client_realm
1595 as_req_self = kdc_dict.pop('as_req_self', False)
1597 self.assertEqual(KRB_AS_REP, rep_type)
1599 if 'sname' in kdc_dict:
1600 sname = kdc_dict.pop('sname')
1603 sname = client_cname
1604 elif rep_type == KRB_AS_REP:
1605 sname = krbtgt_sname
1607 sname = target_sname
1609 if rep_type == KRB_AS_REP:
1610 srealm = krbtgt_realm
1612 srealm = target_realm
1614 if rep_type == KRB_TGS_REP:
1615 tgt_cname = tgt.cname
1617 tgt_cname = client_cname
1619 expect_edata = kdc_dict.pop('expect_edata', None)
1620 if expect_edata is not None:
1621 self.assertTrue(expected_error_mode)
1623 expected_cname = kdc_dict.pop('expected_cname', tgt_cname)
1624 expected_anon = kdc_dict.pop('expected_anon',
1626 expected_crealm = kdc_dict.pop('expected_crealm', client_realm)
1627 expected_sname = kdc_dict.pop('expected_sname', sname)
1628 expected_srealm = kdc_dict.pop('expected_srealm', srealm)
1630 expected_salt = client_creds.get_salt()
1632 authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
1633 if rep_type == KRB_AS_REP:
1635 armor_key = self.generate_armor_key(authenticator_subkey,
1636 armor_tgt.session_key)
1637 armor_subkey = authenticator_subkey
1640 armor_subkey = authenticator_subkey
1642 if fast_armor_type is not None:
1643 armor_subkey = self.RandomKey(kcrypto.Enctype.AES256)
1644 explicit_armor_key = self.generate_armor_key(
1646 armor_tgt.session_key)
1647 armor_key = kcrypto.cf2(explicit_armor_key.key,
1648 authenticator_subkey.key,
1651 armor_key = Krb5EncryptionKey(armor_key, None)
1653 armor_key = self.generate_armor_key(authenticator_subkey,
1655 armor_subkey = authenticator_subkey
1657 if not kdc_dict.pop('include_subkey', True):
1658 authenticator_subkey = None
1661 generate_fast_fn = kdc_dict.pop('gen_fast_fn', None)
1662 if generate_fast_fn is None:
1663 generate_fast_fn = functools.partial(
1664 self.generate_simple_fast,
1665 fast_options=fast_options)
1667 generate_fast_fn = None
1669 generate_fast_armor_fn = (
1670 self.generate_ap_req
1671 if fast_armor_type is not None
1674 def _generate_padata_copy(_kdc_exchange_dict,
1678 return list(padata), req_body
1680 pac_request = kdc_dict.pop('pac_request', None)
1681 expect_pac = kdc_dict.pop('expect_pac', True)
1683 pac_options = kdc_dict.pop('pac_options', '1') # claims support
1685 kdc_options = kdc_dict.pop('kdc_options', kdc_options_default)
1687 gen_padata_fn = kdc_dict.pop('gen_padata_fn', None)
1689 if rep_type == KRB_AS_REP and gen_padata_fn is not None:
1690 self.assertIsNotNone(preauth_etype_info2)
1692 preauth_key = self.PasswordKey_from_etype_info2(
1694 preauth_etype_info2[0],
1695 client_creds.get_kvno())
1700 generate_fast_padata_fn = gen_padata_fn
1701 generate_padata_fn = (functools.partial(_generate_padata_copy,
1702 padata=[fast_cookie])
1703 if fast_cookie is not None else None)
1705 generate_fast_padata_fn = None
1706 generate_padata_fn = gen_padata_fn
1708 gen_authdata_fn = kdc_dict.pop('gen_authdata_fn', None)
1709 if gen_authdata_fn is not None:
1710 auth_data = [gen_authdata_fn()]
1714 gen_enc_authdata_fn = kdc_dict.pop('gen_enc_authdata_fn', None)
1715 if gen_enc_authdata_fn is not None:
1716 enc_auth_data = [gen_enc_authdata_fn()]
1718 enc_auth_data_key = authenticator_subkey
1719 enc_auth_data_usage = KU_TGS_REQ_AUTH_DAT_SUBKEY
1720 if enc_auth_data_key is None:
1721 enc_auth_data_key = tgt.session_key
1722 enc_auth_data_usage = KU_TGS_REQ_AUTH_DAT_SESSION
1724 enc_auth_data = None
1726 enc_auth_data_key = None
1727 enc_auth_data_usage = None
1730 self.assertNotIn('inner_req', kdc_dict)
1731 self.assertNotIn('outer_req', kdc_dict)
1732 inner_req = kdc_dict.pop('inner_req', None)
1733 outer_req = kdc_dict.pop('outer_req', None)
1735 expected_flags = kdc_dict.pop('expected_flags', None)
1736 if expected_flags is not None:
1737 expected_flags = krb5_asn1.TicketFlags(expected_flags)
1738 unexpected_flags = kdc_dict.pop('unexpected_flags', None)
1739 if unexpected_flags is not None:
1740 unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags)
1742 fast_ap_options = kdc_dict.pop('fast_ap_options', None)
1744 strict_edata_checking = kdc_dict.pop('strict_edata_checking', True)
1746 if rep_type == KRB_AS_REP:
1748 expected_supported_etypes = client_etypes
1749 decryption_key = client_decryption_key
1751 expected_supported_etypes = krbtgt_etypes
1752 decryption_key = krbtgt_decryption_key
1754 kdc_exchange_dict = self.as_exchange_dict(
1755 expected_crealm=expected_crealm,
1756 expected_cname=expected_cname,
1757 expected_anon=expected_anon,
1758 expected_srealm=expected_srealm,
1759 expected_sname=expected_sname,
1760 expected_supported_etypes=expected_supported_etypes,
1761 expected_flags=expected_flags,
1762 unexpected_flags=unexpected_flags,
1763 ticket_decryption_key=decryption_key,
1764 generate_fast_fn=generate_fast_fn,
1765 generate_fast_armor_fn=generate_fast_armor_fn,
1766 generate_fast_padata_fn=generate_fast_padata_fn,
1767 fast_armor_type=fast_armor_type,
1768 generate_padata_fn=generate_padata_fn,
1769 check_error_fn=check_error_fn,
1770 check_rep_fn=check_rep_fn,
1771 check_kdc_private_fn=self.generic_check_kdc_private,
1773 expected_error_mode=expected_error_mode,
1774 expected_salt=expected_salt,
1775 authenticator_subkey=authenticator_subkey,
1776 preauth_key=preauth_key,
1777 auth_data=auth_data,
1778 armor_key=armor_key,
1779 armor_tgt=armor_tgt,
1780 armor_subkey=armor_subkey,
1781 kdc_options=kdc_options,
1782 inner_req=inner_req,
1783 outer_req=outer_req,
1784 expect_pac=expect_pac,
1785 pac_request=pac_request,
1786 pac_options=pac_options,
1787 fast_ap_options=fast_ap_options,
1788 strict_edata_checking=strict_edata_checking,
1789 expect_edata=expect_edata)
1791 kdc_exchange_dict = self.tgs_exchange_dict(
1792 expected_crealm=expected_crealm,
1793 expected_cname=expected_cname,
1794 expected_anon=expected_anon,
1795 expected_srealm=expected_srealm,
1796 expected_sname=expected_sname,
1797 expected_supported_etypes=target_etypes,
1798 expected_flags=expected_flags,
1799 unexpected_flags=unexpected_flags,
1800 ticket_decryption_key=target_decryption_key,
1801 generate_fast_fn=generate_fast_fn,
1802 generate_fast_armor_fn=generate_fast_armor_fn,
1803 generate_fast_padata_fn=generate_fast_padata_fn,
1804 fast_armor_type=fast_armor_type,
1805 generate_padata_fn=generate_padata_fn,
1806 check_error_fn=check_error_fn,
1807 check_rep_fn=check_rep_fn,
1808 check_kdc_private_fn=self.generic_check_kdc_private,
1809 expected_error_mode=expected_error_mode,
1812 armor_key=armor_key,
1813 armor_tgt=armor_tgt,
1814 armor_subkey=armor_subkey,
1815 authenticator_subkey=authenticator_subkey,
1816 auth_data=auth_data,
1817 body_checksum_type=None,
1818 kdc_options=kdc_options,
1819 inner_req=inner_req,
1820 outer_req=outer_req,
1821 expect_pac=expect_pac,
1822 pac_request=pac_request,
1823 pac_options=pac_options,
1824 fast_ap_options=fast_ap_options,
1825 strict_edata_checking=strict_edata_checking,
1826 expect_edata=expect_edata)
1828 repeat = kdc_dict.pop('repeat', 1)
1829 for _ in range(repeat):
1830 rep = self._generic_kdc_exchange(
1836 EncAuthorizationData=enc_auth_data,
1837 EncAuthorizationData_key=enc_auth_data_key,
1838 EncAuthorizationData_usage=enc_auth_data_usage)
1839 if len(expected_error_mode) == 0:
1840 self.check_reply(rep, rep_type)
1843 preauth_etype_info2 = None
1845 # Check whether the ticket contains a PAC.
1846 ticket = kdc_exchange_dict['rep_ticket_creds']
1847 pac = self.get_ticket_pac(ticket, expect_pac=expect_pac)
1849 self.assertIsNotNone(pac)
1851 self.assertIsNone(pac)
1853 self.check_error_rep(rep, expected_error_mode)
1855 if 'fast_cookie' in kdc_exchange_dict:
1856 fast_cookie = self.create_fast_cookie(
1857 kdc_exchange_dict['fast_cookie'])
1861 if KDC_ERR_PREAUTH_REQUIRED in expected_error_mode:
1862 preauth_etype_info2 = (
1863 kdc_exchange_dict['preauth_etype_info2'])
1865 preauth_etype_info2 = None
1867 # Ensure we used all the parameters given to us.
1868 self.assertEqual({}, kdc_dict)
1870 def generate_enc_pa_rep_padata(self,
1874 padata = self.PA_DATA_create(PADATA_REQ_ENC_PA_REP, b'')
1876 return [padata], req_body
1878 def generate_enc_pa_rep_challenge_padata(self,
1882 padata, req_body = self.generate_enc_challenge_padata(kdc_exchange_dict,
1886 padata.append(self.PA_DATA_create(PADATA_REQ_ENC_PA_REP, b''))
1888 return padata, req_body
1890 def generate_enc_pa_rep_timestamp_padata(self,
1894 padata, req_body = self.generate_enc_timestamp_padata(kdc_exchange_dict,
1898 padata.append(self.PA_DATA_create(PADATA_REQ_ENC_PA_REP, b''))
1900 return padata, req_body
1902 def generate_fast_armor_auth_data(self):
1903 auth_data = self.AuthorizationData_create(AD_FX_FAST_ARMOR, b'')
1907 def generate_fast_used_auth_data(self):
1908 auth_data = self.AuthorizationData_create(AD_FX_FAST_USED, b'')
1912 def gen_tgt_fast_armor_auth_data(self, opts):
1913 user_tgt = self.get_user_tgt(opts)
1915 auth_data = self.generate_fast_armor_auth_data()
1917 def modify_fn(enc_part):
1918 enc_part['authorization-data'].append(auth_data)
1922 checksum_keys = self.get_krbtgt_checksum_key()
1924 # Use our modifed TGT to replace the one in the request.
1925 return self.modified_ticket(user_tgt,
1926 modify_fn=modify_fn,
1927 checksum_keys=checksum_keys)
1929 def create_fast_cookie(self, cookie):
1930 self.assertIsNotNone(cookie)
1931 if self.strict_checking:
1932 self.assertNotEqual(0, len(cookie))
1934 return self.PA_DATA_create(PADATA_FX_COOKIE, cookie)
1936 def check_kdc_fast_support(self):
1937 # Check that the KDC supports FAST
1939 samdb = self.get_samdb()
1941 krbtgt_rid = security.DOMAIN_RID_KRBTGT
1942 krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid)
1944 res = samdb.search(base='<SID=%s>' % krbtgt_sid,
1945 scope=ldb.SCOPE_BASE,
1946 attrs=['msDS-SupportedEncryptionTypes'])
1948 krbtgt_etypes = int(res[0]['msDS-SupportedEncryptionTypes'][0])
1951 security.KERB_ENCTYPE_FAST_SUPPORTED & krbtgt_etypes)
1953 security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED & krbtgt_etypes)
1955 security.KERB_ENCTYPE_CLAIMS_SUPPORTED & krbtgt_etypes)
1957 def get_mach_tgt(self, opts):
1960 mach_creds = self.get_cached_creds(
1961 account_type=self.AccountType.COMPUTER,
1964 'fast_support': True,
1965 'claims_support': True,
1966 'compound_id_support': True,
1967 'supported_enctypes': (
1968 security.KERB_ENCTYPE_RC4_HMAC_MD5 |
1969 security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96_SK
1972 return self.get_tgt(mach_creds)
1974 def get_rodc_issued_mach_tgt(self, opts):
1975 return self.issued_by_rodc(self.get_mach_tgt(opts))
1977 def get_user_tgt(self, opts):
1978 user_creds = self.get_cached_creds(
1979 account_type=self.AccountType.USER,
1981 return self.get_tgt(user_creds)
1983 def get_user_service_ticket(self, opts):
1984 user_tgt = self.get_user_tgt(opts)
1985 service_creds = self.get_service_creds()
1986 return self.get_service_ticket(user_tgt, service_creds)
1988 def get_mach_service_ticket(self, opts):
1989 mach_tgt = self.get_mach_tgt(opts)
1990 service_creds = self.get_service_creds()
1991 return self.get_service_ticket(mach_tgt, service_creds)
1993 def get_service_ticket_invalid_checksum(self, opts):
1994 ticket = self.get_user_service_ticket(opts)
1996 krbtgt_creds = self.get_krbtgt_creds()
1997 krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
1999 zeroed_key = ZeroedChecksumKey(krbtgt_key.key,
2002 server_key = ticket.decryption_key
2004 krb5pac.PAC_TYPE_SRV_CHECKSUM: server_key,
2005 krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
2006 krb5pac.PAC_TYPE_TICKET_CHECKSUM: zeroed_key,
2009 return self.modified_ticket(
2011 checksum_keys=checksum_keys,
2012 include_checksums={krb5pac.PAC_TYPE_TICKET_CHECKSUM: True})
2015 if __name__ == "__main__":
2016 global_asn1_print = False
2017 global_hexdump = False