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