Exemple #1
0
 def start_kex(self):
     """
     Start the GSS-API / SSPI Authenticated Diffie-Hellman Key Exchange.
     """
     self._generate_x()
     if self.transport.server_mode:
         # compute f = g^x mod p, but don't send it yet
         self.f = pow(self.G, self.x, self.P)
         self.transport._expect_packet(MSG_KEXGSS_INIT)
         return
     # compute e = g^x mod p (where g=2), and send it
     self.e = pow(self.G, self.x, self.P)
     # Initialize GSS-API Key Exchange
     self.gss_host = self.transport.gss_host
     m = Message()
     m.add_byte(c_MSG_KEXGSS_INIT)
     m.add_string(self.kexgss.ssh_init_sec_context(target=self.gss_host))
     m.add_mpint(self.e)
     self.transport._send_message(m)
     self.transport._expect_packet(
         MSG_KEXGSS_HOSTKEY,
         MSG_KEXGSS_CONTINUE,
         MSG_KEXGSS_COMPLETE,
         MSG_KEXGSS_ERROR,
     )
Exemple #2
0
 def _parse_userauth_gssapi_token(self, m):
     client_token = m.get_string()
     # use the client token as input to establish a secure
     # context.
     sshgss = self.sshgss
     try:
         token = sshgss.ssh_accept_sec_context(
             self.gss_host, client_token, self.auth_username
         )
     except Exception as e:
         self.transport.saved_exception = e
         result = AUTH_FAILED
         self._restore_delegate_auth_handler()
         self._send_auth_result(self.auth_username, self.method, result)
         raise
     if token is not None:
         m = Message()
         m.add_byte(cMSG_USERAUTH_GSSAPI_TOKEN)
         m.add_string(token)
         self.transport._expected_packet = (
             MSG_USERAUTH_GSSAPI_TOKEN,
             MSG_USERAUTH_GSSAPI_MIC,
             MSG_USERAUTH_REQUEST,
         )
         self.transport._send_message(m)
Exemple #3
0
 def sign_ssh_data(self, data):
     sig = self.signing_key.sign_deterministic(
         data, sigencode=self._sigencode, hashfunc=sha256)
     m = Message()
     m.add_string('ecdsa-sha2-nistp256')
     m.add_string(sig)
     return m
Exemple #4
0
 def _parse_kexdh_gex_init(self, m):
     self.e = m.get_mpint()
     if (self.e < 1) or (self.e > self.p - 1):
         raise SSHException('Client kex "e" is out of range')
     self._generate_x()
     self.f = pow(self.g, self.x, self.p)
     K = pow(self.e, self.x, self.p)
     key = str(self.transport.get_server_key())
     # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K)
     hm = Message()
     hm.add(self.transport.remote_version, self.transport.local_version,
            self.transport.remote_kex_init, self.transport.local_kex_init,
            key)
     if not self.old_style:
         hm.add_int(self.min_bits)
     hm.add_int(self.preferred_bits)
     if not self.old_style:
         hm.add_int(self.max_bits)
     hm.add_mpint(self.p)
     hm.add_mpint(self.g)
     hm.add_mpint(self.e)
     hm.add_mpint(self.f)
     hm.add_mpint(K)
     H = SHA.new(str(hm)).digest()
     self.transport._set_K_H(K, H)
     # sign it
     sig = self.transport.get_server_key().sign_ssh_data(self.transport.randpool, H)
     # send reply
     m = Message()
     m.add_byte(chr(_MSG_KEXDH_GEX_REPLY))
     m.add_string(key)
     m.add_mpint(self.f)
     m.add_string(str(sig))
     self.transport._send_message(m)
     self.transport._activate_outbound()
Exemple #5
0
    def _parse_kexgss_group(self, m):
        """
        Parse the SSH2_MSG_KEXGSS_GROUP message (client mode).

        :param `Message` m: The content of the SSH2_MSG_KEXGSS_GROUP message
        """
        self.p = m.get_mpint()
        self.g = m.get_mpint()
        # reject if p's bit length < 1024 or > 8192
        bitlen = util.bit_length(self.p)
        if (bitlen < 1024) or (bitlen > 8192):
            raise SSHException(
                'Server-generated gex p (don\'t ask) is out of range '
                '({} bits)'.format(bitlen))
        self.transport._log(DEBUG, 'Got server p ({} bits)'.format(bitlen))  # noqa
        self._generate_x()
        # now compute e = g^x mod p
        self.e = pow(self.g, self.x, self.p)
        m = Message()
        m.add_byte(c_MSG_KEXGSS_INIT)
        m.add_string(self.kexgss.ssh_init_sec_context(target=self.gss_host))
        m.add_mpint(self.e)
        self.transport._send_message(m)
        self.transport._expect_packet(MSG_KEXGSS_HOSTKEY,
                                      MSG_KEXGSS_CONTINUE,
                                      MSG_KEXGSS_COMPLETE,
                                      MSG_KEXGSS_ERROR)
Exemple #6
0
    def resize_pty(self, width=80, height=24):
        """
        Resize the pseudo-terminal.  This can be used to change the width and
        height of the terminal emulation created in a previous L{get_pty} call.

        @param width: new width (in characters) of the terminal screen
        @type width: int
        @param height: new height (in characters) of the terminal screen
        @type height: int
        @return: C{True} if the operation succeeded; C{False} if not.
        @rtype: bool
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('window-change')
        m.add_boolean(1)
        m.add_int(width)
        m.add_int(height)
        m.add_int(0).add_int(0)
        self.event.clear()
        self.transport._send_user_message(m)
        while True:
            self.event.wait(0.1)
            if self.closed:
                return False
            if self.event.isSet():
                return True
Exemple #7
0
    def invoke_subsystem(self, subsystem):
        """
        Request a subsystem on the server (for example, C{sftp}).  If the
        server allows it, the channel will then be directly connected to the
        requested subsystem.
        
        When the subsystem finishes, the channel will be closed and can't be
        reused.

        @param subsystem: name of the subsystem being requested.
        @type subsystem: str
        @return: C{True} if the operation succeeded; C{False} if not.
        @rtype: bool
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('subsystem')
        m.add_boolean(1)
        m.add_string(subsystem)
        self.event.clear()
        self.transport._send_user_message(m)
        while True:
            self.event.wait(0.1)
            if self.closed:
                return False
            if self.event.isSet():
                return True
Exemple #8
0
    def exec_command(self, command):
        """
        Execute a command on the server.  If the server allows it, the channel
        will then be directly connected to the stdin, stdout, and stderr of
        the command being executed.
        
        When the command finishes executing, the channel will be closed and
        can't be reused.  You must open a new channel if you wish to execute
        another command.

        @param command: a shell command to execute.
        @type command: str
        @return: C{True} if the operation succeeded; C{False} if not.
        @rtype: bool
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('exec')
        m.add_boolean(1)
        m.add_string(command)
        self.event.clear()
        self.transport._send_user_message(m)
        while True:
            self.event.wait(0.1)
            if self.closed:
                return False
            if self.event.isSet():
                return True
Exemple #9
0
    def sign_ssh_data(self, data):
        key = dsa.DSAPrivateNumbers(
            x=self.x,
            public_numbers=dsa.DSAPublicNumbers(
                y=self.y,
                parameter_numbers=dsa.DSAParameterNumbers(
                    p=self.p,
                    q=self.q,
                    g=self.g
                )
            )
        ).private_key(backend=default_backend())
        signer = key.signer(hashes.SHA1())
        signer.update(data)
        r, s = decode_dss_signature(signer.finalize())

        m = Message()
        m.add_string('ssh-dss')
        # apparently, in rare cases, r or s may be shorter than 20 bytes!
        rstr = util.deflate_long(r, 0)
        sstr = util.deflate_long(s, 0)
        if len(rstr) < 20:
            rstr = zero_byte * (20 - len(rstr)) + rstr
        if len(sstr) < 20:
            sstr = zero_byte * (20 - len(sstr)) + sstr
        m.add_string(rstr + sstr)
        return m
Exemple #10
0
 def send_stderr(self, s):
     """
     Send data to the channel on the "stderr" stream.  This is normally
     only used by servers to send output from shell commands -- clients
     won't use this.  Returns the number of bytes sent, or 0 if the channel
     stream is closed.  Applications are responsible for checking that all
     data has been sent: if only some of the data was transmitted, the
     application needs to attempt delivery of the remaining data.
     
     @param s: data to send.
     @type s: str
     @return: number of bytes actually sent.
     @rtype: int
     
     @raise socket.timeout: if no data could be sent before the timeout set
         by L{settimeout}.
     
     @since: 1.1
     """
     size = len(s)
     self.lock.acquire()
     try:
         size = self._wait_for_send_window(size)
         if size == 0:
             # eof or similar
             return 0
         m = Message()
         m.add_byte(chr(MSG_CHANNEL_EXTENDED_DATA))
         m.add_int(self.remote_chanid)
         m.add_int(1)
         m.add_string(s[:size])
         self.transport._send_user_message(m)
     finally:
         self.lock.release()
     return size
Exemple #11
0
    def invoke_shell(self):
        """
        Request an interactive shell session on this channel.  If the server
        allows it, the channel will then be directly connected to the stdin,
        stdout, and stderr of the shell.

        Normally you would call `get_pty` before this, in which case the
        shell will operate through the pty, and the channel will be connected
        to the stdin and stdout of the pty.

        When the shell exits, the channel will be closed and can't be reused.
        You must open a new channel if you wish to open another shell.

        :raises:
            `.SSHException` -- if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string("shell")
        m.add_boolean(True)
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #12
0
 def _async_request(self, fileobj, t, *arg):
     # this method may be called from other threads (prefetch)
     self._lock.acquire()
     try:
         msg = Message()
         msg.add_int(self.request_number)
         for item in arg:
             if isinstance(item, long):
                 msg.add_int64(item)
             elif isinstance(item, int):
                 msg.add_int(item)
             elif isinstance(item, (string_types, bytes_types)):
                 msg.add_string(item)
             elif isinstance(item, SFTPAttributes):
                 item._pack(msg)
             else:
                 raise Exception(
                     'unknown type for %r type %r' % (item, type(item)))
         num = self.request_number
         self._expecting[num] = fileobj
         self.request_number += 1
     finally:
         self._lock.release()
     self._send_packet(t, msg)
     return num
Exemple #13
0
 def send_ext_data(self, data):
     m = Message()
     m.add_byte(byte_chr(SSH2_MSG_CHANNEL_EXTENDED_DATA))
     m.add_int(self.channel.remote_chanid)
     m.add_int(SSH2_EXTENDED_DATA_STDERR)
     m.add_string(data)
     self.channel.transport._send_user_message(m)
Exemple #14
0
 def send_stderr(self, s):
     """
     Send data to the channel on the "stderr" stream.  This is normally
     only used by servers to send output from shell commands -- clients
     won't use this.  Returns the number of bytes sent, or 0 if the channel
     stream is closed.  Applications are responsible for checking that all
     data has been sent: if only some of the data was transmitted, the
     application needs to attempt delivery of the remaining data.
     
     :param str s: data to send.
     :return: number of bytes actually sent, as an `int`.
     
     :raises socket.timeout:
         if no data could be sent before the timeout set by `settimeout`.
     
     .. versionadded:: 1.1
     """
     size = len(s)
     self.lock.acquire()
     try:
         size = self._wait_for_send_window(size)
         if size == 0:
             # eof or similar
             return 0
         m = Message()
         m.add_byte(chr(MSG_CHANNEL_EXTENDED_DATA))
         m.add_int(self.remote_chanid)
         m.add_int(1)
         m.add_string(s[:size])
     finally:
         self.lock.release()
     # Note: We release self.lock before calling _send_user_message.
     # Otherwise, we can deadlock during re-keying.
     self.transport._send_user_message(m)
     return size
Exemple #15
0
    def send(self, s):
        """
        Send data to the channel.  Returns the number of bytes sent, or 0 if
        the channel stream is closed.  Applications are responsible for
        checking that all data has been sent: if only some of the data was
        transmitted, the application needs to attempt delivery of the remaining
        data.

        @param s: data to send
        @type s: str
        @return: number of bytes actually sent
        @rtype: int

        @raise socket.timeout: if no data could be sent before the timeout set
            by L{settimeout}.
        """
        size = len(s)
        self.lock.acquire()
        try:
            size = self._wait_for_send_window(size)
            if size == 0:
                # eof or similar
                return 0
            m = Message()
            m.add_byte(chr(MSG_CHANNEL_DATA))
            m.add_int(self.remote_chanid)
            m.add_string(s[:size])
        finally:
            self.lock.release()
        # Note: We release self.lock before calling _send_user_message.
        # Otherwise, we can deadlock during re-keying.
        self.transport._send_user_message(m)
        return size
Exemple #16
0
def generate_key_pair(request):
    """
    Response to generate private/public RSA key pair
    """

    get_user(request, settings.ASTAKOS_AUTH_URL)

    if request.method != "POST":
        return http.HttpResponseNotAllowed(["POST"])

    if not SUPPORT_GENERATE_KEYS:
        raise Exception("Application does not support ssh keys generation")

    if PublicKeyPair.user_limit_exceeded(request.user_uniq):
        return http.HttpResponseServerError("SSH keys limit exceeded")

    # generate RSA key
    from Crypto import Random
    Random.atfork()

    key = rsakey.RSA.generate(SSH_KEY_LENGTH)

    # get PEM string
    pem = exportKey(key, 'PEM')

    public_data = Message()
    public_data.add_string('ssh-rsa')
    public_data.add_mpint(key.key.e)
    public_data.add_mpint(key.key.n)

    # generate public content
    public = str("ssh-rsa %s" % base64.b64encode(str(public_data)))

    data = {'private': pem, 'public': public}
    return http.HttpResponse(json.dumps(data), mimetype="application/json")
Exemple #17
0
    def resize_pty(self, width=80, height=24, width_pixels=0, height_pixels=0):
        """
        Resize the pseudo-terminal.  This can be used to change the width and
        height of the terminal emulation created in a previous `get_pty` call.

        :param int width: new width (in characters) of the terminal screen
        :param int height: new height (in characters) of the terminal screen
        :param int width_pixels: new width (in pixels) of the terminal screen
        :param int height_pixels: new height (in pixels) of the terminal screen

        :raises SSHException:
            if the request was rejected or the channel was closed
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('window-change')
        m.add_boolean(False)
        m.add_int(width)
        m.add_int(height)
        m.add_int(width_pixels)
        m.add_int(height_pixels)
        self.transport._send_user_message(m)
Exemple #18
0
 def invoke_shell(self):
     """
     Request an interactive shell session on this channel.  If the server
     allows it, the channel will then be directly connected to the stdin,
     stdout, and stderr of the shell.
     
     Normally you would call L{get_pty} before this, in which case the
     shell will operate through the pty, and the channel will be connected
     to the stdin and stdout of the pty.
     
     When the shell exits, the channel will be closed and can't be reused.
     You must open a new channel if you wish to open another shell.
     
     @raise SSHException: if the request was rejected or the channel was
         closed
     """
     if self.closed or self.eof_received or self.eof_sent or not self.active:
         raise SSHException('Channel is not open')
     m = Message()
     m.add_byte(chr(MSG_CHANNEL_REQUEST))
     m.add_int(self.remote_chanid)
     m.add_string('shell')
     m.add_boolean(1)
     self.event.clear()
     self.transport._send_user_message(m)
     self._wait_for_event()
Exemple #19
0
    def send_datagram(self, s):
        """
        Send all data to the channel in one message.  Returns the number of bytes sent,
        or 0 if the channel stream is closed.

        @param s: data to send
        @type s: str
        @return: number of bytes actually sent (C{len(s)} or C{0})
        @rtype: int

        @raise socket.timeout: if no data could be sent before the timeout set
            by L{settimeout}.
        """
        self.lock.acquire()
        size = 0
        try:
            while size < len(s):
                size = self._wait_for_send_window(len(s), account = False)
            self.out_window_size -= len(s)
            m = Message()
            m.add_byte(chr(MSG_CHANNEL_DATA))
            m.add_int(self.remote_chanid)
            m.add_string(s)
        finally:
            self.lock.release()
        # Note: We release self.lock before calling _send_user_message.
        # Otherwise, we can deadlock during re-keying.
        self.transport._send_user_message(m)
        return size
Exemple #20
0
    def exec_command(self, command):
        """
        Execute a command on the server.  If the server allows it, the channel
        will then be directly connected to the stdin, stdout, and stderr of
        the command being executed.
        
        When the command finishes executing, the channel will be closed and
        can't be reused.  You must open a new channel if you wish to execute
        another command.

        @param command: a shell command to execute.
        @type command: str

        @raise SSHException: if the request was rejected or the channel was
            closed
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('exec')
        m.add_boolean(True)
        m.add_string(command)
        self.event.clear()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #21
0
    def invoke_subsystem(self, subsystem):
        """
        Request a subsystem on the server (for example, C{sftp}).  If the
        server allows it, the channel will then be directly connected to the
        requested subsystem.
        
        When the subsystem finishes, the channel will be closed and can't be
        reused.

        @param subsystem: name of the subsystem being requested.
        @type subsystem: str

        @raise SSHException: if the request was rejected or the channel was
            closed
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('subsystem')
        m.add_boolean(True)
        m.add_string(subsystem)
        self.event.clear()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #22
0
    def resize_pty(self, width=80, height=24):
        """
        Resize the pseudo-terminal.  This can be used to change the width and
        height of the terminal emulation created in a previous L{get_pty} call.

        @param width: new width (in characters) of the terminal screen
        @type width: int
        @param height: new height (in characters) of the terminal screen
        @type height: int

        @raise SSHException: if the request was rejected or the channel was
            closed
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('window-change')
        m.add_boolean(True)
        m.add_int(width)
        m.add_int(height)
        m.add_int(0).add_int(0)
        self.event.clear()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #23
0
    def exec_command(self, command):
        """
        Execute a command on the server.  If the server allows it, the channel
        will then be directly connected to the stdin, stdout, and stderr of
        the command being executed.

        When the command finishes executing, the channel will be closed and
        can't be reused.  You must open a new channel if you wish to execute
        another command.

        :param str command: a shell command to execute.

        :raises:
            `.SSHException` -- if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string("exec")
        m.add_boolean(True)
        m.add_string(command)
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #24
0
 def __bytes__(self):
     m = Message()
     m.add_string(b'ssh-dss')
     m.add_mpint(self.p)
     m.add_mpint(self.q)
     m.add_mpint(self.g)
     m.add_mpint(self.y)
     return bytes(m)
Exemple #25
0
 def _disconnect_no_more_auth(self):
     m = Message()
     m.add_byte(chr(MSG_DISCONNECT))
     m.add_int(DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE)
     m.add_string('No more auth methods available')
     m.add_string('en')
     self.transport._send_message(m)
     self.transport.close()
Exemple #26
0
 def sign_ssh_data(self, rpool, data):
     digest = SHA.new(data).digest()
     rsa = RSA.construct((long(self.n), long(self.e), long(self.d)))
     sig = util.deflate_long(rsa.sign(self._pkcs1imify(digest), bytes())[0], 0)
     m = Message()
     m.add_string('ssh-rsa')
     m.add_string(sig)
     return m
Exemple #27
0
 def sign_ssh_data(self, rpool, data):
     digest = SHA256.new(data).digest()
     sig = self.signing_key.sign_digest(digest, entropy=rpool.read,
                                        sigencode=self._sigencode)
     m = Message()
     m.add_string('ecdsa-sha2-nistp256')
     m.add_string(sig)
     return m
Exemple #28
0
 def asbytes(self):
     m = Message()
     m.add_string('ssh-dss')
     m.add_mpint(self.p)
     m.add_mpint(self.q)
     m.add_mpint(self.g)
     m.add_mpint(self.y)
     return m.asbytes()
Exemple #29
0
 def _disconnect_service_not_available(self):
     m = Message()
     m.add_byte(chr(MSG_DISCONNECT))
     m.add_int(DISCONNECT_SERVICE_NOT_AVAILABLE)
     m.add_string('Service not available')
     m.add_string('en')
     self.transport._send_message(m)
     self.transport.close()
Exemple #30
0
 def __str__(self):
     m = Message()
     m.add_string("ssh-dss")
     m.add_mpint(self.p)
     m.add_mpint(self.q)
     m.add_mpint(self.g)
     m.add_mpint(self.y)
     return str(m)
Exemple #31
0
 def send_stderr(self, s):
     """
     Send data to the channel on the "stderr" stream.  This is normally
     only used by servers to send output from shell commands -- clients
     won't use this.  Returns the number of bytes sent, or 0 if the channel
     stream is closed.  Applications are responsible for checking that all
     data has been sent: if only some of the data was transmitted, the
     application needs to attempt delivery of the remaining data.
     
     @param s: data to send.
     @type s: str
     @return: number of bytes actually sent.
     @rtype: int
     
     @raise socket.timeout: if no data could be sent before the timeout set
         by L{settimeout}.
     
     @since: 1.1
     """
     size = len(s)
     self.lock.acquire()
     try:
         size = self._wait_for_send_window(size)
         if size == 0:
             # eof or similar
             return 0
         m = Message()
         m.add_byte(chr(MSG_CHANNEL_EXTENDED_DATA))
         m.add_int(self.remote_chanid)
         m.add_int(1)
         m.add_string(s[:size])
     finally:
         self.lock.release()
     # Note: We release self.lock before calling _send_user_message.
     # Otherwise, we can deadlock during re-keying.
     self.transport._send_user_message(m)
     return size
Exemple #32
0
def _parse_ecdsa_key(msg):
    # See comment for _parse_rsa_key
    key_msg = Message()
    curve = msg.get_text()
    key_msg.add_string('ecdsa-sha2-{}'.format(curve))
    key_msg.add_string(curve)
    key_msg.add_string(msg.get_binary())
    key_msg.rewind()
    return ECDSAKey(msg=key_msg)
Exemple #33
0
    def _parse_kexgss_init(self, m):
        """
        Parse the SSH2_MSG_KEXGSS_INIT message (server mode).

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_INIT message
        """
        # server mode
        client_token = m.get_string()
        self.e = m.get_mpint()
        if (self.e < 1) or (self.e > self.P - 1):
            raise SSHException('Client kex "e" is out of range')
        K = pow(self.e, self.x, self.P)
        self.transport.host_key = NullHostKey()
        key = self.transport.host_key.__str__()
        # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K)
        hm = Message()
        hm.add(self.transport.remote_version, self.transport.local_version,
               self.transport.remote_kex_init, self.transport.local_kex_init)
        hm.add_string(key)
        hm.add_mpint(self.e)
        hm.add_mpint(self.f)
        hm.add_mpint(K)
        H = sha1(hm.asbytes()).digest()
        self.transport._set_K_H(K, H)
        srv_token = self.kexgss.ssh_accept_sec_context(self.gss_host,
                                                       client_token)
        m = Message()
        if self.kexgss._gss_srv_ctxt_status:
            mic_token = self.kexgss.ssh_get_mic(self.transport.session_id,
                                                gss_kex=True)
            m.add_byte(c_MSG_KEXGSS_COMPLETE)
            m.add_mpint(self.f)
            m.add_string(mic_token)
            if srv_token is not None:
                m.add_boolean(True)
                m.add_string(srv_token)
            else:
                m.add_boolean(False)
            self.transport._send_message(m)
            self.transport._activate_outbound()
        else:
            m.add_byte(c_MSG_KEXGSS_CONTINUE)
            m.add_string(srv_token)
            self.transport._send_message(m)
            self.transport._expect_packet(MSG_KEXGSS_CONTINUE,
                                          MSG_KEXGSS_COMPLETE,
                                          MSG_KEXGSS_ERROR)
Exemple #34
0
    def _parse_kexgss_complete(self, m):
        """
        Parse the SSH2_MSG_KEXGSS_COMPLETE message (client mode).

        :param `.Message` m: The content of the SSH2_MSG_KEXGSS_COMPLETE message
        """
        # client mode
        if self.transport.host_key is None:
            self.transport.host_key = NullHostKey()
        self.f = m.get_mpint()
        if (self.f < 1) or (self.f > self.P - 1):
            raise SSHException('Server kex "f" is out of range')
        mic_token = m.get_string()
        # This must be TRUE, if there is a GSS-API token in this message.
        bool = m.get_boolean()
        srv_token = None
        if bool:
            srv_token = m.get_string()
        K = pow(self.f, self.x, self.P)
        # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || e || f || K)
        hm = Message()
        hm.add(self.transport.local_version, self.transport.remote_version,
        self.transport.local_kex_init, self.transport.remote_kex_init)
        hm.add_string(self.transport.host_key.__str__())
        hm.add_mpint(self.e)
        hm.add_mpint(self.f)
        hm.add_mpint(K)
        self.transport._set_K_H(K, sha1(str(hm)).digest())
        if srv_token is not None:
            self.kexgss.ssh_init_sec_context(target=self.gss_host,
                                             recv_token=srv_token)
            self.kexgss.ssh_check_mic(mic_token,
                                      self.transport.session_id)
        else:
            self.kexgss.ssh_check_mic(mic_token,
                                      self.transport.session_id)
        self.transport._activate_outbound()
    def sign_ssh_data(self, data, algorithm=None):
        key = dsa.DSAPrivateNumbers(
            x=self.x,
            public_numbers=dsa.DSAPublicNumbers(
                y=self.y,
                parameter_numbers=dsa.DSAParameterNumbers(
                    p=self.p, q=self.q, g=self.g
                ),
            ),
        ).private_key(backend=default_backend())
        sig = key.sign(data, hashes.SHA1())
        r, s = decode_dss_signature(sig)

        m = Message()
        m.add_string("ssh-dss")
        # apparently, in rare cases, r or s may be shorter than 20 bytes!
        rstr = util.deflate_long(r, 0)
        sstr = util.deflate_long(s, 0)
        if len(rstr) < 20:
            rstr = zero_byte * (20 - len(rstr)) + rstr
        if len(sstr) < 20:
            sstr = zero_byte * (20 - len(sstr)) + sstr
        m.add_string(rstr + sstr)
        return m
Exemple #36
0
 def _parse_kexdh_reply(self, m):
     # client mode
     host_key = m.get_string()
     self.f = m.get_mpint()
     if (self.f < 1) or (self.f > self.P - 1):
         raise SSHException('Server kex "f" is out of range')
     sig = m.get_binary()
     K = pow(self.f, self.x, self.P)
     # okay, build up the hash H of
     # (V_C || V_S || I_C || I_S || K_S || e || f || K)
     hm = Message()
     hm.add(
         self.transport.local_version,
         self.transport.remote_version,
         self.transport.local_kex_init,
         self.transport.remote_kex_init,
     )
     hm.add_string(host_key)
     hm.add_mpint(self.e)
     hm.add_mpint(self.f)
     hm.add_mpint(K)
     self.transport._set_K_H(K, sha1(hm.asbytes()).digest())
     self.transport._verify_key(host_key, sig)
     self.transport._activate_outbound()
Exemple #37
0
 def _async_request(self, fileobj, t, *arg):
     # this method may be called from other threads (prefetch)
     self._lock.acquire()
     try:
         msg = Message()
         msg.add_int(self.request_number)
         for item in arg:
             if isinstance(item, long):
                 msg.add_int64(item)
             elif isinstance(item, int):
                 msg.add_int(item)
             elif isinstance(item, (string_types, bytes_types)):
                 msg.add_string(item)
             elif isinstance(item, SFTPAttributes):
                 item._pack(msg)
             else:
                 raise Exception('unknown type for %r type %r' % (item, type(item)))
         num = self.request_number
         self._expecting[num] = fileobj
         self._send_packet(t, msg)
         self.request_number += 1
     finally:
         self._lock.release()
     return num
Exemple #38
0
    def request_forward_agent(self, handler):
        """
        Request for a forward SSH Agent on this channel.
        This is only valid for an ssh-agent from openssh !!!

        @param handler: a required handler to use for incoming SSH Agent connections
        @type handler: function

        @return: if we are ok or not (at that time we always return ok)
        @rtype: boolean

        @raise: SSHException in case of channel problem.
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')

        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('*****@*****.**')
        m.add_boolean(False)
        self.transport._send_user_message(m)
        self.transport._set_forward_agent_handler(handler)
        return True
Exemple #39
0
    def resize_pty(self, width=80, height=24, width_pixels=0, height_pixels=0):
        """
        Resize the pseudo-terminal.  This can be used to change the width and
        height of the terminal emulation created in a previous `get_pty` call.

        :param int width: new width (in characters) of the terminal screen
        :param int height: new height (in characters) of the terminal screen
        :param int width_pixels: new width (in pixels) of the terminal screen
        :param int height_pixels: new height (in pixels) of the terminal screen

        :raises:
            `.SSHException` -- if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string('window-change')
        m.add_boolean(False)
        m.add_int(width)
        m.add_int(height)
        m.add_int(width_pixels)
        m.add_int(height_pixels)
        self.transport._send_user_message(m)
Exemple #40
0
    def exec_command(self, command):
        """
        Execute a command on the server.  If the server allows it, the channel
        will then be directly connected to the stdin, stdout, and stderr of
        the command being executed.

        When the command finishes executing, the channel will be closed and
        can't be reused.  You must open a new channel if you wish to execute
        another command.

        :param str command: a shell command to execute.

        :raises SSHException: if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string('exec')
        m.add_boolean(True)
        m.add_string(command)
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #41
0
 def _parse_userauth_gssapi_token(self, m):
     client_token = m.get_string()
     # use the client token as input to establish a secure
     # context.
     sshgss = self.sshgss
     try:
         token = sshgss.ssh_accept_sec_context(self.gss_host, client_token,
                                               self.auth_username)
     except Exception as e:
         self.transport.saved_exception = e
         result = AUTH_FAILED
         self._restore_delegate_auth_handler()
         self._send_auth_result(self.auth_username, self.method, result)
         raise
     if token is not None:
         m = Message()
         m.add_byte(cMSG_USERAUTH_GSSAPI_TOKEN)
         m.add_string(token)
         self.transport._expected_packet = (
             MSG_USERAUTH_GSSAPI_TOKEN,
             MSG_USERAUTH_GSSAPI_MIC,
             MSG_USERAUTH_REQUEST,
         )
         self.transport._send_message(m)
Exemple #42
0
    def invoke_shell(self):
        """
        Request an interactive shell session on this channel.  If the server
        allows it, the channel will then be directly connected to the stdin,
        stdout, and stderr of the shell.

        Normally you would call `get_pty` before this, in which case the
        shell will operate through the pty, and the channel will be connected
        to the stdin and stdout of the pty.

        When the shell exits, the channel will be closed and can't be reused.
        You must open a new channel if you wish to open another shell.

        :raises SSHException: if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string('shell')
        m.add_boolean(True)
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #43
0
 def _parse_kexdh_gex_init(self, m):
     self.e = m.get_mpint()
     if (self.e < 1) or (self.e > self.p - 1):
         raise SSHException('Client kex "e" is out of range')
     self._generate_x()
     self.f = pow(self.g, self.x, self.p)
     K = pow(self.e, self.x, self.p)
     key = str(self.transport.get_server_key())
     # okay, build up the hash H of (V_C || V_S || I_C || I_S || K_S || min || n || max || p || g || e || f || K)
     hm = Message()
     hm.add(self.transport.remote_version, self.transport.local_version,
            self.transport.remote_kex_init, self.transport.local_kex_init,
            key)
     if not self.old_style:
         hm.add_int(self.min_bits)
     hm.add_int(self.preferred_bits)
     if not self.old_style:
         hm.add_int(self.max_bits)
     hm.add_mpint(self.p)
     hm.add_mpint(self.g)
     hm.add_mpint(self.e)
     hm.add_mpint(self.f)
     hm.add_mpint(K)
     H = SHA.new(str(hm)).digest()
     self.transport._set_K_H(K, H)
     # sign it
     sig = self.transport.get_server_key().sign_ssh_data(
         self.transport.rng, H)
     # send reply
     m = Message()
     m.add_byte(chr(_MSG_KEXDH_GEX_REPLY))
     m.add_string(key)
     m.add_mpint(self.f)
     m.add_string(str(sig))
     self.transport._send_message(m)
     self.transport._activate_outbound()
Exemple #44
0
    def invoke_subsystem(self, subsystem):
        """
        Request a subsystem on the server (for example, ``sftp``).  If the
        server allows it, the channel will then be directly connected to the
        requested subsystem.

        When the subsystem finishes, the channel will be closed and can't be
        reused.

        :param str subsystem: name of the subsystem being requested.

        :raises:
            `.SSHException` -- if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string('subsystem')
        m.add_boolean(True)
        m.add_string(subsystem)
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #45
0
    def close_session(self, channel, status=0):
        # pylint: disable=protected-access
        if channel.closed:
            return

        if not channel.exit_status_ready():
            message = Message()
            message.add_byte(cMSG_CHANNEL_REQUEST)
            message.add_int(channel.remote_chanid)
            message.add_string("exit-status")
            message.add_boolean(False)
            message.add_int(status)
            channel.transport._send_user_message(message)

        if not channel.eof_received:
            message = Message()
            message.add_byte(cMSG_CHANNEL_EOF)
            message.add_int(channel.remote_chanid)
            channel.transport._send_user_message(message)

            message = Message()
            message.add_byte(cMSG_CHANNEL_REQUEST)
            message.add_int(channel.remote_chanid)
            message.add_string('*****@*****.**')
            message.add_boolean(False)
            channel.transport._send_user_message(message)

        message = Message()
        message.add_byte(cMSG_CHANNEL_CLOSE)
        message.add_int(channel.remote_chanid)
        channel.transport._send_user_message(message)

        channel._unlink()

        super(SCPBaseForwarder, self).close_session(channel)
        logging.debug("[chan %d] SCP closed", channel.get_id())
 def _async_request(self, fileobj, t, *arg):
     # this method may be called from other threads (prefetch)
     self._lock.acquire()
     try:
         msg = Message()
         msg.add_int(self.request_number)
         for item in arg:
             if isinstance(item, long):
                 msg.add_int64(item)
             elif isinstance(item, int):
                 msg.add_int(item)
             elif isinstance(item, SFTPAttributes):
                 item._pack(msg)
             else:
                 # For all other types, rely on as_string() to either coerce
                 # to bytes before writing or raise a suitable exception.
                 msg.add_string(item)
         num = self.request_number
         self._expecting[num] = fileobj
         self.request_number += 1
     finally:
         self._lock.release()
     self._send_packet(t, msg)
     return num
Exemple #47
0
 def start_kex(self):
     """
     Start the GSS-API / SSPI Authenticated Diffie-Hellman Key Exchange.
     """
     self.transport.gss_kex_used = True
     self._generate_x()
     if self.transport.server_mode:
         # compute f = g^x mod p, but don't send it yet
         self.f = pow(self.G, self.x, self.P)
         self.transport._expect_packet(MSG_KEXGSS_INIT)
         return
     # compute e = g^x mod p (where g=2), and send it
     self.e = pow(self.G, self.x, self.P)
     # Initialize GSS-API Key Exchange
     self.gss_host = self.transport.gss_host
     m = Message()
     m.add_byte(c_MSG_KEXGSS_INIT)
     m.add_string(self.kexgss.ssh_init_sec_context(target=self.gss_host))
     m.add_mpint(self.e)
     self.transport._send_message(m)
     self.transport._expect_packet(MSG_KEXGSS_HOSTKEY,
                                   MSG_KEXGSS_CONTINUE,
                                   MSG_KEXGSS_COMPLETE,
                                   MSG_KEXGSS_ERROR)
Exemple #48
0
    def __str__(self):
        key = self.verifying_key
        m = Message()
        m.add_string('ecdsa-sha2-nistp256')
        m.add_string('nistp256')

        point_str = "\x04" + key.to_string()

        m.add_string(point_str)
        return str(m)
Exemple #49
0
    def asbytes(self):
        key = self.verifying_key
        m = Message()
        m.add_string('ecdsa-sha2-nistp256')
        m.add_string('nistp256')

        point_str = four_byte + key.to_string()

        m.add_string(point_str)
        return m.asbytes()
Exemple #50
0
    def add_key_cert(self, key, cert):
        if not key.can_sign():
            err = "Key cannot be used for signing or added to the agent {}"
            raise SSHException(err)

        if cert.valid_before < certificate.MAX_CERT_VALID_BEFORE:
            req_type = SSH2_AGENTC_ADD_ID_CONSTRAINED
            time_left = int(cert.valid_before - time.time())
        else:
            req_type = SSH2_AGENTC_ADD_IDENTITY
            time_left = None

        msg = Message()
        msg.add_byte(req_type)
        msg.add_string(cert.get_name())
        msg.add_string(cert.asbytes())

        if type(key) == RSAKey:
            # Convert private key to a cryptography key class. This is to get
            # around the variations in how paramiko handles keys internally
            buf = StringIO()
            key.write_private_key(buf)
            buf.seek(0)
            backend = default_backend()
            new_key = serialization.load_pem_private_key(str(buf.read()),
                                                         password=None,
                                                         backend=backend)
            priv_numbers = new_key.private_numbers()
            msg.add_mpint(priv_numbers.d)
            msg.add_mpint(priv_numbers.iqmp)
            msg.add_mpint(priv_numbers.p)
            msg.add_mpint(priv_numbers.q)
        elif type(key) == DSSKey:
            msg.add_mpint(key.x)
        elif type(key) == ECDSAKey:
            msg.add_mpint(key.signing_key.privkey.secret_multiplier)

        msg.add_string(cert.key_id)

        if time_left:
            msg.add_byte(SSH_AGENT_CONSTRAIN_LIFETIME)
            msg.add_int(time_left)

        restype, res = self._send_message(msg)
        if restype != SSH_AGENT_SUCCESS:
            return False
        return True
Exemple #51
0
    def asbytes(self):
        key = self.verifying_key
        numbers = key.public_numbers()
        key_size_bytes = (key.curve.key_size + 7) // 8

        x_bytes = deflate_long(numbers.x, add_sign_padding=False)
        x_bytes = b'\x00' * (key_size_bytes - len(x_bytes)) + x_bytes
        y_bytes = deflate_long(numbers.y, add_sign_padding=False)
        y_bytes = b'\x00' * (key_size_bytes - len(y_bytes)) + y_bytes

        point_str = four_byte + x_bytes + y_bytes

        m = Message()
        m.add_string(self.ecdsa_curve.key_format_identifier)
        m.add_string(self.ecdsa_curve.nist_name)
        m.add_string(point_str)
        return m.asbytes()
Exemple #52
0
    def asbytes(self):
        key = self.verifying_key
        m = Message()
        m.add_string('ecdsa-sha2-nistp256')
        m.add_string('nistp256')

        numbers = key.public_numbers()

        x_bytes = deflate_long(numbers.x, add_sign_padding=False)
        x_bytes = b'\x00' * (len(x_bytes) - key.curve.key_size // 8) + x_bytes

        y_bytes = deflate_long(numbers.y, add_sign_padding=False)
        y_bytes = b'\x00' * (len(y_bytes) - key.curve.key_size // 8) + y_bytes

        point_str = four_byte + x_bytes + y_bytes
        m.add_string(point_str)
        return m.asbytes()
Exemple #53
0
 def _parse_service_request(self, m):
     service = m.get_text()
     if self.transport.server_mode and (service == 'ssh-userauth'):
         # accepted
         m = Message()
         m.add_byte(cMSG_SERVICE_ACCEPT)
         m.add_string(service)
         self.transport._send_message(m)
         banner, language = self.transport.server_object.get_banner()
         if banner:
             m = Message()
             m.add_byte(cMSG_USERAUTH_BANNER)
             m.add_string(banner)
             m.add_string(language)
             self.transport._send_message(m)
         return
     # dunno this one
     self._disconnect_service_not_available()
Exemple #54
0
    def get_pty(self,
                term='vt100',
                width=80,
                height=24,
                width_pixels=0,
                height_pixels=0):
        """
        Request a pseudo-terminal from the server.  This is usually used right
        after creating a client channel, to ask the server to provide some
        basic terminal semantics for a shell invoked with L{invoke_shell}.
        It isn't necessary (or desirable) to call this method if you're going
        to exectue a single command with L{exec_command}.

        @param term: the terminal type to emulate (for example, C{'vt100'})
        @type term: str
        @param width: width (in characters) of the terminal screen
        @type width: int
        @param height: height (in characters) of the terminal screen
        @type height: int
        @param width_pixels: width (in pixels) of the terminal screen
        @type width_pixels: int
        @param height_pixels: height (in pixels) of the terminal screen
        @type height_pixels: int
        
        @raise SSHException: if the request was rejected or the channel was
            closed
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('pty-req')
        m.add_boolean(True)
        m.add_string(term)
        m.add_int(width)
        m.add_int(height)
        m.add_int(width_pixels)
        m.add_int(height_pixels)
        m.add_string('')
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #55
0
 def _parse_kexecdh_reply(self, m):
     K_S = m.get_string()
     Q_S_bytes = m.get_string()
     self.Q_S = _ecdh_from_encoded_point(self.curve, Q_S_bytes)
     sig = m.get_binary()
     K = self.P.exchange(ec.ECDH(), self.Q_S)
     K = long(hexlify(K), 16)
     # compute exchange hash and verify signature
     hm = Message()
     hm.add(self.transport.local_version, self.transport.remote_version,
            self.transport.local_kex_init, self.transport.remote_kex_init)
     hm.add_string(K_S)
     # SEC1: V2.0  2.3.3 Elliptic-Curve-Point-to-Octet-String Conversion
     hm.add_string(_ecdh_public_bytes(self.Q_C))
     hm.add_string(Q_S_bytes)
     hm.add_mpint(K)
     self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
     self.transport._verify_key(K_S, sig)
     self.transport._activate_outbound()
Exemple #56
0
    def get_pty(
        self,
        term="vt100",
        width=80,
        height=24,
        width_pixels=0,
        height_pixels=0,
    ):
        """
        Request a pseudo-terminal from the server.  This is usually used right
        after creating a client channel, to ask the server to provide some
        basic terminal semantics for a shell invoked with `invoke_shell`.
        It isn't necessary (or desirable) to call this method if you're going
        to execute a single command with `exec_command`.

        :param str term: the terminal type to emulate
            (for example, ``'vt100'``)
        :param int width: width (in characters) of the terminal screen
        :param int height: height (in characters) of the terminal screen
        :param int width_pixels: width (in pixels) of the terminal screen
        :param int height_pixels: height (in pixels) of the terminal screen

        :raises:
            `.SSHException` -- if the request was rejected or the channel was
            closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string("pty-req")
        m.add_boolean(True)
        m.add_string(term)
        m.add_int(width)
        m.add_int(height)
        m.add_int(width_pixels)
        m.add_int(height_pixels)
        m.add_string(bytes())
        self._event_pending()
        self.transport._send_user_message(m)
        self._wait_for_event()
Exemple #57
0
    def get_pty(self, term='vt100', width=80, height=24):
        """
        Request a pseudo-terminal from the server.  This is usually used right
        after creating a client channel, to ask the server to provide some
        basic terminal semantics for a shell invoked with L{invoke_shell}.
        It isn't necessary (or desirable) to call this method if you're going
        to exectue a single command with L{exec_command}.

        @param term: the terminal type to emulate (for example, C{'vt100'}).
        @type term: str
        @param width: width (in characters) of the terminal screen
        @type width: int
        @param height: height (in characters) of the terminal screen
        @type height: int
        @return: C{True} if the operation succeeded; C{False} if not.
        @rtype: bool
        """
        if self.closed or self.eof_received or self.eof_sent or not self.active:
            raise SSHException('Channel is not open')
        m = Message()
        m.add_byte(chr(MSG_CHANNEL_REQUEST))
        m.add_int(self.remote_chanid)
        m.add_string('pty-req')
        m.add_boolean(True)
        m.add_string(term)
        m.add_int(width)
        m.add_int(height)
        # pixel height, width (usually useless)
        m.add_int(0).add_int(0)
        m.add_string('')
        self.event.clear()
        self.transport._send_user_message(m)
        while True:
            self.event.wait(0.1)
            if self.closed:
                return False
            if self.event.isSet():
                return True
Exemple #58
0
    def set_environment_variable(self, name, value):
        """
        Set the value of an environment variable.

        .. warning::
            The server may reject this request depending on its ``AcceptEnv``
            setting; such rejections will fail silently (which is common client
            practice for this particular request type). Make sure you
            understand your server's configuration before using!

        :param str name: name of the environment variable
        :param str value: value of the environment variable

        :raises SSHException:
            if the request was rejected or the channel was closed
        """
        m = Message()
        m.add_byte(cMSG_CHANNEL_REQUEST)
        m.add_int(self.remote_chanid)
        m.add_string('env')
        m.add_boolean(False)
        m.add_string(name)
        m.add_string(value)
        self.transport._send_user_message(m)
Exemple #59
0
    def test_1_encode(self):
        msg = Message()
        msg.add_int(23)
        msg.add_int(123789456)
        msg.add_string('q')
        msg.add_string('hello')
        msg.add_string('x' * 1000)
        self.assertEquals(str(msg), self.__a)

        msg = Message()
        msg.add_boolean(True)
        msg.add_boolean(False)
        msg.add_byte('\xf3')
        msg.add_bytes('\x00\x3f')
        msg.add_list(['huey', 'dewey', 'louie'])
        self.assertEquals(str(msg), self.__b)

        msg = Message()
        msg.add_int64(5)
        msg.add_int64(0xf5e4d3c2b109L)
        msg.add_mpint(17)
        msg.add_mpint(0xf5e4d3c2b109L)
        msg.add_mpint(-0x65e4d3c2b109L)
        self.assertEquals(str(msg), self.__c)
Exemple #60
0
    def _parse_kexc25519_reply(self, m):
        # client mode

        # 3 fields in response:
        #   - KEX host key
        #   - Ephemeral (Curve25519) key
        #   - Signature
        K_S = m.get_string()
        self.Q_S = x25519.X25519PublicKey.from_public_bytes(m.get_string())
        sig = m.get_binary()

        # Compute shared secret
        K = self.P.exchange(self.Q_S)
        K = long(hexlify(K), 16)

        hm = Message()
        hm.add(
            self.transport.local_version,
            self.transport.remote_version,
            self.transport.local_kex_init,
            self.transport.remote_kex_init,
        )

        # "hm" is used as the initial transport key
        hm.add_string(K_S)
        hm.add_string(
            self.Q_C.public_bytes(encoding=Encoding.Raw,
                                  format=PublicFormat.Raw))
        hm.add_string(
            self.Q_S.public_bytes(encoding=Encoding.Raw,
                                  format=PublicFormat.Raw))
        hm.add_mpint(K)
        self.transport._set_K_H(K, self.hash_algo(hm.asbytes()).digest())
        # Verify that server signed kex message with its own pubkey
        self.transport._verify_key(K_S, sig)
        self.transport._activate_outbound()