|
139 | 139 | ) |
140 | 140 | from scapy.layers.inet import TCP, UDP |
141 | 141 | from scapy.layers.smb import _NV_VERSION |
| 142 | +from scapy.layers.x509 import X509_AlgorithmIdentifier |
142 | 143 |
|
143 | 144 | # Typing imports |
144 | 145 | from typing import ( |
@@ -480,8 +481,8 @@ def get_usage(self): |
480 | 481 | # [MS-SFU] sect 2.2.1 |
481 | 482 | return 17 |
482 | 483 | 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 |
485 | 486 | elif isinstance(self.underlayer, AD_KDCIssued): |
486 | 487 | # AD-KDC-ISSUED checksum |
487 | 488 | return 19 |
@@ -672,6 +673,7 @@ class AD_AND_OR(ASN1_Packet): |
672 | 673 | 17: "PA-PK-AS-REP", |
673 | 674 | 19: "PA-ETYPE-INFO2", |
674 | 675 | 20: "PA-SVR-REFERRAL-INFO", |
| 676 | + 111: "TD-CMS-DIGEST-ALGORITHMS", |
675 | 677 | 128: "PA-PAC-REQUEST", |
676 | 678 | 129: "PA-FOR-USER", |
677 | 679 | 130: "PA-FOR-X509-USER", |
@@ -805,6 +807,18 @@ class ETYPE_INFO2(ASN1_Packet): |
805 | 807 |
|
806 | 808 | _PADATA_CLASSES[19] = ETYPE_INFO2 |
807 | 809 |
|
| 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 | + |
808 | 822 | # PADATA Extended with RFC6113 |
809 | 823 |
|
810 | 824 |
|
@@ -1271,7 +1285,9 @@ class S4UUserID(ASN1_Packet): |
1271 | 1285 | [ |
1272 | 1286 | "reserved", |
1273 | 1287 | "KDC_CHECK_LOGON_HOUR_RESTRICTIONS", |
1274 | | - "KDC_KEY_USAGE_27", |
| 1288 | + "USE_REPLY_KEY_USAGE", |
| 1289 | + "NT_AUTH_POLICY_NOT_REQUIRED", |
| 1290 | + "UNCONDITIONAL_DELEGATION", |
1275 | 1291 | ], |
1276 | 1292 | explicit_tag=0xA4, |
1277 | 1293 | ) |
@@ -2690,6 +2706,7 @@ class KerberosClient(Automaton): |
2690 | 2706 | :param u2u: sets the U2U flag |
2691 | 2707 | :param for_user: the UPN of another user in TGS-REQ, to do a S4U2Self |
2692 | 2708 | :param s4u2proxy: sets the S4U2Proxy flag |
| 2709 | + :param dmsa: sets the 'unconditional delegation' mode for DMSA TGT retrieval |
2693 | 2710 | :param kdc_proxy: specify a KDC proxy url |
2694 | 2711 | :param kdc_proxy_no_check_certificate: do not check the KDC proxy certificate |
2695 | 2712 | :param fast: use FAST armoring |
@@ -2725,6 +2742,7 @@ def __init__( |
2725 | 2742 | u2u=False, |
2726 | 2743 | for_user=None, |
2727 | 2744 | s4u2proxy=False, |
| 2745 | + dmsa=False, |
2728 | 2746 | kdc_proxy=None, |
2729 | 2747 | kdc_proxy_no_check_certificate=False, |
2730 | 2748 | fast=False, |
@@ -2838,6 +2856,7 @@ def __init__( |
2838 | 2856 | self.u2u = u2u # U2U |
2839 | 2857 | self.for_user = for_user # FOR-USER |
2840 | 2858 | self.s4u2proxy = s4u2proxy # S4U2Proxy |
| 2859 | + self.dmsa = dmsa # DMSA |
2841 | 2860 | self.key = key |
2842 | 2861 | self.subkey = None # In the AP-REQ authenticator |
2843 | 2862 | self.replykey = None # Key used for reply |
@@ -3152,34 +3171,83 @@ def tgs_req(self): |
3152 | 3171 |
|
3153 | 3172 | # [MS-SFU] FOR-USER extension |
3154 | 3173 | 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(), |
3175 | 3197 | ) |
| 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 | + ) |
3176 | 3216 | padata.append( |
3177 | 3217 | PADATA( |
3178 | | - padataType=ASN1_INTEGER(129), # PA-FOR-USER |
3179 | | - padataValue=paforuser, |
| 3218 | + padataType=ASN1_INTEGER(130), # PA-FOR-X509-USER |
| 3219 | + padataValue=pasfux509, |
3180 | 3220 | ) |
3181 | 3221 | ) |
3182 | 3222 |
|
| 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 | + |
3183 | 3251 | # [MS-SFU] S4U2proxy - sect 3.1.5.2.1 |
3184 | 3252 | if self.s4u2proxy: |
3185 | 3253 | # "PA-PAC-OPTIONS with resource-based constrained-delegation bit set" |
|
0 commit comments