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