diff options
author | Robey Pointer <robey@lag.net> | 2003-12-27 01:49:19 +0000 |
---|---|---|
committer | Robey Pointer <robey@lag.net> | 2003-12-27 01:49:19 +0000 |
commit | 877cd974b8182d26fa76d566072917ea67b64e67 (patch) | |
tree | 577da518d93f7b4d1d6b6fa48dbbbe95ab36ceca /paramiko/ber.py | |
parent | f6e1e84d60ae75cd28030b4c41856ec768566a46 (diff) | |
download | paramiko-877cd974b8182d26fa76d566072917ea67b64e67.tar.gz |
[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-14]
move the paramiko files into a paramiko/ folder.
just moving the files into a folder. it won't build this way yet.
Diffstat (limited to 'paramiko/ber.py')
-rw-r--r-- | paramiko/ber.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/paramiko/ber.py b/paramiko/ber.py new file mode 100644 index 00000000..7fe1dd09 --- /dev/null +++ b/paramiko/ber.py @@ -0,0 +1,112 @@ +#!/usr/bin/python + +import struct + +def inflate_long(s, always_positive=0): + "turns a normalized byte string into a long-int (adapted from Crypto.Util.number)" + out = 0L + if len(s) % 4: + filler = '\x00' + if not always_positive and (ord(s[0]) >= 0x80): + # negative + filler = '\xff' + s = filler * (4 - len(s) % 4) + s + # FIXME: this doesn't actually handle negative. + # luckily ssh never uses negative bignums. + for i in range(0, len(s), 4): + out = (out << 32) + struct.unpack('>I', s[i:i+4])[0] + return out + +def deflate_long(n, add_sign_padding=1): + "turns a long-int into a normalized byte string (adapted from Crypto.Util.number)" + # after much testing, this algorithm was deemed to be the fastest + s = '' + n = long(n) + while n > 0: + s = struct.pack('>I', n & 0xffffffffL) + s + n = n >> 32 + # strip off leading zeros + for i in enumerate(s): + if i[1] != '\000': + break + else: + # only happens when n == 0 + s = '\000' + i = (0,) + s = s[i[0]:] + if (ord(s[0]) >= 0x80) and add_sign_padding: + s = '\x00' + s + return s + + +class BER(object): + + def __init__(self, content=''): + self.content = content + self.idx = 0 + + def __str__(self): + return self.content + + def __repr__(self): + return 'BER(' + repr(self.content) + ')' + + def decode(self): + return self.decode_next() + + def decode_next(self): + if self.idx >= len(self.content): + return None + id = ord(self.content[self.idx]) + self.idx += 1 + if (id & 31) == 31: + # identifier > 30 + id = 0 + while self.idx < len(self.content): + t = ord(self.content[self.idx]) + if not (t & 0x80): + break + id = (id << 7) | (t & 0x7f) + self.idx += 1 + if self.idx >= len(self.content): + return None + # now fetch length + size = ord(self.content[self.idx]) + self.idx += 1 + if size & 0x80: + # more complimicated... + # FIXME: theoretically should handle indefinite-length (0x80) + t = size & 0x7f + if self.idx + t > len(self.content): + return None + size = 0 + while t > 0: + size = (size << 8) | ord(self.content[self.idx]) + self.idx += 1 + t -= 1 + if self.idx + size > len(self.content): + # can't fit + return None + data = self.content[self.idx : self.idx + size] + self.idx += size + # now switch on id + if id == 0x30: + # sequence + return self.decode_sequence(data) + elif id == 2: + # int + return inflate_long(data) + else: + # 1: boolean (00 false, otherwise true) + raise Exception('Unknown ber encoding type %d (robey is lazy)' % id) + + def decode_sequence(data): + out = [] + b = BER(data) + while 1: + x = b.decode_next() + if x == None: + return out + out.append(x) + decode_sequence = staticmethod(decode_sequence) + |