@@ -701,6 +701,8 @@ class AD_AND_OR(ASN1_Packet):
701701 165 : "PA-SUPPORTED-ENCTYPES" ,
702702 166 : "PA-EXTENDED-ERROR" ,
703703 167 : "PA-PAC-OPTIONS" ,
704+ 170 : "KERB-SUPERSEDED-BY-USER" ,
705+ 171 : "KERB-DMSA-KEY-PACKAGE" ,
704706}
705707
706708_PADATA_CLASSES = {
@@ -1053,6 +1055,9 @@ class KERB_SUPERSEDED_BY_USER(ASN1_Packet):
10531055 )
10541056
10551057
1058+ _PADATA_CLASSES [170 ] = KERB_SUPERSEDED_BY_USER
1059+
1060+
10561061# [MS-KILE] sect 2.2.14
10571062
10581063
@@ -1070,14 +1075,17 @@ class KERB_DMSA_KEY_PACKAGE(ASN1_Packet):
10701075 "previousKeys" ,
10711076 [],
10721077 ASN1F_PACKET ("" , None , EncryptionKey ),
1073- explicit_tag = 0xA0 ,
1078+ explicit_tag = 0xA1 ,
10741079 ),
10751080 ),
10761081 KerberosTime ("expirationInterval" , GeneralizedTime (), explicit_tag = 0xA2 ),
10771082 KerberosTime ("fetchInterval" , GeneralizedTime (), explicit_tag = 0xA4 ),
10781083 )
10791084
10801085
1086+ _PADATA_CLASSES [171 ] = KERB_DMSA_KEY_PACKAGE
1087+
1088+
10811089# RFC6113 sect 5.4.1
10821090
10831091
@@ -1558,6 +1566,12 @@ class KRB_TGS_REP(ASN1_Packet):
15581566 implicit_tag = ASN1_Class_KRB .TGS_REP ,
15591567 )
15601568
1569+ def getUPN (self ):
1570+ return "%s@%s" % (
1571+ self .cname .toString (),
1572+ self .crealm .val .decode (),
1573+ )
1574+
15611575
15621576class LastReqItem (ASN1_Packet ):
15631577 ASN1_codec = ASN1_Codecs .BER
@@ -3389,6 +3403,19 @@ def _process_padatas_and_key(self, padatas):
33893403 )
33903404 elif padata .padataType == 137 : # PA-FX-ERROR
33913405 self .fast_error = padata .padataValue
3406+ elif padata .padataType == 130 : # PA-FOR-X509-USER
3407+ # Verify S4U checksum
3408+ key_usage_number = None
3409+ pasfux509 = padata .padataValue
3410+ # [MS-SFU] sect 2.2.2
3411+ # "In a reply, indicates that it was signed with key usage 27"
3412+ if pasfux509 .userId .options .val [2 ] == "1" : # USE_REPLY_KEY_USAGE
3413+ key_usage_number = 27
3414+ pasfux509 .checksum .verify (
3415+ self .key ,
3416+ bytes (pasfux509 .userId ),
3417+ key_usage_number = key_usage_number ,
3418+ )
33923419
33933420 # 2. Update the current key if necessary
33943421
@@ -3455,10 +3482,10 @@ def receive_krb_error_as_req(self, pkt):
34553482 return
34563483
34573484 if pkt .root .errorCode == 25 : # KDC_ERR_PREAUTH_REQUIRED
3458- if not self .key and ( not self . upn or not self . password ) :
3485+ if not self .key :
34593486 log_runtime .error (
34603487 "Got 'KDC_ERR_PREAUTH_REQUIRED', "
3461- "but no key, nor upn+pass was passed ."
3488+ "but no possible key could be computed ."
34623489 )
34633490 raise self .FINAL ()
34643491 self .should_followup = True
@@ -3542,7 +3569,11 @@ def receive_krb_error_tgs_req(self, pkt):
35423569 @ATMT .receive_condition (SENT_TGS_REQ )
35433570 def receive_tgs_rep (self , pkt ):
35443571 if Kerberos in pkt and isinstance (pkt .root , KRB_TGS_REP ):
3545- if not self .renew and pkt .root .ticket .sname .nameString [0 ].val == b"krbtgt" :
3572+ if (
3573+ not self .renew
3574+ and not self .dmsa
3575+ and pkt .root .ticket .sname .nameString [0 ].val == b"krbtgt"
3576+ ):
35463577 log_runtime .warning ("Received a cross-realm referral ticket !" )
35473578 raise self .FINAL ().action_parameters (pkt )
35483579
@@ -3570,6 +3601,8 @@ def decrypt_tgs_rep(self, pkt):
35703601 res = enc .decrypt (self .replykey , key_usage_number = 9 , cls = EncTGSRepPart )
35713602 else :
35723603 res = enc .decrypt (self .replykey )
3604+
3605+ # Store result
35733606 self .result = self .RES_TGS_MODE (pkt .root , res .key .toKey (), res )
35743607
35753608 @ATMT .state (final = 1 )
@@ -4169,6 +4202,8 @@ def GSS_WrapEx(self, Context, msgs, qop_req=0):
41694202 Data = b"" .join (x .data for x in msgs if x .conf_req_flag )
41704203 DataLen = len (Data )
41714204 # 2. Add filler
4205+ # [MS-KILE] sect 3.4.5.4.1 - "For AES-SHA1 ciphers, the EC must not
4206+ # be zero"
41724207 tok .root .EC = ((- DataLen ) % Context .KrbSessionKey .ep .blocksize ) or 16
41734208 Filler = b"\x00 " * tok .root .EC
41744209 Data += Filler
0 commit comments