From bb18f54a295727b060aef66cf40ea5ad6074233a Mon Sep 17 00:00:00 2001
From: Phil <phil@secdev.org>
Date: Sun, 17 Aug 2008 01:23:07 +0200
Subject: [PATCH] Fixed SNMPv1 traps (D. Loss, ticket #99)

---
 scapy/asn1/asn1.py   |  4 ++++
 scapy/asn1/ber.py    | 36 +++++++++++++++++++++++++++++++++++-
 scapy/asn1fields.py  |  6 ++++++
 scapy/layers/snmp.py | 10 ++++++----
 4 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/scapy/asn1/asn1.py b/scapy/asn1/asn1.py
index 0df885ad..c8c42f72 100644
--- a/scapy/asn1/asn1.py
+++ b/scapy/asn1/asn1.py
@@ -159,6 +159,7 @@ class ASN1_Class_UNIVERSAL(ASN1_Class):
     UNIVERSAL_STRING = 28
     CHAR_STRING = 29
     BMP_STRING = 30
+    IPADDRESS = 0x40
     COUNTER32 = 0x41
     TIME_TICKS = 0x43
 
@@ -239,6 +240,9 @@ class ASN1_NUMERIC_STRING(ASN1_STRING):
 class ASN1_VIDEOTEX_STRING(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
 
+class ASN1_IPADDRESS(ASN1_STRING):
+    tag = ASN1_Class_UNIVERSAL.IPADDRESS
+
 class ASN1_UTC_TIME(ASN1_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
diff --git a/scapy/asn1/ber.py b/scapy/asn1/ber.py
index a74aa6c9..b567eaba 100644
--- a/scapy/asn1/ber.py
+++ b/scapy/asn1/ber.py
@@ -4,7 +4,7 @@
 ## This program is published under a GPLv2 license
 
 from scapy.error import warning
-from asn1 import ASN1_Decoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1_Class_UNIVERSAL,ASN1_Error,ASN1_DECODING_ERROR,ASN1_BADTAG
+from asn1 import ASN1_Decoding_Error,ASN1_Encoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1_Class_UNIVERSAL,ASN1_Error,ASN1_DECODING_ERROR,ASN1_BADTAG
 
 ##################
 ## BER encoding ##
@@ -18,6 +18,20 @@ from asn1 import ASN1_Decoding_Error,ASN1_BadTag_Decoding_Error,ASN1_Codecs,ASN1
 class BER_Exception(Exception):
     pass
 
+class BER_Encoding_Error(ASN1_Encoding_Error):
+    def __init__(self, msg, encoded=None, remaining=None):
+        Exception.__init__(self, msg)
+        self.remaining = remaining
+        self.encoded = encoded
+    def __str__(self):
+        s = Exception.__str__(self)
+        if isinstance(self.encoded, BERcodec_Object):
+            s+="\n### Already encoded ###\n%s" % self.encoded.strshow()
+        else:
+            s+="\n### Already encoded ###\n%r" % self.encoded
+        s+="\n### Remaining ###\n%r" % self.remaining
+        return s
+
 class BER_Decoding_Error(ASN1_Decoding_Error):
     def __init__(self, msg, decoded=None, remaining=None):
         Exception.__init__(self, msg)
@@ -239,6 +253,26 @@ class BERcodec_T61_STRING (BERcodec_STRING):
 class BERcodec_IA5_STRING(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.IA5_STRING
 
+class BERcodec_IPADDRESS(BERcodec_STRING):
+    tag = ASN1_Class_UNIVERSAL.IPADDRESS
+    
+    @classmethod
+    def enc(cls, ipaddr_ascii):
+        try:
+            s = inet_aton(ipaddr_ascii)
+        except Exception:
+            raise BER_Encoding_Error("IPv4 address could not be encoded") 
+        return chr(cls.tag)+BER_len_enc(len(s))+s
+    
+    @classmethod
+    def do_dec(cls, s, context=None, safe=False):
+        l,s,t = cls.check_type_check_len(s)
+        try:
+            ipaddr_ascii = inet_ntoa(s)
+        except Exception:
+            raise BER_Decoding_Error("IP address could not be decoded", decoded=obj)
+        return cls.asn1_object(ipaddr_ascii), t
+
 class BERcodec_UTC_TIME(BERcodec_STRING):
     tag = ASN1_Class_UNIVERSAL.UTC_TIME
 
diff --git a/scapy/asn1fields.py b/scapy/asn1fields.py
index 3f564cbd..7351dad4 100644
--- a/scapy/asn1fields.py
+++ b/scapy/asn1fields.py
@@ -160,6 +160,12 @@ class ASN1F_PRINTABLE_STRING(ASN1F_STRING):
 
 class ASN1F_BIT_STRING(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
+    
+class ASN1F_IPADDRESS(ASN1F_STRING):
+    ASN1_tag = ASN1_Class_UNIVERSAL.IPADDRESS    
+
+class ASN1F_TIME_TICKS(ASN1F_INTEGER):
+    ASN1_tag = ASN1_Class_UNIVERSAL.TIME_TICKS
 
 class ASN1F_UTC_TIME(ASN1F_STRING):
     ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
diff --git a/scapy/layers/snmp.py b/scapy/layers/snmp.py
index a3474472..0681825c 100644
--- a/scapy/layers/snmp.py
+++ b/scapy/layers/snmp.py
@@ -179,12 +179,11 @@ class SNMPset(ASN1_Packet):
     
 class SNMPtrapv1(ASN1_Packet):
     ASN1_codec = ASN1_Codecs.BER
-    ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_INTEGER("id",0),
-                                       ASN1F_OID("enterprise", "1.3"),
-                                       ASN1F_STRING("agent_addr",""),
+    ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_OID("enterprise", "1.3"),
+                                       ASN1F_IPADDRESS("agent_addr","0.0.0.0"),
                                        ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types),
                                        ASN1F_INTEGER("specific_trap", 0),
-                                       ASN1F_INTEGER("time_stamp", IntAutoTime()),
+                                       ASN1F_TIME_TICKS("time_stamp", IntAutoTime()),
                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
                                        )
 
@@ -231,6 +230,9 @@ class SNMP(ASN1_Packet):
 
 bind_layers( UDP,           SNMP,          sport=161)
 bind_layers( UDP,           SNMP,          dport=161)
+bind_layers( UDP,           SNMP,          sport=162) 
+bind_layers( UDP,           SNMP,          dport=162) 
+
 def snmpwalk(dst, oid="1", community="public"):
     try:
         while 1:
-- 
GitLab