Package dpkt :: Module asn1
[hide private]
[frames] | no frames]

Source Code for Module dpkt.asn1

  1  # $Id: asn1.py 23 2006-11-08 15:45:33Z dugsong $ 
  2  # -*- coding: utf-8 -*- 
  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  # Type class 
 14  CLASSMASK = 0xc0 
 15  UNIVERSAL = 0x00 
 16  APPLICATION = 0x40 
 17  CONTEXT = 0x80 
 18  PRIVATE = 0xc0 
 19   
 20  # Constructed (vs. primitive) 
 21  CONSTRUCTED = 0x20 
 22   
 23  # Universal-class tags 
 24  TAGMASK = 0x1f 
 25  INTEGER = 2 
 26  BIT_STRING = 3  # arbitrary bit string 
 27  OCTET_STRING = 4  # arbitrary octet string 
 28  NULL = 5 
 29  OID = 6  # object identifier 
 30  SEQUENCE = 16  # ordered collection of types 
 31  SET = 17  # unordered collection of types 
 32  PRINT_STRING = 19  # printable string 
 33  T61_STRING = 20  # T.61 (8-bit) character string 
 34  IA5_STRING = 22  # ASCII 
 35  UTC_TIME = 23 
 36   
 37   
38 -def utctime(buf):
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
70 -def decode(buf):
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 # XXX - constructed, indefinite length 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 # XXX - can be up to 127 bytes, but... 108 raise dpkt.UnpackError('excessive long-form ASN.1 length %d' % l) 109 110 # Skip type, length 111 buf = buf[2 + c:] 112 113 # Parse content 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 # Skip content 136 buf = buf[l:] 137 return msg
138 139
140 -def test_asn1():
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