1f7d24e3fSHanoh Haim## This file is part of Scapy
2f7d24e3fSHanoh Haim## See http://www.secdev.org/projects/scapy for more informations
3f7d24e3fSHanoh Haim## Copyright (C) Philippe Biondi <phil@secdev.org>
4f7d24e3fSHanoh Haim## This program is published under a GPLv2 license
5f7d24e3fSHanoh Haim
6f7d24e3fSHanoh Haim"""
7f7d24e3fSHanoh HaimASN.1 (Abstract Syntax Notation One)
8f7d24e3fSHanoh Haim"""
9f7d24e3fSHanoh Haim
10f7d24e3fSHanoh Haimimport random
11f7d24e3fSHanoh Haimfrom scapy.config import conf
12f7d24e3fSHanoh Haimfrom scapy.error import Scapy_Exception,warning
13f7d24e3fSHanoh Haimfrom scapy.volatile import RandField
14f7d24e3fSHanoh Haimfrom scapy.utils import Enum_metaclass, EnumElement
15f7d24e3fSHanoh Haim
16f7d24e3fSHanoh Haimclass RandASN1Object(RandField):
17f7d24e3fSHanoh Haim    def __init__(self, objlist=None):
18f7d24e3fSHanoh Haim        if objlist is None:
19f7d24e3fSHanoh Haim            objlist = map(lambda x:x._asn1_obj,
20f7d24e3fSHanoh Haim                          filter(lambda x:hasattr(x,"_asn1_obj"), ASN1_Class_UNIVERSAL.__rdict__.values()))
21f7d24e3fSHanoh Haim        self.objlist = objlist
22f7d24e3fSHanoh Haim        self.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
23f7d24e3fSHanoh Haim    def _fix(self, n=0):
24f7d24e3fSHanoh Haim        o = random.choice(self.objlist)
25f7d24e3fSHanoh Haim        if issubclass(o, ASN1_INTEGER):
26f7d24e3fSHanoh Haim            return o(int(random.gauss(0,1000)))
27f7d24e3fSHanoh Haim        elif issubclass(o, ASN1_IPADDRESS):
28f7d24e3fSHanoh Haim            z = RandIP()._fix()
29f7d24e3fSHanoh Haim            return o(z)
30f7d24e3fSHanoh Haim        elif issubclass(o, ASN1_STRING):
31f7d24e3fSHanoh Haim            z = int(random.expovariate(0.05)+1)
32f7d24e3fSHanoh Haim            return o("".join([random.choice(self.chars) for i in range(z)]))
33f7d24e3fSHanoh Haim        elif issubclass(o, ASN1_SEQUENCE) and (n < 10):
34f7d24e3fSHanoh Haim            z = int(random.expovariate(0.08)+1)
35f7d24e3fSHanoh Haim            return o(map(lambda x:x._fix(n+1), [self.__class__(objlist=self.objlist)]*z))
36f7d24e3fSHanoh Haim        return ASN1_INTEGER(int(random.gauss(0,1000)))
37f7d24e3fSHanoh Haim
38f7d24e3fSHanoh Haim
39f7d24e3fSHanoh Haim##############
40f7d24e3fSHanoh Haim#### ASN1 ####
41f7d24e3fSHanoh Haim##############
42f7d24e3fSHanoh Haim
43f7d24e3fSHanoh Haimclass ASN1_Error(Scapy_Exception):
44f7d24e3fSHanoh Haim    pass
45f7d24e3fSHanoh Haim
46f7d24e3fSHanoh Haimclass ASN1_Encoding_Error(ASN1_Error):
47f7d24e3fSHanoh Haim    pass
48f7d24e3fSHanoh Haim
49f7d24e3fSHanoh Haimclass ASN1_Decoding_Error(ASN1_Error):
50f7d24e3fSHanoh Haim    pass
51f7d24e3fSHanoh Haim
52f7d24e3fSHanoh Haimclass ASN1_BadTag_Decoding_Error(ASN1_Decoding_Error):
53f7d24e3fSHanoh Haim    pass
54f7d24e3fSHanoh Haim
55f7d24e3fSHanoh Haim
56f7d24e3fSHanoh Haim
57f7d24e3fSHanoh Haimclass ASN1Codec(EnumElement):
58f7d24e3fSHanoh Haim    def register_stem(cls, stem):
59f7d24e3fSHanoh Haim        cls._stem = stem
60f7d24e3fSHanoh Haim    def dec(cls, s, context=None):
61f7d24e3fSHanoh Haim        return cls._stem.dec(s, context=context)
62f7d24e3fSHanoh Haim    def safedec(cls, s, context=None):
63f7d24e3fSHanoh Haim        return cls._stem.safedec(s, context=context)
64f7d24e3fSHanoh Haim    def get_stem(cls):
65f7d24e3fSHanoh Haim        return cls.stem
66f7d24e3fSHanoh Haim
67f7d24e3fSHanoh Haim
68f7d24e3fSHanoh Haimclass ASN1_Codecs_metaclass(Enum_metaclass):
69f7d24e3fSHanoh Haim    element_class = ASN1Codec
70f7d24e3fSHanoh Haim
71f7d24e3fSHanoh Haimclass ASN1_Codecs:
72f7d24e3fSHanoh Haim    __metaclass__ = ASN1_Codecs_metaclass
73f7d24e3fSHanoh Haim    BER = 1
74f7d24e3fSHanoh Haim    DER = 2
75f7d24e3fSHanoh Haim    PER = 3
76f7d24e3fSHanoh Haim    CER = 4
77f7d24e3fSHanoh Haim    LWER = 5
78f7d24e3fSHanoh Haim    BACnet = 6
79f7d24e3fSHanoh Haim    OER = 7
80f7d24e3fSHanoh Haim    SER = 8
81f7d24e3fSHanoh Haim    XER = 9
82f7d24e3fSHanoh Haim
83f7d24e3fSHanoh Haimclass ASN1Tag(EnumElement):
84f7d24e3fSHanoh Haim    def __init__(self, key, value, context=None, codec=None):
85f7d24e3fSHanoh Haim        EnumElement.__init__(self, key, value)
86f7d24e3fSHanoh Haim        self._context = context
87f7d24e3fSHanoh Haim        if codec == None:
88f7d24e3fSHanoh Haim            codec = {}
89f7d24e3fSHanoh Haim        self._codec = codec
90f7d24e3fSHanoh Haim    def clone(self): # /!\ not a real deep copy. self.codec is shared
91f7d24e3fSHanoh Haim        return self.__class__(self._key, self._value, self._context, self._codec)
92f7d24e3fSHanoh Haim    def register_asn1_object(self, asn1obj):
93f7d24e3fSHanoh Haim        self._asn1_obj = asn1obj
94f7d24e3fSHanoh Haim    def asn1_object(self, val):
95f7d24e3fSHanoh Haim        if hasattr(self,"_asn1_obj"):
96f7d24e3fSHanoh Haim            return self._asn1_obj(val)
97f7d24e3fSHanoh Haim        raise ASN1_Error("%r does not have any assigned ASN1 object" % self)
98f7d24e3fSHanoh Haim    def register(self, codecnum, codec):
99f7d24e3fSHanoh Haim        self._codec[codecnum] = codec
100f7d24e3fSHanoh Haim    def get_codec(self, codec):
101f7d24e3fSHanoh Haim        try:
102f7d24e3fSHanoh Haim            c = self._codec[codec]
103f7d24e3fSHanoh Haim        except KeyError,msg:
104f7d24e3fSHanoh Haim            raise ASN1_Error("Codec %r not found for tag %r" % (codec, self))
105f7d24e3fSHanoh Haim        return c
106f7d24e3fSHanoh Haim
107f7d24e3fSHanoh Haimclass ASN1_Class_metaclass(Enum_metaclass):
108f7d24e3fSHanoh Haim    element_class = ASN1Tag
109f7d24e3fSHanoh Haim    def __new__(cls, name, bases, dct): # XXX factorise a bit with Enum_metaclass.__new__()
110f7d24e3fSHanoh Haim        for b in bases:
111f7d24e3fSHanoh Haim            for k,v in b.__dict__.iteritems():
112f7d24e3fSHanoh Haim                if k not in dct and isinstance(v,ASN1Tag):
113f7d24e3fSHanoh Haim                    dct[k] = v.clone()
114f7d24e3fSHanoh Haim
115f7d24e3fSHanoh Haim        rdict = {}
116f7d24e3fSHanoh Haim        for k,v in dct.iteritems():
117f7d24e3fSHanoh Haim            if type(v) is int:
118f7d24e3fSHanoh Haim                v = ASN1Tag(k,v)
119f7d24e3fSHanoh Haim                dct[k] = v
120f7d24e3fSHanoh Haim                rdict[v] = v
121f7d24e3fSHanoh Haim            elif isinstance(v, ASN1Tag):
122f7d24e3fSHanoh Haim                rdict[v] = v
123f7d24e3fSHanoh Haim        dct["__rdict__"] = rdict
124f7d24e3fSHanoh Haim
125f7d24e3fSHanoh Haim        cls = type.__new__(cls, name, bases, dct)
126f7d24e3fSHanoh Haim        for v in cls.__dict__.values():
127f7d24e3fSHanoh Haim            if isinstance(v, ASN1Tag):
128f7d24e3fSHanoh Haim                v.context = cls # overwrite ASN1Tag contexts, even cloned ones
129f7d24e3fSHanoh Haim        return cls
130f7d24e3fSHanoh Haim
131f7d24e3fSHanoh Haim
132f7d24e3fSHanoh Haimclass ASN1_Class:
133f7d24e3fSHanoh Haim    __metaclass__ = ASN1_Class_metaclass
134f7d24e3fSHanoh Haim
135f7d24e3fSHanoh Haimclass ASN1_Class_UNIVERSAL(ASN1_Class):
136f7d24e3fSHanoh Haim    name = "UNIVERSAL"
137f7d24e3fSHanoh Haim    ERROR = -3
138f7d24e3fSHanoh Haim    RAW = -2
139f7d24e3fSHanoh Haim    NONE = -1
140f7d24e3fSHanoh Haim    ANY = 0
141f7d24e3fSHanoh Haim    BOOLEAN = 1
142f7d24e3fSHanoh Haim    INTEGER = 2
143f7d24e3fSHanoh Haim    BIT_STRING = 3
144f7d24e3fSHanoh Haim    STRING = 4
145f7d24e3fSHanoh Haim    NULL = 5
146f7d24e3fSHanoh Haim    OID = 6
147f7d24e3fSHanoh Haim    OBJECT_DESCRIPTOR = 7
148f7d24e3fSHanoh Haim    EXTERNAL = 8
149f7d24e3fSHanoh Haim    REAL = 9
150f7d24e3fSHanoh Haim    ENUMERATED = 10
151f7d24e3fSHanoh Haim    EMBEDDED_PDF = 11
152f7d24e3fSHanoh Haim    UTF8_STRING = 12
153f7d24e3fSHanoh Haim    RELATIVE_OID = 13
154f7d24e3fSHanoh Haim    SEQUENCE = 0x30#XXX 16 ??
155f7d24e3fSHanoh Haim    SET = 0x31 #XXX 17 ??
156f7d24e3fSHanoh Haim    NUMERIC_STRING = 18
157f7d24e3fSHanoh Haim    PRINTABLE_STRING = 19
158f7d24e3fSHanoh Haim    T61_STRING = 20
159f7d24e3fSHanoh Haim    VIDEOTEX_STRING = 21
160f7d24e3fSHanoh Haim    IA5_STRING = 22
161f7d24e3fSHanoh Haim    UTC_TIME = 23
162f7d24e3fSHanoh Haim    GENERALIZED_TIME = 24
163f7d24e3fSHanoh Haim    GRAPHIC_STRING = 25
164f7d24e3fSHanoh Haim    ISO646_STRING = 26
165f7d24e3fSHanoh Haim    GENERAL_STRING = 27
166f7d24e3fSHanoh Haim    UNIVERSAL_STRING = 28
167f7d24e3fSHanoh Haim    CHAR_STRING = 29
168f7d24e3fSHanoh Haim    BMP_STRING = 30
169f7d24e3fSHanoh Haim    IPADDRESS = 0x40
170f7d24e3fSHanoh Haim    COUNTER32 = 0x41
171f7d24e3fSHanoh Haim    GAUGE32 = 0x42
172f7d24e3fSHanoh Haim    TIME_TICKS = 0x43
173f7d24e3fSHanoh Haim    SEP = 0x80
174f7d24e3fSHanoh Haim
175f7d24e3fSHanoh Haimclass ASN1_Object_metaclass(type):
176f7d24e3fSHanoh Haim    def __new__(cls, name, bases, dct):
177f7d24e3fSHanoh Haim        c = super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)
178f7d24e3fSHanoh Haim        try:
179f7d24e3fSHanoh Haim            c.tag.register_asn1_object(c)
180f7d24e3fSHanoh Haim        except:
181f7d24e3fSHanoh Haim            warning("Error registering %r for %r" % (c.tag, c.codec))
182f7d24e3fSHanoh Haim        return c
183f7d24e3fSHanoh Haim
184f7d24e3fSHanoh Haim
185f7d24e3fSHanoh Haimclass ASN1_Object:
186f7d24e3fSHanoh Haim    __metaclass__ = ASN1_Object_metaclass
187f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.ANY
188f7d24e3fSHanoh Haim    def __init__(self, val):
189f7d24e3fSHanoh Haim        self.val = val
190f7d24e3fSHanoh Haim    def enc(self, codec):
191f7d24e3fSHanoh Haim        return self.tag.get_codec(codec).enc(self.val)
192f7d24e3fSHanoh Haim    def __repr__(self):
193f7d24e3fSHanoh Haim        return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), self.val)
194f7d24e3fSHanoh Haim    def __str__(self):
195f7d24e3fSHanoh Haim        return self.enc(conf.ASN1_default_codec)
196f7d24e3fSHanoh Haim    def strshow(self, lvl=0):
197f7d24e3fSHanoh Haim        return ("  "*lvl)+repr(self)+"\n"
198f7d24e3fSHanoh Haim    def show(self, lvl=0):
199f7d24e3fSHanoh Haim        print self.strshow(lvl)
200f7d24e3fSHanoh Haim    def __eq__(self, other):
201f7d24e3fSHanoh Haim        return self.val == other
202f7d24e3fSHanoh Haim    def __cmp__(self, other):
203f7d24e3fSHanoh Haim        return cmp(self.val, other)
204f7d24e3fSHanoh Haim
205f7d24e3fSHanoh Haimclass ASN1_DECODING_ERROR(ASN1_Object):
206f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.ERROR
207f7d24e3fSHanoh Haim    def __init__(self, val, exc=None):
208f7d24e3fSHanoh Haim        ASN1_Object.__init__(self, val)
209f7d24e3fSHanoh Haim        self.exc = exc
210f7d24e3fSHanoh Haim    def __repr__(self):
211f7d24e3fSHanoh Haim        return "<%s[%r]{{%s}}>" % (self.__dict__.get("name", self.__class__.__name__),
212f7d24e3fSHanoh Haim                                   self.val, self.exc.args[0])
213f7d24e3fSHanoh Haim    def enc(self, codec):
214f7d24e3fSHanoh Haim        if isinstance(self.val, ASN1_Object):
215f7d24e3fSHanoh Haim            return self.val.enc(codec)
216f7d24e3fSHanoh Haim        return self.val
217f7d24e3fSHanoh Haim
218f7d24e3fSHanoh Haimclass ASN1_force(ASN1_Object):
219f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.RAW
220f7d24e3fSHanoh Haim    def enc(self, codec):
221f7d24e3fSHanoh Haim        if isinstance(self.val, ASN1_Object):
222f7d24e3fSHanoh Haim            return self.val.enc(codec)
223f7d24e3fSHanoh Haim        return self.val
224f7d24e3fSHanoh Haim
225f7d24e3fSHanoh Haimclass ASN1_BADTAG(ASN1_force):
226f7d24e3fSHanoh Haim    pass
227f7d24e3fSHanoh Haim
228f7d24e3fSHanoh Haimclass ASN1_INTEGER(ASN1_Object):
229f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.INTEGER
230f7d24e3fSHanoh Haim
231f7d24e3fSHanoh Haimclass ASN1_STRING(ASN1_Object):
232f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.STRING
233f7d24e3fSHanoh Haim
234f7d24e3fSHanoh Haimclass ASN1_BIT_STRING(ASN1_STRING):
235f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.BIT_STRING
236f7d24e3fSHanoh Haim
237f7d24e3fSHanoh Haimclass ASN1_PRINTABLE_STRING(ASN1_STRING):
238f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
239f7d24e3fSHanoh Haim
240f7d24e3fSHanoh Haimclass ASN1_T61_STRING(ASN1_STRING):
241f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.T61_STRING
242f7d24e3fSHanoh Haim
243f7d24e3fSHanoh Haimclass ASN1_IA5_STRING(ASN1_STRING):
244f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.IA5_STRING
245f7d24e3fSHanoh Haim
246f7d24e3fSHanoh Haimclass ASN1_NUMERIC_STRING(ASN1_STRING):
247f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
248f7d24e3fSHanoh Haim
249f7d24e3fSHanoh Haimclass ASN1_VIDEOTEX_STRING(ASN1_STRING):
250f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
251f7d24e3fSHanoh Haim
252f7d24e3fSHanoh Haimclass ASN1_IPADDRESS(ASN1_STRING):
253f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.IPADDRESS
254f7d24e3fSHanoh Haim
255f7d24e3fSHanoh Haimclass ASN1_UTC_TIME(ASN1_STRING):
256f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.UTC_TIME
257f7d24e3fSHanoh Haim
258f7d24e3fSHanoh Haimclass ASN1_GENERALIZED_TIME(ASN1_STRING):
259f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME
260f7d24e3fSHanoh Haim
261f7d24e3fSHanoh Haimclass ASN1_TIME_TICKS(ASN1_INTEGER):
262f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.TIME_TICKS
263f7d24e3fSHanoh Haim
264f7d24e3fSHanoh Haimclass ASN1_BOOLEAN(ASN1_INTEGER):
265f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.BOOLEAN
266f7d24e3fSHanoh Haim
267f7d24e3fSHanoh Haimclass ASN1_ENUMERATED(ASN1_INTEGER):
268f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.ENUMERATED
269f7d24e3fSHanoh Haim
270f7d24e3fSHanoh Haimclass ASN1_NULL(ASN1_INTEGER):
271f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.NULL
272f7d24e3fSHanoh Haim
273f7d24e3fSHanoh Haimclass ASN1_SEP(ASN1_NULL):
274f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.SEP
275f7d24e3fSHanoh Haim
276f7d24e3fSHanoh Haimclass ASN1_GAUGE32(ASN1_INTEGER):
277f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.GAUGE32
278f7d24e3fSHanoh Haim
279f7d24e3fSHanoh Haimclass ASN1_COUNTER32(ASN1_INTEGER):
280f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.COUNTER32
281f7d24e3fSHanoh Haim
282f7d24e3fSHanoh Haimclass ASN1_SEQUENCE(ASN1_Object):
283f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.SEQUENCE
284f7d24e3fSHanoh Haim    def strshow(self, lvl=0):
285f7d24e3fSHanoh Haim        s = ("  "*lvl)+("# %s:" % self.__class__.__name__)+"\n"
286f7d24e3fSHanoh Haim        for o in self.val:
287f7d24e3fSHanoh Haim            s += o.strshow(lvl=lvl+1)
288f7d24e3fSHanoh Haim        return s
289f7d24e3fSHanoh Haim
290f7d24e3fSHanoh Haimclass ASN1_SET(ASN1_SEQUENCE):
291f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.SET
292f7d24e3fSHanoh Haim
293f7d24e3fSHanoh Haimclass ASN1_OID(ASN1_Object):
294f7d24e3fSHanoh Haim    tag = ASN1_Class_UNIVERSAL.OID
295f7d24e3fSHanoh Haim    def __init__(self, val):
296f7d24e3fSHanoh Haim        val = conf.mib._oid(val)
297f7d24e3fSHanoh Haim        ASN1_Object.__init__(self, val)
298f7d24e3fSHanoh Haim    def __repr__(self):
299f7d24e3fSHanoh Haim        return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), conf.mib._oidname(self.val))
300f7d24e3fSHanoh Haim    def __oidname__(self):
301f7d24e3fSHanoh Haim        return '%s'%conf.mib._oidname(self.val)
302f7d24e3fSHanoh Haim
303f7d24e3fSHanoh Haim
304f7d24e3fSHanoh Haim
305f7d24e3fSHanoh Haimconf.ASN1_default_codec = ASN1_Codecs.BER