paramiko.transport

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

# Source Code for Module paramiko.transport

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