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

Source Code for Module paramiko.transport

   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  Core protocol implementation 
  21  """ 
  22   
  23  import os 
  24  import socket 
  25  import sys 
  26  import threading 
  27  import time 
  28  import weakref 
  29  from hashlib import md5, sha1 
  30   
  31  import paramiko 
  32  from paramiko import util 
  33  from paramiko.auth_handler import AuthHandler 
  34  from paramiko.channel import Channel 
  35  from paramiko.common import xffffffff, cMSG_CHANNEL_OPEN, cMSG_IGNORE, \ 
  36      cMSG_GLOBAL_REQUEST, DEBUG, MSG_KEXINIT, MSG_IGNORE, MSG_DISCONNECT, \ 
  37      MSG_DEBUG, ERROR, WARNING, cMSG_UNIMPLEMENTED, INFO, cMSG_KEXINIT, \ 
  38      cMSG_NEWKEYS, MSG_NEWKEYS, cMSG_REQUEST_SUCCESS, cMSG_REQUEST_FAILURE, \ 
  39      CONNECTION_FAILED_CODE, OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED, \ 
  40      OPEN_SUCCEEDED, cMSG_CHANNEL_OPEN_FAILURE, cMSG_CHANNEL_OPEN_SUCCESS, \ 
  41      MSG_GLOBAL_REQUEST, MSG_REQUEST_SUCCESS, MSG_REQUEST_FAILURE, \ 
  42      MSG_CHANNEL_OPEN_SUCCESS, MSG_CHANNEL_OPEN_FAILURE, MSG_CHANNEL_OPEN, \ 
  43      MSG_CHANNEL_SUCCESS, MSG_CHANNEL_FAILURE, MSG_CHANNEL_DATA, \ 
  44      MSG_CHANNEL_EXTENDED_DATA, MSG_CHANNEL_WINDOW_ADJUST, MSG_CHANNEL_REQUEST, \ 
  45      MSG_CHANNEL_EOF, MSG_CHANNEL_CLOSE 
  46  from paramiko.compress import ZlibCompressor, ZlibDecompressor 
  47  from paramiko.dsskey import DSSKey 
  48  from paramiko.kex_gex import KexGex 
  49  from paramiko.kex_group1 import KexGroup1 
  50  from paramiko.message import Message 
  51  from paramiko.packet import Packetizer, NeedRekeyException 
  52  from paramiko.primes import ModulusPack 
  53  from paramiko.py3compat import string_types, long, byte_ord, b 
  54  from paramiko.rsakey import RSAKey 
  55  from paramiko.ecdsakey import ECDSAKey 
  56  from paramiko.server import ServerInterface 
  57  from paramiko.sftp_client import SFTPClient 
  58  from paramiko.ssh_exception import (SSHException, BadAuthenticationType, 
  59                                      ChannelException, ProxyCommandFailure) 
  60  from paramiko.util import retry_on_signal 
  61   
  62  from Crypto.Cipher import Blowfish, AES, DES3, ARC4 
  63  try: 
  64      from Crypto.Util import Counter 
  65  except ImportError: 
  66      from paramiko.util import Counter 
  67   
  68   
  69  # for thread cleanup 
  70  _active_threads = [] 
  71   
72 -def _join_lingering_threads():
73 for thr in _active_threads: 74 thr.stop_thread()
75 76 import atexit 77 atexit.register(_join_lingering_threads) 78 79
80 -class Transport (threading.Thread):
81 """ 82 An SSH Transport attaches to a stream (usually a socket), negotiates an 83 encrypted session, authenticates, and then creates stream tunnels, called 84 `channels <.Channel>`, across the session. Multiple channels can be 85 multiplexed across a single session (and often are, in the case of port 86 forwardings). 87 """ 88 _PROTO_ID = '2.0' 89 _CLIENT_ID = 'paramiko_%s' % paramiko.__version__ 90 91 _preferred_ciphers = ('aes128-ctr', 'aes256-ctr', 'aes128-cbc', 'blowfish-cbc', 92 'aes256-cbc', '3des-cbc', 'arcfour128', 'arcfour256') 93 _preferred_macs = ('hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96') 94 _preferred_keys = ('ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256') 95 _preferred_kex = ('diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1') 96 _preferred_compression = ('none',) 97 98 _cipher_info = { 99 'aes128-ctr': {'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 16}, 100 'aes256-ctr': {'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 32}, 101 'blowfish-cbc': {'class': Blowfish, 'mode': Blowfish.MODE_CBC, 'block-size': 8, 'key-size': 16}, 102 'aes128-cbc': {'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 16}, 103 'aes256-cbc': {'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 32}, 104 '3des-cbc': {'class': DES3, 'mode': DES3.MODE_CBC, 'block-size': 8, 'key-size': 24}, 105 'arcfour128': {'class': ARC4, 'mode': None, 'block-size': 8, 'key-size': 16}, 106 'arcfour256': {'class': ARC4, 'mode': None, 'block-size': 8, 'key-size': 32}, 107 } 108 109 _mac_info = { 110 'hmac-sha1': {'class': sha1, 'size': 20}, 111 'hmac-sha1-96': {'class': sha1, 'size': 12}, 112 'hmac-md5': {'class': md5, 'size': 16}, 113 'hmac-md5-96': {'class': md5, 'size': 12}, 114 } 115 116 _key_info = { 117 'ssh-rsa': RSAKey, 118 'ssh-dss': DSSKey, 119 'ecdsa-sha2-nistp256': ECDSAKey, 120 } 121 122 _kex_info = { 123 'diffie-hellman-group1-sha1': KexGroup1, 124 'diffie-hellman-group-exchange-sha1': KexGex, 125 } 126 127 _compression_info = { 128 # zlib@openssh.com is just zlib, but only turned on after a successful 129 # authentication. openssh servers may only offer this type because 130 # they've had troubles with security holes in zlib in the past. 131 'zlib@openssh.com': (ZlibCompressor, ZlibDecompressor), 132 'zlib': (ZlibCompressor, ZlibDecompressor), 133 'none': (None, None), 134 } 135 136 _modulus_pack = None 137
138 - def __init__(self, sock):
139 """ 140 Create a new SSH session over an existing socket, or socket-like 141 object. This only creates the `.Transport` object; it doesn't begin the 142 SSH session yet. Use `connect` or `start_client` to begin a client 143 session, or `start_server` to begin a server session. 144 145 If the object is not actually a socket, it must have the following 146 methods: 147 148 - ``send(str)``: Writes from 1 to ``len(str)`` bytes, and returns an 149 int representing the number of bytes written. Returns 150 0 or raises ``EOFError`` if the stream has been closed. 151 - ``recv(int)``: Reads from 1 to ``int`` bytes and returns them as a 152 string. Returns 0 or raises ``EOFError`` if the stream has been 153 closed. 154 - ``close()``: Closes the socket. 155 - ``settimeout(n)``: Sets a (float) timeout on I/O operations. 156 157 For ease of use, you may also pass in an address (as a tuple) or a host 158 string as the ``sock`` argument. (A host string is a hostname with an 159 optional port (separated by ``":"``) which will be converted into a 160 tuple of ``(hostname, port)``.) A socket will be connected to this 161 address and used for communication. Exceptions from the ``socket`` 162 call may be thrown in this case. 163 164 :param socket sock: 165 a socket or socket-like object to create the session over. 166 """ 167 self.active = False 168 169 if isinstance(sock, string_types): 170 # convert "host:port" into (host, port) 171 hl = sock.split(':', 1) 172 if len(hl) == 1: 173 sock = (hl[0], 22) 174 else: 175 sock = (hl[0], int(hl[1])) 176 if type(sock) is tuple: 177 # connect to the given (host, port) 178 hostname, port = sock 179 reason = 'No suitable address family' 180 for (family, socktype, proto, canonname, sockaddr) in socket.getaddrinfo(hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM): 181 if socktype == socket.SOCK_STREAM: 182 af = family 183 addr = sockaddr 184 sock = socket.socket(af, socket.SOCK_STREAM) 185 try: 186 retry_on_signal(lambda: sock.connect((hostname, port))) 187 except socket.error as e: 188 reason = str(e) 189 else: 190 break 191 else: 192 raise SSHException( 193 'Unable to connect to %s: %s' % (hostname, reason)) 194 # okay, normal socket-ish flow here... 195 threading.Thread.__init__(self) 196 self.setDaemon(True) 197 self.sock = sock 198 # Python < 2.3 doesn't have the settimeout method - RogerB 199 try: 200 # we set the timeout so we can check self.active periodically to 201 # see if we should bail. socket.timeout exception is never 202 # propagated. 203 self.sock.settimeout(0.1) 204 except AttributeError: 205 pass 206 207 # negotiated crypto parameters 208 self.packetizer = Packetizer(sock) 209 self.local_version = 'SSH-' + self._PROTO_ID + '-' + self._CLIENT_ID 210 self.remote_version = '' 211 self.local_cipher = self.remote_cipher = '' 212 self.local_kex_init = self.remote_kex_init = None 213 self.local_mac = self.remote_mac = None 214 self.local_compression = self.remote_compression = None 215 self.session_id = None 216 self.host_key_type = None 217 self.host_key = None 218 219 # state used during negotiation 220 self.kex_engine = None 221 self.H = None 222 self.K = None 223 224 self.initial_kex_done = False 225 self.in_kex = False 226 self.authenticated = False 227 self._expected_packet = tuple() 228 self.lock = threading.Lock() # synchronization (always higher level than write_lock) 229 230 # tracking open channels 231 self._channels = ChannelMap() 232 self.channel_events = {} # (id -> Event) 233 self.channels_seen = {} # (id -> True) 234 self._channel_counter = 1 235 self.window_size = 65536 236 self.max_packet_size = 34816 237 self._forward_agent_handler = None 238 self._x11_handler = None 239 self._tcp_handler = None 240 241 self.saved_exception = None 242 self.clear_to_send = threading.Event() 243 self.clear_to_send_lock = threading.Lock() 244 self.clear_to_send_timeout = 30.0 245 self.log_name = 'paramiko.transport' 246 self.logger = util.get_logger(self.log_name) 247 self.packetizer.set_log(self.logger) 248 self.auth_handler = None 249 self.global_response = None # response Message from an arbitrary global request 250 self.completion_event = None # user-defined event callbacks 251 self.banner_timeout = 15 # how long (seconds) to wait for the SSH banner 252 253 # server mode: 254 self.server_mode = False 255 self.server_object = None 256 self.server_key_dict = {} 257 self.server_accepts = [] 258 self.server_accept_cv = threading.Condition(self.lock) 259 self.subsystem_table = {}
260
261 - def __repr__(self):
262 """ 263 Returns a string representation of this object, for debugging. 264 """ 265 out = '<paramiko.Transport at %s' % hex(long(id(self)) & xffffffff) 266 if not self.active: 267 out += ' (unconnected)' 268 else: 269 if self.local_cipher != '': 270 out += ' (cipher %s, %d bits)' % (self.local_cipher, 271 self._cipher_info[self.local_cipher]['key-size'] * 8) 272 if self.is_authenticated(): 273 out += ' (active; %d open channel(s))' % len(self._channels) 274 elif self.initial_kex_done: 275 out += ' (connected; awaiting auth)' 276 else: 277 out += ' (connecting)' 278 out += '>' 279 return out
280
281 - def atfork(self):
282 """ 283 Terminate this Transport without closing the session. On posix 284 systems, if a Transport is open during process forking, both parent 285 and child will share the underlying socket, but only one process can 286 use the connection (without corrupting the session). Use this method 287 to clean up a Transport object without disrupting the other process. 288 289 .. versionadded:: 1.5.3 290 """ 291 self.close()
292
293 - def get_security_options(self):
294 """ 295 Return a `.SecurityOptions` object which can be used to tweak the 296 encryption algorithms this transport will permit (for encryption, 297 digest/hash operations, public keys, and key exchanges) and the order 298 of preference for them. 299 """ 300 return SecurityOptions(self)
301
302 - def start_client(self, event=None):
303 """ 304 Negotiate a new SSH2 session as a client. This is the first step after 305 creating a new `.Transport`. A separate thread is created for protocol 306 negotiation. 307 308 If an event is passed in, this method returns immediately. When 309 negotiation is done (successful or not), the given ``Event`` will 310 be triggered. On failure, `is_active` will return ``False``. 311 312 (Since 1.4) If ``event`` is ``None``, this method will not return until 313 negotation is done. On success, the method returns normally. 314 Otherwise an SSHException is raised. 315 316 After a successful negotiation, you will usually want to authenticate, 317 calling `auth_password <Transport.auth_password>` or 318 `auth_publickey <Transport.auth_publickey>`. 319 320 .. note:: `connect` is a simpler method for connecting as a client. 321 322 .. note:: After calling this method (or `start_server` or `connect`), 323 you should no longer directly read from or write to the original 324 socket object. 325 326 :param .threading.Event event: 327 an event to trigger when negotiation is complete (optional) 328 329 :raises SSHException: if negotiation fails (and no ``event`` was passed 330 in) 331 """ 332 self.active = True 333 if event is not None: 334 # async, return immediately and let the app poll for completion 335 self.completion_event = event 336 self.start() 337 return 338 339 # synchronous, wait for a result 340 self.completion_event = event = threading.Event() 341 self.start() 342 while True: 343 event.wait(0.1) 344 if not self.active: 345 e = self.get_exception() 346 if e is not None: 347 raise e 348 raise SSHException('Negotiation failed.') 349 if event.isSet(): 350 break
351
352 - def start_server(self, event=None, server=None):
353 """ 354 Negotiate a new SSH2 session as a server. This is the first step after 355 creating a new `.Transport` and setting up your server host key(s). A 356 separate thread is created for protocol negotiation. 357 358 If an event is passed in, this method returns immediately. When 359 negotiation is done (successful or not), the given ``Event`` will 360 be triggered. On failure, `is_active` will return ``False``. 361 362 (Since 1.4) If ``event`` is ``None``, this method will not return until 363 negotation is done. On success, the method returns normally. 364 Otherwise an SSHException is raised. 365 366 After a successful negotiation, the client will need to authenticate. 367 Override the methods `get_allowed_auths 368 <.ServerInterface.get_allowed_auths>`, `check_auth_none 369 <.ServerInterface.check_auth_none>`, `check_auth_password 370 <.ServerInterface.check_auth_password>`, and `check_auth_publickey 371 <.ServerInterface.check_auth_publickey>` in the given ``server`` object 372 to control the authentication process. 373 374 After a successful authentication, the client should request to open a 375 channel. Override `check_channel_request 376 <.ServerInterface.check_channel_request>` in the given ``server`` 377 object to allow channels to be opened. 378 379 .. note:: 380 After calling this method (or `start_client` or `connect`), you 381 should no longer directly read from or write to the original socket 382 object. 383 384 :param .threading.Event event: 385 an event to trigger when negotiation is complete. 386 :param .ServerInterface server: 387 an object used to perform authentication and create `channels 388 <.Channel>` 389 390 :raises SSHException: if negotiation fails (and no ``event`` was passed 391 in) 392 """ 393 if server is None: 394 server = ServerInterface() 395 self.server_mode = True 396 self.server_object = server 397 self.active = True 398 if event is not None: 399 # async, return immediately and let the app poll for completion 400 self.completion_event = event 401 self.start() 402 return 403 404 # synchronous, wait for a result 405 self.completion_event = event = threading.Event() 406 self.start() 407 while True: 408 event.wait(0.1) 409 if not self.active: 410 e = self.get_exception() 411 if e is not None: 412 raise e 413 raise SSHException('Negotiation failed.') 414 if event.isSet(): 415 break
416
417 - def add_server_key(self, key):
418 """ 419 Add a host key to the list of keys used for server mode. When behaving 420 as a server, the host key is used to sign certain packets during the 421 SSH2 negotiation, so that the client can trust that we are who we say 422 we are. Because this is used for signing, the key must contain private 423 key info, not just the public half. Only one key of each type (RSA or 424 DSS) is kept. 425 426 :param .PKey key: 427 the host key to add, usually an `.RSAKey` or `.DSSKey`. 428 """ 429 self.server_key_dict[key.get_name()] = key
430
431 - def get_server_key(self):
432 """ 433 Return the active host key, in server mode. After negotiating with the 434 client, this method will return the negotiated host key. If only one 435 type of host key was set with `add_server_key`, that's the only key 436 that will ever be returned. But in cases where you have set more than 437 one type of host key (for example, an RSA key and a DSS key), the key 438 type will be negotiated by the client, and this method will return the 439 key of the type agreed on. If the host key has not been negotiated 440 yet, ``None`` is returned. In client mode, the behavior is undefined. 441 442 :return: 443 host key (`.PKey`) of the type negotiated by the client, or 444 ``None``. 445 """ 446 try: 447 return self.server_key_dict[self.host_key_type] 448 except KeyError: 449 pass 450 return None
451
452 - def load_server_moduli(filename=None):
453 """ 454 (optional) 455 Load a file of prime moduli for use in doing group-exchange key 456 negotiation in server mode. It's a rather obscure option and can be 457 safely ignored. 458 459 In server mode, the remote client may request "group-exchange" key 460 negotiation, which asks the server to send a random prime number that 461 fits certain criteria. These primes are pretty difficult to compute, 462 so they can't be generated on demand. But many systems contain a file 463 of suitable primes (usually named something like ``/etc/ssh/moduli``). 464 If you call `load_server_moduli` and it returns ``True``, then this 465 file of primes has been loaded and we will support "group-exchange" in 466 server mode. Otherwise server mode will just claim that it doesn't 467 support that method of key negotiation. 468 469 :param str filename: 470 optional path to the moduli file, if you happen to know that it's 471 not in a standard location. 472 :return: 473 True if a moduli file was successfully loaded; False otherwise. 474 475 .. note:: This has no effect when used in client mode. 476 """ 477 Transport._modulus_pack = ModulusPack() 478 # places to look for the openssh "moduli" file 479 file_list = ['/etc/ssh/moduli', '/usr/local/etc/moduli'] 480 if filename is not None: 481 file_list.insert(0, filename) 482 for fn in file_list: 483 try: 484 Transport._modulus_pack.read_file(fn) 485 return True 486 except IOError: 487 pass 488 # none succeeded 489 Transport._modulus_pack = None 490 return False
491 load_server_moduli = staticmethod(load_server_moduli) 492
493 - def close(self):
494 """ 495 Close this session, and any open channels that are tied to it. 496 """ 497 if not self.active: 498 return 499 self.stop_thread() 500 for chan in list(self._channels.values()): 501 chan._unlink() 502 self.sock.close()
503
504 - def get_remote_server_key(self):
505 """ 506 Return the host key of the server (in client mode). 507 508 .. note:: 509 Previously this call returned a tuple of ``(key type, key 510 string)``. You can get the same effect by calling `.PKey.get_name` 511 for the key type, and ``str(key)`` for the key string. 512 513 :raises SSHException: if no session is currently active. 514 515 :return: public key (`.PKey`) of the remote server 516 """ 517 if (not self.active) or (not self.initial_kex_done): 518 raise SSHException('No existing session') 519 return self.host_key
520
521 - def is_active(self):
522 """ 523 Return true if this session is active (open). 524 525 :return: 526 True if the session is still active (open); False if the session is 527 closed 528 """ 529 return self.active
530
531 - def open_session(self):
532 """ 533 Request a new channel to the server, of type ``"session"``. This is 534 just an alias for calling `open_channel` with an argument of 535 ``"session"``. 536 537 :return: a new `.Channel` 538 539 :raises SSHException: if the request is rejected or the session ends 540 prematurely 541 """ 542 return self.open_channel('session')
543
544 - def open_x11_channel(self, src_addr=None):
545 """ 546 Request a new channel to the client, of type ``"x11"``. This 547 is just an alias for ``open_channel('x11', src_addr=src_addr)``. 548 549 :param tuple src_addr: 550 the source address (``(str, int)``) of the x11 server (port is the 551 x11 port, ie. 6010) 552 :return: a new `.Channel` 553 554 :raises SSHException: if the request is rejected or the session ends 555 prematurely 556 """ 557 return self.open_channel('x11', src_addr=src_addr)
558
559 - def open_forward_agent_channel(self):
560 """ 561 Request a new channel to the client, of type 562 ``"auth-agent@openssh.com"``. 563 564 This is just an alias for ``open_channel('auth-agent@openssh.com')``. 565 566 :return: a new `.Channel` 567 568 :raises SSHException: 569 if the request is rejected or the session ends prematurely 570 """ 571 return self.open_channel('auth-agent@openssh.com')
572
573 - def open_forwarded_tcpip_channel(self, src_addr, dest_addr):
574 """ 575 Request a new channel back to the client, of type ``"forwarded-tcpip"``. 576 This is used after a client has requested port forwarding, for sending 577 incoming connections back to the client. 578 579 :param src_addr: originator's address 580 :param dest_addr: local (server) connected address 581 """ 582 return self.open_channel('forwarded-tcpip', dest_addr, src_addr)
583
584 - def open_channel(self, kind, dest_addr=None, src_addr=None):
585 """ 586 Request a new channel to the server. `Channels <.Channel>` are 587 socket-like objects used for the actual transfer of data across the 588 session. You may only request a channel after negotiating encryption 589 (using `connect` or `start_client`) and authenticating. 590 591 :param str kind: 592 the kind of channel requested (usually ``"session"``, 593 ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``) 594 :param tuple dest_addr: 595 the destination address (address + port tuple) of this port 596 forwarding, if ``kind`` is ``"forwarded-tcpip"`` or 597 ``"direct-tcpip"`` (ignored for other channel types) 598 :param src_addr: the source address of this port forwarding, if 599 ``kind`` is ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"`` 600 :return: a new `.Channel` on success 601 602 :raises SSHException: if the request is rejected or the session ends 603 prematurely 604 """ 605 if not self.active: 606 raise SSHException('SSH session not active') 607 self.lock.acquire() 608 try: 609 chanid = self._next_channel() 610 m = Message() 611 m.add_byte(cMSG_CHANNEL_OPEN) 612 m.add_string(kind) 613 m.add_int(chanid) 614 m.add_int(self.window_size) 615 m.add_int(self.max_packet_size) 616 if (kind == 'forwarded-tcpip') or (kind == 'direct-tcpip'): 617 m.add_string(dest_addr[0]) 618 m.add_int(dest_addr[1]) 619 m.add_string(src_addr[0]) 620 m.add_int(src_addr[1]) 621 elif kind == 'x11': 622 m.add_string(src_addr[0]) 623 m.add_int(src_addr[1]) 624 chan = Channel(chanid) 625 self._channels.put(chanid, chan) 626 self.channel_events[chanid] = event = threading.Event() 627 self.channels_seen[chanid] = True 628 chan._set_transport(self) 629 chan._set_window(self.window_size, self.max_packet_size) 630 finally: 631 self.lock.release() 632 self._send_user_message(m) 633 while True: 634 event.wait(0.1) 635 if not self.active: 636 e = self.get_exception() 637 if e is None: 638 e = SSHException('Unable to open channel.') 639 raise e 640 if event.isSet(): 641 break 642 chan = self._channels.get(chanid) 643 if chan is not None: 644 return chan 645 e = self.get_exception() 646 if e is None: 647 e = SSHException('Unable to open channel.') 648 raise e
649
650 - def request_port_forward(self, address, port, handler=None):
651 """ 652 Ask the server to forward TCP connections from a listening port on 653 the server, across this SSH session. 654 655 If a handler is given, that handler is called from a different thread 656 whenever a forwarded connection arrives. The handler parameters are:: 657 658 handler(channel, (origin_addr, origin_port), (server_addr, server_port)) 659 660 where ``server_addr`` and ``server_port`` are the address and port that 661 the server was listening on. 662 663 If no handler is set, the default behavior is to send new incoming 664 forwarded connections into the accept queue, to be picked up via 665 `accept`. 666 667 :param str address: the address to bind when forwarding 668 :param int port: 669 the port to forward, or 0 to ask the server to allocate any port 670 :param callable handler: 671 optional handler for incoming forwarded connections, of the form 672 ``func(Channel, (str, int), (str, int))``. 673 :return: the port number (`int`) allocated by the server 674 675 :raises SSHException: if the server refused the TCP forward request 676 """ 677 if not self.active: 678 raise SSHException('SSH session not active') 679 port = int(port) 680 response = self.global_request('tcpip-forward', (address, port), wait=True) 681 if response is None: 682 raise SSHException('TCP forwarding request denied') 683 if port == 0: 684 port = response.get_int() 685 if handler is None: 686 def default_handler(channel, src_addr, dest_addr_port): 687 #src_addr, src_port = src_addr_port 688 #dest_addr, dest_port = dest_addr_port 689 self._queue_incoming_channel(channel)
690 handler = default_handler 691 self._tcp_handler = handler 692 return port
693
694 - def cancel_port_forward(self, address, port):
695 """ 696 Ask the server to cancel a previous port-forwarding request. No more 697 connections to the given address & port will be forwarded across this 698 ssh connection. 699 700 :param str address: the address to stop forwarding 701 :param int port: the port to stop forwarding 702 """ 703 if not self.active: 704 return 705 self._tcp_handler = None 706 self.global_request('cancel-tcpip-forward', (address, port), wait=True)
707
708 - def open_sftp_client(self):
709 """ 710 Create an SFTP client channel from an open transport. On success, an 711 SFTP session will be opened with the remote host, and a new 712 `.SFTPClient` object will be returned. 713 714 :return: 715 a new `.SFTPClient` referring to an sftp session (channel) across 716 this transport 717 """ 718 return SFTPClient.from_transport(self)
719
720 - def send_ignore(self, byte_count=None):
721 """ 722 Send a junk packet across the encrypted link. This is sometimes used 723 to add "noise" to a connection to confuse would-be attackers. It can 724 also be used as a keep-alive for long lived connections traversing 725 firewalls. 726 727 :param int byte_count: 728 the number of random bytes to send in the payload of the ignored 729 packet -- defaults to a random number from 10 to 41. 730 """ 731 m = Message() 732 m.add_byte(cMSG_IGNORE) 733 if byte_count is None: 734 byte_count = (byte_ord(os.urandom(1)) % 32) + 10 735 m.add_bytes(os.urandom(byte_count)) 736 self._send_user_message(m)
737
738 - def renegotiate_keys(self):
739 """ 740 Force this session to switch to new keys. Normally this is done 741 automatically after the session hits a certain number of packets or 742 bytes sent or received, but this method gives you the option of forcing 743 new keys whenever you want. Negotiating new keys causes a pause in 744 traffic both ways as the two sides swap keys and do computations. This 745 method returns when the session has switched to new keys. 746 747 :raises SSHException: if the key renegotiation failed (which causes the 748 session to end) 749 """ 750 self.completion_event = threading.Event() 751 self._send_kex_init() 752 while True: 753 self.completion_event.wait(0.1) 754 if not self.active: 755 e = self.get_exception() 756 if e is not None: 757 raise e 758 raise SSHException('Negotiation failed.') 759 if self.completion_event.isSet(): 760 break 761 return
762
763 - def set_keepalive(self, interval):
764 """ 765 Turn on/off keepalive packets (default is off). If this is set, after 766 ``interval`` seconds without sending any data over the connection, a 767 "keepalive" packet will be sent (and ignored by the remote host). This 768 can be useful to keep connections alive over a NAT, for example. 769 770 :param int interval: 771 seconds to wait before sending a keepalive packet (or 772 0 to disable keepalives). 773 """ 774 self.packetizer.set_keepalive(interval, 775 lambda x=weakref.proxy(self): x.global_request('keepalive@lag.net', wait=False))
776
777 - def global_request(self, kind, data=None, wait=True):
778 """ 779 Make a global request to the remote host. These are normally 780 extensions to the SSH2 protocol. 781 782 :param str kind: name of the request. 783 :param tuple data: 784 an optional tuple containing additional data to attach to the 785 request. 786 :param bool wait: 787 ``True`` if this method should not return until a response is 788 received; ``False`` otherwise. 789 :return: 790 a `.Message` containing possible additional data if the request was 791 successful (or an empty `.Message` if ``wait`` was ``False``); 792 ``None`` if the request was denied. 793 """ 794 if wait: 795 self.completion_event = threading.Event() 796 m = Message() 797 m.add_byte(cMSG_GLOBAL_REQUEST) 798 m.add_string(kind) 799 m.add_boolean(wait) 800 if data is not None: 801 m.add(*data) 802 self._log(DEBUG, 'Sending global request "%s"' % kind) 803 self._send_user_message(m) 804 if not wait: 805 return None 806 while True: 807 self.completion_event.wait(0.1) 808 if not self.active: 809 return None 810 if self.completion_event.isSet(): 811 break 812 return self.global_response
813
814 - def accept(self, timeout=None):
815 """ 816 Return the next channel opened by the client over this transport, in 817 server mode. If no channel is opened before the given timeout, ``None`` 818 is returned. 819 820 :param int timeout: 821 seconds to wait for a channel, or ``None`` to wait forever 822 :return: a new `.Channel` opened by the client 823 """ 824 self.lock.acquire() 825 try: 826 if len(self.server_accepts) > 0: 827 chan = self.server_accepts.pop(0) 828 else: 829 self.server_accept_cv.wait(timeout) 830 if len(self.server_accepts) > 0: 831 chan = self.server_accepts.pop(0) 832 else: 833 # timeout 834 chan = None 835 finally: 836 self.lock.release() 837 return chan
838
839 - def connect(self, hostkey=None, username='', password=None, pkey=None):
840 """ 841 Negotiate an SSH2 session, and optionally verify the server's host key 842 and authenticate using a password or private key. This is a shortcut 843 for `start_client`, `get_remote_server_key`, and 844 `Transport.auth_password` or `Transport.auth_publickey`. Use those 845 methods if you want more control. 846 847 You can use this method immediately after creating a Transport to 848 negotiate encryption with a server. If it fails, an exception will be 849 thrown. On success, the method will return cleanly, and an encrypted 850 session exists. You may immediately call `open_channel` or 851 `open_session` to get a `.Channel` object, which is used for data 852 transfer. 853 854 .. note:: 855 If you fail to supply a password or private key, this method may 856 succeed, but a subsequent `open_channel` or `open_session` call may 857 fail because you haven't authenticated yet. 858 859 :param .PKey hostkey: 860 the host key expected from the server, or ``None`` if you don't 861 want to do host key verification. 862 :param str username: the username to authenticate as. 863 :param str password: 864 a password to use for authentication, if you want to use password 865 authentication; otherwise ``None``. 866 :param .PKey pkey: 867 a private key to use for authentication, if you want to use private 868 key authentication; otherwise ``None``. 869 870 :raises SSHException: if the SSH2 negotiation fails, the host key 871 supplied by the server is incorrect, or authentication fails. 872 """ 873 if hostkey is not None: 874 self._preferred_keys = [hostkey.get_name()] 875 876 self.start_client() 877 878 # check host key if we were given one 879 if hostkey is not None: 880 key = self.get_remote_server_key() 881 if (key.get_name() != hostkey.get_name()) or (key.asbytes() != hostkey.asbytes()): 882 self._log(DEBUG, 'Bad host key from server') 883 self._log(DEBUG, 'Expected: %s: %s' % (hostkey.get_name(), repr(hostkey.asbytes()))) 884 self._log(DEBUG, 'Got : %s: %s' % (key.get_name(), repr(key.asbytes()))) 885 raise SSHException('Bad host key from server') 886 self._log(DEBUG, 'Host key verified (%s)' % hostkey.get_name()) 887 888 if (pkey is not None) or (password is not None): 889 if password is not None: 890 self._log(DEBUG, 'Attempting password auth...') 891 self.auth_password(username, password) 892 else: 893 self._log(DEBUG, 'Attempting public-key auth...') 894 self.auth_publickey(username, pkey) 895 896 return
897
898 - def get_exception(self):
899 """ 900 Return any exception that happened during the last server request. 901 This can be used to fetch more specific error information after using 902 calls like `start_client`. The exception (if any) is cleared after 903 this call. 904 905 :return: 906 an exception, or ``None`` if there is no stored exception. 907 908 .. versionadded:: 1.1 909 """ 910 self.lock.acquire() 911 try: 912 e = self.saved_exception 913 self.saved_exception = None 914 return e 915 finally: 916 self.lock.release()
917
918 - def set_subsystem_handler(self, name, handler, *larg, **kwarg):
919 """ 920 Set the handler class for a subsystem in server mode. If a request 921 for this subsystem is made on an open ssh channel later, this handler 922 will be constructed and called -- see `.SubsystemHandler` for more 923 detailed documentation. 924 925 Any extra parameters (including keyword arguments) are saved and 926 passed to the `.SubsystemHandler` constructor later. 927 928 :param str name: name of the subsystem. 929 :param class handler: 930 subclass of `.SubsystemHandler` that handles this subsystem. 931 """ 932 try: 933 self.lock.acquire() 934 self.subsystem_table[name] = (handler, larg, kwarg) 935 finally: 936 self.lock.release()
937
938 - def is_authenticated(self):
939 """ 940 Return true if this session is active and authenticated. 941 942 :return: 943 True if the session is still open and has been authenticated 944 successfully; False if authentication failed and/or the session is 945 closed. 946 """ 947 return self.active and (self.auth_handler is not None) and self.auth_handler.is_authenticated()
948
949 - def get_username(self):
950 """ 951 Return the username this connection is authenticated for. If the 952 session is not authenticated (or authentication failed), this method 953 returns ``None``. 954 955 :return: username that was authenticated (a `str`), or ``None``. 956 """ 957 if not self.active or (self.auth_handler is None): 958 return None 959 return self.auth_handler.get_username()
960
961 - def get_banner(self):
962 """ 963 Return the banner supplied by the server upon connect. If no banner is 964 supplied, this method returns C{None}. 965 966 @return: server supplied banner, or C{None}. 967 @rtype: string 968 """ 969 if not self.active or (self.auth_handler is None): 970 return None 971 return self.auth_handler.banner
972
973 - def auth_none(self, username):
974 """ 975 Try to authenticate to the server using no authentication at all. 976 This will almost always fail. It may be useful for determining the 977 list of authentication types supported by the server, by catching the 978 `.BadAuthenticationType` exception raised. 979 980 :param str username: the username to authenticate as 981 :return: 982 `list` of auth types permissible for the next stage of 983 authentication (normally empty) 984 985 :raises BadAuthenticationType: if "none" authentication isn't allowed 986 by the server for this user 987 :raises SSHException: if the authentication failed due to a network 988 error 989 990 .. versionadded:: 1.5 991 """ 992 if (not self.active) or (not self.initial_kex_done): 993 raise SSHException('No existing session') 994 my_event = threading.Event() 995 self.auth_handler = AuthHandler(self) 996 self.auth_handler.auth_none(username, my_event) 997 return self.auth_handler.wait_for_response(my_event)
998
999 - def auth_password(self, username, password, event=None, fallback=True):
1000 """ 1001 Authenticate to the server using a password. The username and password 1002 are sent over an encrypted link. 1003 1004 If an ``event`` is passed in, this method will return immediately, and 1005 the event will be triggered once authentication succeeds or fails. On 1006 success, `is_authenticated` will return ``True``. On failure, you may 1007 use `get_exception` to get more detailed error information. 1008 1009 Since 1.1, if no event is passed, this method will block until the 1010 authentication succeeds or fails. On failure, an exception is raised. 1011 Otherwise, the method simply returns. 1012 1013 Since 1.5, if no event is passed and ``fallback`` is ``True`` (the 1014 default), if the server doesn't support plain password authentication 1015 but does support so-called "keyboard-interactive" mode, an attempt 1016 will be made to authenticate using this interactive mode. If it fails, 1017 the normal exception will be thrown as if the attempt had never been 1018 made. This is useful for some recent Gentoo and Debian distributions, 1019 which turn off plain password authentication in a misguided belief 1020 that interactive authentication is "more secure". (It's not.) 1021 1022 If the server requires multi-step authentication (which is very rare), 1023 this method will return a list of auth types permissible for the next 1024 step. Otherwise, in the normal case, an empty list is returned. 1025 1026 :param str username: the username to authenticate as 1027 :param basestring password: the password to authenticate with 1028 :param .threading.Event event: 1029 an event to trigger when the authentication attempt is complete 1030 (whether it was successful or not) 1031 :param bool fallback: 1032 ``True`` if an attempt at an automated "interactive" password auth 1033 should be made if the server doesn't support normal password auth 1034 :return: 1035 `list` of auth types permissible for the next stage of 1036 authentication (normally empty) 1037 1038 :raises BadAuthenticationType: if password authentication isn't 1039 allowed by the server for this user (and no event was passed in) 1040 :raises AuthenticationException: if the authentication failed (and no 1041 event was passed in) 1042 :raises SSHException: if there was a network error 1043 """ 1044 if (not self.active) or (not self.initial_kex_done): 1045 # we should never try to send the password unless we're on a secure link 1046 raise SSHException('No existing session') 1047 if event is None: 1048 my_event = threading.Event() 1049 else: 1050 my_event = event 1051 self.auth_handler = AuthHandler(self) 1052 self.auth_handler.auth_password(username, password, my_event) 1053 if event is not None: 1054 # caller wants to wait for event themselves 1055 return [] 1056 try: 1057 return self.auth_handler.wait_for_response(my_event) 1058 except BadAuthenticationType as e: 1059 # if password auth isn't allowed, but keyboard-interactive *is*, try to fudge it 1060 if not fallback or ('keyboard-interactive' not in e.allowed_types): 1061 raise 1062 try: 1063 def handler(title, instructions, fields): 1064 if len(fields) > 1: 1065 raise SSHException('Fallback authentication failed.') 1066 if len(fields) == 0: 1067 # for some reason, at least on os x, a 2nd request will 1068 # be made with zero fields requested. maybe it's just 1069 # to try to fake out automated scripting of the exact 1070 # type we're doing here. *shrug* :) 1071 return [] 1072 return [password]
1073 return self.auth_interactive(username, handler) 1074 except SSHException: 1075 # attempt failed; just raise the original exception 1076 raise e 1077
1078 - def auth_publickey(self, username, key, event=None):
1079 """ 1080 Authenticate to the server using a private key. The key is used to 1081 sign data from the server, so it must include the private part. 1082 1083 If an ``event`` is passed in, this method will return immediately, and 1084 the event will be triggered once authentication succeeds or fails. On 1085 success, `is_authenticated` will return ``True``. On failure, you may 1086 use `get_exception` to get more detailed error information. 1087 1088 Since 1.1, if no event is passed, this method will block until the 1089 authentication succeeds or fails. On failure, an exception is raised. 1090 Otherwise, the method simply returns. 1091 1092 If the server requires multi-step authentication (which is very rare), 1093 this method will return a list of auth types permissible for the next 1094 step. Otherwise, in the normal case, an empty list is returned. 1095 1096 :param str username: the username to authenticate as 1097 :param .PKey key: the private key to authenticate with 1098 :param .threading.Event event: 1099 an event to trigger when the authentication attempt is complete 1100 (whether it was successful or not) 1101 :return: 1102 `list` of auth types permissible for the next stage of 1103 authentication (normally empty) 1104 1105 :raises BadAuthenticationType: if public-key authentication isn't 1106 allowed by the server for this user (and no event was passed in) 1107 :raises AuthenticationException: if the authentication failed (and no 1108 event was passed in) 1109 :raises SSHException: if there was a network error 1110 """ 1111 if (not self.active) or (not self.initial_kex_done): 1112 # we should never try to authenticate unless we're on a secure link 1113 raise SSHException('No existing session') 1114 if event is None: 1115 my_event = threading.Event() 1116 else: 1117 my_event = event 1118 self.auth_handler = AuthHandler(self) 1119 self.auth_handler.auth_publickey(username, key, my_event) 1120 if event is not None: 1121 # caller wants to wait for event themselves 1122 return [] 1123 return self.auth_handler.wait_for_response(my_event)
1124
1125 - def auth_interactive(self, username, handler, submethods=''):
1126 """ 1127 Authenticate to the server interactively. A handler is used to answer 1128 arbitrary questions from the server. On many servers, this is just a 1129 dumb wrapper around PAM. 1130 1131 This method will block until the authentication succeeds or fails, 1132 peroidically calling the handler asynchronously to get answers to 1133 authentication questions. The handler may be called more than once 1134 if the server continues to ask questions. 1135 1136 The handler is expected to be a callable that will handle calls of the 1137 form: ``handler(title, instructions, prompt_list)``. The ``title`` is 1138 meant to be a dialog-window title, and the ``instructions`` are user 1139 instructions (both are strings). ``prompt_list`` will be a list of 1140 prompts, each prompt being a tuple of ``(str, bool)``. The string is 1141 the prompt and the boolean indicates whether the user text should be 1142 echoed. 1143 1144 A sample call would thus be: 1145 ``handler('title', 'instructions', [('Password:', False)])``. 1146 1147 The handler should return a list or tuple of answers to the server's 1148 questions. 1149 1150 If the server requires multi-step authentication (which is very rare), 1151 this method will return a list of auth types permissible for the next 1152 step. Otherwise, in the normal case, an empty list is returned. 1153 1154 :param str username: the username to authenticate as 1155 :param callable handler: a handler for responding to server questions 1156 :param str submethods: a string list of desired submethods (optional) 1157 :return: 1158 `list` of auth types permissible for the next stage of 1159 authentication (normally empty). 1160 1161 :raises BadAuthenticationType: if public-key authentication isn't 1162 allowed by the server for this user 1163 :raises AuthenticationException: if the authentication failed 1164 :raises SSHException: if there was a network error 1165 1166 .. versionadded:: 1.5 1167 """ 1168 if (not self.active) or (not self.initial_kex_done): 1169 # we should never try to authenticate unless we're on a secure link 1170 raise SSHException('No existing session') 1171 my_event = threading.Event() 1172 self.auth_handler = AuthHandler(self) 1173 self.auth_handler.auth_interactive(username, handler, my_event, submethods) 1174 return self.auth_handler.wait_for_response(my_event)
1175
1176 - def set_log_channel(self, name):
1177 """ 1178 Set the channel for this transport's logging. The default is 1179 ``"paramiko.transport"`` but it can be set to anything you want. (See 1180 the `.logging` module for more info.) SSH Channels will log to a 1181 sub-channel of the one specified. 1182 1183 :param str name: new channel name for logging 1184 1185 .. versionadded:: 1.1 1186 """ 1187 self.log_name = name 1188 self.logger = util.get_logger(name) 1189 self.packetizer.set_log(self.logger)
1190
1191 - def get_log_channel(self):
1192 """ 1193 Return the channel name used for this transport's logging. 1194 1195 :return: channel name as a `str` 1196 1197 .. versionadded:: 1.2 1198 """ 1199 return self.log_name
1200
1201 - def set_hexdump(self, hexdump):
1202 """ 1203 Turn on/off logging a hex dump of protocol traffic at DEBUG level in 1204 the logs. Normally you would want this off (which is the default), 1205 but if you are debugging something, it may be useful. 1206 1207 :param bool hexdump: 1208 ``True`` to log protocol traffix (in hex) to the log; ``False`` 1209 otherwise. 1210 """ 1211 self.packetizer.set_hexdump(hexdump)
1212
1213 - def get_hexdump(self):
1214 """ 1215 Return ``True`` if the transport is currently logging hex dumps of 1216 protocol traffic. 1217 1218 :return: ``True`` if hex dumps are being logged, else ``False``. 1219 1220 .. versionadded:: 1.4 1221 """ 1222 return self.packetizer.get_hexdump()
1223
1224 - def use_compression(self, compress=True):
1225 """ 1226 Turn on/off compression. This will only have an affect before starting 1227 the transport (ie before calling `connect`, etc). By default, 1228 compression is off since it negatively affects interactive sessions. 1229 1230 :param bool compress: 1231 ``True`` to ask the remote client/server to compress traffic; 1232 ``False`` to refuse compression 1233 1234 .. versionadded:: 1.5.2 1235 """ 1236 if compress: 1237 self._preferred_compression = ('zlib@openssh.com', 'zlib', 'none') 1238 else: 1239 self._preferred_compression = ('none',)
1240
1241 - def getpeername(self):
1242 """ 1243 Return the address of the remote side of this Transport, if possible. 1244 This is effectively a wrapper around ``'getpeername'`` on the underlying 1245 socket. If the socket-like object has no ``'getpeername'`` method, 1246 then ``("unknown", 0)`` is returned. 1247 1248 :return: 1249 the address of the remote host, if known, as a ``(str, int)`` 1250 tuple. 1251 """ 1252 gp = getattr(self.sock, 'getpeername', None) 1253 if gp is None: 1254 return 'unknown', 0 1255 return gp()
1256
1257 - def stop_thread(self):
1258 self.active = False 1259 self.packetizer.close() 1260 while self.isAlive(): 1261 self.join(10)
1262 1263 ### internals... 1264
1265 - def _log(self, level, msg, *args):
1266 if issubclass(type(msg), list): 1267 for m in msg: 1268 self.logger.log(level, m) 1269 else: 1270 self.logger.log(level, msg, *args)
1271
1272 - def _get_modulus_pack(self):
1273 """used by KexGex to find primes for group exchange""" 1274 return self._modulus_pack
1275
1276 - def _next_channel(self):
1277 """you are holding the lock""" 1278 chanid = self._channel_counter 1279 while self._channels.get(chanid) is not None: 1280 self._channel_counter = (self._channel_counter + 1) & 0xffffff 1281 chanid = self._channel_counter 1282 self._channel_counter = (self._channel_counter + 1) & 0xffffff 1283 return chanid
1284 1288
1289 - def _send_message(self, data):
1290 self.packetizer.send_message(data)
1291
1292 - def _send_user_message(self, data):
1293 """ 1294 send a message, but block if we're in key negotiation. this is used 1295 for user-initiated requests. 1296 """ 1297 start = time.time() 1298 while True: 1299 self.clear_to_send.wait(0.1) 1300 if not self.active: 1301 self._log(DEBUG, 'Dropping user packet because connection is dead.') 1302 return 1303 self.clear_to_send_lock.acquire() 1304 if self.clear_to_send.isSet(): 1305 break 1306 self.clear_to_send_lock.release() 1307 if time.time() > start + self.clear_to_send_timeout: 1308 raise SSHException('Key-exchange timed out waiting for key negotiation') 1309 try: 1310 self._send_message(data) 1311 finally: 1312 self.clear_to_send_lock.release()
1313
1314 - def _set_K_H(self, k, h):
1315 """used by a kex object to set the K (root key) and H (exchange hash)""" 1316 self.K = k 1317 self.H = h 1318 if self.session_id is None: 1319 self.session_id = h
1320
1321 - def _expect_packet(self, *ptypes):
1322 """used by a kex object to register the next packet type it expects to see""" 1323 self._expected_packet = tuple(ptypes)
1324
1325 - def _verify_key(self, host_key, sig):
1326 key = self._key_info[self.host_key_type](Message(host_key)) 1327 if key is None: 1328 raise SSHException('Unknown host key type') 1329 if not key.verify_ssh_sig(self.H, Message(sig)): 1330 raise SSHException('Signature verification (%s) failed.' % self.host_key_type) 1331 self.host_key = key
1332
1333 - def _compute_key(self, id, nbytes):
1334 """id is 'A' - 'F' for the various keys used by ssh""" 1335 m = Message() 1336 m.add_mpint(self.K) 1337 m.add_bytes(self.H) 1338 m.add_byte(b(id)) 1339 m.add_bytes(self.session_id) 1340 out = sofar = sha1(m.asbytes()).digest() 1341 while len(out) < nbytes: 1342 m = Message() 1343 m.add_mpint(self.K) 1344 m.add_bytes(self.H) 1345 m.add_bytes(sofar) 1346 digest = sha1(m.asbytes()).digest() 1347 out += digest 1348 sofar += digest 1349 return out[:nbytes]
1350
1351 - def _get_cipher(self, name, key, iv):
1352 if name not in self._cipher_info: 1353 raise SSHException('Unknown client cipher ' + name) 1354 if name in ('arcfour128', 'arcfour256'): 1355 # arcfour cipher 1356 cipher = self._cipher_info[name]['class'].new(key) 1357 # as per RFC 4345, the first 1536 bytes of keystream 1358 # generated by the cipher MUST be discarded 1359 cipher.encrypt(" " * 1536) 1360 return cipher 1361 elif name.endswith("-ctr"): 1362 # CTR modes, we need a counter 1363 counter = Counter.new(nbits=self._cipher_info[name]['block-size'] * 8, initial_value=util.inflate_long(iv, True)) 1364 return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv, counter) 1365 else: 1366 return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv)
1367
1368 - def _set_forward_agent_handler(self, handler):
1369 if handler is None: 1370 def default_handler(channel): 1371 self._queue_incoming_channel(channel)
1372 self._forward_agent_handler = default_handler 1373 else: 1374 self._forward_agent_handler = handler 1375
1376 - def _set_x11_handler(self, handler):
1377 # only called if a channel has turned on x11 forwarding 1378 if handler is None: 1379 # by default, use the same mechanism as accept() 1380 def default_handler(channel, src_addr_port): 1381 self._queue_incoming_channel(channel)
1382 self._x11_handler = default_handler 1383 else: 1384 self._x11_handler = handler 1385
1386 - def _queue_incoming_channel(self, channel):
1387 self.lock.acquire() 1388 try: 1389 self.server_accepts.append(channel) 1390 self.server_accept_cv.notify() 1391 finally: 1392 self.lock.release()
1393
1394 - def run(self):
1395 # (use the exposed "run" method, because if we specify a thread target 1396 # of a private method, threading.Thread will keep a reference to it 1397 # indefinitely, creating a GC cycle and not letting Transport ever be 1398 # GC'd. it's a bug in Thread.) 1399 1400 # Hold reference to 'sys' so we can test sys.modules to detect 1401 # interpreter shutdown. 1402 self.sys = sys 1403 1404 # active=True occurs before the thread is launched, to avoid a race 1405 _active_threads.append(self) 1406 if self.server_mode: 1407 self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & xffffffff)) 1408 else: 1409 self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & xffffffff)) 1410 try: 1411 try: 1412 self.packetizer.write_all(b(self.local_version + '\r\n')) 1413 self._check_banner() 1414 self._send_kex_init() 1415 self._expect_packet(MSG_KEXINIT) 1416 1417 while self.active: 1418 if self.packetizer.need_rekey() and not self.in_kex: 1419 self._send_kex_init() 1420 try: 1421 ptype, m = self.packetizer.read_message() 1422 except NeedRekeyException: 1423 continue 1424 if ptype == MSG_IGNORE: 1425 continue 1426 elif ptype == MSG_DISCONNECT: 1427 self._parse_disconnect(m) 1428 self.active = False 1429 self.packetizer.close() 1430 break 1431 elif ptype == MSG_DEBUG: 1432 self._parse_debug(m) 1433 continue 1434 if len(self._expected_packet) > 0: 1435 if ptype not in self._expected_packet: 1436 raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype)) 1437 self._expected_packet = tuple() 1438 if (ptype >= 30) and (ptype <= 39): 1439 self.kex_engine.parse_next(ptype, m) 1440 continue 1441 1442 if ptype in self._handler_table: 1443 self._handler_table[ptype](self, m) 1444 elif ptype in self._channel_handler_table: 1445 chanid = m.get_int() 1446 chan = self._channels.get(chanid) 1447 if chan is not None: 1448 self._channel_handler_table[ptype](chan, m) 1449 elif chanid in self.channels_seen: 1450 self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid) 1451 else: 1452 self._log(ERROR, 'Channel request for unknown channel %d' % chanid) 1453 self.active = False 1454 self.packetizer.close() 1455 elif (self.auth_handler is not None) and (ptype in self.auth_handler._handler_table): 1456 self.auth_handler._handler_table[ptype](self.auth_handler, m) 1457 else: 1458 self._log(WARNING, 'Oops, unhandled type %d' % ptype) 1459 msg = Message() 1460 msg.add_byte(cMSG_UNIMPLEMENTED) 1461 msg.add_int(m.seqno) 1462 self._send_message(msg) 1463 except SSHException as e: 1464 self._log(ERROR, 'Exception: ' + str(e)) 1465 self._log(ERROR, util.tb_strings()) 1466 self.saved_exception = e 1467 except EOFError as e: 1468 self._log(DEBUG, 'EOF in transport thread') 1469 #self._log(DEBUG, util.tb_strings()) 1470 self.saved_exception = e 1471 except socket.error as e: 1472 if type(e.args) is tuple: 1473 if e.args: 1474 emsg = '%s (%d)' % (e.args[1], e.args[0]) 1475 else: # empty tuple, e.g. socket.timeout 1476 emsg = str(e) or repr(e) 1477 else: 1478 emsg = e.args 1479 self._log(ERROR, 'Socket exception: ' + emsg) 1480 self.saved_exception = e 1481 except Exception as e: 1482 self._log(ERROR, 'Unknown exception: ' + str(e)) 1483 self._log(ERROR, util.tb_strings()) 1484 self.saved_exception = e 1485 _active_threads.remove(self) 1486 for chan in list(self._channels.values()): 1487 chan._unlink() 1488 if self.active: 1489 self.active = False 1490 self.packetizer.close() 1491 if self.completion_event is not None: 1492 self.completion_event.set() 1493 if self.auth_handler is not None: 1494 self.auth_handler.abort() 1495 for event in self.channel_events.values(): 1496 event.set() 1497 try: 1498 self.lock.acquire() 1499 self.server_accept_cv.notify() 1500 finally: 1501 self.lock.release() 1502 self.sock.close() 1503 except: 1504 # Don't raise spurious 'NoneType has no attribute X' errors when we 1505 # wake up during interpreter shutdown. Or rather -- raise 1506 # everything *if* sys.modules (used as a convenient sentinel) 1507 # appears to still exist. 1508 if self.sys.modules is not None: 1509 raise
1510 1511 ### protocol stages 1512
1513 - def _negotiate_keys(self, m):
1514 # throws SSHException on anything unusual 1515 self.clear_to_send_lock.acquire() 1516 try: 1517 self.clear_to_send.clear() 1518 finally: 1519 self.clear_to_send_lock.release() 1520 if self.local_kex_init is None: 1521 # remote side wants to renegotiate 1522 self._send_kex_init() 1523 self._parse_kex_init(m) 1524 self.kex_engine.start_kex()
1525
1526 - def _check_banner(self):
1527 # this is slow, but we only have to do it once 1528 for i in range(100): 1529 # give them 15 seconds for the first line, then just 2 seconds 1530 # each additional line. (some sites have very high latency.) 1531 if i == 0: 1532 timeout = self.banner_timeout 1533 else: 1534 timeout = 2 1535 try: 1536 buf = self.packetizer.readline(timeout) 1537 except ProxyCommandFailure: 1538 raise 1539 except Exception as e: 1540 raise SSHException('Error reading SSH protocol banner' + str(e)) 1541 if buf[:4] == 'SSH-': 1542 break 1543 self._log(DEBUG, 'Banner: ' + buf) 1544 if buf[:4] != 'SSH-': 1545 raise SSHException('Indecipherable protocol version "' + buf + '"') 1546 # save this server version string for later 1547 self.remote_version = buf 1548 # pull off any attached comment 1549 comment = '' 1550 i = buf.find(' ') 1551 if i >= 0: 1552 comment = buf[i+1:] 1553 buf = buf[:i] 1554 # parse out version string and make sure it matches 1555 segs = buf.split('-', 2) 1556 if len(segs) < 3: 1557 raise SSHException('Invalid SSH banner') 1558 version = segs[1] 1559 client = segs[2] 1560 if version != '1.99' and version != '2.0': 1561 raise SSHException('Incompatible version (%s instead of 2.0)' % (version,)) 1562 self._log(INFO, 'Connected (version %s, client %s)' % (version, client))
1563
1564 - def _send_kex_init(self):
1565 """ 1566 announce to the other side that we'd like to negotiate keys, and what 1567 kind of key negotiation we support. 1568 """ 1569 self.clear_to_send_lock.acquire() 1570 try: 1571 self.clear_to_send.clear() 1572 finally: 1573 self.clear_to_send_lock.release() 1574 self.in_kex = True 1575 if self.server_mode: 1576 if (self._modulus_pack is None) and ('diffie-hellman-group-exchange-sha1' in self._preferred_kex): 1577 # can't do group-exchange if we don't have a pack of potential primes 1578 pkex = list(self.get_security_options().kex) 1579 pkex.remove('diffie-hellman-group-exchange-sha1') 1580 self.get_security_options().kex = pkex 1581 available_server_keys = list(filter(list(self.server_key_dict.keys()).__contains__, 1582 self._preferred_keys)) 1583 else: 1584 available_server_keys = self._preferred_keys 1585 1586 m = Message() 1587 m.add_byte(cMSG_KEXINIT) 1588 m.add_bytes(os.urandom(16)) 1589 m.add_list(self._preferred_kex) 1590 m.add_list(available_server_keys) 1591 m.add_list(self._preferred_ciphers) 1592 m.add_list(self._preferred_ciphers) 1593 m.add_list(self._preferred_macs) 1594 m.add_list(self._preferred_macs) 1595 m.add_list(self._preferred_compression) 1596 m.add_list(self._preferred_compression) 1597 m.add_string(bytes()) 1598 m.add_string(bytes()) 1599 m.add_boolean(False) 1600 m.add_int(0) 1601 # save a copy for later (needed to compute a hash) 1602 self.local_kex_init = m.asbytes() 1603 self._send_message(m)
1604
1605 - def _parse_kex_init(self, m):
1606 cookie = m.get_bytes(16) 1607 kex_algo_list = m.get_list() 1608 server_key_algo_list = m.get_list() 1609 client_encrypt_algo_list = m.get_list() 1610 server_encrypt_algo_list = m.get_list() 1611 client_mac_algo_list = m.get_list() 1612 server_mac_algo_list = m.get_list() 1613 client_compress_algo_list = m.get_list() 1614 server_compress_algo_list = m.get_list() 1615 client_lang_list = m.get_list() 1616 server_lang_list = m.get_list() 1617 kex_follows = m.get_boolean() 1618 unused = m.get_int() 1619 1620 self._log(DEBUG, 'kex algos:' + str(kex_algo_list) + ' server key:' + str(server_key_algo_list) + 1621 ' client encrypt:' + str(client_encrypt_algo_list) + 1622 ' server encrypt:' + str(server_encrypt_algo_list) + 1623 ' client mac:' + str(client_mac_algo_list) + 1624 ' server mac:' + str(server_mac_algo_list) + 1625 ' client compress:' + str(client_compress_algo_list) + 1626 ' server compress:' + str(server_compress_algo_list) + 1627 ' client lang:' + str(client_lang_list) + 1628 ' server lang:' + str(server_lang_list) + 1629 ' kex follows?' + str(kex_follows)) 1630 1631 # as a server, we pick the first item in the client's list that we support. 1632 # as a client, we pick the first item in our list that the server supports. 1633 if self.server_mode: 1634 agreed_kex = list(filter(self._preferred_kex.__contains__, kex_algo_list)) 1635 else: 1636 agreed_kex = list(filter(kex_algo_list.__contains__, self._preferred_kex)) 1637 if len(agreed_kex) == 0: 1638 raise SSHException('Incompatible ssh peer (no acceptable kex algorithm)') 1639 self.kex_engine = self._kex_info[agreed_kex[0]](self) 1640 1641 if self.server_mode: 1642 available_server_keys = list(filter(list(self.server_key_dict.keys()).__contains__, 1643 self._preferred_keys)) 1644 agreed_keys = list(filter(available_server_keys.__contains__, server_key_algo_list)) 1645 else: 1646 agreed_keys = list(filter(server_key_algo_list.__contains__, self._preferred_keys)) 1647 if len(agreed_keys) == 0: 1648 raise SSHException('Incompatible ssh peer (no acceptable host key)') 1649 self.host_key_type = agreed_keys[0] 1650 if self.server_mode and (self.get_server_key() is None): 1651 raise SSHException('Incompatible ssh peer (can\'t match requested host key type)') 1652 1653 if self.server_mode: 1654 agreed_local_ciphers = list(filter(self._preferred_ciphers.__contains__, 1655 server_encrypt_algo_list)) 1656 agreed_remote_ciphers = list(filter(self._preferred_ciphers.__contains__, 1657 client_encrypt_algo_list)) 1658 else: 1659 agreed_local_ciphers = list(filter(client_encrypt_algo_list.__contains__, 1660 self._preferred_ciphers)) 1661 agreed_remote_ciphers = list(filter(server_encrypt_algo_list.__contains__, 1662 self._preferred_ciphers)) 1663 if (len(agreed_local_ciphers) == 0) or (len(agreed_remote_ciphers) == 0): 1664 raise SSHException('Incompatible ssh server (no acceptable ciphers)') 1665 self.local_cipher = agreed_local_ciphers[0] 1666 self.remote_cipher = agreed_remote_ciphers[0] 1667 self._log(DEBUG, 'Ciphers agreed: local=%s, remote=%s' % (self.local_cipher, self.remote_cipher)) 1668 1669 if self.server_mode: 1670 agreed_remote_macs = list(filter(self._preferred_macs.__contains__, client_mac_algo_list)) 1671 agreed_local_macs = list(filter(self._preferred_macs.__contains__, server_mac_algo_list)) 1672 else: 1673 agreed_local_macs = list(filter(client_mac_algo_list.__contains__, self._preferred_macs)) 1674 agreed_remote_macs = list(filter(server_mac_algo_list.__contains__, self._preferred_macs)) 1675 if (len(agreed_local_macs) == 0) or (len(agreed_remote_macs) == 0): 1676 raise SSHException('Incompatible ssh server (no acceptable macs)') 1677 self.local_mac = agreed_local_macs[0] 1678 self.remote_mac = agreed_remote_macs[0] 1679 1680 if self.server_mode: 1681 agreed_remote_compression = list(filter(self._preferred_compression.__contains__, client_compress_algo_list)) 1682 agreed_local_compression = list(filter(self._preferred_compression.__contains__, server_compress_algo_list)) 1683 else: 1684 agreed_local_compression = list(filter(client_compress_algo_list.__contains__, self._preferred_compression)) 1685 agreed_remote_compression = list(filter(server_compress_algo_list.__contains__, self._preferred_compression)) 1686 if (len(agreed_local_compression) == 0) or (len(agreed_remote_compression) == 0): 1687 raise SSHException('Incompatible ssh server (no acceptable compression) %r %r %r' % (agreed_local_compression, agreed_remote_compression, self._preferred_compression)) 1688 self.local_compression = agreed_local_compression[0] 1689 self.remote_compression = agreed_remote_compression[0] 1690 1691 self._log(DEBUG, 'using kex %s; server key type %s; cipher: local %s, remote %s; mac: local %s, remote %s; compression: local %s, remote %s' % 1692 (agreed_kex[0], self.host_key_type, self.local_cipher, self.remote_cipher, self.local_mac, 1693 self.remote_mac, self.local_compression, self.remote_compression)) 1694 1695 # save for computing hash later... 1696 # now wait! openssh has a bug (and others might too) where there are 1697 # actually some extra bytes (one NUL byte in openssh's case) added to 1698 # the end of the packet but not parsed. turns out we need to throw 1699 # away those bytes because they aren't part of the hash. 1700 self.remote_kex_init = cMSG_KEXINIT + m.get_so_far()
1701
1702 - def _activate_inbound(self):
1703 """switch on newly negotiated encryption parameters for inbound traffic""" 1704 block_size = self._cipher_info[self.remote_cipher]['block-size'] 1705 if self.server_mode: 1706 IV_in = self._compute_key('A', block_size) 1707 key_in = self._compute_key('C', self._cipher_info[self.remote_cipher]['key-size']) 1708 else: 1709 IV_in = self._compute_key('B', block_size) 1710 key_in = self._compute_key('D', self._cipher_info[self.remote_cipher]['key-size']) 1711 engine = self._get_cipher(self.remote_cipher, key_in, IV_in) 1712 mac_size = self._mac_info[self.remote_mac]['size'] 1713 mac_engine = self._mac_info[self.remote_mac]['class'] 1714 # initial mac keys are done in the hash's natural size (not the potentially truncated 1715 # transmission size) 1716 if self.server_mode: 1717 mac_key = self._compute_key('E', mac_engine().digest_size) 1718 else: 1719 mac_key = self._compute_key('F', mac_engine().digest_size) 1720 self.packetizer.set_inbound_cipher(engine, block_size, mac_engine, mac_size, mac_key) 1721 compress_in = self._compression_info[self.remote_compression][1] 1722 if (compress_in is not None) and ((self.remote_compression != 'zlib@openssh.com') or self.authenticated): 1723 self._log(DEBUG, 'Switching on inbound compression ...') 1724 self.packetizer.set_inbound_compressor(compress_in())
1725
1726 - def _activate_outbound(self):
1727 """switch on newly negotiated encryption parameters for outbound traffic""" 1728 m = Message() 1729 m.add_byte(cMSG_NEWKEYS) 1730 self._send_message(m) 1731 block_size = self._cipher_info[self.local_cipher]['block-size'] 1732 if self.server_mode: 1733 IV_out = self._compute_key('B', block_size) 1734 key_out = self._compute_key('D', self._cipher_info[self.local_cipher]['key-size']) 1735 else: 1736 IV_out = self._compute_key('A', block_size) 1737 key_out = self._compute_key('C', self._cipher_info[self.local_cipher]['key-size']) 1738 engine = self._get_cipher(self.local_cipher, key_out, IV_out) 1739 mac_size = self._mac_info[self.local_mac]['size'] 1740 mac_engine = self._mac_info[self.local_mac]['class'] 1741 # initial mac keys are done in the hash's natural size (not the potentially truncated 1742 # transmission size) 1743 if self.server_mode: 1744 mac_key = self._compute_key('F', mac_engine().digest_size) 1745 else: 1746 mac_key = self._compute_key('E', mac_engine().digest_size) 1747 sdctr = self.local_cipher.endswith('-ctr') 1748 self.packetizer.set_outbound_cipher(engine, block_size, mac_engine, mac_size, mac_key, sdctr) 1749 compress_out = self._compression_info[self.local_compression][0] 1750 if (compress_out is not None) and ((self.local_compression != 'zlib@openssh.com') or self.authenticated): 1751 self._log(DEBUG, 'Switching on outbound compression ...') 1752 self.packetizer.set_outbound_compressor(compress_out()) 1753 if not self.packetizer.need_rekey(): 1754 self.in_kex = False 1755 # we always expect to receive NEWKEYS now 1756 self._expect_packet(MSG_NEWKEYS)
1757
1758 - def _auth_trigger(self):
1759 self.authenticated = True 1760 # delayed initiation of compression 1761 if self.local_compression == 'zlib@openssh.com': 1762 compress_out = self._compression_info[self.local_compression][0] 1763 self._log(DEBUG, 'Switching on outbound compression ...') 1764 self.packetizer.set_outbound_compressor(compress_out()) 1765 if self.remote_compression == 'zlib@openssh.com': 1766 compress_in = self._compression_info[self.remote_compression][1] 1767 self._log(DEBUG, 'Switching on inbound compression ...') 1768 self.packetizer.set_inbound_compressor(compress_in())
1769
1770 - def _parse_newkeys(self, m):
1771 self._log(DEBUG, 'Switch to new keys ...') 1772 self._activate_inbound() 1773 # can also free a bunch of stuff here 1774 self.local_kex_init = self.remote_kex_init = None 1775 self.K = None 1776 self.kex_engine = None 1777 if self.server_mode and (self.auth_handler is None): 1778 # create auth handler for server mode 1779 self.auth_handler = AuthHandler(self) 1780 if not self.initial_kex_done: 1781 # this was the first key exchange 1782 self.initial_kex_done = True 1783 # send an event? 1784 if self.completion_event is not None: 1785 self.completion_event.set() 1786 # it's now okay to send data again (if this was a re-key) 1787 if not self.packetizer.need_rekey(): 1788 self.in_kex = False 1789 self.clear_to_send_lock.acquire() 1790 try: 1791 self.clear_to_send.set() 1792 finally: 1793 self.clear_to_send_lock.release() 1794 return
1795
1796 - def _parse_disconnect(self, m):
1797 code = m.get_int() 1798 desc = m.get_text() 1799 self._log(INFO, 'Disconnect (code %d): %s' % (code, desc))
1800
1801 - def _parse_global_request(self, m):
1802 kind = m.get_text() 1803 self._log(DEBUG, 'Received global request "%s"' % kind) 1804 want_reply = m.get_boolean() 1805 if not self.server_mode: 1806 self._log(DEBUG, 'Rejecting "%s" global request from server.' % kind) 1807 ok = False 1808 elif kind == 'tcpip-forward': 1809 address = m.get_text() 1810 port = m.get_int() 1811 ok = self.server_object.check_port_forward_request(address, port) 1812 if ok: 1813 ok = (ok,) 1814 elif kind == 'cancel-tcpip-forward': 1815 address = m.get_text() 1816 port = m.get_int() 1817 self.server_object.cancel_port_forward_request(address, port) 1818 ok = True 1819 else: 1820 ok = self.server_object.check_global_request(kind, m) 1821 extra = () 1822 if type(ok) is tuple: 1823 extra = ok 1824 ok = True 1825 if want_reply: 1826 msg = Message() 1827 if ok: 1828 msg.add_byte(cMSG_REQUEST_SUCCESS) 1829 msg.add(*extra) 1830 else: 1831 msg.add_byte(cMSG_REQUEST_FAILURE) 1832 self._send_message(msg)
1833
1834 - def _parse_request_success(self, m):
1835 self._log(DEBUG, 'Global request successful.') 1836 self.global_response = m 1837 if self.completion_event is not None: 1838 self.completion_event.set()
1839
1840 - def _parse_request_failure(self, m):
1841 self._log(DEBUG, 'Global request denied.') 1842 self.global_response = None 1843 if self.completion_event is not None: 1844 self.completion_event.set()
1845
1846 - def _parse_channel_open_success(self, m):
1847 chanid = m.get_int() 1848 server_chanid = m.get_int() 1849 server_window_size = m.get_int() 1850 server_max_packet_size = m.get_int() 1851 chan = self._channels.get(chanid) 1852 if chan is None: 1853 self._log(WARNING, 'Success for unrequested channel! [??]') 1854 return 1855 self.lock.acquire() 1856 try: 1857 chan._set_remote_channel(server_chanid, server_window_size, server_max_packet_size) 1858 self._log(INFO, 'Secsh channel %d opened.' % chanid) 1859 if chanid in self.channel_events: 1860 self.channel_events[chanid].set() 1861 del self.channel_events[chanid] 1862 finally: 1863 self.lock.release() 1864 return
1865
1866 - def _parse_channel_open_failure(self, m):
1867 chanid = m.get_int() 1868 reason = m.get_int() 1869 reason_str = m.get_text() 1870 lang = m.get_text() 1871 reason_text = CONNECTION_FAILED_CODE.get(reason, '(unknown code)') 1872 self._log(INFO, 'Secsh channel %d open FAILED: %s: %s' % (chanid, reason_str, reason_text)) 1873 self.lock.acquire() 1874 try: 1875 self.saved_exception = ChannelException(reason, reason_text) 1876 if chanid in self.channel_events: 1877 self._channels.delete(chanid) 1878 if chanid in self.channel_events: 1879 self.channel_events[chanid].set() 1880 del self.channel_events[chanid] 1881 finally: 1882 self.lock.release() 1883 return
1884
1885 - def _parse_channel_open(self, m):
1886 kind = m.get_text() 1887 chanid = m.get_int() 1888 initial_window_size = m.get_int() 1889 max_packet_size = m.get_int() 1890 reject = False 1891 if (kind == 'auth-agent@openssh.com') and (self._forward_agent_handler is not None): 1892 self._log(DEBUG, 'Incoming forward agent connection') 1893 self.lock.acquire() 1894 try: 1895 my_chanid = self._next_channel() 1896 finally: 1897 self.lock.release() 1898 elif (kind == 'x11') and (self._x11_handler is not None): 1899 origin_addr = m.get_text() 1900 origin_port = m.get_int() 1901 self._log(DEBUG, 'Incoming x11 connection from %s:%d' % (origin_addr, origin_port)) 1902 self.lock.acquire() 1903 try: 1904 my_chanid = self._next_channel() 1905 finally: 1906 self.lock.release() 1907 elif (kind == 'forwarded-tcpip') and (self._tcp_handler is not None): 1908 server_addr = m.get_text() 1909 server_port = m.get_int() 1910 origin_addr = m.get_text() 1911 origin_port = m.get_int() 1912 self._log(DEBUG, 'Incoming tcp forwarded connection from %s:%d' % (origin_addr, origin_port)) 1913 self.lock.acquire() 1914 try: 1915 my_chanid = self._next_channel() 1916 finally: 1917 self.lock.release() 1918 elif not self.server_mode: 1919 self._log(DEBUG, 'Rejecting "%s" channel request from server.' % kind) 1920 reject = True 1921 reason = OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED 1922 else: 1923 self.lock.acquire() 1924 try: 1925 my_chanid = self._next_channel() 1926 finally: 1927 self.lock.release() 1928 if kind == 'direct-tcpip': 1929 # handle direct-tcpip requests comming from the client 1930 dest_addr = m.get_text() 1931 dest_port = m.get_int() 1932 origin_addr = m.get_text() 1933 origin_port = m.get_int() 1934 reason = self.server_object.check_channel_direct_tcpip_request( 1935 my_chanid, (origin_addr, origin_port), (dest_addr, dest_port)) 1936 else: 1937 reason = self.server_object.check_channel_request(kind, my_chanid) 1938 if reason != OPEN_SUCCEEDED: 1939 self._log(DEBUG, 'Rejecting "%s" channel request from client.' % kind) 1940 reject = True 1941 if reject: 1942 msg = Message() 1943 msg.add_byte(cMSG_CHANNEL_OPEN_FAILURE) 1944 msg.add_int(chanid) 1945 msg.add_int(reason) 1946 msg.add_string('') 1947 msg.add_string('en') 1948 self._send_message(msg) 1949 return 1950 1951 chan = Channel(my_chanid) 1952 self.lock.acquire() 1953 try: 1954 self._channels.put(my_chanid, chan) 1955 self.channels_seen[my_chanid] = True 1956 chan._set_transport(self) 1957 chan._set_window(self.window_size, self.max_packet_size) 1958 chan._set_remote_channel(chanid, initial_window_size, max_packet_size) 1959 finally: 1960 self.lock.release() 1961 m = Message() 1962 m.add_byte(cMSG_CHANNEL_OPEN_SUCCESS) 1963 m.add_int(chanid) 1964 m.add_int(my_chanid) 1965 m.add_int(self.window_size) 1966 m.add_int(self.max_packet_size) 1967 self._send_message(m) 1968 self._log(INFO, 'Secsh channel %d (%s) opened.', my_chanid, kind) 1969 if kind == 'auth-agent@openssh.com': 1970 self._forward_agent_handler(chan) 1971 elif kind == 'x11': 1972 self._x11_handler(chan, (origin_addr, origin_port)) 1973 elif kind == 'forwarded-tcpip': 1974 chan.origin_addr = (origin_addr, origin_port) 1975 self._tcp_handler(chan, (origin_addr, origin_port), (server_addr, server_port)) 1976 else: 1977 self._queue_incoming_channel(chan)
1978
1979 - def _parse_debug(self, m):
1980 always_display = m.get_boolean() 1981 msg = m.get_string() 1982 lang = m.get_string() 1983 self._log(DEBUG, 'Debug msg: ' + util.safe_string(msg))
1984
1985 - def _get_subsystem_handler(self, name):
1986 try: 1987 self.lock.acquire() 1988 if name not in self.subsystem_table: 1989 return None, [], {} 1990 return self.subsystem_table[name] 1991 finally: 1992 self.lock.release()
1993 1994 _handler_table = { 1995 MSG_NEWKEYS: _parse_newkeys, 1996 MSG_GLOBAL_REQUEST: _parse_global_request, 1997 MSG_REQUEST_SUCCESS: _parse_request_success, 1998 MSG_REQUEST_FAILURE: _parse_request_failure, 1999 MSG_CHANNEL_OPEN_SUCCESS: _parse_channel_open_success, 2000 MSG_CHANNEL_OPEN_FAILURE: _parse_channel_open_failure, 2001 MSG_CHANNEL_OPEN: _parse_channel_open, 2002 MSG_KEXINIT: _negotiate_keys, 2003 } 2004 2005 _channel_handler_table = { 2006 MSG_CHANNEL_SUCCESS: Channel._request_success, 2007 MSG_CHANNEL_FAILURE: Channel._request_failed, 2008 MSG_CHANNEL_DATA: Channel._feed, 2009 MSG_CHANNEL_EXTENDED_DATA: Channel._feed_extended, 2010 MSG_CHANNEL_WINDOW_ADJUST: Channel._window_adjust, 2011 MSG_CHANNEL_REQUEST: Channel._handle_request, 2012 MSG_CHANNEL_EOF: Channel._handle_eof, 2013 MSG_CHANNEL_CLOSE: Channel._handle_close, 2014 } 2015 2016
2017 -class SecurityOptions (object):
2018 """ 2019 Simple object containing the security preferences of an ssh transport. 2020 These are tuples of acceptable ciphers, digests, key types, and key 2021 exchange algorithms, listed in order of preference. 2022 2023 Changing the contents and/or order of these fields affects the underlying 2024 `.Transport` (but only if you change them before starting the session). 2025 If you try to add an algorithm that paramiko doesn't recognize, 2026 ``ValueError`` will be raised. If you try to assign something besides a 2027 tuple to one of the fields, ``TypeError`` will be raised. 2028 """ 2029 #__slots__ = [ 'ciphers', 'digests', 'key_types', 'kex', 'compression', '_transport' ] 2030 __slots__ = '_transport' 2031
2032 - def __init__(self, transport):
2033 self._transport = transport
2034
2035 - def __repr__(self):
2036 """ 2037 Returns a string representation of this object, for debugging. 2038 """ 2039 return '<paramiko.SecurityOptions for %s>' % repr(self._transport)
2040
2041 - def _get_ciphers(self):
2042 return self._transport._preferred_ciphers
2043
2044 - def _get_digests(self):
2045 return self._transport._preferred_macs
2046
2047 - def _get_key_types(self):
2048 return self._transport._preferred_keys
2049
2050 - def _get_kex(self):
2051 return self._transport._preferred_kex
2052
2053 - def _get_compression(self):
2054 return self._transport._preferred_compression
2055
2056 - def _set(self, name, orig, x):
2057 if type(x) is list: 2058 x = tuple(x) 2059 if type(x) is not tuple: 2060 raise TypeError('expected tuple or list') 2061 possible = list(getattr(self._transport, orig).keys()) 2062 forbidden = [n for n in x if n not in possible] 2063 if len(forbidden) > 0: 2064 raise ValueError('unknown cipher') 2065 setattr(self._transport, name, x)
2066
2067 - def _set_ciphers(self, x):
2068 self._set('_preferred_ciphers', '_cipher_info', x)
2069
2070 - def _set_digests(self, x):
2071 self._set('_preferred_macs', '_mac_info', x)
2072
2073 - def _set_key_types(self, x):
2074 self._set('_preferred_keys', '_key_info', x)
2075
2076 - def _set_kex(self, x):
2077 self._set('_preferred_kex', '_kex_info', x)
2078
2079 - def _set_compression(self, x):
2080 self._set('_preferred_compression', '_compression_info', x)
2081 2082 ciphers = property(_get_ciphers, _set_ciphers, None, 2083 "Symmetric encryption ciphers") 2084 digests = property(_get_digests, _set_digests, None, 2085 "Digest (one-way hash) algorithms") 2086 key_types = property(_get_key_types, _set_key_types, None, 2087 "Public-key algorithms") 2088 kex = property(_get_kex, _set_kex, None, "Key exchange algorithms") 2089 compression = property(_get_compression, _set_compression, None, 2090 "Compression algorithms")
2091 2092
2093 -class ChannelMap (object):
2094 - def __init__(self):
2095 # (id -> Channel) 2096 self._map = weakref.WeakValueDictionary() 2097 self._lock = threading.Lock()
2098
2099 - def put(self, chanid, chan):
2100 self._lock.acquire() 2101 try: 2102 self._map[chanid] = chan 2103 finally: 2104 self._lock.release()
2105
2106 - def get(self, chanid):
2107 self._lock.acquire() 2108 try: 2109 return self._map.get(chanid, None) 2110 finally: 2111 self._lock.release()
2112
2113 - def delete(self, chanid):
2114 self._lock.acquire() 2115 try: 2116 try: 2117 del self._map[chanid] 2118 except KeyError: 2119 pass 2120 finally: 2121 self._lock.release()
2122
2123 - def values(self):
2124 self._lock.acquire() 2125 try: 2126 return list(self._map.values()) 2127 finally: 2128 self._lock.release()
2129
2130 - def __len__(self):
2131 self._lock.acquire() 2132 try: 2133 return len(self._map) 2134 finally: 2135 self._lock.release()
2136