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