blob: 70354239312d5bff76fa89cb204cb5caf61561c8 [file] [log] [blame]
## This file is part of Scapy
## See http://www.secdev.org/projects/scapy for more informations
## Copyright (C) Philippe Biondi <phil@secdev.org>
## This program is published under a GPLv2 license
"""
PPP (Point to Point Protocol)
[RFC 1661]
"""
import struct
from scapy.config import conf
from scapy.data import DLT_PPP, DLT_PPP_SERIAL, DLT_PPP_ETHER
from scapy.compat import *
from scapy.packet import Packet, bind_layers
from scapy.layers.eap import EAP
from scapy.layers.l2 import Ether, CookedLinux, GRE_PPTP
from scapy.layers.inet import IP
from scapy.layers.inet6 import IPv6
from scapy.fields import BitField, ByteEnumField, ByteField, \
ConditionalField, FieldLenField, IntField, IPField, \
PacketListField, PacketField, ShortEnumField, ShortField, \
StrFixedLenField, StrLenField, XByteField, XShortField, XStrLenField
class PPPoE(Packet):
name = "PPP over Ethernet"
fields_desc = [ BitField("version", 1, 4),
BitField("type", 1, 4),
ByteEnumField("code", 0, {0:"Session"}),
XShortField("sessionid", 0x0),
ShortField("len", None) ]
def post_build(self, p, pay):
p += pay
if self.len is None:
l = len(p)-6
p = p[:4]+struct.pack("!H", l)+p[6:]
return p
class PPPoED(PPPoE):
name = "PPP over Ethernet Discovery"
fields_desc = [ BitField("version", 1, 4),
BitField("type", 1, 4),
ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}),
XShortField("sessionid", 0x0),
ShortField("len", None) ]
_PPP_proto = { 0x0001: "Padding Protocol",
0x0003: "ROHC small-CID [RFC3095]",
0x0005: "ROHC large-CID [RFC3095]",
0x0021: "Internet Protocol version 4",
0x0023: "OSI Network Layer",
0x0025: "Xerox NS IDP",
0x0027: "DECnet Phase IV",
0x0029: "Appletalk",
0x002b: "Novell IPX",
0x002d: "Van Jacobson Compressed TCP/IP",
0x002f: "Van Jacobson Uncompressed TCP/IP",
0x0031: "Bridging PDU",
0x0033: "Stream Protocol (ST-II)",
0x0035: "Banyan Vines",
0x0037: "reserved (until 1993) [Typo in RFC1172]",
0x0039: "AppleTalk EDDP",
0x003b: "AppleTalk SmartBuffered",
0x003d: "Multi-Link [RFC1717]",
0x003f: "NETBIOS Framing",
0x0041: "Cisco Systems",
0x0043: "Ascom Timeplex",
0x0045: "Fujitsu Link Backup and Load Balancing (LBLB)",
0x0047: "DCA Remote Lan",
0x0049: "Serial Data Transport Protocol (PPP-SDTP)",
0x004b: "SNA over 802.2",
0x004d: "SNA",
0x004f: "IPv6 Header Compression",
0x0051: "KNX Bridging Data [ianp]",
0x0053: "Encryption [Meyer]",
0x0055: "Individual Link Encryption [Meyer]",
0x0057: "Internet Protocol version 6 [Hinden]",
0x0059: "PPP Muxing [RFC3153]",
0x005b: "Vendor-Specific Network Protocol (VSNP) [RFC3772]",
0x0061: "RTP IPHC Full Header [RFC3544]",
0x0063: "RTP IPHC Compressed TCP [RFC3544]",
0x0065: "RTP IPHC Compressed Non TCP [RFC3544]",
0x0067: "RTP IPHC Compressed UDP 8 [RFC3544]",
0x0069: "RTP IPHC Compressed RTP 8 [RFC3544]",
0x006f: "Stampede Bridging",
0x0071: "Reserved [Fox]",
0x0073: "MP+ Protocol [Smith]",
0x007d: "reserved (Control Escape) [RFC1661]",
0x007f: "reserved (compression inefficient [RFC1662]",
0x0081: "Reserved Until 20-Oct-2000 [IANA]",
0x0083: "Reserved Until 20-Oct-2000 [IANA]",
0x00c1: "NTCITS IPI [Ungar]",
0x00cf: "reserved (PPP NLID)",
0x00fb: "single link compression in multilink [RFC1962]",
0x00fd: "compressed datagram [RFC1962]",
0x00ff: "reserved (compression inefficient)",
0x0201: "802.1d Hello Packets",
0x0203: "IBM Source Routing BPDU",
0x0205: "DEC LANBridge100 Spanning Tree",
0x0207: "Cisco Discovery Protocol [Sastry]",
0x0209: "Netcs Twin Routing [Korfmacher]",
0x020b: "STP - Scheduled Transfer Protocol [Segal]",
0x020d: "EDP - Extreme Discovery Protocol [Grosser]",
0x0211: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
0x0213: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
0x0231: "Luxcom",
0x0233: "Sigma Network Systems",
0x0235: "Apple Client Server Protocol [Ridenour]",
0x0281: "MPLS Unicast [RFC3032] ",
0x0283: "MPLS Multicast [RFC3032]",
0x0285: "IEEE p1284.4 standard - data packets [Batchelder]",
0x0287: "ETSI TETRA Network Protocol Type 1 [Nieminen]",
0x0289: "Multichannel Flow Treatment Protocol [McCann]",
0x2063: "RTP IPHC Compressed TCP No Delta [RFC3544]",
0x2065: "RTP IPHC Context State [RFC3544]",
0x2067: "RTP IPHC Compressed UDP 16 [RFC3544]",
0x2069: "RTP IPHC Compressed RTP 16 [RFC3544]",
0x4001: "Cray Communications Control Protocol [Stage]",
0x4003: "CDPD Mobile Network Registration Protocol [Quick]",
0x4005: "Expand accelerator protocol [Rachmani]",
0x4007: "ODSICP NCP [Arvind]",
0x4009: "DOCSIS DLL [Gaedtke]",
0x400B: "Cetacean Network Detection Protocol [Siller]",
0x4021: "Stacker LZS [Simpson]",
0x4023: "RefTek Protocol [Banfill]",
0x4025: "Fibre Channel [Rajagopal]",
0x4027: "EMIT Protocols [Eastham]",
0x405b: "Vendor-Specific Protocol (VSP) [RFC3772]",
0x8021: "Internet Protocol Control Protocol",
0x8023: "OSI Network Layer Control Protocol",
0x8025: "Xerox NS IDP Control Protocol",
0x8027: "DECnet Phase IV Control Protocol",
0x8029: "Appletalk Control Protocol",
0x802b: "Novell IPX Control Protocol",
0x802d: "reserved",
0x802f: "reserved",
0x8031: "Bridging NCP",
0x8033: "Stream Protocol Control Protocol",
0x8035: "Banyan Vines Control Protocol",
0x8037: "reserved (until 1993)",
0x8039: "reserved",
0x803b: "reserved",
0x803d: "Multi-Link Control Protocol",
0x803f: "NETBIOS Framing Control Protocol",
0x8041: "Cisco Systems Control Protocol",
0x8043: "Ascom Timeplex",
0x8045: "Fujitsu LBLB Control Protocol",
0x8047: "DCA Remote Lan Network Control Protocol (RLNCP)",
0x8049: "Serial Data Control Protocol (PPP-SDCP)",
0x804b: "SNA over 802.2 Control Protocol",
0x804d: "SNA Control Protocol",
0x804f: "IP6 Header Compression Control Protocol",
0x8051: "KNX Bridging Control Protocol [ianp]",
0x8053: "Encryption Control Protocol [Meyer]",
0x8055: "Individual Link Encryption Control Protocol [Meyer]",
0x8057: "IPv6 Control Protovol [Hinden]",
0x8059: "PPP Muxing Control Protocol [RFC3153]",
0x805b: "Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]",
0x806f: "Stampede Bridging Control Protocol",
0x8073: "MP+ Control Protocol [Smith]",
0x8071: "Reserved [Fox]",
0x807d: "Not Used - reserved [RFC1661]",
0x8081: "Reserved Until 20-Oct-2000 [IANA]",
0x8083: "Reserved Until 20-Oct-2000 [IANA]",
0x80c1: "NTCITS IPI Control Protocol [Ungar]",
0x80cf: "Not Used - reserved [RFC1661]",
0x80fb: "single link compression in multilink control [RFC1962]",
0x80fd: "Compression Control Protocol [RFC1962]",
0x80ff: "Not Used - reserved [RFC1661]",
0x8207: "Cisco Discovery Protocol Control [Sastry]",
0x8209: "Netcs Twin Routing [Korfmacher]",
0x820b: "STP - Control Protocol [Segal]",
0x820d: "EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]",
0x8235: "Apple Client Server Protocol Control [Ridenour]",
0x8281: "MPLSCP [RFC3032]",
0x8285: "IEEE p1284.4 standard - Protocol Control [Batchelder]",
0x8287: "ETSI TETRA TNP1 Control Protocol [Nieminen]",
0x8289: "Multichannel Flow Treatment Protocol [McCann]",
0xc021: "Link Control Protocol",
0xc023: "Password Authentication Protocol",
0xc025: "Link Quality Report",
0xc027: "Shiva Password Authentication Protocol",
0xc029: "CallBack Control Protocol (CBCP)",
0xc02b: "BACP Bandwidth Allocation Control Protocol [RFC2125]",
0xc02d: "BAP [RFC2125]",
0xc05b: "Vendor-Specific Authentication Protocol (VSAP) [RFC3772]",
0xc081: "Container Control Protocol [KEN]",
0xc223: "Challenge Handshake Authentication Protocol",
0xc225: "RSA Authentication Protocol [Narayana]",
0xc227: "Extensible Authentication Protocol [RFC2284]",
0xc229: "Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]",
0xc26f: "Stampede Bridging Authorization Protocol",
0xc281: "Proprietary Authentication Protocol [KEN]",
0xc283: "Proprietary Authentication Protocol [Tackabury]",
0xc481: "Proprietary Node ID Authentication Protocol [KEN]"}
class HDLC(Packet):
fields_desc = [ XByteField("address",0xff),
XByteField("control",0x03) ]
class PPP(Packet):
name = "PPP Link Layer"
fields_desc = [ ShortEnumField("proto", 0x0021, _PPP_proto) ]
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and orb(_pkt[0]) == 0xff:
cls = HDLC
return cls
_PPP_conftypes = { 1:"Configure-Request",
2:"Configure-Ack",
3:"Configure-Nak",
4:"Configure-Reject",
5:"Terminate-Request",
6:"Terminate-Ack",
7:"Code-Reject",
8:"Protocol-Reject",
9:"Echo-Request",
10:"Echo-Reply",
11:"Discard-Request",
14:"Reset-Request",
15:"Reset-Ack",
}
### PPP IPCP stuff (RFC 1332)
# All IPCP options are defined below (names and associated classes)
_PPP_ipcpopttypes = { 1:"IP-Addresses (Deprecated)",
2:"IP-Compression-Protocol",
3:"IP-Address",
4:"Mobile-IPv4", # not implemented, present for completeness
129:"Primary-DNS-Address",
130:"Primary-NBNS-Address",
131:"Secondary-DNS-Address",
132:"Secondary-NBNS-Address"}
class PPP_IPCP_Option(Packet):
name = "PPP IPCP Option"
fields_desc = [ ByteEnumField("type" , None , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
def extract_padding(self, pay):
return b"",pay
registered_options = {}
@classmethod
def register_variant(cls):
cls.registered_options[cls.type.default] = cls
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt:
o = orb(_pkt[0])
return cls.registered_options.get(o, cls)
return cls
class PPP_IPCP_Option_IPAddress(PPP_IPCP_Option):
name = "PPP IPCP Option: IP Address"
fields_desc = [ ByteEnumField("type" , 3 , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
IPField("data","0.0.0.0"),
ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
class PPP_IPCP_Option_DNS1(PPP_IPCP_Option):
name = "PPP IPCP Option: DNS1 Address"
fields_desc = [ ByteEnumField("type" , 129 , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
IPField("data","0.0.0.0"),
ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
class PPP_IPCP_Option_DNS2(PPP_IPCP_Option):
name = "PPP IPCP Option: DNS2 Address"
fields_desc = [ ByteEnumField("type" , 131 , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
IPField("data","0.0.0.0"),
ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
class PPP_IPCP_Option_NBNS1(PPP_IPCP_Option):
name = "PPP IPCP Option: NBNS1 Address"
fields_desc = [ ByteEnumField("type" , 130 , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
IPField("data","0.0.0.0"),
ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
class PPP_IPCP_Option_NBNS2(PPP_IPCP_Option):
name = "PPP IPCP Option: NBNS2 Address"
fields_desc = [ ByteEnumField("type" , 132 , _PPP_ipcpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
IPField("data","0.0.0.0"),
ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
class PPP_IPCP(Packet):
fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
XByteField("id", 0 ),
FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
PacketListField("options", [], PPP_IPCP_Option, length_from=lambda p:p.len-4,) ]
### ECP
_PPP_ecpopttypes = { 0:"OUI",
1:"DESE", }
class PPP_ECP_Option(Packet):
name = "PPP ECP Option"
fields_desc = [ ByteEnumField("type" , None , _PPP_ecpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
def extract_padding(self, pay):
return b"",pay
registered_options = {}
@classmethod
def register_variant(cls):
cls.registered_options[cls.type.default] = cls
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt:
o = orb(_pkt[0])
return cls.registered_options.get(o, cls)
return cls
class PPP_ECP_Option_OUI(PPP_ECP_Option):
fields_desc = [ ByteEnumField("type" , 0 , _PPP_ecpopttypes),
FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
StrFixedLenField("oui","",3),
ByteField("subtype",0),
StrLenField("data", "", length_from=lambda p:p.len-6) ]
class PPP_ECP(Packet):
fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
XByteField("id", 0 ),
FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
PacketListField("options", [], PPP_ECP_Option, length_from=lambda p:p.len-4,) ]
### Link Control Protocol (RFC 1661)
_PPP_lcptypes = {1: "Configure-Request",
2: "Configure-Ack",
3: "Configure-Nak",
4: "Configure-Reject",
5: "Terminate-Request",
6: "Terminate-Ack",
7: "Code-Reject",
8: "Protocol-Reject",
9: "Echo-Request",
10: "Echo-Reply",
11: "Discard-Request"}
class PPP_LCP(Packet):
name = "PPP Link Control Protocol"
fields_desc = [ByteEnumField("code", 5, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="data",
adjust=lambda p, x: x + 4),
StrLenField("data", "",
length_from=lambda p:p.len-4)]
def mysummary(self):
return self.sprintf('LCP %code%')
def extract_padding(self, pay):
return b"", pay
@classmethod
def dispatch_hook(cls, _pkt = None, *args, **kargs):
if _pkt:
o = orb(_pkt[0])
if o in [1, 2, 3, 4]:
return PPP_LCP_Configure
elif o in [5,6]:
return PPP_LCP_Terminate
elif o == 7:
return PPP_LCP_Code_Reject
elif o == 8:
return PPP_LCP_Protocol_Reject
elif o in [9, 10]:
return PPP_LCP_Echo
elif o == 11:
return PPP_LCP_Discard_Request
else:
return cls
return cls
_PPP_lcp_optiontypes = {1: "Maximum-Receive-Unit",
2: "Async-Control-Character-Map",
3: "Authentication-protocol",
4: "Quality-protocol",
5: "Magic-number",
7: "Protocol-Field-Compression",
8: "Address-and-Control-Field-Compression",
13: "Callback"}
class PPP_LCP_Option(Packet):
name = "PPP LCP Option"
fields_desc = [ByteEnumField("type", None, _PPP_lcp_optiontypes),
FieldLenField("len", None, fmt="B", length_of="data",
adjust=lambda p,x:x+2),
StrLenField("data", None, length_from=lambda p:p.len-2)]
def extract_padding(self, pay):
return b"", pay
registered_options = {}
@classmethod
def register_variant(cls):
cls.registered_options[cls.type.default] = cls
@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt:
o = orb(_pkt[0])
return cls.registered_options.get(o, cls)
return cls
class PPP_LCP_MRU_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 1, _PPP_lcp_optiontypes),
FieldLenField("len", 4, fmt="B", adjust=lambda p,x:4),
ShortField("max_recv_unit", 1500)]
_PPP_LCP_auth_protocols = {0xc023: "Password authentication protocol",
0xc223: "Challenge-response authentication protocol",
0xc227: "PPP Extensible authentication protocol"}
_PPP_LCP_CHAP_algorithms = {5: "MD5",
6: "SHA1",
128: "MS-CHAP",
129: "MS-CHAP-v2"}
class PPP_LCP_ACCM_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 2, _PPP_lcp_optiontypes),
FieldLenField("len", 6, fmt="B"),
BitField("accm", 0x00000000, 32)]
def adjust_auth_len(pkt, x):
if pkt.auth_protocol == 0xc223:
return 5
elif pkt.auth_protocol == 0xc023:
return 4
else:
return x + 4
class PPP_LCP_Auth_Protocol_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 3, _PPP_lcp_optiontypes),
FieldLenField("len", None, fmt="B", length_of="data",
adjust=adjust_auth_len),
ShortEnumField("auth_protocol", 0xc023, _PPP_LCP_auth_protocols),
ConditionalField(StrLenField("data", '', length_from=lambda p:p.len-4),
lambda p:p.auth_protocol != 0xc223),
ConditionalField(ByteEnumField("algorithm", 5, _PPP_LCP_CHAP_algorithms),
lambda p:p.auth_protocol == 0xc223)]
_PPP_LCP_quality_protocols = {0xc025: "Link Quality Report"}
class PPP_LCP_Quality_Protocol_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 4, _PPP_lcp_optiontypes),
FieldLenField("len", None, fmt="B", length_of="data",
adjust=lambda p,x:x+4),
ShortEnumField("quality_protocol", 0xc025, _PPP_LCP_quality_protocols),
StrLenField("data", "", length_from=lambda p:p.len-4)]
class PPP_LCP_Magic_Number_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 5, _PPP_lcp_optiontypes),
FieldLenField("len", 6, fmt="B", adjust = lambda p,x:6),
IntField("magic_number", None)]
_PPP_lcp_callback_operations = {0: "Location determined by user authentication",
1: "Dialing string",
2: "Location identifier",
3: "E.164 number",
4: "Distinguished name"}
class PPP_LCP_Callback_Option(PPP_LCP_Option):
fields_desc = [ByteEnumField("type", 13, _PPP_lcp_optiontypes),
FieldLenField("len", None, fmt="B", length_of="message",
adjust=lambda p,x:x+3),
ByteEnumField("operation", 0, _PPP_lcp_callback_operations),
StrLenField("message", "", length_from=lambda p:p.len-3)]
class PPP_LCP_Configure(PPP_LCP):
fields_desc = [ByteEnumField("code", 1, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="options",
adjust=lambda p,x:x+4),
PacketListField("options", [], PPP_LCP_Option,
length_from=lambda p:p.len-4)]
def answers(self, other):
return isinstance(other, PPP_LCP_Configure) and self.code in [2, 3, 4]\
and other.code == 1 and other.id == self.id
class PPP_LCP_Terminate(PPP_LCP):
def answers(self, other):
return isinstance(other, PPP_LCP_Terminate) and self.code == 6\
and other.code == 5 and other.id == self.id
class PPP_LCP_Code_Reject(PPP_LCP):
fields_desc = [ByteEnumField("code", 7, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="rejected_packet",
adjust=lambda p,x:x+4),
PacketField("rejected_packet", None, PPP_LCP)]
class PPP_LCP_Protocol_Reject(PPP_LCP):
fields_desc = [ByteEnumField("code", 8, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="rejected_information",
adjust=lambda p,x:x+6),
ShortEnumField("rejected_protocol", None, _PPP_proto),
PacketField("rejected_information", None, Packet)]
class PPP_LCP_Echo(PPP_LCP):
fields_desc = [ByteEnumField("code", 9, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="data",
adjust=lambda p,x:x+8),
IntField("magic_number", None),
StrLenField("data", "", length_from=lambda p:p.len-8)]
def answers(self, other):
return isinstance(other, PPP_LCP_Echo) and self.code == 10\
and other.code == 9 and self.id == other.id
class PPP_LCP_Discard_Request(PPP_LCP):
fields_desc = [ByteEnumField("code", 11, _PPP_lcptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="H", length_of="data",
adjust=lambda p,x:x+8),
IntField("magic_number", None),
StrLenField("data", "", length_from=lambda p:p.len-8)]
### Password authentication protocol (RFC 1334)
_PPP_paptypes = {1: "Authenticate-Request",
2: "Authenticate-Ack",
3: "Authenticate-Nak"}
class PPP_PAP(Packet):
name = "PPP Password Authentication Protocol"
fields_desc = [ByteEnumField("code", 1, _PPP_paptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="!H", length_of="data",
adjust=lambda _, x: x + 4),
StrLenField("data", "", length_from=lambda p: p.len-4)]
@classmethod
def dispatch_hook(cls, _pkt=None, *_, **kargs):
code = None
if _pkt:
code = orb(_pkt[0])
elif "code" in kargs:
code = kargs["code"]
if isinstance(code, six.string_types):
code = cls.fields_desc[0].s2i[code]
if code == 1:
return PPP_PAP_Request
elif code in [2, 3]:
return PPP_PAP_Response
return cls
def extract_padding(self, pay):
return "", pay
class PPP_PAP_Request(PPP_PAP):
fields_desc = [ByteEnumField("code", 1, _PPP_paptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="!H", length_of="username",
adjust=lambda p, x: x + 6 + len(p.password)),
FieldLenField("username_len", None, fmt="B", length_of="username"),
StrLenField("username", None, length_from=lambda p: p.username_len),
FieldLenField("passwd_len", None, fmt="B", length_of="password"),
StrLenField("password", None, length_from=lambda p: p.passwd_len)]
def mysummary(self):
return self.sprintf("PAP-Request username=%PPP_PAP_Request.username%" +
" password=%PPP_PAP_Request.password%")
class PPP_PAP_Response(PPP_PAP):
fields_desc = [ByteEnumField("code", 2, _PPP_paptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="!H", length_of="message",
adjust=lambda _, x: x + 5),
FieldLenField("msg_len", None, fmt="B", length_of="message"),
StrLenField("message", "", length_from=lambda p: p.msg_len)]
def answers(self, other):
return isinstance(other, PPP_PAP_Request) and other.id == self.id
def mysummary(self):
res = "PAP-Ack" if self.code == 2 else "PAP-Nak"
if self.msg_len > 0:
res += self.sprintf(" msg=%PPP_PAP_Response.message%")
return res
### Challenge Handshake Authentication protocol (RFC1994)
_PPP_chaptypes = {1: "Challenge",
2: "Response",
3: "Success",
4: "Failure"}
class PPP_CHAP(Packet):
name = "PPP Challenge Handshake Authentication Protocol"
fields_desc = [ByteEnumField("code", 1, _PPP_chaptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="!H", length_of="data",
adjust=lambda _, x: x + 4),
StrLenField("data", "", length_from=lambda p: p.len - 4)]
def answers(self, other):
return isinstance(other, PPP_CHAP_ChallengeResponse) and other.code == 2\
and self.code in (3, 4) and self.id == other.id
@classmethod
def dispatch_hook(cls, _pkt=None, *_, **kargs):
code = None
if _pkt:
code = orb(_pkt[0])
elif "code" in kargs:
code = kargs["code"]
if isinstance(code, six.string_types):
code = cls.fields_desc[0].s2i[code]
if code in (1, 2):
return PPP_CHAP_ChallengeResponse
return cls
def extract_padding(self, pay):
return "", pay
def mysummary(self):
if self.code == 3:
return self.sprintf("CHAP Success message=%PPP_CHAP.data%")
elif self.code == 4:
return self.sprintf("CHAP Failure message=%PPP_CHAP.data%")
class PPP_CHAP_ChallengeResponse(PPP_CHAP):
fields_desc = [ByteEnumField("code", 1, _PPP_chaptypes),
XByteField("id", 0),
FieldLenField("len", None, fmt="!H", length_of="value",
adjust=lambda p, x: x + len(p.optional_name) + 5),
FieldLenField("value_size", None, fmt="B", length_of="value"),
XStrLenField("value", b"\0"*8, length_from=lambda p: p.value_size),
StrLenField("optional_name", "", length_from=lambda p: p.len - p.value_size - 5)]
def answers(self, other):
return isinstance(other, PPP_CHAP_ChallengeResponse) and other.code == 1\
and self.code == 2 and self.id == other.id
def mysummary(self):
if self.code == 1:
return self.sprintf("CHAP challenge=0x%PPP_CHAP_ChallengeResponse.value% " +
"optional_name=%PPP_CHAP_ChallengeResponse.optional_name%")
elif self.code == 2:
return self.sprintf("CHAP response=0x%PPP_CHAP_ChallengeResponse.value% " +
"optional_name=%PPP_CHAP_ChallengeResponse.optional_name%")
else:
return PPP_CHAP.mysummary(self)
bind_layers( Ether, PPPoED, type=0x8863)
bind_layers( Ether, PPPoE, type=0x8864)
bind_layers( CookedLinux, PPPoED, proto=0x8863)
bind_layers( CookedLinux, PPPoE, proto=0x8864)
bind_layers( PPPoE, PPP, code=0)
bind_layers( HDLC, PPP, )
bind_layers( PPP, EAP, proto=0xc227)
bind_layers( PPP, IP, proto=0x0021)
bind_layers( PPP, IPv6, proto=0x0057)
bind_layers( PPP, PPP_CHAP, proto=0xc223)
bind_layers( PPP, PPP_IPCP, proto=0x8021)
bind_layers( PPP, PPP_ECP, proto=0x8053)
bind_layers( PPP, PPP_LCP, proto=0xc021)
bind_layers( PPP, PPP_PAP, proto=0xc023)
bind_layers( Ether, PPP_IPCP, type=0x8021)
bind_layers( Ether, PPP_ECP, type=0x8053)
bind_layers( GRE_PPTP, PPP, proto=0x880b)
conf.l2types.register(DLT_PPP, PPP)
conf.l2types.register(DLT_PPP_SERIAL, HDLC)
conf.l2types.register(DLT_PPP_ETHER, PPPoE)