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/>.
27 from samba.dcerpc import krb5pac, security
28 from samba.tests.krb5.raw_testcase import Krb5EncryptionKey, ZeroedChecksumKey
29 from samba.tests.krb5.kdc_base_test import KDCBaseTest
30 from samba.tests.krb5.rfc4120_constants import (
33 AES256_CTS_HMAC_SHA1_96,
35 FX_FAST_ARMOR_AP_REQUEST,
36 KDC_ERR_BAD_INTEGRITY,
39 KDC_ERR_S_PRINCIPAL_UNKNOWN,
43 KDC_ERR_PREAUTH_FAILED,
44 KDC_ERR_PREAUTH_REQUIRED,
46 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
49 KU_TGS_REQ_AUTH_DAT_SESSION,
50 KU_TGS_REQ_AUTH_DAT_SUBKEY,
57 import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
58 import samba.tests.krb5.kcrypto as kcrypto
60 sys.path.insert(0, "bin/python")
61 os.environ["PYTHONUNBUFFERED"] = "1"
63 global_asn1_print = False
64 global_hexdump = False
67 class FAST_Tests(KDCBaseTest):
73 cls.user_service_ticket = None
76 cls.mach_service_ticket = None
80 self.do_asn1_print = global_asn1_print
81 self.do_hexdump = global_hexdump
83 def test_simple(self):
84 self._run_test_sequence([
86 'rep_type': KRB_AS_REP,
87 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
91 'rep_type': KRB_AS_REP,
92 'expected_error_mode': 0,
94 'gen_padata_fn': self.generate_enc_timestamp_padata
98 def test_simple_as_req_self(self):
99 self._run_test_sequence([
101 'rep_type': KRB_AS_REP,
102 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
107 'rep_type': KRB_AS_REP,
108 'expected_error_mode': 0,
110 'gen_padata_fn': self.generate_enc_timestamp_padata,
113 ], client_account=self.AccountType.COMPUTER)
115 def test_simple_tgs(self):
116 self._run_test_sequence([
118 'rep_type': KRB_TGS_REP,
119 'expected_error_mode': 0,
121 'gen_tgt_fn': self.get_user_tgt
125 def test_simple_no_sname(self):
126 expected_sname = self.get_krbtgt_sname()
128 self._run_test_sequence([
130 'rep_type': KRB_AS_REP,
131 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
134 'expected_sname': expected_sname,
135 'expect_edata': False
139 def test_simple_tgs_no_sname(self):
140 expected_sname = self.get_krbtgt_sname()
142 self._run_test_sequence([
144 'rep_type': KRB_TGS_REP,
145 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
147 'gen_tgt_fn': self.get_user_tgt,
149 'expected_sname': expected_sname,
150 'expect_edata': False
154 def test_fast_no_sname(self):
155 expected_sname = self.get_krbtgt_sname()
157 self._run_test_sequence([
159 'rep_type': KRB_AS_REP,
160 'expected_error_mode': (KDC_ERR_GENERIC,
161 KDC_ERR_S_PRINCIPAL_UNKNOWN),
163 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
164 'gen_armor_tgt_fn': self.get_mach_tgt,
166 'expected_sname': expected_sname,
167 'strict_edata_checking': False
171 def test_fast_tgs_no_sname(self):
172 expected_sname = self.get_krbtgt_sname()
174 self._run_test_sequence([
176 'rep_type': KRB_TGS_REP,
177 'expected_error_mode': (KDC_ERR_GENERIC, KDC_ERR_S_PRINCIPAL_UNKNOWN),
179 'gen_tgt_fn': self.get_user_tgt,
182 'expected_sname': expected_sname,
183 'strict_edata_checking': False
187 def test_fast_inner_no_sname(self):
188 expected_sname = self.get_krbtgt_sname()
190 self._run_test_sequence([
192 'rep_type': KRB_AS_REP,
193 'expected_error_mode': (KDC_ERR_GENERIC,
194 KDC_ERR_S_PRINCIPAL_UNKNOWN),
196 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
197 'gen_armor_tgt_fn': self.get_mach_tgt,
199 'sname': None # should be ignored
201 'expected_sname': expected_sname,
202 'strict_edata_checking': False
206 def test_fast_tgs_inner_no_sname(self):
207 expected_sname = self.get_krbtgt_sname()
209 self._run_test_sequence([
211 'rep_type': KRB_TGS_REP,
212 'expected_error_mode': (KDC_ERR_GENERIC,
213 KDC_ERR_S_PRINCIPAL_UNKNOWN),
215 'gen_tgt_fn': self.get_user_tgt,
218 'sname': None # should be ignored
220 'expected_sname': expected_sname,
221 'strict_edata_checking': False
225 def test_simple_tgs_wrong_principal(self):
226 self._run_test_sequence([
228 'rep_type': KRB_TGS_REP,
229 'expected_error_mode': 0,
231 'gen_tgt_fn': self.get_mach_tgt
235 def test_simple_tgs_service_ticket(self):
236 self._run_test_sequence([
238 'rep_type': KRB_TGS_REP,
239 'expected_error_mode': (KDC_ERR_NOT_US,
242 'gen_tgt_fn': self.get_user_service_ticket,
243 'expect_edata': False
247 def test_simple_tgs_service_ticket_mach(self):
248 self._run_test_sequence([
250 'rep_type': KRB_TGS_REP,
251 'expected_error_mode': (KDC_ERR_NOT_US,
254 'gen_tgt_fn': self.get_mach_service_ticket,
255 'expect_edata': False
259 def test_fast_no_claims(self):
260 self._run_test_sequence([
262 'rep_type': KRB_AS_REP,
263 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
265 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
266 'gen_armor_tgt_fn': self.get_mach_tgt,
270 'rep_type': KRB_AS_REP,
271 'expected_error_mode': 0,
273 'gen_padata_fn': self.generate_enc_challenge_padata,
274 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
275 'gen_armor_tgt_fn': self.get_mach_tgt,
280 def test_fast_tgs_no_claims(self):
281 self._run_test_sequence([
283 'rep_type': KRB_TGS_REP,
284 'expected_error_mode': 0,
286 'gen_tgt_fn': self.get_user_tgt,
292 def test_fast_no_claims_or_canon(self):
293 self._run_test_sequence([
295 'rep_type': KRB_AS_REP,
296 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
298 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
299 'gen_armor_tgt_fn': self.get_mach_tgt,
304 'rep_type': KRB_AS_REP,
305 'expected_error_mode': 0,
307 'gen_padata_fn': self.generate_enc_challenge_padata,
308 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
309 'gen_armor_tgt_fn': self.get_mach_tgt,
315 def test_fast_tgs_no_claims_or_canon(self):
316 self._run_test_sequence([
318 'rep_type': KRB_TGS_REP,
319 'expected_error_mode': 0,
321 'gen_tgt_fn': self.get_user_tgt,
328 def test_fast_no_canon(self):
329 self._run_test_sequence([
331 'rep_type': KRB_AS_REP,
332 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
334 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
335 'gen_armor_tgt_fn': self.get_mach_tgt,
339 'rep_type': KRB_AS_REP,
340 'expected_error_mode': 0,
342 'gen_padata_fn': self.generate_enc_challenge_padata,
343 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
344 'gen_armor_tgt_fn': self.get_mach_tgt,
349 def test_fast_tgs_no_canon(self):
350 self._run_test_sequence([
352 'rep_type': KRB_TGS_REP,
353 'expected_error_mode': 0,
355 'gen_tgt_fn': self.get_user_tgt,
361 def test_simple_tgs_no_etypes(self):
362 self._run_test_sequence([
364 'rep_type': KRB_TGS_REP,
365 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
367 'gen_tgt_fn': self.get_mach_tgt,
369 'expect_edata': False
373 def test_fast_tgs_no_etypes(self):
374 self._run_test_sequence([
376 'rep_type': KRB_TGS_REP,
377 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
379 'gen_tgt_fn': self.get_mach_tgt,
382 'strict_edata_checking': False
386 def test_simple_no_etypes(self):
387 self._run_test_sequence([
389 'rep_type': KRB_AS_REP,
390 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
396 def test_simple_fast_no_etypes(self):
397 self._run_test_sequence([
399 'rep_type': KRB_AS_REP,
400 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP,
402 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
403 'gen_armor_tgt_fn': self.get_mach_tgt,
405 'strict_edata_checking': False
409 def test_empty_fast(self):
410 # Add an empty PA-FX-FAST in the initial AS-REQ. This should get
411 # rejected with a Generic error.
412 self._run_test_sequence([
414 'rep_type': KRB_AS_REP,
415 'expected_error_mode': (KDC_ERR_GENERIC,
416 KDC_ERR_PREAUTH_FAILED),
418 'gen_fast_fn': self.generate_empty_fast,
420 'gen_armor_tgt_fn': self.get_mach_tgt,
421 'expect_edata': False
425 def test_fast_unknown_critical_option(self):
426 self._run_test_sequence([
428 'rep_type': KRB_AS_REP,
429 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
431 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
432 'gen_armor_tgt_fn': self.get_mach_tgt
435 'rep_type': KRB_AS_REP,
436 'expected_error_mode': KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
438 'gen_padata_fn': self.generate_enc_challenge_padata,
439 'fast_options': '001', # unsupported critical option
440 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
441 'gen_armor_tgt_fn': self.get_mach_tgt
445 def test_unarmored_as_req(self):
446 self._run_test_sequence([
448 'rep_type': KRB_AS_REP,
449 'expected_error_mode': (KDC_ERR_GENERIC,
450 KDC_ERR_PREAUTH_FAILED),
452 'fast_armor': None, # no armor,
453 'gen_armor_tgt_fn': self.get_mach_tgt,
454 'expect_edata': False
458 def test_fast_invalid_armor_type(self):
459 self._run_test_sequence([
461 'rep_type': KRB_AS_REP,
462 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
464 'fast_armor': 0, # invalid armor type
465 'gen_armor_tgt_fn': self.get_mach_tgt
469 def test_fast_invalid_armor_type2(self):
470 self._run_test_sequence([
472 'rep_type': KRB_AS_REP,
473 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
475 'fast_armor': 2, # invalid armor type
476 'gen_armor_tgt_fn': self.get_mach_tgt
480 def test_fast_encrypted_challenge(self):
481 self._run_test_sequence([
483 'rep_type': KRB_AS_REP,
484 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
486 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
487 'gen_armor_tgt_fn': self.get_mach_tgt
490 'rep_type': KRB_AS_REP,
491 'expected_error_mode': 0,
493 'gen_padata_fn': self.generate_enc_challenge_padata,
494 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
495 'gen_armor_tgt_fn': self.get_mach_tgt
499 def test_fast_encrypted_challenge_as_req_self(self):
500 self._run_test_sequence([
502 'rep_type': KRB_AS_REP,
503 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
505 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
506 'gen_armor_tgt_fn': self.get_mach_tgt,
510 'rep_type': KRB_AS_REP,
511 'expected_error_mode': 0,
513 'gen_padata_fn': self.generate_enc_challenge_padata,
514 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
515 'gen_armor_tgt_fn': self.get_mach_tgt,
518 ], client_account=self.AccountType.COMPUTER)
520 def test_fast_encrypted_challenge_wrong_key(self):
521 self._run_test_sequence([
523 'rep_type': KRB_AS_REP,
524 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
526 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
527 'gen_armor_tgt_fn': self.get_mach_tgt
530 'rep_type': KRB_AS_REP,
531 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
533 'gen_padata_fn': self.generate_enc_challenge_padata_wrong_key,
534 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
535 'gen_armor_tgt_fn': self.get_mach_tgt
539 def test_fast_encrypted_challenge_wrong_key_kdc(self):
540 self._run_test_sequence([
542 'rep_type': KRB_AS_REP,
543 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
545 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
546 'gen_armor_tgt_fn': self.get_mach_tgt
549 'rep_type': KRB_AS_REP,
550 'expected_error_mode': KDC_ERR_PREAUTH_FAILED,
553 self.generate_enc_challenge_padata_wrong_key_kdc,
554 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
555 'gen_armor_tgt_fn': self.get_mach_tgt
559 def test_fast_encrypted_challenge_no_fast(self):
560 self._run_test_sequence([
562 'rep_type': KRB_AS_REP,
563 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
567 'rep_type': KRB_AS_REP,
568 'expected_error_mode': (KDC_ERR_PREAUTH_FAILED,
569 KDC_ERR_PREAUTH_REQUIRED),
571 'gen_padata_fn': self.generate_enc_challenge_padata_wrong_key
575 def test_fast_encrypted_challenge_clock_skew(self):
576 # The KDC is supposed to confirm that the timestamp is within its
577 # current clock skew, and return KRB_APP_ERR_SKEW if it is not (RFC6113
578 # 5.4.6). However, this test fails against Windows, which accepts a
579 # skewed timestamp in the encrypted challenge.
580 self._run_test_sequence([
582 'rep_type': KRB_AS_REP,
583 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
585 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
586 'gen_armor_tgt_fn': self.get_mach_tgt
589 'rep_type': KRB_AS_REP,
590 'expected_error_mode': KDC_ERR_SKEW,
592 'gen_padata_fn': functools.partial(
593 self.generate_enc_challenge_padata,
595 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
596 'gen_armor_tgt_fn': self.get_mach_tgt
600 def test_fast_invalid_tgt(self):
601 # The armor ticket 'sname' field is required to identify the target
602 # realm TGS (RFC6113 5.4.1.1). However, this test fails against
603 # Windows, which will still accept a service ticket identifying a
604 # different server principal.
605 self._run_test_sequence([
607 'rep_type': KRB_AS_REP,
608 'expected_error_mode': (KDC_ERR_POLICY,
609 KDC_ERR_S_PRINCIPAL_UNKNOWN),
611 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
612 'gen_armor_tgt_fn': self.get_user_service_ticket
613 # ticket not identifying TGS of current
618 # Similarly, this test fails against Windows, which accepts a service
619 # ticket identifying a different server principal.
620 def test_fast_invalid_tgt_mach(self):
621 self._run_test_sequence([
623 'rep_type': KRB_AS_REP,
624 'expected_error_mode': (KDC_ERR_POLICY,
625 KDC_ERR_S_PRINCIPAL_UNKNOWN),
627 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
628 'gen_armor_tgt_fn': self.get_mach_service_ticket
629 # ticket not identifying TGS of current
634 def test_fast_invalid_checksum_tgt(self):
635 # The armor ticket 'sname' field is required to identify the target
636 # realm TGS (RFC6113 5.4.1.1). However, this test fails against
637 # Windows, which will still accept a service ticket identifying a
638 # different server principal even if the ticket checksum is invalid.
639 self._run_test_sequence([
641 'rep_type': KRB_AS_REP,
642 'expected_error_mode': (KDC_ERR_POLICY,
643 KDC_ERR_S_PRINCIPAL_UNKNOWN),
645 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
646 'gen_armor_tgt_fn': self.get_service_ticket_invalid_checksum
650 def test_fast_enc_timestamp(self):
651 # Provide ENC-TIMESTAMP as FAST padata when we should be providing
652 # ENCRYPTED-CHALLENGE - ensure that we get PREAUTH_REQUIRED.
653 self._run_test_sequence([
655 'rep_type': KRB_AS_REP,
656 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
658 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
659 'gen_armor_tgt_fn': self.get_mach_tgt
662 'rep_type': KRB_AS_REP,
663 'expected_error_mode': (KDC_ERR_PREAUTH_REQUIRED,
666 'gen_padata_fn': self.generate_enc_timestamp_padata,
667 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
668 'gen_armor_tgt_fn': self.get_mach_tgt
673 self._run_test_sequence([
675 'rep_type': KRB_AS_REP,
676 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
678 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
679 'gen_armor_tgt_fn': self.get_mach_tgt
682 'rep_type': KRB_AS_REP,
683 'expected_error_mode': 0,
685 'gen_padata_fn': self.generate_enc_challenge_padata,
686 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
687 'gen_armor_tgt_fn': self.get_mach_tgt
691 def test_fast_tgs(self):
692 self._run_test_sequence([
694 'rep_type': KRB_TGS_REP,
695 'expected_error_mode': 0,
697 'gen_tgt_fn': self.get_user_tgt,
702 def test_fast_tgs_armor(self):
703 self._run_test_sequence([
705 'rep_type': KRB_TGS_REP,
706 'expected_error_mode': 0,
708 'gen_tgt_fn': self.get_user_tgt,
709 'gen_armor_tgt_fn': self.get_mach_tgt,
710 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
714 def test_fast_session_key(self):
715 # Ensure that specified APOptions are ignored.
716 self._run_test_sequence([
718 'rep_type': KRB_AS_REP,
719 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
721 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
722 'gen_armor_tgt_fn': self.get_mach_tgt,
723 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
726 'rep_type': KRB_AS_REP,
727 'expected_error_mode': 0,
729 'gen_padata_fn': self.generate_enc_challenge_padata,
730 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
731 'gen_armor_tgt_fn': self.get_mach_tgt,
732 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
736 def test_fast_tgs_armor_session_key(self):
737 # Ensure that specified APOptions are ignored.
738 self._run_test_sequence([
740 'rep_type': KRB_TGS_REP,
741 'expected_error_mode': 0,
743 'gen_tgt_fn': self.get_user_tgt,
744 'gen_armor_tgt_fn': self.get_mach_tgt,
745 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
746 'fast_ap_options': str(krb5_asn1.APOptions('use-session-key'))
750 def test_fast_outer_wrong_realm(self):
751 self._run_test_sequence([
753 'rep_type': KRB_AS_REP,
754 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
756 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
757 'gen_armor_tgt_fn': self.get_mach_tgt,
759 'realm': 'TEST' # should be ignored
763 'rep_type': KRB_AS_REP,
764 'expected_error_mode': 0,
766 'gen_padata_fn': self.generate_enc_challenge_padata,
767 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
768 'gen_armor_tgt_fn': self.get_mach_tgt,
770 'realm': 'TEST' # should be ignored
775 def test_fast_tgs_outer_wrong_realm(self):
776 self._run_test_sequence([
778 'rep_type': KRB_TGS_REP,
779 'expected_error_mode': 0,
781 'gen_tgt_fn': self.get_user_tgt,
784 'realm': 'TEST' # should be ignored
789 def test_fast_outer_wrong_nonce(self):
790 self._run_test_sequence([
792 'rep_type': KRB_AS_REP,
793 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
795 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
796 'gen_armor_tgt_fn': self.get_mach_tgt,
798 'nonce': '123' # should be ignored
802 'rep_type': KRB_AS_REP,
803 'expected_error_mode': 0,
805 'gen_padata_fn': self.generate_enc_challenge_padata,
806 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
807 'gen_armor_tgt_fn': self.get_mach_tgt,
809 'nonce': '123' # should be ignored
814 def test_fast_tgs_outer_wrong_nonce(self):
815 self._run_test_sequence([
817 'rep_type': KRB_TGS_REP,
818 'expected_error_mode': 0,
820 'gen_tgt_fn': self.get_user_tgt,
823 'nonce': '123' # should be ignored
828 def test_fast_outer_wrong_flags(self):
829 self._run_test_sequence([
831 'rep_type': KRB_AS_REP,
832 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
834 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
835 'gen_armor_tgt_fn': self.get_mach_tgt,
837 'kdc-options': '11111111111111111' # should be ignored
841 'rep_type': KRB_AS_REP,
842 'expected_error_mode': 0,
844 'gen_padata_fn': self.generate_enc_challenge_padata,
845 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
846 'gen_armor_tgt_fn': self.get_mach_tgt,
848 'kdc-options': '11111111111111111' # should be ignored
853 def test_fast_tgs_outer_wrong_flags(self):
854 self._run_test_sequence([
856 'rep_type': KRB_TGS_REP,
857 'expected_error_mode': 0,
859 'gen_tgt_fn': self.get_user_tgt,
862 'kdc-options': '11111111111111111' # should be ignored
867 def test_fast_outer_no_sname(self):
868 self._run_test_sequence([
870 'rep_type': KRB_AS_REP,
871 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
873 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
874 'gen_armor_tgt_fn': self.get_mach_tgt,
876 'sname': None # should be ignored
880 'rep_type': KRB_AS_REP,
881 'expected_error_mode': 0,
883 'gen_padata_fn': self.generate_enc_challenge_padata,
884 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
885 'gen_armor_tgt_fn': self.get_mach_tgt,
887 'sname': None # should be ignored
892 def test_fast_tgs_outer_no_sname(self):
893 self._run_test_sequence([
895 'rep_type': KRB_TGS_REP,
896 'expected_error_mode': 0,
898 'gen_tgt_fn': self.get_user_tgt,
901 'sname': None # should be ignored
906 def test_fast_outer_wrong_till(self):
907 self._run_test_sequence([
909 'rep_type': KRB_AS_REP,
910 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
912 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
913 'gen_armor_tgt_fn': self.get_mach_tgt,
915 'till': '15000101000000Z' # should be ignored
919 'rep_type': KRB_AS_REP,
920 'expected_error_mode': 0,
922 'gen_padata_fn': self.generate_enc_challenge_padata,
923 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
924 'gen_armor_tgt_fn': self.get_mach_tgt,
926 'till': '15000101000000Z' # should be ignored
931 def test_fast_tgs_outer_wrong_till(self):
932 self._run_test_sequence([
934 'rep_type': KRB_TGS_REP,
935 'expected_error_mode': 0,
937 'gen_tgt_fn': self.get_user_tgt,
940 'till': '15000101000000Z' # should be ignored
945 def test_fast_authdata_fast_used(self):
946 self._run_test_sequence([
948 'rep_type': KRB_TGS_REP,
949 'expected_error_mode': 0,
951 'gen_authdata_fn': self.generate_fast_used_auth_data,
952 'gen_tgt_fn': self.get_user_tgt,
957 def test_fast_authdata_fast_not_used(self):
958 # The AD-fx-fast-used authdata type can be included in the
959 # authenticator or the TGT authentication data to indicate that FAST
960 # must be used. The KDC must return KRB_APP_ERR_MODIFIED if it receives
961 # this authdata type in a request not using FAST (RFC6113 5.4.2).
962 self._run_test_sequence([
963 # This request works without FAST.
965 'rep_type': KRB_TGS_REP,
966 'expected_error_mode': 0,
968 'gen_tgt_fn': self.get_user_tgt
970 # Add the 'FAST used' auth data and it now fails.
972 'rep_type': KRB_TGS_REP,
973 'expected_error_mode': (KDC_ERR_MODIFIED,
976 'gen_authdata_fn': self.generate_fast_used_auth_data,
977 'gen_tgt_fn': self.get_user_tgt,
978 'expect_edata': False
982 def test_fast_ad_fx_fast_armor(self):
983 expected_sname = self.get_krbtgt_sname()
985 # If the authenticator or TGT authentication data contains the
986 # AD-fx-fast-armor authdata type, the KDC must reject the request
988 self._run_test_sequence([
989 # This request works.
991 'rep_type': KRB_TGS_REP,
992 'expected_error_mode': 0,
994 'gen_tgt_fn': self.get_user_tgt,
997 # Add the 'FAST armor' auth data and it now fails.
999 'rep_type': KRB_TGS_REP,
1000 'expected_error_mode': (KDC_ERR_GENERIC,
1001 KDC_ERR_BAD_INTEGRITY),
1003 'gen_authdata_fn': self.generate_fast_armor_auth_data,
1004 'gen_tgt_fn': self.get_user_tgt,
1006 'expected_sname': expected_sname,
1007 'expect_edata': False
1011 def test_fast_ad_fx_fast_armor2(self):
1012 # Show that we can still use the AD-fx-fast-armor authorization data in
1013 # FAST armor tickets.
1014 self._run_test_sequence([
1016 'rep_type': KRB_AS_REP,
1017 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1019 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1020 'gen_armor_tgt_fn': self.get_mach_tgt
1023 'rep_type': KRB_AS_REP,
1024 'expected_error_mode': 0,
1026 'gen_padata_fn': self.generate_enc_challenge_padata,
1027 'gen_authdata_fn': self.generate_fast_armor_auth_data,
1028 # include the auth data in the FAST armor.
1029 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1030 'gen_armor_tgt_fn': self.get_mach_tgt
1034 def test_fast_ad_fx_fast_armor_ticket(self):
1035 expected_sname = self.get_krbtgt_sname()
1037 # If the authenticator or TGT authentication data contains the
1038 # AD-fx-fast-armor authdata type, the KDC must reject the request
1040 self._run_test_sequence([
1041 # This request works.
1043 'rep_type': KRB_TGS_REP,
1044 'expected_error_mode': 0,
1046 'gen_tgt_fn': self.get_user_tgt,
1049 # Add AD-fx-fast-armor authdata element to user TGT. This request
1052 'rep_type': KRB_TGS_REP,
1053 'expected_error_mode': (KDC_ERR_GENERIC,
1054 KDC_ERR_BAD_INTEGRITY),
1056 'gen_tgt_fn': self.gen_tgt_fast_armor_auth_data,
1058 'expected_sname': expected_sname,
1059 'expect_edata': False
1063 def test_fast_ad_fx_fast_armor_enc_auth_data(self):
1064 # If the authenticator or TGT authentication data contains the
1065 # AD-fx-fast-armor authdata type, the KDC must reject the request
1066 # (RFC6113 5.4.2). However, the KDC should not reject a request that
1067 # contains this authdata type in enc-authorization-data.
1068 self._run_test_sequence([
1069 # This request works.
1071 'rep_type': KRB_TGS_REP,
1072 'expected_error_mode': 0,
1074 'gen_tgt_fn': self.get_user_tgt,
1077 # Add AD-fx-fast-armor authdata element to
1078 # enc-authorization-data. This request also works.
1080 'rep_type': KRB_TGS_REP,
1081 'expected_error_mode': 0,
1083 'gen_enc_authdata_fn': self.generate_fast_armor_auth_data,
1084 'gen_tgt_fn': self.get_user_tgt,
1089 def test_fast_ad_fx_fast_armor_ticket2(self):
1090 self._run_test_sequence([
1091 # Show that we can still use the modified ticket as armor.
1093 'rep_type': KRB_AS_REP,
1094 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1096 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1097 'gen_armor_tgt_fn': self.get_mach_tgt
1100 'rep_type': KRB_AS_REP,
1101 'expected_error_mode': 0,
1103 'gen_padata_fn': self.generate_enc_challenge_padata,
1104 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1105 'gen_armor_tgt_fn': self.gen_tgt_fast_armor_auth_data
1109 def test_fast_tgs_service_ticket(self):
1110 # Try to use a non-TGT ticket to establish an armor key, which fails
1112 self._run_test_sequence([
1114 'rep_type': KRB_TGS_REP,
1115 'expected_error_mode': (KDC_ERR_NOT_US,
1118 'gen_tgt_fn': self.get_user_service_ticket, # fails
1123 def test_fast_tgs_service_ticket_mach(self):
1124 self._run_test_sequence([
1126 'rep_type': KRB_TGS_REP,
1127 'expected_error_mode': (KDC_ERR_NOT_US, # fails
1130 'gen_tgt_fn': self.get_mach_service_ticket,
1135 def test_simple_tgs_no_subkey(self):
1136 self._run_test_sequence([
1138 'rep_type': KRB_TGS_REP,
1139 'expected_error_mode': 0,
1141 'gen_tgt_fn': self.get_user_tgt,
1142 'include_subkey': False
1146 def test_fast_tgs_no_subkey(self):
1147 expected_sname = self.get_krbtgt_sname()
1149 # Show that omitting the subkey in the TGS-REQ authenticator fails
1151 self._run_test_sequence([
1153 'rep_type': KRB_TGS_REP,
1154 'expected_error_mode': (KDC_ERR_GENERIC,
1155 KDC_ERR_PREAUTH_FAILED),
1157 'gen_tgt_fn': self.get_user_tgt,
1159 'include_subkey': False,
1160 'expected_sname': expected_sname,
1161 'expect_edata': False
1165 def test_fast_hide_client_names(self):
1166 self._run_test_sequence([
1168 'rep_type': KRB_AS_REP,
1169 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1171 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1172 'gen_armor_tgt_fn': self.get_mach_tgt,
1173 'fast_options': str(krb5_asn1.FastOptions(
1174 'hide-client-names')),
1175 'expected_anon': True
1178 'rep_type': KRB_AS_REP,
1179 'expected_error_mode': 0,
1181 'gen_padata_fn': self.generate_enc_challenge_padata,
1182 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1183 'gen_armor_tgt_fn': self.get_mach_tgt,
1184 'fast_options': str(krb5_asn1.FastOptions(
1185 'hide-client-names')),
1186 'expected_anon': True
1190 def test_fast_tgs_hide_client_names(self):
1191 self._run_test_sequence([
1193 'rep_type': KRB_TGS_REP,
1194 'expected_error_mode': 0,
1196 'gen_tgt_fn': self.get_user_tgt,
1198 'fast_options': str(krb5_asn1.FastOptions(
1199 'hide-client-names')),
1200 'expected_anon': True
1204 def test_fast_encrypted_challenge_replay(self):
1205 # The KDC is supposed to check that encrypted challenges are not
1206 # replays (RFC6113 5.4.6), but timestamps may be reused; an encrypted
1207 # challenge is only considered a replay if the ciphertext is identical
1208 # to a previous challenge. Windows does not perform this check.
1210 self._run_test_sequence([
1212 'rep_type': KRB_AS_REP,
1213 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED,
1215 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1216 'gen_armor_tgt_fn': self.get_mach_tgt
1219 'rep_type': KRB_AS_REP,
1220 'expected_error_mode': 0,
1222 'gen_padata_fn': self.generate_enc_challenge_padata_replay,
1223 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
1224 'gen_armor_tgt_fn': self.get_mach_tgt,
1229 def generate_enc_timestamp_padata(self,
1233 key = kdc_exchange_dict['preauth_key']
1235 padata = self.get_enc_timestamp_pa_data_from_key(key)
1236 return [padata], req_body
1238 def generate_enc_challenge_padata(self,
1243 armor_key = kdc_exchange_dict['armor_key']
1244 key = kdc_exchange_dict['preauth_key']
1246 client_challenge_key = (
1247 self.generate_client_challenge_key(armor_key, key))
1248 padata = self.get_challenge_pa_data(client_challenge_key, skew=skew)
1249 return [padata], req_body
1251 def generate_enc_challenge_padata_wrong_key_kdc(self,
1255 armor_key = kdc_exchange_dict['armor_key']
1256 key = kdc_exchange_dict['preauth_key']
1258 kdc_challenge_key = (
1259 self.generate_kdc_challenge_key(armor_key, key))
1260 padata = self.get_challenge_pa_data(kdc_challenge_key)
1261 return [padata], req_body
1263 def generate_enc_challenge_padata_wrong_key(self,
1267 key = kdc_exchange_dict['preauth_key']
1269 padata = self.get_challenge_pa_data(key)
1270 return [padata], req_body
1272 def generate_enc_challenge_padata_replay(self,
1276 padata = callback_dict.get('replay_padata')
1279 armor_key = kdc_exchange_dict['armor_key']
1280 key = kdc_exchange_dict['preauth_key']
1282 client_challenge_key = (
1283 self.generate_client_challenge_key(armor_key, key))
1284 padata = self.get_challenge_pa_data(client_challenge_key)
1285 callback_dict['replay_padata'] = padata
1287 return [padata], req_body
1289 def generate_empty_fast(self,
1297 fast_padata = self.PA_DATA_create(PADATA_FX_FAST, b'')
1301 def _run_test_sequence(self, test_sequence,
1302 client_account=KDCBaseTest.AccountType.USER):
1303 if self.strict_checking:
1304 self.check_kdc_fast_support()
1306 kdc_options_default = str(krb5_asn1.KDCOptions('forwardable,'
1309 client_creds = self.get_cached_creds(account_type=client_account)
1310 target_creds = self.get_service_creds()
1311 krbtgt_creds = self.get_krbtgt_creds()
1313 client_username = client_creds.get_username()
1314 client_realm = client_creds.get_realm()
1315 client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
1316 names=[client_username])
1318 krbtgt_username = krbtgt_creds.get_username()
1319 krbtgt_realm = krbtgt_creds.get_realm()
1320 krbtgt_sname = self.PrincipalName_create(
1321 name_type=NT_SRV_INST, names=[krbtgt_username, krbtgt_realm])
1322 krbtgt_decryption_key = self.TicketDecryptionKey_from_creds(
1324 krbtgt_etypes = krbtgt_creds.tgs_supported_enctypes
1326 target_username = target_creds.get_username()[:-1]
1327 target_realm = target_creds.get_realm()
1328 target_service = 'host'
1329 target_sname = self.PrincipalName_create(
1330 name_type=NT_SRV_HST, names=[target_service, target_username])
1331 target_decryption_key = self.TicketDecryptionKey_from_creds(
1333 target_etypes = target_creds.tgs_supported_enctypes
1335 client_decryption_key = self.TicketDecryptionKey_from_creds(
1337 client_etypes = client_creds.tgs_supported_enctypes
1340 preauth_etype_info2 = None
1342 for kdc_dict in test_sequence:
1343 rep_type = kdc_dict.pop('rep_type')
1344 self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP))
1346 expected_error_mode = kdc_dict.pop('expected_error_mode')
1347 if expected_error_mode == 0:
1348 expected_error_mode = ()
1349 elif not isinstance(expected_error_mode, collections.abc.Container):
1350 expected_error_mode = (expected_error_mode,)
1351 for error in expected_error_mode:
1352 self.assertIn(error, range(240))
1354 use_fast = kdc_dict.pop('use_fast')
1355 self.assertIs(type(use_fast), bool)
1358 self.assertIn('fast_armor', kdc_dict)
1359 fast_armor_type = kdc_dict.pop('fast_armor')
1361 if fast_armor_type is not None:
1362 self.assertIn('gen_armor_tgt_fn', kdc_dict)
1363 elif KDC_ERR_GENERIC not in expected_error_mode:
1364 self.assertNotIn('gen_armor_tgt_fn', kdc_dict)
1366 gen_armor_tgt_fn = kdc_dict.pop('gen_armor_tgt_fn', None)
1367 if gen_armor_tgt_fn is not None:
1368 armor_tgt = gen_armor_tgt_fn()
1372 fast_options = kdc_dict.pop('fast_options', '')
1374 fast_armor_type = None
1377 self.assertNotIn('fast_options', kdc_dict)
1380 if rep_type == KRB_TGS_REP:
1381 gen_tgt_fn = kdc_dict.pop('gen_tgt_fn')
1384 self.assertNotIn('gen_tgt_fn', kdc_dict)
1387 if len(expected_error_mode) != 0:
1388 check_error_fn = self.generic_check_kdc_error
1391 check_error_fn = None
1392 check_rep_fn = self.generic_check_kdc_rep
1394 etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96,
1397 cname = client_cname if rep_type == KRB_AS_REP else None
1398 crealm = client_realm
1400 as_req_self = kdc_dict.pop('as_req_self', False)
1402 self.assertEqual(KRB_AS_REP, rep_type)
1404 if 'sname' in kdc_dict:
1405 sname = kdc_dict.pop('sname')
1408 sname = client_cname
1409 elif rep_type == KRB_AS_REP:
1410 sname = krbtgt_sname
1412 sname = target_sname
1414 if rep_type == KRB_AS_REP:
1415 srealm = krbtgt_realm
1417 srealm = target_realm
1419 if rep_type == KRB_TGS_REP:
1420 tgt_cname = tgt.cname
1422 tgt_cname = client_cname
1424 expect_edata = kdc_dict.pop('expect_edata', None)
1425 if expect_edata is not None:
1426 self.assertTrue(expected_error_mode)
1428 expected_cname = kdc_dict.pop('expected_cname', tgt_cname)
1429 expected_anon = kdc_dict.pop('expected_anon',
1431 expected_crealm = kdc_dict.pop('expected_crealm', client_realm)
1432 expected_sname = kdc_dict.pop('expected_sname', sname)
1433 expected_srealm = kdc_dict.pop('expected_srealm', srealm)
1435 expected_salt = client_creds.get_salt()
1437 authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
1438 if rep_type == KRB_AS_REP:
1440 armor_key = self.generate_armor_key(authenticator_subkey,
1441 armor_tgt.session_key)
1442 armor_subkey = authenticator_subkey
1445 armor_subkey = authenticator_subkey
1447 if fast_armor_type is not None:
1448 armor_subkey = self.RandomKey(kcrypto.Enctype.AES256)
1449 explicit_armor_key = self.generate_armor_key(
1451 armor_tgt.session_key)
1452 armor_key = kcrypto.cf2(explicit_armor_key.key,
1453 authenticator_subkey.key,
1456 armor_key = Krb5EncryptionKey(armor_key, None)
1458 armor_key = self.generate_armor_key(authenticator_subkey,
1460 armor_subkey = authenticator_subkey
1462 if not kdc_dict.pop('include_subkey', True):
1463 authenticator_subkey = None
1466 generate_fast_fn = kdc_dict.pop('gen_fast_fn', None)
1467 if generate_fast_fn is None:
1468 generate_fast_fn = functools.partial(
1469 self.generate_simple_fast,
1470 fast_options=fast_options)
1472 generate_fast_fn = None
1474 generate_fast_armor_fn = (
1475 self.generate_ap_req
1476 if fast_armor_type is not None
1479 def _generate_padata_copy(_kdc_exchange_dict,
1483 return list(padata), req_body
1485 pac_options = kdc_dict.pop('pac_options', '1') # claims support
1487 kdc_options = kdc_dict.pop('kdc_options', kdc_options_default)
1489 gen_padata_fn = kdc_dict.pop('gen_padata_fn', None)
1491 if rep_type == KRB_AS_REP and gen_padata_fn is not None:
1492 self.assertIsNotNone(preauth_etype_info2)
1494 preauth_key = self.PasswordKey_from_etype_info2(
1496 preauth_etype_info2[0],
1497 client_creds.get_kvno())
1502 generate_fast_padata_fn = gen_padata_fn
1503 generate_padata_fn = (functools.partial(_generate_padata_copy,
1504 padata=[fast_cookie])
1505 if fast_cookie is not None else None)
1507 generate_fast_padata_fn = None
1508 generate_padata_fn = gen_padata_fn
1510 gen_authdata_fn = kdc_dict.pop('gen_authdata_fn', None)
1511 if gen_authdata_fn is not None:
1512 auth_data = [gen_authdata_fn()]
1516 gen_enc_authdata_fn = kdc_dict.pop('gen_enc_authdata_fn', None)
1517 if gen_enc_authdata_fn is not None:
1518 enc_auth_data = [gen_enc_authdata_fn()]
1520 enc_auth_data_key = authenticator_subkey
1521 enc_auth_data_usage = KU_TGS_REQ_AUTH_DAT_SUBKEY
1522 if enc_auth_data_key is None:
1523 enc_auth_data_key = tgt.session_key
1524 enc_auth_data_usage = KU_TGS_REQ_AUTH_DAT_SESSION
1526 enc_auth_data = None
1528 enc_auth_data_key = None
1529 enc_auth_data_usage = None
1532 self.assertNotIn('inner_req', kdc_dict)
1533 self.assertNotIn('outer_req', kdc_dict)
1534 inner_req = kdc_dict.pop('inner_req', None)
1535 outer_req = kdc_dict.pop('outer_req', None)
1537 expected_flags = kdc_dict.pop('expected_flags', None)
1538 if expected_flags is not None:
1539 expected_flags = krb5_asn1.TicketFlags(expected_flags)
1540 unexpected_flags = kdc_dict.pop('unexpected_flags', None)
1541 if unexpected_flags is not None:
1542 unexpected_flags = krb5_asn1.TicketFlags(unexpected_flags)
1544 fast_ap_options = kdc_dict.pop('fast_ap_options', None)
1546 strict_edata_checking = kdc_dict.pop('strict_edata_checking', True)
1548 if rep_type == KRB_AS_REP:
1550 expected_supported_etypes = client_etypes
1551 decryption_key = client_decryption_key
1553 expected_supported_etypes = krbtgt_etypes
1554 decryption_key = krbtgt_decryption_key
1556 kdc_exchange_dict = self.as_exchange_dict(
1557 expected_crealm=expected_crealm,
1558 expected_cname=expected_cname,
1559 expected_anon=expected_anon,
1560 expected_srealm=expected_srealm,
1561 expected_sname=expected_sname,
1562 expected_supported_etypes=expected_supported_etypes,
1563 expected_flags=expected_flags,
1564 unexpected_flags=unexpected_flags,
1565 ticket_decryption_key=decryption_key,
1566 generate_fast_fn=generate_fast_fn,
1567 generate_fast_armor_fn=generate_fast_armor_fn,
1568 generate_fast_padata_fn=generate_fast_padata_fn,
1569 fast_armor_type=fast_armor_type,
1570 generate_padata_fn=generate_padata_fn,
1571 check_error_fn=check_error_fn,
1572 check_rep_fn=check_rep_fn,
1573 check_kdc_private_fn=self.generic_check_kdc_private,
1575 expected_error_mode=expected_error_mode,
1576 client_as_etypes=etypes,
1577 expected_salt=expected_salt,
1578 authenticator_subkey=authenticator_subkey,
1579 preauth_key=preauth_key,
1580 auth_data=auth_data,
1581 armor_key=armor_key,
1582 armor_tgt=armor_tgt,
1583 armor_subkey=armor_subkey,
1584 kdc_options=kdc_options,
1585 inner_req=inner_req,
1586 outer_req=outer_req,
1588 pac_options=pac_options,
1589 fast_ap_options=fast_ap_options,
1590 strict_edata_checking=strict_edata_checking,
1591 expect_edata=expect_edata)
1593 kdc_exchange_dict = self.tgs_exchange_dict(
1594 expected_crealm=expected_crealm,
1595 expected_cname=expected_cname,
1596 expected_anon=expected_anon,
1597 expected_srealm=expected_srealm,
1598 expected_sname=expected_sname,
1599 expected_supported_etypes=target_etypes,
1600 expected_flags=expected_flags,
1601 unexpected_flags=unexpected_flags,
1602 ticket_decryption_key=target_decryption_key,
1603 generate_fast_fn=generate_fast_fn,
1604 generate_fast_armor_fn=generate_fast_armor_fn,
1605 generate_fast_padata_fn=generate_fast_padata_fn,
1606 fast_armor_type=fast_armor_type,
1607 generate_padata_fn=generate_padata_fn,
1608 check_error_fn=check_error_fn,
1609 check_rep_fn=check_rep_fn,
1610 check_kdc_private_fn=self.generic_check_kdc_private,
1611 expected_error_mode=expected_error_mode,
1614 armor_key=armor_key,
1615 armor_tgt=armor_tgt,
1616 armor_subkey=armor_subkey,
1617 authenticator_subkey=authenticator_subkey,
1618 auth_data=auth_data,
1619 body_checksum_type=None,
1620 kdc_options=kdc_options,
1621 inner_req=inner_req,
1622 outer_req=outer_req,
1624 pac_options=pac_options,
1625 fast_ap_options=fast_ap_options,
1626 strict_edata_checking=strict_edata_checking,
1627 expect_edata=expect_edata)
1629 repeat = kdc_dict.pop('repeat', 1)
1630 for _ in range(repeat):
1631 rep = self._generic_kdc_exchange(
1637 EncAuthorizationData=enc_auth_data,
1638 EncAuthorizationData_key=enc_auth_data_key,
1639 EncAuthorizationData_usage=enc_auth_data_usage)
1640 if len(expected_error_mode) == 0:
1641 self.check_reply(rep, rep_type)
1644 preauth_etype_info2 = None
1646 self.check_error_rep(rep, expected_error_mode)
1648 if 'fast_cookie' in kdc_exchange_dict:
1649 fast_cookie = self.create_fast_cookie(
1650 kdc_exchange_dict['fast_cookie'])
1654 if KDC_ERR_PREAUTH_REQUIRED in expected_error_mode:
1655 preauth_etype_info2 = (
1656 kdc_exchange_dict['preauth_etype_info2'])
1658 preauth_etype_info2 = None
1660 # Ensure we used all the parameters given to us.
1661 self.assertEqual({}, kdc_dict)
1663 def generate_fast_armor_auth_data(self):
1664 auth_data = self.AuthorizationData_create(AD_FX_FAST_ARMOR, b'')
1668 def generate_fast_used_auth_data(self):
1669 auth_data = self.AuthorizationData_create(AD_FX_FAST_USED, b'')
1673 def gen_tgt_fast_armor_auth_data(self):
1674 user_tgt = self.get_user_tgt()
1676 auth_data = self.generate_fast_armor_auth_data()
1678 def modify_fn(enc_part):
1679 enc_part['authorization-data'].append(auth_data)
1683 checksum_keys = self.get_krbtgt_checksum_key()
1685 # Use our modifed TGT to replace the one in the request.
1686 return self.modified_ticket(user_tgt,
1687 modify_fn=modify_fn,
1688 checksum_keys=checksum_keys)
1690 def create_fast_cookie(self, cookie):
1691 self.assertIsNotNone(cookie)
1692 if self.strict_checking:
1693 self.assertNotEqual(0, len(cookie))
1695 return self.PA_DATA_create(PADATA_FX_COOKIE, cookie)
1697 def check_kdc_fast_support(self):
1698 # Check that the KDC supports FAST
1700 samdb = self.get_samdb()
1702 krbtgt_rid = security.DOMAIN_RID_KRBTGT
1703 krbtgt_sid = '%s-%d' % (samdb.get_domain_sid(), krbtgt_rid)
1705 res = samdb.search(base='<SID=%s>' % krbtgt_sid,
1706 scope=ldb.SCOPE_BASE,
1707 attrs=['msDS-SupportedEncryptionTypes'])
1709 krbtgt_etypes = int(res[0]['msDS-SupportedEncryptionTypes'][0])
1712 security.KERB_ENCTYPE_FAST_SUPPORTED & krbtgt_etypes)
1714 security.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED & krbtgt_etypes)
1716 security.KERB_ENCTYPE_CLAIMS_SUPPORTED & krbtgt_etypes)
1718 def get_mach_tgt(self):
1719 if self.mach_tgt is None:
1720 mach_creds = self.get_mach_creds()
1721 type(self).mach_tgt = self.get_tgt(mach_creds)
1723 return self.mach_tgt
1725 def get_user_tgt(self):
1726 if self.user_tgt is None:
1727 user_creds = self.get_client_creds()
1728 type(self).user_tgt = self.get_tgt(user_creds)
1730 return self.user_tgt
1732 def get_user_service_ticket(self):
1733 if self.user_service_ticket is None:
1734 user_tgt = self.get_user_tgt()
1735 service_creds = self.get_service_creds()
1736 type(self).user_service_ticket = (
1737 self.get_service_ticket(user_tgt, service_creds))
1739 return self.user_service_ticket
1741 def get_mach_service_ticket(self):
1742 if self.mach_service_ticket is None:
1743 mach_tgt = self.get_mach_tgt()
1744 service_creds = self.get_service_creds()
1745 type(self).mach_service_ticket = (
1746 self.get_service_ticket(mach_tgt, service_creds))
1748 return self.mach_service_ticket
1750 def get_service_ticket_invalid_checksum(self):
1751 ticket = self.get_user_service_ticket()
1753 krbtgt_creds = self.get_krbtgt_creds()
1754 krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
1756 zeroed_key = ZeroedChecksumKey(krbtgt_key.key,
1759 server_key = ticket.decryption_key
1761 krb5pac.PAC_TYPE_SRV_CHECKSUM: server_key,
1762 krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
1763 krb5pac.PAC_TYPE_TICKET_CHECKSUM: zeroed_key,
1766 return self.modified_ticket(
1768 checksum_keys=checksum_keys,
1769 include_checksums={krb5pac.PAC_TYPE_TICKET_CHECKSUM: True})
1772 if __name__ == "__main__":
1773 global_asn1_print = False
1774 global_hexdump = False