scapy.layers.spnego

SPNEGO

Implements parts of:

  • GSSAPI SPNEGO: RFC4178 > RFC2478

  • GSSAPI SPNEGO NEGOEX: [MS-NEGOEX]

Note

You will find more complete documentation for this layer over at GSSAPI

class scapy.layers.spnego.NEGOEX_BYTE_VECTOR(_pkt, /, *, ByteArrayBufferOffset=0, ByteArrayLength=0)[source]

Bases: Packet

aliastypes = [<class 'scapy.layers.spnego.NEGOEX_BYTE_VECTOR'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<LEIntField (NEGOEX_BYTE_VECTOR).ByteArrayBufferOffset>, <LEIntField (NEGOEX_BYTE_VECTOR).ByteArrayLength>]
guess_payload_class(payload)[source]
class scapy.layers.spnego.NEGOEX_CHECKSUM(_pkt, /, *, cbHeaderLength=20, ChecksumScheme=1, ChecksumType=None, ChecksumValue=b'')[source]

Bases: Packet

aliastypes = [<class 'scapy.layers.spnego.NEGOEX_CHECKSUM'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<LELongField (NEGOEX_CHECKSUM).cbHeaderLength>, <LELongEnumField (NEGOEX_CHECKSUM).ChecksumScheme>, <LELongEnumField (NEGOEX_CHECKSUM).ChecksumType>, <XStrLenField (NEGOEX_CHECKSUM).ChecksumValue>]
class scapy.layers.spnego.NEGOEX_EXCHANGE_MESSAGE(_pkt, /, *, Signature=b'NEGOEXTS', MessageType=0, SequenceNum=0, cbHeaderLength=None, cbMessageLength=None, ConversationId=None, AuthScheme=None, ExchangeBufferOffset=0, ExchangeLen=0, Payload=[])[source]

Bases: _NTLMPayloadPacket

OFFSET = 64
aliastypes = [<class 'scapy.layers.spnego.NEGOEX_EXCHANGE_MESSAGE'>, <class 'scapy.layers.ntlm._NTLMPayloadPacket'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<StrFixedLenField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).Signature>, <LEIntEnumField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).MessageType>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).SequenceNum>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbHeaderLength>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbMessageLength>, <UUIDField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).ConversationId>, <UUIDEnumField (NEGOEX_EXCHANGE_MESSAGE).AuthScheme>, <LEIntField (NEGOEX_EXCHANGE_MESSAGE).ExchangeBufferOffset>, <LEIntField (NEGOEX_EXCHANGE_MESSAGE).ExchangeLen>, <_NTLMPayloadField (NEGOEX_EXCHANGE_MESSAGE).Payload>]
show_indent = 0
class scapy.layers.spnego.NEGOEX_EXTENSION_VECTOR(_pkt, /, *, ExtensionArrayOffset=0, ExtensionCount=0)[source]

Bases: Packet

aliastypes = [<class 'scapy.layers.spnego.NEGOEX_EXTENSION_VECTOR'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<LELongField (NEGOEX_EXTENSION_VECTOR).ExtensionArrayOffset>, <LEShortField (NEGOEX_EXTENSION_VECTOR).ExtensionCount>]
class scapy.layers.spnego.NEGOEX_MESSAGE_HEADER(_pkt, /, *, Signature=b'NEGOEXTS', MessageType=0, SequenceNum=0, cbHeaderLength=None, cbMessageLength=None, ConversationId=None)[source]

Bases: Packet

aliastypes = [<class 'scapy.layers.spnego.NEGOEX_MESSAGE_HEADER'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<StrFixedLenField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).Signature>, <LEIntEnumField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).MessageType>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).SequenceNum>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbHeaderLength>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbMessageLength>, <UUIDField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).ConversationId>]
post_build(pkt, pay)[source]
class scapy.layers.spnego.NEGOEX_NEGO_MESSAGE(_pkt, /, *, Signature=b'NEGOEXTS', MessageType=0, SequenceNum=0, cbHeaderLength=None, cbMessageLength=None, ConversationId=None, Random=b'', ProtocolVersion=0, AuthSchemeBufferOffset=None, AuthSchemeCount=None, ExtensionBufferOffset=None, ExtensionCount=None, Payload=[])[source]

Bases: _NTLMPayloadPacket

OFFSET = 92
aliastypes = [<class 'scapy.layers.spnego.NEGOEX_NEGO_MESSAGE'>, <class 'scapy.layers.ntlm._NTLMPayloadPacket'>, <class 'scapy.packet.Packet'>]
classmethod dispatch_hook(_pkt=None, *args, **kargs)[source]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<StrFixedLenField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).Signature>, <LEIntEnumField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).MessageType>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).SequenceNum>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbHeaderLength>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbMessageLength>, <UUIDField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).ConversationId>, <XStrFixedLenField (NEGOEX_NEGO_MESSAGE).Random>, <LELongField (NEGOEX_NEGO_MESSAGE).ProtocolVersion>, <LEIntField (NEGOEX_NEGO_MESSAGE).AuthSchemeBufferOffset>, <LEShortField (NEGOEX_NEGO_MESSAGE).AuthSchemeCount>, <LEIntField (NEGOEX_NEGO_MESSAGE).ExtensionBufferOffset>, <LEShortField (NEGOEX_NEGO_MESSAGE).ExtensionCount>, <_NTLMPayloadField (NEGOEX_NEGO_MESSAGE).Payload>]
payload_guess: List[Tuple[Dict[str, Any], Type[Packet]]] = [({}, <class 'scapy.layers.spnego.NEGOEX_NEGO_MESSAGE'>)]
post_build(pkt: bytes, pay: bytes) bytes[source]
show_indent = 0
class scapy.layers.spnego.NEGOEX_VERIFY_MESSAGE(_pkt, /, *, Signature=b'NEGOEXTS', MessageType=0, SequenceNum=0, cbHeaderLength=None, cbMessageLength=None, ConversationId=None, AuthScheme=None, Checksum=<NEGOEX_CHECKSUM  |>)[source]

Bases: Packet

aliastypes = [<class 'scapy.layers.spnego.NEGOEX_VERIFY_MESSAGE'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<StrFixedLenField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).Signature>, <LEIntEnumField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).MessageType>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).SequenceNum>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbHeaderLength>, <LEIntField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).cbMessageLength>, <UUIDField (NEGOEX_MESSAGE_HEADER,NEGOEX_NEGO_MESSAGE,NEGOEX_EXCHANGE_MESSAGE,NEGOEX_VERIFY_MESSAGE).ConversationId>, <UUIDEnumField (NEGOEX_VERIFY_MESSAGE).AuthScheme>, <PacketField (NEGOEX_VERIFY_MESSAGE).Checksum>]
show_indent = 0
class scapy.layers.spnego.SPNEGOSSP(ssps: List[SSP], **kwargs)[source]

Bases: SSP

The SPNEGO SSP

Parameters:

ssps – a dict with keys being the SSP class, and the value being a dictionary of the keyword arguments to pass it on init.

Example:

from scapy.layers.ntlm import NTLMSSP
from scapy.layers.kerberos import KerberosSSP
from scapy.layers.spnego import SPNEGOSSP
from scapy.layers.smbserver import smbserver
from scapy.libs.rfc3961 import Encryption, Key

ssp = SPNEGOSSP([
    NTLMSSP(
        IDENTITIES={
            "User1": MD4le("Password1"),
            "Administrator": MD4le("Password123!"),
        }
    ),
    KerberosSSP(
        SPN="cifs/server2.domain.local",
        KEY=Key(
            Encryption.AES256,
            key=hex_bytes("5e9255c907b2f7e969ddad816eabbec8f1f7a387c7194ecc98b827bdc9421c2b")
        )
    )
])
smbserver(ssp=ssp)
class CONTEXT(ssps: List[SSP], req_flags=None)[source]

Bases: CONTEXT

clifailure()[source]
first_choice
property flags
get_supported_mechtypes()[source]

Return an ordered list of mechtypes that are still available.

negotiate_ssp() None[source]

Perform SSP negotiation.

This updates our context and sets it with the first SSP that is common to both client and server. This also applies rules from [MS-SPNG] and RFC4178 to determine if mechListMIC is required.

other_mechtypes
raw
req_flags
require_mic
sent_mechtypes
ssp
ssp_context
ssp_mechtype
ssps
verified_mic
GSS_Accept_sec_context(Context: CONTEXT, input_token=None, req_flags: GSS_S_FLAGS | None = <GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS: 268435456>, chan_bindings: GssChannelBindings = b'\x00')[source]
GSS_GetMICEx(Context, *args, **kwargs)[source]
GSS_Init_sec_context(Context: CONTEXT, input_token=None, target_name: str | None = None, req_flags: GSS_C_FLAGS | None = None, chan_bindings: GssChannelBindings = b'\x00')[source]
GSS_Passive(Context: CONTEXT, input_token=None, req_flags=None)[source]
GSS_Passive_set_Direction(Context: CONTEXT, IsAcceptor=False)[source]
GSS_UnwrapEx(Context, *args, **kwargs)[source]
GSS_VerifyMICEx(Context, *args, **kwargs)[source]
GSS_WrapEx(Context, *args, **kwargs)[source]
GuessOtherMechtypes(Context: CONTEXT, input_token)[source]

Guesses the mechtype of the peer when the “raw” fallback is used.

LegsAmount(Context: CONTEXT)[source]
MapStatusToNegState(status: int) int[source]

Map a GSSAPI return code to SPNEGO negState codes

MaximumSignatureLength(Context: CONTEXT)[source]
NegTokenInit2()[source]

Server-Initiation of GSSAPI/SPNEGO. See [MS-SPNG] sect 3.2.5.2

class STATE(*values)[source]

Bases: STATE

FIRST = 1
SUBSEQUENT = 2
auth_type = 9
classmethod from_cli_arguments(UPN: str, target: str, password: str = None, HashNt: bytes = None, HashAes256Sha96: bytes = None, HashAes128Sha96: bytes = None, kerberos_required: bool = False, ST=None, TGT=None, KEY=None, ccache: str = None, debug: int = 0, use_krb5ccname: bool = False, use_winssp: bool = False)[source]

Initialize a SPNEGOSSP from a list of many arguments.

This is useful in a CLI, as it will try to build the best SPNEGOSSP with NTLM and Kerberos based on the various parameters.

Parameters:
  • UPN – the UPN of the user to use.

  • target – the target IP/hostname entered by the user.

  • kerberos_required – require kerberos

  • password – (string) if provided, used for auth

  • HashNt – (bytes) if provided, used for auth (NTLM)

  • HashAes256Sha96 – (bytes) if provided, used for auth (Kerberos)

  • HashAes128Sha96 – (bytes) if provided, used for auth (Kerberos)

  • ST – if provided, the service ticket to use (Kerberos)

  • TGT – if provided, the TGT to use (Kerberos)

  • KEY – if ST provided, the session key associated to the ticket (Kerberos). This can be either for the ST or TGT. Else, the user secret key.

  • ccache – (str) if provided, a path to a CCACHE (Kerberos)

  • use_krb5ccname – (bool) if true, the KRB5CCNAME environment variable will be used if available.

  • use_winssp – (bool) (only works on Windows). Use implicit authentication through WinSSP.

ssps
class scapy.layers.spnego.SPNEGO_MechListMIC(_pkt, /, *, value=<ASN1_STRING['']>)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <scapy.asn1fields.ASN1F_STRING_ENCAPS object>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_MechListMIC'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.asn1fields.ASN1F_STRING_ENCAPS object>]
class scapy.layers.spnego.SPNEGO_MechType(_pkt, /, *, oid=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <scapy.asn1fields.ASN1F_OID object>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_MechType'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.asn1fields.ASN1F_OID object>]
class scapy.layers.spnego.SPNEGO_MechTypes(_pkt, /, *, mechTypes=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <ASN1F_SEQUENCE_OF mechTypes>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_MechTypes'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<ASN1F_SEQUENCE_OF mechTypes>]
class scapy.layers.spnego.SPNEGO_Token(_pkt, /, *, value=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <scapy.layers.spnego._SPNEGO_Token_Field object>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_Token'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.layers.spnego._SPNEGO_Token_Field object>]
class scapy.layers.spnego.SPNEGO_negHints(_pkt, /, *, hintName=<ASN1_GENERAL_STRING['not_defined_in_RFC4178@please_ignore']>, hintAddress=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <ASN1F_SEQUENCE(<scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>)>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_negHints'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.asn1fields.ASN1F_GENERAL_STRING object>, <scapy.asn1fields.ASN1F_GENERAL_STRING object>]
class scapy.layers.spnego.SPNEGO_negToken(_pkt, /, *, token=<SPNEGO_negTokenInit  |>)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <scapy.asn1fields.ASN1F_CHOICE object>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_negToken'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.asn1fields.ASN1F_CHOICE object>]
class scapy.layers.spnego.SPNEGO_negTokenInit(_pkt, /, *, mechTypes=None, reqFlags=None, mechToken=None, negHints=None, mechListMIC=None, _mechListMIC=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <ASN1F_SEQUENCE(<scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>)>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_negTokenInit'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<ASN1F_SEQUENCE_OF mechTypes>, <scapy.asn1fields.ASN1F_FLAGS object>, <scapy.asn1fields.ASN1F_PACKET object>, <scapy.asn1fields.ASN1F_PACKET object>, <scapy.asn1fields.ASN1F_PACKET object>, <scapy.asn1fields.ASN1F_PACKET object>]
class scapy.layers.spnego.SPNEGO_negTokenResp(_pkt, /, *, negState=0x0 <ASN1_ENUMERATED[0]>, supportedMech=<SPNEGO_MechType  |>, responseToken=None, mechListMIC=None)[source]

Bases: ASN1_Packet

ASN1_codec = <ASN1Codec BER[1]>
ASN1_root = <ASN1F_SEQUENCE(<scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>, <scapy.asn1fields.ASN1F_optional object>)>
aliastypes = [<class 'scapy.layers.spnego.SPNEGO_negTokenResp'>, <class 'scapy.asn1packet.ASN1_Packet'>, <class 'scapy.packet.Packet'>]
fields_desc: ClassVar[List[Field[Any, Any] | _FieldContainer]] = [<scapy.asn1fields.ASN1F_ENUMERATED object>, <scapy.asn1fields.ASN1F_PACKET object>, <scapy.asn1fields.ASN1F_PACKET object>, <scapy.asn1fields.ASN1F_PACKET object>]
scapy.layers.spnego.mechListMIC(oids)[source]

Implementation of RFC 4178 - Appendix D. mechListMIC Computation

NOTE: The documentation on mechListMIC isn’t super clear, so note that:

  • The mechListMIC that the client sends is computed over the list of mechanisms that it requests.

  • the mechListMIC that the server sends is computed over the list of mechanisms that the client requested.

This also means that NegTokenInit2 added by [MS-SPNG] is NOT protected. That’s not necessarily an issue, since it was optional in most cases, but it’s something to keep in mind.