From 2cd6d3347faca1bd705460fcd1bd55fa8aa7be47 Mon Sep 17 00:00:00 2001 From: Pierre Lorinquer <pierre.lorinquer@ssi.gouv.fr> Date: Tue, 28 Mar 2017 11:21:35 +0200 Subject: [PATCH] Fix EAP_MD5 "len" field computation. The default values of the "value_size" field is None. This can trigger an issue when computing the "len" field. Test: str(EAP_MD5()) In order to fix this issue, the default value of the "value_size" field has been set to 0. Tests have been added in "regression.uts". Added regression tests for EAP_TLS and EAP_FAST. Use XStrLenField in EAP_MD5, EAP_TLS and EAP_FAST packets instead of StrLenField. Delete blank lines before the class description (EAPOL, EAP, EAP_MD5, EAP_TLS and EAP_FAST packet classes). "registered_options" dictionary was renamed "registered_methods" (EAP-MD5, EAP-TLS etc are not options, but authentication methods). EAP getlayer() and haslayer() methods have been overloaded in order to allow access to a given "EAP layer" (such as EAP_TLS, for instance) by providing the parent class name ("EAP"). For example, this is now possible: >>> eap_tls = EAP_TLS() >>> EAP_TLS in eap_tls True >>> EAP in eap_tls True >>> eap_tls[EAP_TLS] <EAP_TLS |> >>> eap_tls[EAP] <EAP_TLS |> Regression tests have been added. --- scapy/layers/l2.py | 43 ++++++++++++++++++++++++++++++------------- test/regression.uts | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py index 1bda6318..252d8a22 100644 --- a/scapy/layers/l2.py +++ b/scapy/layers/l2.py @@ -310,7 +310,6 @@ eapol_types = { class EAPOL(Packet): - """ EAPOL - IEEE Std 802.1X-2010 """ @@ -438,7 +437,6 @@ eap_codes = { class EAP(Packet): - """ RFC 3748 - Extensible Authentication Protocol (EAP) """ @@ -475,11 +473,11 @@ class EAP(Packet): INITIATE = 5 FINISH = 6 - registered_options = {} + registered_methods = {} @classmethod def register_variant(cls): - cls.registered_options[cls.type.default] = cls + cls.registered_methods[cls.type.default] = cls @classmethod def dispatch_hook(cls, _pkt=None, *args, **kargs): @@ -487,9 +485,31 @@ class EAP(Packet): c = ord(_pkt[0]) if c in [1, 2] and len(_pkt) >= 5: t = ord(_pkt[4]) - return cls.registered_options.get(t, cls) + return cls.registered_methods.get(t, cls) return cls + def haslayer(self, cls): + ret = 0 + if cls == EAP: + for eap_class in EAP.registered_methods.values(): + if isinstance(self, eap_class): + ret = 1 + break + elif cls in EAP.registered_methods.values() and isinstance(self, cls): + ret = 1 + return ret + + def getlayer(self, cls, nb=1, _track=None): + layer = None + if cls == EAP: + for eap_class in EAP.registered_methods.values(): + if isinstance(self, eap_class): + layer = self + break + else: + layer = Packet.getlayer(self, cls, nb, _track) + return layer + def answers(self, other): if isinstance(other, EAP): if self.code == self.REQUEST: @@ -510,7 +530,6 @@ class EAP(Packet): class EAP_MD5(EAP): - """ RFC 3748 - "Extensible Authentication Protocol (EAP)" """ @@ -522,14 +541,13 @@ class EAP_MD5(EAP): FieldLenField("len", None, fmt="H", length_of="optional_name", adjust=lambda p, x: x + p.value_size + 6), ByteEnumField("type", 4, eap_types), - FieldLenField("value_size", None, fmt="B", length_of="value"), - StrLenField("value", '', length_from=lambda p: p.value_size), - StrLenField("optional_name", '', length_from=lambda p: p.len - p.value_size - 6) + FieldLenField("value_size", 0, fmt="B", length_of="value"), + XStrLenField("value", '', length_from=lambda p: p.value_size), + XStrLenField("optional_name", '', length_from=lambda p: p.len - p.value_size - 6) ] class EAP_TLS(EAP): - """ RFC 5216 - "The EAP-TLS Authentication Protocol" """ @@ -546,12 +564,11 @@ class EAP_TLS(EAP): BitField('S', 0, 1), BitField('reserved', 0, 5), ConditionalField(IntField('tls_message_len', 0), lambda pkt: pkt.L == 1), - StrLenField('tls_data', '', length_from=lambda pkt: pkt.len - 10 if pkt.L == 1 else pkt.len - 6) + XStrLenField('tls_data', '', length_from=lambda pkt: pkt.len - 10 if pkt.L == 1 else pkt.len - 6) ] class EAP_FAST(EAP): - """ RFC 4851 - "The Flexible Authentication via Secure Tunneling Extensible Authentication Protocol Method (EAP-FAST)" @@ -570,7 +587,7 @@ class EAP_FAST(EAP): BitField('reserved', 0, 2), BitField('version', 0, 3), ConditionalField(IntField('message_len', 0), lambda pkt: pkt.L == 1), - StrLenField('data', '', length_from=lambda pkt: pkt.len - 10 if pkt.L == 1 else pkt.len - 6) + XStrLenField('data', '', length_from=lambda pkt: pkt.len - 10 if pkt.L == 1 else pkt.len - 6) ] diff --git a/test/regression.uts b/test/regression.uts index be34b65d..a4205431 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -5805,6 +5805,15 @@ assert(eap.type == 3) assert(hasattr(eap, 'desired_auth_type')) assert(eap.desired_auth_type == 43) += EAP - EAP_TLS - Basic Instantiation +str(EAP_TLS()) == b'\x01\x00\x00\x06\r\x00' + += EAP - EAP_FAST - Basic Instantiation +str(EAP_FAST()) == b'\x01\x00\x00\x06+\x00' + += EAP - EAP_MD5 - Basic Instantiation +str(EAP_MD5()) == b'\x01\x00\x00\x06\x04\x00' + = EAP - EAP_MD5 - Request - Dissection (8) s = b'\x01\x02\x00\x16\x04\x10\x86\xf9\x89\x94\x81\x01\xb3 nHh\x1b\x8d\xe7^\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' eap = EAP(s) @@ -5829,6 +5838,33 @@ assert(eap[EAP_MD5].value_size == 16) assert(eap[EAP_MD5].value == b'\xfd\x1e\xffe\xf5\x80y\xa8\xe3\xc8\xf1\xbd\xc2\x85\xae\xcf') assert(eap[EAP_MD5].optional_name == '') += EAP - Layers (1) +eap = EAP_MD5() +assert(EAP_MD5 in eap) +assert(not EAP_TLS in eap) +assert(not EAP_FAST in eap) +assert(EAP in eap) +eap = EAP_TLS() +assert(EAP_TLS in eap) +assert(not EAP_MD5 in eap) +assert(not EAP_FAST in eap) +assert(EAP in eap) +eap = EAP_FAST() +assert(EAP_FAST in eap) +assert(not EAP_MD5 in eap) +assert(not EAP_TLS in eap) +assert(EAP in eap) + + += EAP - Layers (2) +eap = EAP_MD5() +assert(type(eap[EAP]) == EAP_MD5) +eap = EAP_TLS() +assert(type(eap[EAP]) == EAP_TLS) +eap = EAP_FAST() +assert(type(eap[EAP]) == EAP_FAST) + + ############ ############ + NTP module tests -- GitLab