From 1a716ed46d1d556d4ba6798608ab498320acd886 Mon Sep 17 00:00:00 2001 From: "Jeremy T. Bouse" Date: Sat, 25 May 2013 00:04:32 -0400 Subject: Imported Upstream version 1.10.1 --- docs/paramiko.packet-pysrc.html | 920 ---------------------------------------- 1 file changed, 920 deletions(-) delete mode 100644 docs/paramiko.packet-pysrc.html (limited to 'docs/paramiko.packet-pysrc.html') diff --git a/docs/paramiko.packet-pysrc.html b/docs/paramiko.packet-pysrc.html deleted file mode 100644 index 8341e2c..0000000 --- a/docs/paramiko.packet-pysrc.html +++ /dev/null @@ -1,920 +0,0 @@ - - - - - paramiko.packet - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Package paramiko :: - Module packet - - - - - -
[frames] | no frames]
-
-

Source Code for Module paramiko.packet

-
-  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  Packetizer. 
- 21  """ 
- 22   
- 23  import errno 
- 24  import select 
- 25  import socket 
- 26  import struct 
- 27  import threading 
- 28  import time 
- 29   
- 30  from paramiko.common import * 
- 31  from paramiko import util 
- 32  from paramiko.ssh_exception import SSHException 
- 33  from paramiko.message import Message 
- 34   
- 35   
- 36  got_r_hmac = False 
- 37  try: 
- 38      import r_hmac 
- 39      got_r_hmac = True 
- 40  except ImportError: 
- 41      pass 
-
42 -def compute_hmac(key, message, digest_class): -
43 if got_r_hmac: - 44 return r_hmac.HMAC(key, message, digest_class).digest() - 45 from Crypto.Hash import HMAC - 46 return HMAC.HMAC(key, message, digest_class).digest() -
47 - 48 -
49 -class NeedRekeyException (Exception): -
50 pass -
51 - 52 -
53 -class Packetizer (object): -
54 """ - 55 Implementation of the base SSH packet protocol. - 56 """ - 57 - 58 # READ the secsh RFC's before raising these values. if anything, - 59 # they should probably be lower. - 60 REKEY_PACKETS = pow(2, 30) - 61 REKEY_BYTES = pow(2, 30) - 62 -
63 - def __init__(self, socket): -
64 self.__socket = socket - 65 self.__logger = None - 66 self.__closed = False - 67 self.__dump_packets = False - 68 self.__need_rekey = False - 69 self.__init_count = 0 - 70 self.__remainder = '' - 71 - 72 # used for noticing when to re-key: - 73 self.__sent_bytes = 0 - 74 self.__sent_packets = 0 - 75 self.__received_bytes = 0 - 76 self.__received_packets = 0 - 77 self.__received_packets_overflow = 0 - 78 - 79 # current inbound/outbound ciphering: - 80 self.__block_size_out = 8 - 81 self.__block_size_in = 8 - 82 self.__mac_size_out = 0 - 83 self.__mac_size_in = 0 - 84 self.__block_engine_out = None - 85 self.__block_engine_in = None - 86 self.__mac_engine_out = None - 87 self.__mac_engine_in = None - 88 self.__mac_key_out = '' - 89 self.__mac_key_in = '' - 90 self.__compress_engine_out = None - 91 self.__compress_engine_in = None - 92 self.__sequence_number_out = 0L - 93 self.__sequence_number_in = 0L - 94 - 95 # lock around outbound writes (packet computation) - 96 self.__write_lock = threading.RLock() - 97 - 98 # keepalives: - 99 self.__keepalive_interval = 0 -100 self.__keepalive_last = time.time() -101 self.__keepalive_callback = None -
102 -
103 - def set_log(self, log): -
104 """ -105 Set the python log object to use for logging. -106 """ -107 self.__logger = log -
108 -
109 - def set_outbound_cipher(self, block_engine, block_size, mac_engine, mac_size, mac_key): -
110 """ -111 Switch outbound data cipher. -112 """ -113 self.__block_engine_out = block_engine -114 self.__block_size_out = block_size -115 self.__mac_engine_out = mac_engine -116 self.__mac_size_out = mac_size -117 self.__mac_key_out = mac_key -118 self.__sent_bytes = 0 -119 self.__sent_packets = 0 -120 # wait until the reset happens in both directions before clearing rekey flag -121 self.__init_count |= 1 -122 if self.__init_count == 3: -123 self.__init_count = 0 -124 self.__need_rekey = False -
125 -
126 - def set_inbound_cipher(self, block_engine, block_size, mac_engine, mac_size, mac_key): -
127 """ -128 Switch inbound data cipher. -129 """ -130 self.__block_engine_in = block_engine -131 self.__block_size_in = block_size -132 self.__mac_engine_in = mac_engine -133 self.__mac_size_in = mac_size -134 self.__mac_key_in = mac_key -135 self.__received_bytes = 0 -136 self.__received_packets = 0 -137 self.__received_packets_overflow = 0 -138 # wait until the reset happens in both directions before clearing rekey flag -139 self.__init_count |= 2 -140 if self.__init_count == 3: -141 self.__init_count = 0 -142 self.__need_rekey = False -
143 -
144 - def set_outbound_compressor(self, compressor): -
145 self.__compress_engine_out = compressor -
146 -
147 - def set_inbound_compressor(self, compressor): -
148 self.__compress_engine_in = compressor -
149 -
150 - def close(self): -
151 self.__closed = True -152 self.__socket.close() -
153 -
154 - def set_hexdump(self, hexdump): -
155 self.__dump_packets = hexdump -
156 -
157 - def get_hexdump(self): -
158 return self.__dump_packets -
159 -
160 - def get_mac_size_in(self): -
161 return self.__mac_size_in -
162 -
163 - def get_mac_size_out(self): -
164 return self.__mac_size_out -
165 -
166 - def need_rekey(self): -
167 """ -168 Returns C{True} if a new set of keys needs to be negotiated. This -169 will be triggered during a packet read or write, so it should be -170 checked after every read or write, or at least after every few. -171 -172 @return: C{True} if a new set of keys needs to be negotiated -173 """ -174 return self.__need_rekey -
175 -
176 - def set_keepalive(self, interval, callback): -
177 """ -178 Turn on/off the callback keepalive. If C{interval} seconds pass with -179 no data read from or written to the socket, the callback will be -180 executed and the timer will be reset. -181 """ -182 self.__keepalive_interval = interval -183 self.__keepalive_callback = callback -184 self.__keepalive_last = time.time() -
185 -
186 - def read_all(self, n, check_rekey=False): -
187 """ -188 Read as close to N bytes as possible, blocking as long as necessary. -189 -190 @param n: number of bytes to read -191 @type n: int -192 @return: the data read -193 @rtype: str -194 @raise EOFError: if the socket was closed before all the bytes could -195 be read -196 """ -197 out = '' -198 # handle over-reading from reading the banner line -199 if len(self.__remainder) > 0: -200 out = self.__remainder[:n] -201 self.__remainder = self.__remainder[n:] -202 n -= len(out) -203 if PY22: -204 return self._py22_read_all(n, out) -205 while n > 0: -206 got_timeout = False -207 try: -208 x = self.__socket.recv(n) -209 if len(x) == 0: -210 raise EOFError() -211 out += x -212 n -= len(x) -213 except socket.timeout: -214 got_timeout = True -215 except socket.error, e: -216 # on Linux, sometimes instead of socket.timeout, we get -217 # EAGAIN. this is a bug in recent (> 2.6.9) kernels but -218 # we need to work around it. -219 if (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EAGAIN): -220 got_timeout = True -221 elif (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EINTR): -222 # syscall interrupted; try again -223 pass -224 elif self.__closed: -225 raise EOFError() -226 else: -227 raise -228 if got_timeout: -229 if self.__closed: -230 raise EOFError() -231 if check_rekey and (len(out) == 0) and self.__need_rekey: -232 raise NeedRekeyException() -233 self._check_keepalive() -234 return out -
235 -
236 - def write_all(self, out): -
237 self.__keepalive_last = time.time() -238 while len(out) > 0: -239 got_timeout = False -240 try: -241 n = self.__socket.send(out) -242 except socket.timeout: -243 got_timeout = True -244 except socket.error, e: -245 if (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EAGAIN): -246 got_timeout = True -247 elif (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EINTR): -248 # syscall interrupted; try again -249 pass -250 else: -251 n = -1 -252 except Exception: -253 # could be: (32, 'Broken pipe') -254 n = -1 -255 if got_timeout: -256 n = 0 -257 if self.__closed: -258 n = -1 -259 if n < 0: -260 raise EOFError() -261 if n == len(out): -262 break -263 out = out[n:] -264 return -
265 -
266 - def readline(self, timeout): -
267 """ -268 Read a line from the socket. We assume no data is pending after the -269 line, so it's okay to attempt large reads. -270 """ -271 buf = self.__remainder -272 while not '\n' in buf: -273 buf += self._read_timeout(timeout) -274 n = buf.index('\n') -275 self.__remainder = buf[n+1:] -276 buf = buf[:n] -277 if (len(buf) > 0) and (buf[-1] == '\r'): -278 buf = buf[:-1] -279 return buf -
280 -
281 - def send_message(self, data): -
282 """ -283 Write a block of data using the current cipher, as an SSH block. -284 """ -285 # encrypt this sucka -286 data = str(data) -287 cmd = ord(data[0]) -288 if cmd in MSG_NAMES: -289 cmd_name = MSG_NAMES[cmd] -290 else: -291 cmd_name = '$%x' % cmd -292 orig_len = len(data) -293 self.__write_lock.acquire() -294 try: -295 if self.__compress_engine_out is not None: -296 data = self.__compress_engine_out(data) -297 packet = self._build_packet(data) -298 if self.__dump_packets: -299 self._log(DEBUG, 'Write packet <%s>, length %d' % (cmd_name, orig_len)) -300 self._log(DEBUG, util.format_binary(packet, 'OUT: ')) -301 if self.__block_engine_out != None: -302 out = self.__block_engine_out.encrypt(packet) -303 else: -304 out = packet -305 # + mac -306 if self.__block_engine_out != None: -307 payload = struct.pack('>I', self.__sequence_number_out) + packet -308 out += compute_hmac(self.__mac_key_out, payload, self.__mac_engine_out)[:self.__mac_size_out] -309 self.__sequence_number_out = (self.__sequence_number_out + 1) & 0xffffffffL -310 self.write_all(out) -311 -312 self.__sent_bytes += len(out) -313 self.__sent_packets += 1 -314 if ((self.__sent_packets >= self.REKEY_PACKETS) or (self.__sent_bytes >= self.REKEY_BYTES)) \ -315 and not self.__need_rekey: -316 # only ask once for rekeying -317 self._log(DEBUG, 'Rekeying (hit %d packets, %d bytes sent)' % -318 (self.__sent_packets, self.__sent_bytes)) -319 self.__received_packets_overflow = 0 -320 self._trigger_rekey() -321 finally: -322 self.__write_lock.release() -
323 -
324 - def read_message(self): -
325 """ -326 Only one thread should ever be in this function (no other locking is -327 done). -328 -329 @raise SSHException: if the packet is mangled -330 @raise NeedRekeyException: if the transport should rekey -331 """ -332 header = self.read_all(self.__block_size_in, check_rekey=True) -333 if self.__block_engine_in != None: -334 header = self.__block_engine_in.decrypt(header) -335 if self.__dump_packets: -336 self._log(DEBUG, util.format_binary(header, 'IN: ')); -337 packet_size = struct.unpack('>I', header[:4])[0] -338 # leftover contains decrypted bytes from the first block (after the length field) -339 leftover = header[4:] -340 if (packet_size - len(leftover)) % self.__block_size_in != 0: -341 raise SSHException('Invalid packet blocking') -342 buf = self.read_all(packet_size + self.__mac_size_in - len(leftover)) -343 packet = buf[:packet_size - len(leftover)] -344 post_packet = buf[packet_size - len(leftover):] -345 if self.__block_engine_in != None: -346 packet = self.__block_engine_in.decrypt(packet) -347 if self.__dump_packets: -348 self._log(DEBUG, util.format_binary(packet, 'IN: ')); -349 packet = leftover + packet -350 -351 if self.__mac_size_in > 0: -352 mac = post_packet[:self.__mac_size_in] -353 mac_payload = struct.pack('>II', self.__sequence_number_in, packet_size) + packet -354 my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in] -355 if my_mac != mac: -356 raise SSHException('Mismatched MAC') -357 padding = ord(packet[0]) -358 payload = packet[1:packet_size - padding] -359 -360 if self.__dump_packets: -361 self._log(DEBUG, 'Got payload (%d bytes, %d padding)' % (packet_size, padding)) -362 -363 if self.__compress_engine_in is not None: -364 payload = self.__compress_engine_in(payload) -365 -366 msg = Message(payload[1:]) -367 msg.seqno = self.__sequence_number_in -368 self.__sequence_number_in = (self.__sequence_number_in + 1) & 0xffffffffL -369 -370 # check for rekey -371 self.__received_bytes += packet_size + self.__mac_size_in + 4 -372 self.__received_packets += 1 -373 if self.__need_rekey: -374 # we've asked to rekey -- give them 20 packets to comply before -375 # dropping the connection -376 self.__received_packets_overflow += 1 -377 if self.__received_packets_overflow >= 20: -378 raise SSHException('Remote transport is ignoring rekey requests') -379 elif (self.__received_packets >= self.REKEY_PACKETS) or \ -380 (self.__received_bytes >= self.REKEY_BYTES): -381 # only ask once for rekeying -382 self._log(DEBUG, 'Rekeying (hit %d packets, %d bytes received)' % -383 (self.__received_packets, self.__received_bytes)) -384 self.__received_packets_overflow = 0 -385 self._trigger_rekey() -386 -387 cmd = ord(payload[0]) -388 if cmd in MSG_NAMES: -389 cmd_name = MSG_NAMES[cmd] -390 else: -391 cmd_name = '$%x' % cmd -392 if self.__dump_packets: -393 self._log(DEBUG, 'Read packet <%s>, length %d' % (cmd_name, len(payload))) -394 return cmd, msg -
395 -396 -397 ########## protected -398 -399 -
400 - def _log(self, level, msg): -
401 if self.__logger is None: -402 return -403 if issubclass(type(msg), list): -404 for m in msg: -405 self.__logger.log(level, m) -406 else: -407 self.__logger.log(level, msg) -
408 -
409 - def _check_keepalive(self): -
410 if (not self.__keepalive_interval) or (not self.__block_engine_out) or \ -411 self.__need_rekey: -412 # wait till we're encrypting, and not in the middle of rekeying -413 return -414 now = time.time() -415 if now > self.__keepalive_last + self.__keepalive_interval: -416 self.__keepalive_callback() -417 self.__keepalive_last = now -
418 -
419 - def _py22_read_all(self, n, out): -
420 while n > 0: -421 r, w, e = select.select([self.__socket], [], [], 0.1) -422 if self.__socket not in r: -423 if self.__closed: -424 raise EOFError() -425 self._check_keepalive() -426 else: -427 x = self.__socket.recv(n) -428 if len(x) == 0: -429 raise EOFError() -430 out += x -431 n -= len(x) -432 return out -
433 -
434 - def _py22_read_timeout(self, timeout): -
435 start = time.time() -436 while True: -437 r, w, e = select.select([self.__socket], [], [], 0.1) -438 if self.__socket in r: -439 x = self.__socket.recv(1) -440 if len(x) == 0: -441 raise EOFError() -442 break -443 if self.__closed: -444 raise EOFError() -445 now = time.time() -446 if now - start >= timeout: -447 raise socket.timeout() -448 return x -
449 -
450 - def _read_timeout(self, timeout): -
451 if PY22: -452 return self._py22_read_timeout(timeout) -453 start = time.time() -454 while True: -455 try: -456 x = self.__socket.recv(128) -457 if len(x) == 0: -458 raise EOFError() -459 break -460 except socket.timeout: -461 pass -462 if self.__closed: -463 raise EOFError() -464 now = time.time() -465 if now - start >= timeout: -466 raise socket.timeout() -467 return x -
468 -
469 - def _build_packet(self, payload): -
470 # pad up at least 4 bytes, to nearest block-size (usually 8) -471 bsize = self.__block_size_out -472 padding = 3 + bsize - ((len(payload) + 8) % bsize) -473 packet = struct.pack('>IB', len(payload) + padding + 1, padding) -474 packet += payload -475 if self.__block_engine_out is not None: -476 packet += rng.read(padding) -477 else: -478 # cute trick i caught openssh doing: if we're not encrypting, -479 # don't waste random bytes for the padding -480 packet += (chr(0) * padding) -481 return packet -
482 -
483 - def _trigger_rekey(self): -
484 # outside code should check for this flag -485 self.__need_rekey = True -
486 -
-
- - - - - - - - - - - - - - - - - - - - - - - -
- - - - -- cgit v1.2.3