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   
  3  """Abstract Syntax Notation #1.""" 
  4   
  5  import struct, time 
  6  import dpkt 
  7   
  8  # Type class 
  9  CLASSMASK    = 0xc0 
 10  UNIVERSAL    = 0x00 
 11  APPLICATION  = 0x40 
 12  CONTEXT      = 0x80 
 13  PRIVATE      = 0xc0 
 14   
 15  # Constructed (vs. primitive) 
 16  CONSTRUCTED  = 0x20 
 17   
 18  # Universal-class tags 
 19  TAGMASK      = 0x1f 
 20  INTEGER      = 2 
 21  BIT_STRING   = 3        # arbitrary bit string 
 22  OCTET_STRING = 4        # arbitrary octet string 
 23  NULL         = 5 
 24  OID          = 6        # object identifier 
 25  SEQUENCE     = 16       # ordered collection of types 
 26  SET          = 17       # unordered collection of types 
 27  PRINT_STRING = 19       # printable string 
 28  T61_STRING   = 20       # T.61 (8-bit) character string 
 29  IA5_STRING   = 22       # ASCII 
 30  UTC_TIME     = 23 
 31   
32 -def utctime(buf):
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
53 -def decode(buf):
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 # XXX - constructed, indefinite length 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 # XXX - can be up to 127 bytes, but... 80 raise dpkt.UnpackError('excessive long-form ASN.1 length %d' % l) 81 82 # Skip type, length 83 buf = buf[2+c:] 84 85 # Parse content 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 # Skip content 108 buf = buf[l:] 109 return msg
110 111 if __name__ == '__main__': 112 import unittest 113
114 - class ASN1TestCase(unittest.TestCase):
115 - def test_asn1(self):
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