Skip to content

Commit 059b3a2

Browse files
committed
Support DMSA in Kerberos tgs_req
1 parent d7ce0e4 commit 059b3a2

2 files changed

Lines changed: 94 additions & 26 deletions

File tree

scapy/layers/kerberos.py

Lines changed: 93 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
)
140140
from scapy.layers.inet import TCP, UDP
141141
from scapy.layers.smb import _NV_VERSION
142+
from scapy.layers.x509 import X509_AlgorithmIdentifier
142143

143144
# Typing imports
144145
from typing import (
@@ -480,8 +481,8 @@ def get_usage(self):
480481
# [MS-SFU] sect 2.2.1
481482
return 17
482483
elif isinstance(self.underlayer, PA_S4U_X509_USER):
483-
# [MS-SFU] sect 2.2.1
484-
return 17
484+
# [MS-SFU] sect 2.2.2
485+
return 26
485486
elif isinstance(self.underlayer, AD_KDCIssued):
486487
# AD-KDC-ISSUED checksum
487488
return 19
@@ -672,6 +673,7 @@ class AD_AND_OR(ASN1_Packet):
672673
17: "PA-PK-AS-REP",
673674
19: "PA-ETYPE-INFO2",
674675
20: "PA-SVR-REFERRAL-INFO",
676+
111: "TD-CMS-DIGEST-ALGORITHMS",
675677
128: "PA-PAC-REQUEST",
676678
129: "PA-FOR-USER",
677679
130: "PA-FOR-X509-USER",
@@ -805,6 +807,18 @@ class ETYPE_INFO2(ASN1_Packet):
805807

806808
_PADATA_CLASSES[19] = ETYPE_INFO2
807809

810+
811+
# RFC8636 - PKINIT Algorithm Agility
812+
813+
814+
class TD_CMS_DIGEST_ALGORITHMS(ASN1_Packet):
815+
ASN1_codec = ASN1_Codecs.BER
816+
ASN1_root = ASN1F_SEQUENCE_OF("seq", [], X509_AlgorithmIdentifier)
817+
818+
819+
_PADATA_CLASSES[111] = TD_CMS_DIGEST_ALGORITHMS
820+
821+
808822
# PADATA Extended with RFC6113
809823

810824

@@ -1271,7 +1285,9 @@ class S4UUserID(ASN1_Packet):
12711285
[
12721286
"reserved",
12731287
"KDC_CHECK_LOGON_HOUR_RESTRICTIONS",
1274-
"KDC_KEY_USAGE_27",
1288+
"USE_REPLY_KEY_USAGE",
1289+
"NT_AUTH_POLICY_NOT_REQUIRED",
1290+
"UNCONDITIONAL_DELEGATION",
12751291
],
12761292
explicit_tag=0xA4,
12771293
)
@@ -2690,6 +2706,7 @@ class KerberosClient(Automaton):
26902706
:param u2u: sets the U2U flag
26912707
:param for_user: the UPN of another user in TGS-REQ, to do a S4U2Self
26922708
:param s4u2proxy: sets the S4U2Proxy flag
2709+
:param dmsa: sets the 'unconditional delegation' mode for DMSA TGT retrieval
26932710
:param kdc_proxy: specify a KDC proxy url
26942711
:param kdc_proxy_no_check_certificate: do not check the KDC proxy certificate
26952712
:param fast: use FAST armoring
@@ -2725,6 +2742,7 @@ def __init__(
27252742
u2u=False,
27262743
for_user=None,
27272744
s4u2proxy=False,
2745+
dmsa=False,
27282746
kdc_proxy=None,
27292747
kdc_proxy_no_check_certificate=False,
27302748
fast=False,
@@ -2838,6 +2856,7 @@ def __init__(
28382856
self.u2u = u2u # U2U
28392857
self.for_user = for_user # FOR-USER
28402858
self.s4u2proxy = s4u2proxy # S4U2Proxy
2859+
self.dmsa = dmsa # DMSA
28412860
self.key = key
28422861
self.subkey = None # In the AP-REQ authenticator
28432862
self.replykey = None # Key used for reply
@@ -3152,34 +3171,83 @@ def tgs_req(self):
31523171

31533172
# [MS-SFU] FOR-USER extension
31543173
if self.for_user is not None:
3155-
from scapy.libs.rfc3961 import ChecksumType
3156-
3157-
paforuser = PA_FOR_USER(
3158-
userName=PrincipalName.fromUPN(self.for_user),
3159-
userRealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]),
3160-
cksum=Checksum(),
3161-
)
3162-
S4UByteArray = struct.pack( # [MS-SFU] sect 2.2.1
3163-
"<I", paforuser.userName.nameType.val
3164-
) + (
3165-
(
3166-
"".join(x.val for x in paforuser.userName.nameString)
3167-
+ paforuser.userRealm.val
3168-
+ paforuser.authPackage.val
3169-
).encode()
3170-
)
3171-
paforuser.cksum.make(
3172-
self.key,
3173-
S4UByteArray,
3174-
cksumtype=ChecksumType.HMAC_MD5,
3174+
from scapy.libs.rfc3961 import ChecksumType, EncryptionType
3175+
3176+
# [MS-SFU] note 4:
3177+
# "Windows Vista, Windows Server 2008, Windows 7, and Windows Server
3178+
# 2008 R2 send the PA-S4U-X509-USER padata type alone if the user's
3179+
# certificate is available.
3180+
# If the user's certificate is not available, it sends both the
3181+
# PA-S4U-X509-USER padata type and the PA-FOR-USER padata type.
3182+
# When the PA-S4U-X509-USER padata type is used without the user's
3183+
# certificate, the certificate field is not present."
3184+
3185+
# 1. Add PA_S4U_X509_USER
3186+
pasfux509 = PA_S4U_X509_USER(
3187+
userId=S4UUserID(
3188+
nonce=kdc_req.nonce,
3189+
# [MS-SFU] note 5:
3190+
# "Windows S4U clients always set this option."
3191+
options="USE_REPLY_KEY_USAGE",
3192+
cname=PrincipalName.fromUPN(self.for_user),
3193+
crealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]),
3194+
subjectCertificate=None, # TODO
3195+
),
3196+
checksum=Checksum(),
31753197
)
3198+
3199+
if self.dmsa:
3200+
# DMSA = set UNCONDITIONAL_DELEGATION to 1
3201+
pasfux509.userId.options.set(4, 1)
3202+
3203+
if self.key.etype in [EncryptionType.RC4_HMAC, EncryptionType.RC4_HMAC_EXP]:
3204+
# "if the key's encryption type is RC4_HMAC_NT (23) the checksum type
3205+
# is rsa-md4 (2) as defined in section 6.2.6 of [RFC3961]."
3206+
pasfux509.checksum.make(
3207+
self.key,
3208+
bytes(pasfux509.userId),
3209+
cksumtype=ChecksumType.RSA_MD4,
3210+
)
3211+
else:
3212+
pasfux509.checksum.make(
3213+
self.key,
3214+
bytes(pasfux509.userId),
3215+
)
31763216
padata.append(
31773217
PADATA(
3178-
padataType=ASN1_INTEGER(129), # PA-FOR-USER
3179-
padataValue=paforuser,
3218+
padataType=ASN1_INTEGER(130), # PA-FOR-X509-USER
3219+
padataValue=pasfux509,
31803220
)
31813221
)
31823222

3223+
# 2. Add PA_FOR_USER
3224+
if True: # XXX user's certificate is not available.
3225+
paforuser = PA_FOR_USER(
3226+
userName=PrincipalName.fromUPN(self.for_user),
3227+
userRealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]),
3228+
cksum=Checksum(),
3229+
)
3230+
S4UByteArray = struct.pack( # [MS-SFU] sect 2.2.1
3231+
"<I", paforuser.userName.nameType.val
3232+
) + (
3233+
(
3234+
"".join(x.val for x in paforuser.userName.nameString)
3235+
+ paforuser.userRealm.val
3236+
+ paforuser.authPackage.val
3237+
).encode()
3238+
)
3239+
paforuser.cksum.make(
3240+
self.key,
3241+
S4UByteArray,
3242+
cksumtype=ChecksumType.HMAC_MD5,
3243+
)
3244+
padata.append(
3245+
PADATA(
3246+
padataType=ASN1_INTEGER(129), # PA-FOR-USER
3247+
padataValue=paforuser,
3248+
)
3249+
)
3250+
31833251
# [MS-SFU] S4U2proxy - sect 3.1.5.2.1
31843252
if self.s4u2proxy:
31853253
# "PA-PAC-OPTIONS with resource-based constrained-delegation bit set"

scapy/libs/rfc3961.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class EncryptionType(enum.IntEnum):
149149

150150
class ChecksumType(enum.IntEnum):
151151
CRC32 = 1
152-
# RSA_MD4 = 2
152+
RSA_MD4 = 2
153153
RSA_MD4_DES = 3
154154
# RSA_MD5 = 7
155155
RSA_MD5_DES = 8

0 commit comments

Comments
 (0)