1
2
3 """Abstract Syntax Notation #1."""
4 from __future__ import absolute_import
5 from __future__ import print_function
6
7 import struct
8 import time
9
10 from . import dpkt
11 from .compat import compat_ord
12
13
14 CLASSMASK = 0xc0
15 UNIVERSAL = 0x00
16 APPLICATION = 0x40
17 CONTEXT = 0x80
18 PRIVATE = 0xc0
19
20
21 CONSTRUCTED = 0x20
22
23
24 TAGMASK = 0x1f
25 INTEGER = 2
26 BIT_STRING = 3
27 OCTET_STRING = 4
28 NULL = 5
29 OID = 6
30 SEQUENCE = 16
31 SET = 17
32 PRINT_STRING = 19
33 T61_STRING = 20
34 IA5_STRING = 22
35 UTC_TIME = 23
36
37
39 """Convert ASN.1 UTCTime string to UTC float.
40
41 TODO: Long description here.
42
43 Args:
44 buf: A buffer with format "yymnddhhmm"
45
46 Returns:
47 A floating point number, indicates seconds since the Epoch.
48 """
49
50 yy = int(buf[:2])
51 mn = int(buf[2:4])
52 dd = int(buf[4:6])
53 hh = int(buf[6:8])
54 mm = int(buf[8:10])
55 try:
56 ss = int(buf[10:12])
57 buf = buf[12:]
58 except TypeError:
59 ss = 0
60 buf = buf[10:]
61 if buf[0] == '+':
62 hh -= int(buf[1:3])
63 mm -= int(buf[3:5])
64 elif buf[0] == '-':
65 hh += int(buf[1:3])
66 mm += int(buf[3:5])
67 return time.mktime((2000 + yy, mn, dd, hh, mm, ss, 0, 0, 0))
68
69
71 """Sleazy ASN.1 decoder.
72
73 TODO: Long description here.
74
75 Args:
76 buf: A buffer with Sleazy ASN.1 data.
77
78 Returns:
79 A list of (id, value) tuples from ASN.1 BER/DER encoded buffer.
80
81 Raises:
82 UnpackError: An error occurred the ASN.1 length exceed.
83 """
84
85 msg = []
86 while buf:
87 t = compat_ord(buf[0])
88 constructed = t & CONSTRUCTED
89 tag = t & TAGMASK
90 l = compat_ord(buf[1])
91 c = 0
92 if constructed and l == 128:
93
94 msg.append((t, decode(buf[2:])))
95 elif l >= 128:
96 c = l & 127
97 if c == 1:
98 l = compat_ord(buf[2])
99 elif c == 2:
100 l = struct.unpack('>H', buf[2:4])[0]
101 elif c == 3:
102 l = struct.unpack('>I', buf[1:5])[0] & 0xfff
103 c = 2
104 elif c == 4:
105 l = struct.unpack('>I', buf[2:6])[0]
106 else:
107
108 raise dpkt.UnpackError('excessive long-form ASN.1 length %d' % l)
109
110
111 buf = buf[2 + c:]
112
113
114 if constructed:
115 msg.append((t, decode(buf)))
116 elif tag == INTEGER:
117 if l == 0:
118 n = 0
119 elif l == 1:
120 n = compat_ord(buf[0])
121 elif l == 2:
122 n = struct.unpack('>H', buf[:2])[0]
123 elif l == 3:
124 n = struct.unpack('>I', buf[:4])[0] >> 8
125 elif l == 4:
126 n = struct.unpack('>I', buf[:4])[0]
127 else:
128 raise dpkt.UnpackError('excessive integer length > %d bytes' % l)
129 msg.append((t, n))
130 elif tag == UTC_TIME:
131 msg.append((t, utctime(buf[:l])))
132 else:
133 msg.append((t, buf[:l]))
134
135
136 buf = buf[l:]
137 return msg
138
139
141 s = b'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'
142 assert (decode(s) == [(48, [(2, 11), (99, [(4, b'cn=Douglas J Song 1, ou=Information Technology Division, ou=Faculty and Staff, ou=People, o=University of Michigan, c=US'), (10, b'\x00'), (10, b'\x03'), (2, 0), (2, 0), (1, b'\x00'), (135, b'objectclass'), (48, [(4, b'memberOfGroup'), (4, b'acl'), (4, b'cn'), (4, b'title'), (4, b'postalAddress'), (4, b'telephoneNumber'), (4, b'mail'), (4, b'member'), (4, b'homePhone'), (4, b'homePostalAddress'), (4, b'objectClass'), (4, b'description'), (4, b'facsimileTelephoneNumber'), (4, b'pager'), (4, b'uid'), (4, b'userPassword'), (4, b'joinable'), (4, b'associatedDomain'), (4, b'owner'), (4, b'rfc822ErrorsTo'), (4, b'ErrorsTo'), (4, b'rfc822RequestsTo'), (4, b'RequestsTo'), (4, b'moderator'), (4, b'labeledURL'), (4, b'onVacation'), (4, b'vacationMessage'), (4, b'drink'), (4, b'lastModifiedBy'), (4, b'lastModifiedTime'), (4, b'modifiersname'), (4, b'modifytimestamp'), (4, b'creatorsname'), (4, b'createtimestamp')])])])])
143
144 if __name__ == '__main__':
145 test_asn1()
146 print('Tests Successful...')
147