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