Package paramiko :: Module util
[frames] | no frames]

Source Code for Module paramiko.util

  1  # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com> 
  2  # 
  3  # This file is part of paramiko. 
  4  # 
  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
  6  # terms of the GNU Lesser General Public License as published by the Free 
  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
  8  # any later version. 
  9  # 
 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 13  # details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public License 
 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 18   
 19  """ 
 20  Useful functions used by the rest of paramiko. 
 21  """ 
 22   
 23  from __future__ import generators 
 24   
 25  import array 
 26  from binascii import hexlify, unhexlify 
 27  import sys 
 28  import struct 
 29  import traceback 
 30  import threading 
 31   
 32  from paramiko.common import * 
 33  from paramiko.config import SSHConfig 
 34   
 35   
 36  # Change by RogerB - python < 2.3 doesn't have enumerate so we implement it 
 37  if sys.version_info < (2,3): 
38 - class enumerate:
39 - def __init__ (self, sequence):
40 self.sequence = sequence
41 - def __iter__ (self):
42 count = 0 43 for item in self.sequence: 44 yield (count, item) 45 count += 1
46 47
48 -def inflate_long(s, always_positive=False):
49 "turns a normalized byte string into a long-int (adapted from Crypto.Util.number)" 50 out = 0L 51 negative = 0 52 if not always_positive and (len(s) > 0) and (ord(s[0]) >= 0x80): 53 negative = 1 54 if len(s) % 4: 55 filler = '\x00' 56 if negative: 57 filler = '\xff' 58 s = filler * (4 - len(s) % 4) + s 59 for i in range(0, len(s), 4): 60 out = (out << 32) + struct.unpack('>I', s[i:i+4])[0] 61 if negative: 62 out -= (1L << (8 * len(s))) 63 return out
64
65 -def deflate_long(n, add_sign_padding=True):
66 "turns a long-int into a normalized byte string (adapted from Crypto.Util.number)" 67 # after much testing, this algorithm was deemed to be the fastest 68 s = '' 69 n = long(n) 70 while (n != 0) and (n != -1): 71 s = struct.pack('>I', n & 0xffffffffL) + s 72 n = n >> 32 73 # strip off leading zeros, FFs 74 for i in enumerate(s): 75 if (n == 0) and (i[1] != '\000'): 76 break 77 if (n == -1) and (i[1] != '\xff'): 78 break 79 else: 80 # degenerate case, n was either 0 or -1 81 i = (0,) 82 if n == 0: 83 s = '\000' 84 else: 85 s = '\xff' 86 s = s[i[0]:] 87 if add_sign_padding: 88 if (n == 0) and (ord(s[0]) >= 0x80): 89 s = '\x00' + s 90 if (n == -1) and (ord(s[0]) < 0x80): 91 s = '\xff' + s 92 return s
93
94 -def format_binary_weird(data):
95 out = '' 96 for i in enumerate(data): 97 out += '%02X' % ord(i[1]) 98 if i[0] % 2: 99 out += ' ' 100 if i[0] % 16 == 15: 101 out += '\n' 102 return out
103
104 -def format_binary(data, prefix=''):
105 x = 0 106 out = [] 107 while len(data) > x + 16: 108 out.append(format_binary_line(data[x:x+16])) 109 x += 16 110 if x < len(data): 111 out.append(format_binary_line(data[x:])) 112 return [prefix + x for x in out]
113
114 -def format_binary_line(data):
115 left = ' '.join(['%02X' % ord(c) for c in data]) 116 right = ''.join([('.%c..' % c)[(ord(c)+63)//95] for c in data]) 117 return '%-50s %s' % (left, right)
118
119 -def hexify(s):
120 return hexlify(s).upper()
121
122 -def unhexify(s):
123 return unhexlify(s)
124
125 -def safe_string(s):
126 out = '' 127 for c in s: 128 if (ord(c) >= 32) and (ord(c) <= 127): 129 out += c 130 else: 131 out += '%%%02X' % ord(c) 132 return out
133 134 # ''.join([['%%%02X' % ord(c), c][(ord(c) >= 32) and (ord(c) <= 127)] for c in s]) 135
136 -def bit_length(n):
137 norm = deflate_long(n, 0) 138 hbyte = ord(norm[0]) 139 if hbyte == 0: 140 return 1 141 bitlen = len(norm) * 8 142 while not (hbyte & 0x80): 143 hbyte <<= 1 144 bitlen -= 1 145 return bitlen
146
147 -def tb_strings():
148 return ''.join(traceback.format_exception(*sys.exc_info())).split('\n')
149
150 -def generate_key_bytes(hashclass, salt, key, nbytes):
151 """ 152 Given a password, passphrase, or other human-source key, scramble it 153 through a secure hash into some keyworthy bytes. This specific algorithm 154 is used for encrypting/decrypting private key files. 155 156 @param hashclass: class from L{Crypto.Hash} that can be used as a secure 157 hashing function (like C{MD5} or C{SHA}). 158 @type hashclass: L{Crypto.Hash} 159 @param salt: data to salt the hash with. 160 @type salt: string 161 @param key: human-entered password or passphrase. 162 @type key: string 163 @param nbytes: number of bytes to generate. 164 @type nbytes: int 165 @return: key data 166 @rtype: string 167 """ 168 keydata = '' 169 digest = '' 170 if len(salt) > 8: 171 salt = salt[:8] 172 while nbytes > 0: 173 hash_obj = hashclass.new() 174 if len(digest) > 0: 175 hash_obj.update(digest) 176 hash_obj.update(key) 177 hash_obj.update(salt) 178 digest = hash_obj.digest() 179 size = min(nbytes, len(digest)) 180 keydata += digest[:size] 181 nbytes -= size 182 return keydata
183
184 -def load_host_keys(filename):
185 """ 186 Read a file of known SSH host keys, in the format used by openssh, and 187 return a compound dict of C{hostname -> keytype ->} L{PKey <paramiko.pkey.PKey>}. 188 The hostname may be an IP address or DNS name. The keytype will be either 189 C{"ssh-rsa"} or C{"ssh-dss"}. 190 191 This type of file unfortunately doesn't exist on Windows, but on posix, 192 it will usually be stored in C{os.path.expanduser("~/.ssh/known_hosts")}. 193 194 Since 1.5.3, this is just a wrapper around L{HostKeys}. 195 196 @param filename: name of the file to read host keys from 197 @type filename: str 198 @return: dict of host keys, indexed by hostname and then keytype 199 @rtype: dict(hostname, dict(keytype, L{PKey <paramiko.pkey.PKey>})) 200 """ 201 from paramiko.hostkeys import HostKeys 202 return HostKeys(filename)
203
204 -def parse_ssh_config(file_obj):
205 """ 206 Provided only as a backward-compatible wrapper around L{SSHConfig}. 207 """ 208 config = SSHConfig() 209 config.parse(file_obj) 210 return config
211
212 -def lookup_ssh_host_config(hostname, config):
213 """ 214 Provided only as a backward-compatible wrapper around L{SSHConfig}. 215 """ 216 return config.lookup(hostname)
217
218 -def mod_inverse(x, m):
219 # it's crazy how small python can make this function. 220 u1, u2, u3 = 1, 0, m 221 v1, v2, v3 = 0, 1, x 222 223 while v3 > 0: 224 q = u3 // v3 225 u1, v1 = v1, u1 - v1 * q 226 u2, v2 = v2, u2 - v2 * q 227 u3, v3 = v3, u3 - v3 * q 228 if u2 < 0: 229 u2 += m 230 return u2
231 232 _g_thread_ids = {} 233 _g_thread_counter = 0 234 _g_thread_lock = threading.Lock()
235 -def get_thread_id():
236 global _g_thread_ids, _g_thread_counter, _g_thread_lock 237 tid = id(threading.currentThread()) 238 try: 239 return _g_thread_ids[tid] 240 except KeyError: 241 _g_thread_lock.acquire() 242 try: 243 _g_thread_counter += 1 244 ret = _g_thread_ids[tid] = _g_thread_counter 245 finally: 246 _g_thread_lock.release() 247 return ret
248
249 -def log_to_file(filename, level=DEBUG):
250 "send paramiko logs to a logfile, if they're not already going somewhere" 251 l = logging.getLogger("paramiko") 252 if len(l.handlers) > 0: 253 return 254 l.setLevel(level) 255 f = open(filename, 'w') 256 lh = logging.StreamHandler(f) 257 lh.setFormatter(logging.Formatter('%(levelname)-.3s [%(asctime)s.%(msecs)03d] thr=%(_threadid)-3d %(name)s: %(message)s', 258 '%Y%m%d-%H:%M:%S')) 259 l.addHandler(lh)
260 261 # make only one filter object, so it doesn't get applied more than once
262 -class PFilter (object):
263 - def filter(self, record):
264 record._threadid = get_thread_id() 265 return True
266 _pfilter = PFilter() 267
268 -def get_logger(name):
269 l = logging.getLogger(name) 270 l.addFilter(_pfilter) 271 return l
272 273
274 -class Counter (object):
275 """Stateful counter for CTR mode crypto"""
276 - def __init__(self, nbits, initial_value=1L, overflow=0L):
277 self.blocksize = nbits / 8 278 self.overflow = overflow 279 # start with value - 1 so we don't have to store intermediate values when counting 280 # could the iv be 0? 281 if initial_value == 0: 282 self.value = array.array('c', '\xFF' * self.blocksize) 283 else: 284 x = deflate_long(initial_value - 1, add_sign_padding=False) 285 self.value = array.array('c', '\x00' * (self.blocksize - len(x)) + x)
286
287 - def __call__(self):
288 """Increament the counter and return the new value""" 289 i = self.blocksize - 1 290 while i > -1: 291 c = self.value[i] = chr((ord(self.value[i]) + 1) % 256) 292 if c != '\x00': 293 return self.value.tostring() 294 i -= 1 295 # counter reset 296 x = deflate_long(self.overflow, add_sign_padding=False) 297 self.value = array.array('c', '\x00' * (self.blocksize - len(x)) + x) 298 return self.value.tostring()
299
300 - def new(cls, nbits, initial_value=1L, overflow=0L):
301 return cls(nbits, initial_value=initial_value, overflow=overflow)
302 new = classmethod(new)
303