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/>.
26 from samba
.dcerpc
import security
27 from samba
.tests
.krb5
.raw_testcase
import (
31 from samba
.tests
.krb5
.kdc_base_test
import KDCBaseTest
32 from samba
.tests
.krb5
.rfc4120_constants
import (
35 AES256_CTS_HMAC_SHA1_96
,
37 FX_FAST_ARMOR_AP_REQUEST
,
41 KDC_ERR_PREAUTH_FAILED
,
42 KDC_ERR_PREAUTH_REQUIRED
,
43 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS
,
55 import samba
.tests
.krb5
.rfc4120_pyasn1
as krb5_asn1
56 import samba
.tests
.krb5
.kcrypto
as kcrypto
58 sys
.path
.insert(0, "bin/python")
59 os
.environ
["PYTHONUNBUFFERED"] = "1"
61 global_asn1_print
= False
62 global_hexdump
= False
65 class FAST_Tests(KDCBaseTest
):
71 cls
.user_enc_part
= None
72 cls
.user_service_ticket
= None
75 cls
.mach_enc_part
= 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_tgs(self
):
99 self
._run
_test
_sequence
([
101 'rep_type': KRB_TGS_REP
,
102 'expected_error_mode': 0,
104 'gen_tgt_fn': self
.get_user_tgt
108 def test_simple_no_sname(self
):
109 krbtgt_creds
= self
.get_krbtgt_creds()
110 krbtgt_username
= krbtgt_creds
.get_username()
111 krbtgt_realm
= krbtgt_creds
.get_realm()
112 expected_sname
= self
.PrincipalName_create(
113 name_type
=NT_SRV_INST
, names
=[krbtgt_username
, krbtgt_realm
])
115 self
._run
_test
_sequence
([
117 'rep_type': KRB_AS_REP
,
118 'expected_error_mode': KDC_ERR_GENERIC
,
121 'expected_sname': expected_sname
125 def test_simple_tgs_no_sname(self
):
126 krbtgt_creds
= self
.get_krbtgt_creds()
127 krbtgt_username
= krbtgt_creds
.get_username()
128 krbtgt_realm
= krbtgt_creds
.get_realm()
129 expected_sname
= self
.PrincipalName_create(
130 name_type
=NT_SRV_INST
, names
=[krbtgt_username
, krbtgt_realm
])
132 self
._run
_test
_sequence
([
134 'rep_type': KRB_TGS_REP
,
135 'expected_error_mode': KDC_ERR_GENERIC
,
137 'gen_tgt_fn': self
.get_user_tgt
,
139 'expected_sname': expected_sname
143 def test_fast_no_sname(self
):
144 krbtgt_creds
= self
.get_krbtgt_creds()
145 krbtgt_username
= krbtgt_creds
.get_username()
146 krbtgt_realm
= krbtgt_creds
.get_realm()
147 expected_sname
= self
.PrincipalName_create(
148 name_type
=NT_SRV_INST
, names
=[krbtgt_username
, krbtgt_realm
])
150 self
._run
_test
_sequence
([
152 'rep_type': KRB_AS_REP
,
153 'expected_error_mode': KDC_ERR_GENERIC
,
155 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
156 'gen_armor_tgt_fn': self
.get_mach_tgt
,
158 'expected_sname': expected_sname
162 def test_fast_tgs_no_sname(self
):
163 krbtgt_creds
= self
.get_krbtgt_creds()
164 krbtgt_username
= krbtgt_creds
.get_username()
165 krbtgt_realm
= krbtgt_creds
.get_realm()
166 expected_sname
= self
.PrincipalName_create(
167 name_type
=NT_SRV_INST
, names
=[krbtgt_username
, krbtgt_realm
])
169 self
._run
_test
_sequence
([
171 'rep_type': KRB_TGS_REP
,
172 'expected_error_mode': KDC_ERR_GENERIC
,
174 'gen_tgt_fn': self
.get_user_tgt
,
177 'expected_sname': expected_sname
181 def test_simple_tgs_wrong_principal(self
):
182 mach_creds
= self
.get_mach_creds()
183 mach_name
= mach_creds
.get_username()
184 expected_cname
= self
.PrincipalName_create(
185 name_type
=NT_PRINCIPAL
, names
=[mach_name
])
187 self
._run
_test
_sequence
([
189 'rep_type': KRB_TGS_REP
,
190 'expected_error_mode': 0,
192 'gen_tgt_fn': self
.get_mach_tgt
,
193 'expected_cname': expected_cname
197 def test_simple_tgs_service_ticket(self
):
198 self
._run
_test
_sequence
([
200 'rep_type': KRB_TGS_REP
,
201 'expected_error_mode': KDC_ERR_NOT_US
,
203 'gen_tgt_fn': self
.get_user_service_ticket
,
207 def test_simple_tgs_service_ticket_mach(self
):
208 self
._run
_test
_sequence
([
210 'rep_type': KRB_TGS_REP
,
211 'expected_error_mode': KDC_ERR_NOT_US
,
213 'gen_tgt_fn': self
.get_mach_service_ticket
,
217 def test_fast_no_claims(self
):
218 self
._run
_test
_sequence
([
220 'rep_type': KRB_AS_REP
,
221 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
223 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
224 'gen_armor_tgt_fn': self
.get_mach_tgt
,
228 'rep_type': KRB_AS_REP
,
229 'expected_error_mode': 0,
231 'gen_padata_fn': self
.generate_enc_challenge_padata
,
232 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
233 'gen_armor_tgt_fn': self
.get_mach_tgt
,
238 def test_fast_tgs_no_claims(self
):
239 self
._run
_test
_sequence
([
241 'rep_type': KRB_TGS_REP
,
242 'expected_error_mode': 0,
244 'gen_tgt_fn': self
.get_user_tgt
,
250 def test_fast_no_claims_or_canon(self
):
251 self
._run
_test
_sequence
([
253 'rep_type': KRB_AS_REP
,
254 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
256 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
257 'gen_armor_tgt_fn': self
.get_mach_tgt
,
262 'rep_type': KRB_AS_REP
,
263 'expected_error_mode': 0,
265 'gen_padata_fn': self
.generate_enc_challenge_padata
,
266 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
267 'gen_armor_tgt_fn': self
.get_mach_tgt
,
273 def test_fast_tgs_no_claims_or_canon(self
):
274 self
._run
_test
_sequence
([
276 'rep_type': KRB_TGS_REP
,
277 'expected_error_mode': 0,
279 'gen_tgt_fn': self
.get_user_tgt
,
286 def test_fast_no_canon(self
):
287 self
._run
_test
_sequence
([
289 'rep_type': KRB_AS_REP
,
290 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
292 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
293 'gen_armor_tgt_fn': self
.get_mach_tgt
,
297 'rep_type': KRB_AS_REP
,
298 'expected_error_mode': 0,
300 'gen_padata_fn': self
.generate_enc_challenge_padata
,
301 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
302 'gen_armor_tgt_fn': self
.get_mach_tgt
,
307 def test_fast_tgs_no_canon(self
):
308 self
._run
_test
_sequence
([
310 'rep_type': KRB_TGS_REP
,
311 'expected_error_mode': 0,
313 'gen_tgt_fn': self
.get_user_tgt
,
319 def test_simple_tgs_no_etypes(self
):
320 self
._run
_test
_sequence
([
322 'rep_type': KRB_TGS_REP
,
323 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP
,
325 'gen_tgt_fn': self
.get_mach_tgt
,
330 def test_fast_tgs_no_etypes(self
):
331 self
._run
_test
_sequence
([
333 'rep_type': KRB_TGS_REP
,
334 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP
,
336 'gen_tgt_fn': self
.get_mach_tgt
,
342 def test_simple_no_etypes(self
):
343 self
._run
_test
_sequence
([
345 'rep_type': KRB_AS_REP
,
346 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP
,
352 def test_simple_fast_no_etypes(self
):
353 self
._run
_test
_sequence
([
355 'rep_type': KRB_AS_REP
,
356 'expected_error_mode': KDC_ERR_ETYPE_NOSUPP
,
358 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
359 'gen_armor_tgt_fn': self
.get_mach_tgt
,
364 def test_empty_fast(self
):
365 # Add an empty PA-FX-FAST in the initial AS-REQ. This should get
366 # rejected with a Generic error.
367 self
._run
_test
_sequence
([
369 'rep_type': KRB_AS_REP
,
370 'expected_error_mode': KDC_ERR_GENERIC
,
372 'gen_fast_fn': self
.generate_empty_fast
,
374 'gen_armor_tgt_fn': self
.get_mach_tgt
378 def test_fast_unknown_critical_option(self
):
379 self
._run
_test
_sequence
([
381 'rep_type': KRB_AS_REP
,
382 'expected_error_mode': KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS
,
384 'fast_options': '001', # unsupported critical option
385 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
386 'gen_armor_tgt_fn': self
.get_mach_tgt
390 def test_unarmored_as_req(self
):
391 self
._run
_test
_sequence
([
393 'rep_type': KRB_AS_REP
,
394 'expected_error_mode': KDC_ERR_GENERIC
,
396 'fast_armor': None, # no armor,
397 'gen_armor_tgt_fn': self
.get_mach_tgt
401 def test_fast_invalid_armor_type(self
):
402 self
._run
_test
_sequence
([
404 'rep_type': KRB_AS_REP
,
405 'expected_error_mode': KDC_ERR_PREAUTH_FAILED
,
407 'fast_armor': 0, # invalid armor type
408 'gen_armor_tgt_fn': self
.get_mach_tgt
412 def test_fast_invalid_armor_type2(self
):
413 self
._run
_test
_sequence
([
415 'rep_type': KRB_AS_REP
,
416 'expected_error_mode': KDC_ERR_PREAUTH_FAILED
,
418 'fast_armor': 2, # invalid armor type
419 'gen_armor_tgt_fn': self
.get_mach_tgt
423 def test_fast_encrypted_challenge(self
):
424 self
._run
_test
_sequence
([
426 'rep_type': KRB_AS_REP
,
427 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
429 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
430 'gen_armor_tgt_fn': self
.get_mach_tgt
433 'rep_type': KRB_AS_REP
,
434 'expected_error_mode': 0,
436 'gen_padata_fn': self
.generate_enc_challenge_padata
,
437 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
438 'gen_armor_tgt_fn': self
.get_mach_tgt
442 def test_fast_encrypted_challenge_wrong_key(self
):
443 self
._run
_test
_sequence
([
445 'rep_type': KRB_AS_REP
,
446 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
448 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
449 'gen_armor_tgt_fn': self
.get_mach_tgt
452 'rep_type': KRB_AS_REP
,
453 'expected_error_mode': KDC_ERR_PREAUTH_FAILED
,
455 'gen_padata_fn': self
.generate_enc_challenge_padata_wrong_key
,
456 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
457 'gen_armor_tgt_fn': self
.get_mach_tgt
461 def test_fast_encrypted_challenge_wrong_key_kdc(self
):
462 self
._run
_test
_sequence
([
464 'rep_type': KRB_AS_REP
,
465 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
467 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
468 'gen_armor_tgt_fn': self
.get_mach_tgt
471 'rep_type': KRB_AS_REP
,
472 'expected_error_mode': KDC_ERR_PREAUTH_FAILED
,
475 self
.generate_enc_challenge_padata_wrong_key_kdc
,
476 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
477 'gen_armor_tgt_fn': self
.get_mach_tgt
481 def test_fast_encrypted_challenge_no_fast(self
):
482 self
._run
_test
_sequence
([
484 'rep_type': KRB_AS_REP
,
485 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
489 'rep_type': KRB_AS_REP
,
490 'expected_error_mode': KDC_ERR_PREAUTH_FAILED
,
492 'gen_padata_fn': self
.generate_enc_challenge_padata_wrong_key
496 def test_fast_encrypted_challenge_clock_skew(self
):
497 # The KDC is supposed to confirm that the timestamp is within its
498 # current clock skew, and return KRB_APP_ERR_SKEW if it is not (RFC6113
499 # 5.4.6). However, Windows accepts a skewed timestamp in the encrypted
501 self
._run
_test
_sequence
([
503 'rep_type': KRB_AS_REP
,
504 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
506 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
507 'gen_armor_tgt_fn': self
.get_mach_tgt
510 'rep_type': KRB_AS_REP
,
511 'expected_error_mode': 0,
513 'gen_padata_fn': functools
.partial(
514 self
.generate_enc_challenge_padata
,
516 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
517 'gen_armor_tgt_fn': self
.get_mach_tgt
521 def test_fast_invalid_tgt(self
):
522 # The armor ticket 'sname' field is required to identify the target
523 # realm TGS (RFC6113 5.4.1.1). However, Windows will still accept a
524 # service ticket identifying a different server principal.
525 self
._run
_test
_sequence
([
527 'rep_type': KRB_AS_REP
,
528 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
530 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
531 'gen_armor_tgt_fn': self
.get_user_service_ticket
534 'rep_type': KRB_AS_REP
,
535 'expected_error_mode': 0,
537 'gen_padata_fn': self
.generate_enc_challenge_padata
,
538 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
539 'gen_armor_tgt_fn': self
.get_user_service_ticket
540 # ticket not identifying TGS of current
545 def test_fast_invalid_tgt_mach(self
):
546 self
._run
_test
_sequence
([
548 'rep_type': KRB_AS_REP
,
549 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
551 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
552 'gen_armor_tgt_fn': self
.get_mach_service_ticket
555 'rep_type': KRB_AS_REP
,
556 'expected_error_mode': 0,
558 'gen_padata_fn': self
.generate_enc_challenge_padata
,
559 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
560 'gen_armor_tgt_fn': self
.get_mach_service_ticket
561 # ticket not identifying TGS of current
566 def test_fast_enc_timestamp(self
):
567 # Provide ENC-TIMESTAMP as FAST padata when we should be providing
568 # ENCRYPTED-CHALLENGE - ensure that we get PREAUTH_REQUIRED.
569 self
._run
_test
_sequence
([
571 'rep_type': KRB_AS_REP
,
572 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
574 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
575 'gen_armor_tgt_fn': self
.get_mach_tgt
578 'rep_type': KRB_AS_REP
,
579 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
581 'gen_padata_fn': self
.generate_enc_timestamp_padata
,
582 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
583 'gen_armor_tgt_fn': self
.get_mach_tgt
588 self
._run
_test
_sequence
([
590 'rep_type': KRB_AS_REP
,
591 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
593 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
594 'gen_armor_tgt_fn': self
.get_mach_tgt
597 'rep_type': KRB_AS_REP
,
598 'expected_error_mode': 0,
600 'gen_padata_fn': self
.generate_enc_challenge_padata
,
601 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
602 'gen_armor_tgt_fn': self
.get_mach_tgt
606 def test_fast_tgs(self
):
607 self
._run
_test
_sequence
([
609 'rep_type': KRB_TGS_REP
,
610 'expected_error_mode': 0,
612 'gen_tgt_fn': self
.get_user_tgt
,
617 def test_fast_tgs_armor(self
):
618 self
._run
_test
_sequence
([
620 'rep_type': KRB_TGS_REP
,
621 'expected_error_mode': 0,
623 'gen_tgt_fn': self
.get_user_tgt
,
624 'gen_armor_tgt_fn': self
.get_mach_tgt
,
625 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
629 def test_fast_outer_wrong_realm(self
):
630 self
._run
_test
_sequence
([
632 'rep_type': KRB_AS_REP
,
633 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
635 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
636 'gen_armor_tgt_fn': self
.get_mach_tgt
,
638 'realm': 'TEST' # should be ignored
642 'rep_type': KRB_AS_REP
,
643 'expected_error_mode': 0,
645 'gen_padata_fn': self
.generate_enc_challenge_padata
,
646 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
647 'gen_armor_tgt_fn': self
.get_mach_tgt
,
649 'realm': 'TEST' # should be ignored
654 def test_fast_tgs_outer_wrong_realm(self
):
655 self
._run
_test
_sequence
([
657 'rep_type': KRB_TGS_REP
,
658 'expected_error_mode': 0,
660 'gen_tgt_fn': self
.get_user_tgt
,
663 'realm': 'TEST' # should be ignored
668 def test_fast_outer_wrong_nonce(self
):
669 self
._run
_test
_sequence
([
671 'rep_type': KRB_AS_REP
,
672 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
674 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
675 'gen_armor_tgt_fn': self
.get_mach_tgt
,
677 'nonce': '123' # should be ignored
681 'rep_type': KRB_AS_REP
,
682 'expected_error_mode': 0,
684 'gen_padata_fn': self
.generate_enc_challenge_padata
,
685 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
686 'gen_armor_tgt_fn': self
.get_mach_tgt
,
688 'nonce': '123' # should be ignored
693 def test_fast_tgs_outer_wrong_nonce(self
):
694 self
._run
_test
_sequence
([
696 'rep_type': KRB_TGS_REP
,
697 'expected_error_mode': 0,
699 'gen_tgt_fn': self
.get_user_tgt
,
702 'nonce': '123' # should be ignored
707 def test_fast_outer_wrong_flags(self
):
708 self
._run
_test
_sequence
([
710 'rep_type': KRB_AS_REP
,
711 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
713 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
714 'gen_armor_tgt_fn': self
.get_mach_tgt
,
716 'kdc-options': '11111111111111111' # should be ignored
720 'rep_type': KRB_AS_REP
,
721 'expected_error_mode': 0,
723 'gen_padata_fn': self
.generate_enc_challenge_padata
,
724 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
725 'gen_armor_tgt_fn': self
.get_mach_tgt
,
727 'kdc-options': '11111111111111111' # should be ignored
732 def test_fast_tgs_outer_wrong_flags(self
):
733 self
._run
_test
_sequence
([
735 'rep_type': KRB_TGS_REP
,
736 'expected_error_mode': 0,
738 'gen_tgt_fn': self
.get_user_tgt
,
741 'kdc-options': '11111111111111111' # should be ignored
746 def test_fast_outer_no_sname(self
):
747 self
._run
_test
_sequence
([
749 'rep_type': KRB_AS_REP
,
750 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
752 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
753 'gen_armor_tgt_fn': self
.get_mach_tgt
,
755 'sname': None # should be ignored
759 'rep_type': KRB_AS_REP
,
760 'expected_error_mode': 0,
762 'gen_padata_fn': self
.generate_enc_challenge_padata
,
763 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
764 'gen_armor_tgt_fn': self
.get_mach_tgt
,
766 'sname': None # should be ignored
771 def test_fast_tgs_outer_no_sname(self
):
772 self
._run
_test
_sequence
([
774 'rep_type': KRB_TGS_REP
,
775 'expected_error_mode': 0,
777 'gen_tgt_fn': self
.get_user_tgt
,
780 'sname': None # should be ignored
785 def test_fast_outer_wrong_till(self
):
786 self
._run
_test
_sequence
([
788 'rep_type': KRB_AS_REP
,
789 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
791 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
792 'gen_armor_tgt_fn': self
.get_mach_tgt
,
794 'till': '15000101000000Z' # should be ignored
798 'rep_type': KRB_AS_REP
,
799 'expected_error_mode': 0,
801 'gen_padata_fn': self
.generate_enc_challenge_padata
,
802 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
803 'gen_armor_tgt_fn': self
.get_mach_tgt
,
805 'till': '15000101000000Z' # should be ignored
810 def test_fast_tgs_outer_wrong_till(self
):
811 self
._run
_test
_sequence
([
813 'rep_type': KRB_TGS_REP
,
814 'expected_error_mode': 0,
816 'gen_tgt_fn': self
.get_user_tgt
,
819 'till': '15000101000000Z' # should be ignored
824 def test_fast_authdata_fast_used(self
):
825 self
._run
_test
_sequence
([
827 'rep_type': KRB_TGS_REP
,
828 'expected_error_mode': 0,
830 'gen_authdata_fn': self
.generate_fast_used_auth_data
,
831 'gen_tgt_fn': self
.get_user_tgt
,
836 def test_fast_authdata_fast_not_used(self
):
837 # The AD-fx-fast-used authdata type can be included in the
838 # authenticator or the TGT authentication data to indicate that FAST
839 # must be used. The KDC must return KRB_APP_ERR_MODIFIED if it receives
840 # this authdata type in a request not using FAST (RFC6113 5.4.2).
841 self
._run
_test
_sequence
([
842 # This request works without FAST.
844 'rep_type': KRB_TGS_REP
,
845 'expected_error_mode': 0,
847 'gen_tgt_fn': self
.get_user_tgt
849 # Add the 'FAST used' auth data and it now fails.
851 'rep_type': KRB_TGS_REP
,
852 'expected_error_mode': KDC_ERR_GENERIC
,
853 # should be KRB_APP_ERR_MODIFIED
855 'gen_authdata_fn': self
.generate_fast_used_auth_data
,
856 'gen_tgt_fn': self
.get_user_tgt
860 def test_fast_ad_fx_fast_armor(self
):
861 # If the authenticator or TGT authentication data contains the
862 # AD-fx-fast-armor authdata type, the KDC must reject the request
864 self
._run
_test
_sequence
([
865 # This request works.
867 'rep_type': KRB_TGS_REP
,
868 'expected_error_mode': 0,
870 'gen_tgt_fn': self
.get_user_tgt
,
873 # Add the 'FAST armor' auth data and it now fails.
875 'rep_type': KRB_TGS_REP
,
876 'expected_error_mode': KDC_ERR_GENERIC
,
878 'gen_authdata_fn': self
.generate_fast_armor_auth_data
,
879 'gen_tgt_fn': self
.get_user_tgt
,
884 def test_fast_ad_fx_fast_armor2(self
):
885 # Show that we can still use the AD-fx-fast-armor authorization data in
886 # FAST armor tickets.
887 self
._run
_test
_sequence
([
889 'rep_type': KRB_AS_REP
,
890 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
892 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
893 'gen_armor_tgt_fn': self
.get_mach_tgt
896 'rep_type': KRB_AS_REP
,
897 'expected_error_mode': 0,
899 'gen_padata_fn': self
.generate_enc_challenge_padata
,
900 'gen_authdata_fn': self
.generate_fast_armor_auth_data
,
901 # include the auth data in the FAST armor.
902 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
903 'gen_armor_tgt_fn': self
.get_mach_tgt
907 def test_fast_ad_fx_fast_armor_ticket(self
):
908 # If the authenticator or TGT authentication data contains the
909 # AD-fx-fast-armor authdata type, the KDC must reject the request
911 self
._run
_test
_sequence
([
912 # This request works.
914 'rep_type': KRB_TGS_REP
,
915 'expected_error_mode': 0,
917 'gen_tgt_fn': self
.get_user_tgt
,
920 # Add AD-fx-fast-armor authdata element to user TGT. This request
923 'rep_type': KRB_TGS_REP
,
924 'expected_error_mode': KDC_ERR_GENERIC
,
926 'gen_tgt_fn': self
.gen_tgt_fast_armor_auth_data
,
931 def test_fast_ad_fx_fast_armor_ticket2(self
):
932 self
._run
_test
_sequence
([
933 # Show that we can still use the modified ticket as armor.
935 'rep_type': KRB_AS_REP
,
936 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
938 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
939 'gen_armor_tgt_fn': self
.get_mach_tgt
942 'rep_type': KRB_AS_REP
,
943 'expected_error_mode': 0,
945 'gen_padata_fn': self
.generate_enc_challenge_padata
,
946 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
947 'gen_armor_tgt_fn': self
.gen_tgt_fast_armor_auth_data
951 def test_fast_tgs_service_ticket(self
):
952 # Try to use a non-TGT ticket to establish an armor key, which fails
954 self
._run
_test
_sequence
([
956 'rep_type': KRB_TGS_REP
,
957 'expected_error_mode': KDC_ERR_NOT_US
,
959 'gen_tgt_fn': self
.get_user_service_ticket
, # fails
964 def test_fast_tgs_service_ticket_mach(self
):
965 self
._run
_test
_sequence
([
967 'rep_type': KRB_TGS_REP
,
968 'expected_error_mode': KDC_ERR_NOT_US
, # fails
970 'gen_tgt_fn': self
.get_mach_service_ticket
,
975 def test_simple_tgs_no_subkey(self
):
976 self
._run
_test
_sequence
([
978 'rep_type': KRB_TGS_REP
,
979 'expected_error_mode': 0,
981 'gen_tgt_fn': self
.get_user_tgt
,
982 'include_subkey': False
986 def test_fast_tgs_no_subkey(self
):
987 # Show that omitting the subkey in the TGS-REQ authenticator fails
989 self
._run
_test
_sequence
([
991 'rep_type': KRB_TGS_REP
,
992 'expected_error_mode': KDC_ERR_GENERIC
,
994 'gen_tgt_fn': self
.get_user_tgt
,
996 'include_subkey': False
1000 def test_fast_hide_client_names(self
):
1001 user_creds
= self
.get_client_creds()
1002 user_name
= user_creds
.get_username()
1003 user_cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
1006 expected_cname
= self
.PrincipalName_create(
1007 name_type
=NT_WELLKNOWN
, names
=['WELLKNOWN', 'ANONYMOUS'])
1009 self
._run
_test
_sequence
([
1011 'rep_type': KRB_AS_REP
,
1012 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
1014 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
1015 'gen_armor_tgt_fn': self
.get_mach_tgt
,
1016 'fast_options': '01', # hide client names
1017 'expected_cname': expected_cname
1020 'rep_type': KRB_AS_REP
,
1021 'expected_error_mode': 0,
1023 'gen_padata_fn': self
.generate_enc_challenge_padata
,
1024 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
1025 'gen_armor_tgt_fn': self
.get_mach_tgt
,
1026 'fast_options': '01', # hide client names
1027 'expected_cname': expected_cname
,
1028 'expected_cname_private': user_cname
1032 def test_fast_tgs_hide_client_names(self
):
1033 user_creds
= self
.get_client_creds()
1034 user_name
= user_creds
.get_username()
1035 user_cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
1038 expected_cname
= self
.PrincipalName_create(
1039 name_type
=NT_WELLKNOWN
, names
=['WELLKNOWN', 'ANONYMOUS'])
1041 self
._run
_test
_sequence
([
1043 'rep_type': KRB_TGS_REP
,
1044 'expected_error_mode': 0,
1046 'gen_tgt_fn': self
.get_user_tgt
,
1048 'fast_options': '01', # hide client names
1049 'expected_cname': expected_cname
,
1050 'expected_cname_private': user_cname
1054 def test_fast_encrypted_challenge_replay(self
):
1055 # The KDC is supposed to check that encrypted challenges are not
1056 # replays (RFC6113 5.4.6), but timestamps may be reused; an encrypted
1057 # challenge is only considered a replay if the ciphertext is identical
1058 # to a previous challenge. Windows does not perform this check.
1060 class GenerateEncChallengePadataReplay
:
1061 def __init__(replay
):
1062 replay
._padata
= None
1064 def __call__(replay
, key
, armor_key
):
1065 if replay
._padata
is None:
1066 client_challenge_key
= (
1067 self
.generate_client_challenge_key(armor_key
, key
))
1068 replay
._padata
= self
.get_challenge_pa_data(
1069 client_challenge_key
)
1071 return replay
._padata
1073 self
._run
_test
_sequence
([
1075 'rep_type': KRB_AS_REP
,
1076 'expected_error_mode': KDC_ERR_PREAUTH_REQUIRED
,
1078 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
1079 'gen_armor_tgt_fn': self
.get_mach_tgt
1082 'rep_type': KRB_AS_REP
,
1083 'expected_error_mode': 0,
1085 'gen_padata_fn': GenerateEncChallengePadataReplay(),
1086 'fast_armor': FX_FAST_ARMOR_AP_REQUEST
,
1087 'gen_armor_tgt_fn': self
.get_mach_tgt
,
1092 def generate_enc_timestamp_padata(self
, key
, _armor_key
):
1093 return self
.get_enc_timestamp_pa_data_from_key(key
)
1095 def generate_enc_challenge_padata(self
, key
, armor_key
, skew
=0):
1096 client_challenge_key
= (
1097 self
.generate_client_challenge_key(armor_key
, key
))
1098 return self
.get_challenge_pa_data(client_challenge_key
, skew
=skew
)
1100 def generate_enc_challenge_padata_wrong_key_kdc(self
, key
, armor_key
):
1101 kdc_challenge_key
= (
1102 self
.generate_kdc_challenge_key(armor_key
, key
))
1103 return self
.get_challenge_pa_data(kdc_challenge_key
)
1105 def generate_enc_challenge_padata_wrong_key(self
, key
, _armor_key
):
1106 return self
.get_challenge_pa_data(key
)
1108 def generate_empty_fast(self
,
1116 fast_padata
= self
.PA_DATA_create(PADATA_FX_FAST
, b
'')
1120 def _run_test_sequence(self
, test_sequence
):
1121 if self
.strict_checking
:
1122 self
.check_kdc_fast_support()
1124 kdc_options_default
= str(krb5_asn1
.KDCOptions('forwardable,'
1129 pac_request
= self
.get_pa_pac_request()
1131 client_creds
= self
.get_client_creds()
1132 target_creds
= self
.get_service_creds()
1133 krbtgt_creds
= self
.get_krbtgt_creds()
1135 client_username
= client_creds
.get_username()
1136 client_realm
= client_creds
.get_realm()
1137 client_cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
1138 names
=[client_username
])
1140 krbtgt_username
= krbtgt_creds
.get_username()
1141 krbtgt_realm
= krbtgt_creds
.get_realm()
1142 krbtgt_sname
= self
.PrincipalName_create(
1143 name_type
=NT_SRV_INST
, names
=[krbtgt_username
, krbtgt_realm
])
1144 krbtgt_decryption_key
= self
.TicketDecryptionKey_from_creds(
1147 target_username
= target_creds
.get_username()[:-1]
1148 target_realm
= target_creds
.get_realm()
1149 target_service
= 'host'
1150 target_sname
= self
.PrincipalName_create(
1151 name_type
=NT_SRV_INST
, names
=[target_service
, target_username
])
1152 target_decryption_key
= self
.TicketDecryptionKey_from_creds(
1153 target_creds
, etype
=kcrypto
.Enctype
.RC4
)
1156 preauth_etype_info2
= None
1160 for kdc_dict
in test_sequence
:
1161 rep_type
= kdc_dict
.pop('rep_type')
1162 self
.assertIn(rep_type
, (KRB_AS_REP
, KRB_TGS_REP
))
1164 expected_error_mode
= kdc_dict
.pop('expected_error_mode')
1165 self
.assertIn(expected_error_mode
, range(240))
1167 use_fast
= kdc_dict
.pop('use_fast')
1168 self
.assertIs(type(use_fast
), bool)
1171 self
.assertIn('fast_armor', kdc_dict
)
1172 fast_armor_type
= kdc_dict
.pop('fast_armor')
1174 if fast_armor_type
is not None:
1175 self
.assertIn('gen_armor_tgt_fn', kdc_dict
)
1176 elif expected_error_mode
!= KDC_ERR_GENERIC
:
1177 self
.assertNotIn('gen_armor_tgt_fn', kdc_dict
)
1179 gen_armor_tgt_fn
= kdc_dict
.pop('gen_armor_tgt_fn', None)
1180 if gen_armor_tgt_fn
is not None:
1181 armor_tgt
= gen_armor_tgt_fn()
1185 fast_options
= kdc_dict
.pop('fast_options', '')
1187 fast_armor_type
= None
1190 self
.assertNotIn('fast_options', kdc_dict
)
1193 if rep_type
== KRB_TGS_REP
:
1194 gen_tgt_fn
= kdc_dict
.pop('gen_tgt_fn')
1197 self
.assertNotIn('gen_tgt_fn', kdc_dict
)
1200 if expected_error_mode
!= 0:
1201 check_error_fn
= self
.generic_check_kdc_error
1204 check_error_fn
= None
1205 check_rep_fn
= self
.generic_check_kdc_rep
1207 etypes
= kdc_dict
.pop('etypes', (AES256_CTS_HMAC_SHA1_96
,
1210 cname
= client_cname
if rep_type
== KRB_AS_REP
else None
1211 crealm
= client_realm
1213 if 'sname' in kdc_dict
:
1214 sname
= kdc_dict
.pop('sname')
1216 if rep_type
== KRB_AS_REP
:
1217 sname
= krbtgt_sname
1219 sname
= target_sname
1221 if rep_type
== KRB_AS_REP
:
1222 srealm
= krbtgt_realm
1224 srealm
= target_realm
1226 expected_cname
= kdc_dict
.pop('expected_cname', client_cname
)
1227 expected_cname_private
= kdc_dict
.pop('expected_cname_private',
1229 expected_crealm
= kdc_dict
.pop('expected_crealm', client_realm
)
1230 expected_sname
= kdc_dict
.pop('expected_sname', sname
)
1231 expected_srealm
= kdc_dict
.pop('expected_srealm', srealm
)
1233 expected_salt
= client_creds
.get_salt()
1235 authenticator_subkey
= self
.RandomKey(kcrypto
.Enctype
.AES256
)
1236 if rep_type
== KRB_AS_REP
:
1238 armor_key
= self
.generate_armor_key(authenticator_subkey
,
1239 armor_tgt
.session_key
)
1240 armor_subkey
= authenticator_subkey
1243 armor_subkey
= authenticator_subkey
1245 if fast_armor_type
is not None:
1246 armor_subkey
= self
.RandomKey(kcrypto
.Enctype
.AES256
)
1247 explicit_armor_key
= self
.generate_armor_key(
1249 armor_tgt
.session_key
)
1250 armor_key
= kcrypto
.cf2(explicit_armor_key
.key
,
1251 authenticator_subkey
.key
,
1254 armor_key
= Krb5EncryptionKey(armor_key
, None)
1256 armor_key
= self
.generate_armor_key(authenticator_subkey
,
1258 armor_subkey
= authenticator_subkey
1260 if not kdc_dict
.pop('include_subkey', True):
1261 authenticator_subkey
= None
1264 generate_fast_fn
= kdc_dict
.pop('gen_fast_fn', None)
1265 if generate_fast_fn
is None:
1266 generate_fast_fn
= functools
.partial(
1267 self
.generate_simple_fast
,
1268 fast_options
=fast_options
)
1270 generate_fast_fn
= None
1272 generate_fast_armor_fn
= (
1273 self
.generate_ap_req
1274 if fast_armor_type
is not None
1277 def _generate_padata_copy(_kdc_exchange_dict
,
1281 return padata
, req_body
1283 def _check_padata_preauth_key(_kdc_exchange_dict
,
1287 as_rep_usage
= KU_AS_REP_ENC_PART
1288 return preauth_key
, as_rep_usage
1290 pac_options
= kdc_dict
.pop('pac_options', '1') # claims support
1291 pac_options
= self
.get_pa_pac_options(pac_options
)
1293 kdc_options
= kdc_dict
.pop('kdc_options', kdc_options_default
)
1295 if rep_type
== KRB_AS_REP
:
1296 padata
= [pac_request
, pac_options
]
1298 padata
= [pac_options
]
1300 gen_padata_fn
= kdc_dict
.pop('gen_padata_fn', None)
1301 if gen_padata_fn
is not None:
1302 self
.assertEqual(KRB_AS_REP
, rep_type
)
1303 self
.assertIsNotNone(preauth_etype_info2
)
1305 preauth_key
= self
.PasswordKey_from_etype_info2(
1307 preauth_etype_info2
[0],
1308 client_creds
.get_kvno())
1309 gen_padata
= gen_padata_fn(preauth_key
, armor_key
)
1310 padata
.insert(0, gen_padata
)
1314 if rep_type
== KRB_AS_REP
:
1315 check_padata_fn
= _check_padata_preauth_key
1317 check_padata_fn
= self
.check_simple_tgs_padata
1320 inner_padata
= padata
1324 outer_padata
= padata
1326 if use_fast
and fast_cookie
is not None:
1327 outer_padata
.append(fast_cookie
)
1329 generate_fast_padata_fn
= (functools
.partial(_generate_padata_copy
,
1330 padata
=inner_padata
)
1331 if inner_padata
else None)
1332 generate_padata_fn
= (functools
.partial(_generate_padata_copy
,
1333 padata
=outer_padata
)
1334 if outer_padata
else None)
1336 gen_authdata_fn
= kdc_dict
.pop('gen_authdata_fn', None)
1337 if gen_authdata_fn
is not None:
1338 auth_data
= [gen_authdata_fn()]
1343 self
.assertNotIn('inner_req', kdc_dict
)
1344 self
.assertNotIn('outer_req', kdc_dict
)
1345 inner_req
= kdc_dict
.pop('inner_req', None)
1346 outer_req
= kdc_dict
.pop('outer_req', None)
1348 if rep_type
== KRB_AS_REP
:
1349 kdc_exchange_dict
= self
.as_exchange_dict(
1350 expected_crealm
=expected_crealm
,
1351 expected_cname
=expected_cname
,
1352 expected_cname_private
=expected_cname_private
,
1353 expected_srealm
=expected_srealm
,
1354 expected_sname
=expected_sname
,
1355 ticket_decryption_key
=krbtgt_decryption_key
,
1356 generate_fast_fn
=generate_fast_fn
,
1357 generate_fast_armor_fn
=generate_fast_armor_fn
,
1358 generate_fast_padata_fn
=generate_fast_padata_fn
,
1359 fast_armor_type
=fast_armor_type
,
1360 generate_padata_fn
=generate_padata_fn
,
1361 check_error_fn
=check_error_fn
,
1362 check_rep_fn
=check_rep_fn
,
1363 check_padata_fn
=check_padata_fn
,
1364 check_kdc_private_fn
=self
.generic_check_kdc_private
,
1366 expected_error_mode
=expected_error_mode
,
1367 client_as_etypes
=etypes
,
1368 expected_salt
=expected_salt
,
1369 authenticator_subkey
=authenticator_subkey
,
1370 auth_data
=auth_data
,
1371 armor_key
=armor_key
,
1372 armor_tgt
=armor_tgt
,
1373 armor_subkey
=armor_subkey
,
1374 kdc_options
=kdc_options
,
1375 inner_req
=inner_req
,
1376 outer_req
=outer_req
)
1378 kdc_exchange_dict
= self
.tgs_exchange_dict(
1379 expected_crealm
=expected_crealm
,
1380 expected_cname
=expected_cname
,
1381 expected_cname_private
=expected_cname_private
,
1382 expected_srealm
=expected_srealm
,
1383 expected_sname
=expected_sname
,
1384 ticket_decryption_key
=target_decryption_key
,
1385 generate_fast_fn
=generate_fast_fn
,
1386 generate_fast_armor_fn
=generate_fast_armor_fn
,
1387 generate_fast_padata_fn
=generate_fast_padata_fn
,
1388 fast_armor_type
=fast_armor_type
,
1389 generate_padata_fn
=generate_padata_fn
,
1390 check_error_fn
=check_error_fn
,
1391 check_rep_fn
=check_rep_fn
,
1392 check_padata_fn
=check_padata_fn
,
1393 check_kdc_private_fn
=self
.generic_check_kdc_private
,
1394 expected_error_mode
=expected_error_mode
,
1397 armor_key
=armor_key
,
1398 armor_tgt
=armor_tgt
,
1399 armor_subkey
=armor_subkey
,
1400 authenticator_subkey
=authenticator_subkey
,
1401 auth_data
=auth_data
,
1402 body_checksum_type
=None,
1403 kdc_options
=kdc_options
,
1404 inner_req
=inner_req
,
1405 outer_req
=outer_req
)
1407 repeat
= kdc_dict
.pop('repeat', 1)
1408 for _
in range(repeat
):
1409 rep
= self
._generic
_kdc
_exchange
(kdc_exchange_dict
,
1414 if expected_error_mode
== 0:
1415 self
.check_reply(rep
, rep_type
)
1418 preauth_etype_info2
= None
1420 self
.check_error_rep(rep
, expected_error_mode
)
1422 if 'fast_cookie' in kdc_exchange_dict
:
1423 fast_cookie
= self
.create_fast_cookie(
1424 kdc_exchange_dict
['fast_cookie'])
1428 if expected_error_mode
== KDC_ERR_PREAUTH_REQUIRED
:
1429 preauth_etype_info2
= (
1430 kdc_exchange_dict
['preauth_etype_info2'])
1432 preauth_etype_info2
= None
1434 # Ensure we used all the parameters given to us.
1435 self
.assertEqual({}, kdc_dict
)
1437 def generate_fast_armor_auth_data(self
):
1438 auth_data
= self
.AuthorizationData_create(AD_FX_FAST_ARMOR
, b
'')
1442 def generate_fast_used_auth_data(self
):
1443 auth_data
= self
.AuthorizationData_create(AD_FX_FAST_USED
, b
'')
1447 def gen_tgt_fast_armor_auth_data(self
):
1448 user_tgt
= self
.get_user_tgt()
1450 ticket_decryption_key
= user_tgt
.decryption_key
1452 tgt_encpart
= self
.getElementValue(user_tgt
.ticket
, 'enc-part')
1453 self
.assertElementEqual(tgt_encpart
, 'etype',
1454 ticket_decryption_key
.etype
)
1455 self
.assertElementKVNO(tgt_encpart
, 'kvno',
1456 ticket_decryption_key
.kvno
)
1457 tgt_cipher
= self
.getElementValue(tgt_encpart
, 'cipher')
1458 tgt_decpart
= ticket_decryption_key
.decrypt(KU_TICKET
, tgt_cipher
)
1459 tgt_private
= self
.der_decode(tgt_decpart
,
1460 asn1Spec
=krb5_asn1
.EncTicketPart())
1462 auth_data
= self
.generate_fast_armor_auth_data()
1463 tgt_private
['authorization-data'].append(auth_data
)
1465 # Re-encrypt the user TGT.
1466 tgt_private_new
= self
.der_encode(
1468 asn1Spec
=krb5_asn1
.EncTicketPart())
1469 tgt_encpart
= self
.EncryptedData_create(ticket_decryption_key
,
1472 user_ticket
= user_tgt
.ticket
.copy()
1473 user_ticket
['enc-part'] = tgt_encpart
1475 user_tgt
= KerberosTicketCreds(
1477 session_key
=user_tgt
.session_key
,
1478 crealm
=user_tgt
.crealm
,
1479 cname
=user_tgt
.cname
,
1480 srealm
=user_tgt
.srealm
,
1481 sname
=user_tgt
.sname
,
1482 decryption_key
=user_tgt
.decryption_key
,
1483 ticket_private
=tgt_private
,
1484 encpart_private
=user_tgt
.encpart_private
)
1486 # Use our modifed TGT to replace the one in the request.
1489 def create_fast_cookie(self
, cookie
):
1490 self
.assertIsNotNone(cookie
)
1491 if self
.strict_checking
:
1492 self
.assertNotEqual(0, len(cookie
))
1494 return self
.PA_DATA_create(PADATA_FX_COOKIE
, cookie
)
1496 def get_pa_pac_request(self
, request_pac
=True):
1497 pac_request
= self
.KERB_PA_PAC_REQUEST_create(request_pac
)
1501 def get_pa_pac_options(self
, options
):
1502 pac_options
= self
.PA_PAC_OPTIONS_create(options
)
1503 pac_options
= self
.der_encode(pac_options
,
1504 asn1Spec
=krb5_asn1
.PA_PAC_OPTIONS())
1505 pac_options
= self
.PA_DATA_create(PADATA_PAC_OPTIONS
, pac_options
)
1509 def check_kdc_fast_support(self
):
1510 # Check that the KDC supports FAST
1512 samdb
= self
.get_samdb()
1515 krbtgt_sid
= '%s-%d' % (samdb
.get_domain_sid(), krbtgt_rid
)
1517 res
= samdb
.search(base
='<SID=%s>' % krbtgt_sid
,
1518 scope
=ldb
.SCOPE_BASE
,
1519 attrs
=['msDS-SupportedEncryptionTypes'])
1521 krbtgt_etypes
= int(res
[0]['msDS-SupportedEncryptionTypes'][0])
1524 security
.KERB_ENCTYPE_FAST_SUPPORTED
& krbtgt_etypes
)
1526 security
.KERB_ENCTYPE_COMPOUND_IDENTITY_SUPPORTED
& krbtgt_etypes
)
1528 security
.KERB_ENCTYPE_CLAIMS_SUPPORTED
& krbtgt_etypes
)
1530 def get_service_ticket(self
, tgt
, target_creds
, service
='host'):
1531 etype
= (AES256_CTS_HMAC_SHA1_96
, ARCFOUR_HMAC_MD5
)
1533 key
= tgt
.session_key
1539 target_name
= target_creds
.get_username()[:-1]
1540 sname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
1541 names
=[service
, target_name
])
1543 rep
, enc_part
= self
.tgs_req(cname
, sname
, realm
, ticket
, key
, etype
)
1545 service_ticket
= rep
['ticket']
1547 ticket_etype
= service_ticket
['enc-part']['etype']
1548 target_key
= self
.TicketDecryptionKey_from_creds(target_creds
,
1551 session_key
= self
.EncryptionKey_import(enc_part
['key'])
1553 service_ticket_creds
= KerberosTicketCreds(service_ticket
,
1559 decryption_key
=target_key
)
1561 return service_ticket_creds
1563 def get_tgt(self
, creds
):
1564 user_name
= creds
.get_username()
1565 realm
= creds
.get_realm()
1567 salt
= creds
.get_salt()
1569 etype
= (AES256_CTS_HMAC_SHA1_96
, ARCFOUR_HMAC_MD5
)
1570 cname
= self
.PrincipalName_create(name_type
=NT_PRINCIPAL
,
1572 sname
= self
.PrincipalName_create(name_type
=NT_SRV_INST
,
1573 names
=['krbtgt', realm
])
1575 till
= self
.get_KerberosTime(offset
=36000)
1577 krbtgt_creds
= self
.get_krbtgt_creds()
1578 ticket_decryption_key
= (
1579 self
.TicketDecryptionKey_from_creds(krbtgt_creds
))
1581 kdc_options
= str(krb5_asn1
.KDCOptions('forwardable,'
1586 pac_request
= self
.get_pa_pac_request()
1587 pac_options
= self
.get_pa_pac_options('1') # supports claims
1589 padata
= [pac_request
, pac_options
]
1591 rep
, kdc_exchange_dict
= self
._test
_as
_exchange
(
1596 client_as_etypes
=etype
,
1597 expected_error_mode
=KDC_ERR_PREAUTH_REQUIRED
,
1598 expected_crealm
=realm
,
1599 expected_cname
=cname
,
1600 expected_srealm
=realm
,
1601 expected_sname
=sname
,
1605 kdc_options
=kdc_options
,
1607 ticket_decryption_key
=ticket_decryption_key
)
1608 self
.check_pre_authentication(rep
)
1610 etype_info2
= kdc_exchange_dict
['preauth_etype_info2']
1612 preauth_key
= self
.PasswordKey_from_etype_info2(creds
,
1616 ts_enc_padata
= self
.get_enc_timestamp_pa_data(creds
, rep
)
1618 padata
= [ts_enc_padata
, pac_request
, pac_options
]
1620 expected_realm
= realm
.upper()
1622 expected_sname
= self
.PrincipalName_create(
1623 name_type
=NT_SRV_INST
, names
=['krbtgt', realm
.upper()])
1625 rep
, kdc_exchange_dict
= self
._test
_as
_exchange
(
1630 client_as_etypes
=etype
,
1631 expected_error_mode
=0,
1632 expected_crealm
=expected_realm
,
1633 expected_cname
=cname
,
1634 expected_srealm
=expected_realm
,
1635 expected_sname
=expected_sname
,
1639 kdc_options
=kdc_options
,
1640 preauth_key
=preauth_key
,
1641 ticket_decryption_key
=ticket_decryption_key
)
1642 self
.check_as_reply(rep
)
1646 enc_part
= self
.get_as_rep_enc_data(preauth_key
, rep
)
1647 session_key
= self
.EncryptionKey_import(enc_part
['key'])
1649 ticket_creds
= KerberosTicketCreds(
1656 decryption_key
=ticket_decryption_key
)
1658 return ticket_creds
, enc_part
1660 def get_mach_tgt(self
):
1661 if self
.mach_tgt
is None:
1662 mach_creds
= self
.get_mach_creds()
1663 type(self
).mach_tgt
, type(self
).mach_enc_part
= (
1664 self
.get_tgt(mach_creds
))
1666 return self
.mach_tgt
1668 def get_user_tgt(self
):
1669 if self
.user_tgt
is None:
1670 user_creds
= self
.get_client_creds()
1671 type(self
).user_tgt
, type(self
).user_enc_part
= (
1672 self
.get_tgt(user_creds
))
1674 return self
.user_tgt
1676 def get_user_service_ticket(self
):
1677 if self
.user_service_ticket
is None:
1678 user_tgt
= self
.get_user_tgt()
1679 service_creds
= self
.get_service_creds()
1680 type(self
).user_service_ticket
= (
1681 self
.get_service_ticket(user_tgt
, service_creds
))
1683 return self
.user_service_ticket
1685 def get_mach_service_ticket(self
):
1686 if self
.mach_service_ticket
is None:
1687 mach_tgt
= self
.get_mach_tgt()
1688 service_creds
= self
.get_service_creds()
1689 type(self
).mach_service_ticket
= (
1690 self
.get_service_ticket(mach_tgt
, service_creds
))
1692 return self
.mach_service_ticket
1695 if __name__
== "__main__":
1696 global_asn1_print
= False
1697 global_hexdump
= False