1
2
3 """Abstract Syntax Notation #1."""
4
5 import struct, time
6 import dpkt
7
8
9 CLASSMASK = 0xc0
10 UNIVERSAL = 0x00
11 APPLICATION = 0x40
12 CONTEXT = 0x80
13 PRIVATE = 0xc0
14
15
16 CONSTRUCTED = 0x20
17
18
19 TAGMASK = 0x1f
20 INTEGER = 2
21 BIT_STRING = 3
22 OCTET_STRING = 4
23 NULL = 5
24 OID = 6
25 SEQUENCE = 16
26 SET = 17
27 PRINT_STRING = 19
28 T61_STRING = 20
29 IA5_STRING = 22
30 UTC_TIME = 23
31
33 """Convert ASN.1 UTCTime string to UTC float."""
34 yy = int(buf[:2])
35 mm = int(buf[2:4])
36 dd = int(buf[4:6])
37 hh = int(buf[6:8])
38 mm = int(buf[8:10])
39 try:
40 ss = int(buf[10:12])
41 buf = buf[12:]
42 except TypeError:
43 ss = 0
44 buf = buf[10:]
45 if buf[0] == '+':
46 hh -= int(buf[1:3])
47 mm -= int(buf[3:5])
48 elif buf[0] == '-':
49 hh += int(buf[1:3])
50 mm += int(buf[3:5])
51 return time.mktime((2000 + yy, mm, dd, hh, mm, ss, 0, 0, 0))
52
54 """Sleazy ASN.1 decoder.
55 Return list of (id, value) tuples from ASN.1 BER/DER encoded buffer.
56 """
57 msg = []
58 while buf:
59 t = ord(buf[0])
60 constructed = t & CONSTRUCTED
61 tag = t & TAGMASK
62 l = ord(buf[1])
63 c = 0
64 if constructed and l == 128:
65
66 msg.append(t, decode(buf[2:]))
67 elif l >= 128:
68 c = l & 127
69 if c == 1:
70 l = ord(buf[2])
71 elif c == 2:
72 l = struct.unpack('>H', buf[2:4])[0]
73 elif c == 3:
74 l = struct.unpack('>I', buf[1:5])[0] & 0xfff
75 c = 2
76 elif c == 4:
77 l = struct.unpack('>I', buf[2:6])[0]
78 else:
79
80 raise dpkt.UnpackError('excessive long-form ASN.1 length %d' % l)
81
82
83 buf = buf[2+c:]
84
85
86 if constructed:
87 msg.append((t, decode(buf)))
88 elif tag == INTEGER:
89 if l == 0:
90 n = 0
91 elif l == 1:
92 n = ord(buf[0])
93 elif l == 2:
94 n = struct.unpack('>H', buf[:2])[0]
95 elif l == 3:
96 n = struct.unpack('>I', buf[:4])[0] >> 8
97 elif l == 4:
98 n = struct.unpack('>I', buf[:4])[0]
99 else:
100 raise dpkt.UnpackError('excessive integer length > %d bytes' % l)
101 msg.append((t, n))
102 elif tag == UTC_TIME:
103 msg.append((t, utctime(buf[:l])))
104 else:
105 msg.append((t, buf[:l]))
106
107
108 buf = buf[l:]
109 return msg
110
111 if __name__ == '__main__':
112 import unittest
113
116 s = '0\x82\x02Q\x02\x01\x0bc\x82\x02J\x04xcn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US\n\x01\x00\n\x01\x03\x02\x01\x00\x02\x01\x00\x01\x01\x00\x87\x0bobjectclass0\x82\x01\xb0\x04\rmemberOfGroup\x04\x03acl\x04\x02cn\x04\x05title\x04\rpostalAddress\x04\x0ftelephoneNumber\x04\x04mail\x04\x06member\x04\thomePhone\x04\x11homePostalAddress\x04\x0bobjectClass\x04\x0bdescription\x04\x18facsimileTelephoneNumber\x04\x05pager\x04\x03uid\x04\x0cuserPassword\x04\x08joinable\x04\x10associatedDomain\x04\x05owner\x04\x0erfc822ErrorsTo\x04\x08ErrorsTo\x04\x10rfc822RequestsTo\x04\nRequestsTo\x04\tmoderator\x04\nlabeledURL\x04\nonVacation\x04\x0fvacationMessage\x04\x05drink\x04\x0elastModifiedBy\x04\x10lastModifiedTime\x04\rmodifiersname\x04\x0fmodifytimestamp\x04\x0ccreatorsname\x04\x0fcreatetimestamp'
117 self.failUnless(decode(s) == [(48, [(2, 11), (99, [(4, 'cn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US'), (10, '\x00'), (10, '\x03'), (2, 0), (2, 0), (1, '\x00'), (135, 'objectclass'), (48, [(4, 'memberOfGroup'), (4, 'acl'), (4, 'cn'), (4, 'title'), (4, 'postalAddress'), (4, 'telephoneNumber'), (4, 'mail'), (4, 'member'), (4, 'homePhone'), (4, 'homePostalAddress'), (4, 'objectClass'), (4, 'description'), (4, 'facsimileTelephoneNumber'), (4, 'pager'), (4, 'uid'), (4, 'userPassword'), (4, 'joinable'), (4, 'associatedDomain'), (4, 'owner'), (4, 'rfc822ErrorsTo'), (4, 'ErrorsTo'), (4, 'rfc822RequestsTo'), (4, 'RequestsTo'), (4, 'moderator'), (4, 'labeledURL'), (4, 'onVacation'), (4, 'vacationMessage'), (4, 'drink'), (4, 'lastModifiedBy'), (4, 'lastModifiedTime'), (4, 'modifiersname'), (4, 'modifytimestamp'), (4, 'creatorsname'), (4, 'createtimestamp')])])])])
118
119 unittest.main()
120