From 78418047632fbc2bb5cfb004d1cc56990206b054 Mon Sep 17 00:00:00 2001 From: gpotter2 <10530980+gpotter2@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:52:23 +0200 Subject: [PATCH] kerberos: update IAKERB flags AI-Assisted: no --- scapy/layers/kerberos.py | 52 +++++++++++++++++++++++++++++++----- scapy/layers/spnego.py | 10 +++---- test/scapy/layers/spnego.uts | 2 +- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/scapy/layers/kerberos.py b/scapy/layers/kerberos.py index 904449b860e..990e0ebcf68 100644 --- a/scapy/layers/kerberos.py +++ b/scapy/layers/kerberos.py @@ -151,7 +151,6 @@ SSP, ) from scapy.layers.inet import TCP, UDP -from scapy.layers.smb import _NV_VERSION from scapy.layers.tls.cert import ( Cert, CertList, @@ -2677,6 +2676,44 @@ def default_payload_class(self, payload): _InitialContextTokens[b"\x05\x04"] = KRB_GSS_Wrap +# [MS-NRPC] 3.5.4.3.1 in theory, dsgetdc.h (WinSDK) for details + +_GetDcName_Flags = [ + "DS_RETURN_FLAT_NAME", # 0x80000000 + "DS_RETURN_DNS_NAME", # 0x40000000 + "reserved2", # 0x20000000 + "reserved3", # 0x10000000 + "reserved4", # 0x08000000 + "reserved5", # 0x04000000 + "DS_DIRECTORY_SERVICE_13_REQUIRED", # 0x02000000 - Windows Server 2025 or later + "DS_KEY_LIST_SUPPORT_REQUIRED", # 0x01000000 + "DS_DIRECTORY_SERVICE_10_REQUIRED", # 0x00800000 - Windows Server 2016 or later + "DS_DIRECTORY_SERVICE_9_REQUIRED", # 0x00400000 - Windows Server 2012R2 or later + "DS_DIRECTORY_SERVICE_8_REQUIRED", # 0x00200000 - Windows Server 2012 or later + "DS_WEB_SERVICE_REQUIRED", # 0x00100000 + "DS_DIRECTORY_SERVICE_6_REQUIRED", # 0x00080000 - Windows Server 2008 or later + "DS_TRY_NEXTCLOSEST_SITE", # 0x00040000 + "DS_IS_DNS_NAME", # 0x00020000 + "DS_IS_FLAT_NAME", # 0x00010000 + "DS_ONLY_LDAP_NEEDED", # 0x00008000 + "DS_AVOID_SELF", # 0x00004000 + "DS_GOOD_TIMESERV_PREFERRED", # 0x00002000 + "DS_WRITABLE_REQUIRED", # 0x00001000 + "DS_TIMESERV_REQUIRED", # 0x00000800 + "DS_KDC_REQUIRED", # 0x00000400 + "DS_IP_REQUIRED", # 0x00000200 + "DS_BACKGROUND_ONLY", # 0x00000100 + "DS_PDC_REQUIRED", # 0x00000080 + "DS_GC_SERVER_REQUIRED", # 0x00000040 + "DS_DIRECTORY_SERVICE_PREFERRED", # 0x00000020 + "DS_DIRECTORY_SERVICE_REQUIRED", # 0x00000010 + "reserved-28", # 0x00000008 + "reserved-29", # 0x00000004 + "reserved-30", # 0x00000002 + "DS_FORCE_REDISCOVERY", # 0x00000001 +] + + # Kerberos IAKERB - draft-ietf-kitten-iakerb-03 @@ -2688,12 +2725,12 @@ class IAKERB_HEADER(ASN1_Packet): ASN1F_STRING("cookie", None, explicit_tag=0xA2), ), # [MS-SPNG] addition. This is mentioned on [kitten] IETF mailing list - # (but I've sent an email to dochelp for questions) + # (and dochelp@ answered with details, should be updated soon) ASN1F_optional( ASN1F_FLAGS( - "dclocatorHint", - "", - FlagsField("", 0, -32, _NV_VERSION).names, + "headerFlags", + None, + _GetDcName_Flags, explicit_tag=0xA3, ) ), @@ -2982,7 +3019,7 @@ class KDC_PROXY_MESSAGE(ASN1_Packet): ASN1F_FLAGS( "dclocatorHint", None, - FlagsField("", 0, -32, _NV_VERSION).names, + _GetDcName_Flags, explicit_tag=0xA2, ) ), @@ -3090,7 +3127,8 @@ def send(self, x, **kwargs): root=IAKERB_HEADER( targetRealm=ASN1_UTF8_STRING( self.realm, - ) + ), + headerFlags="DS_FORCE_REDISCOVERY", ) / x, ), diff --git a/scapy/layers/spnego.py b/scapy/layers/spnego.py index d5590963cab..3dc1154f0c8 100644 --- a/scapy/layers/spnego.py +++ b/scapy/layers/spnego.py @@ -244,7 +244,7 @@ class SPNEGO_negTokenResp(ASN1_Packet): ), # [MS-SPNG] Late Fallback Mechanism ASN1F_optional( - ASN1F_PACKET("mechTypes", None, SPNEGO_MechTypes, explicit_tag=0xA4) + ASN1F_SEQUENCE_OF("mechTypes", None, SPNEGO_MechType, explicit_tag=0xA4) ), ) @@ -1141,7 +1141,7 @@ def GSS_Init_sec_context( # [MS-SPNG] Late Fallback Mechanism if input_token.mechTypes is not None: - Context.server_mechtypes = input_token.mechTypes.mechTypes + Context.server_mechtypes = input_token.mechTypes Context.all_mechtypes.append(self._LATE_FALLBACK_ACCEPTOR) Context.all_mechtypes += Context.server_mechtypes Context.all_mechtypes += [input_token.supportedMech] @@ -1397,9 +1397,7 @@ def GSS_Accept_sec_context( if Context.late_fallback_negotiated: # [MS-SPNG] Late Fallback Mechanism - spnego_tok.token.mechTypes = SPNEGO_MechTypes( - mechTypes=Context.server_mechtypes - ) + spnego_tok.token.mechTypes = Context.server_mechtypes Context.all_mechtypes.append(self._LATE_FALLBACK_ACCEPTOR) Context.all_mechtypes += Context.server_mechtypes Context.all_mechtypes += [Context.ssp_mechtype] @@ -1471,7 +1469,7 @@ def GSS_Passive( # [MS-SPNG] Late Fallback Mechanism if input_token.mechTypes is not None: - Context.server_mechtypes = input_token.mechTypes.mechTypes + Context.server_mechtypes = input_token.mechTypes Context.all_mechtypes.append(self._LATE_FALLBACK_ACCEPTOR) Context.all_mechtypes += Context.server_mechtypes Context.all_mechtypes += [input_token.supportedMech] diff --git a/test/scapy/layers/spnego.uts b/test/scapy/layers/spnego.uts index b7b3ae38f10..620b5d86408 100644 --- a/test/scapy/layers/spnego.uts +++ b/test/scapy/layers/spnego.uts @@ -176,7 +176,7 @@ assert status == GSS_S_CONTINUE_NEEDED, status assert tok.token.mechListMIC is None assert tok.token.negState == 1 assert tok.token.supportedMech.oid.val == '1.3.6.1.4.1.311.2.2.10' -assert [x.oid.val for x in tok.token.mechTypes.mechTypes] == [ +assert [x.oid.val for x in tok.token.mechTypes] == [ '1.3.6.1.4.1.311.2.2.10', '1.2.840.48018.1.2.2', '1.2.840.113554.1.2.2',