Example #1
0
    def login(self, server, username, password='', original_prompt=r'[#$]', login_timeout=10,
              auto_prompt_reset=True, sync_multiplier=1):
        cmd = 'telnet -l {} {}'.format(username, server)

        spawn._spawn(self, cmd)  # pylint: disable=protected-access
        i = self.expect('(?i)(?:password)', timeout=login_timeout)
        if i == 0:
            self.sendline(password)
            i = self.expect([original_prompt, 'Login incorrect'], timeout=login_timeout)
        else:
            raise pxssh.ExceptionPxssh('could not log in: did not see a password prompt')

        if i:
            raise pxssh.ExceptionPxssh('could not log in: password was incorrect')

        if not self.sync_original_prompt(sync_multiplier):
            self.close()
            raise pxssh.ExceptionPxssh('could not synchronize with original prompt')

        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                message = 'could not set shell prompt (recieved: {}, expected: {}).'
                raise pxssh.ExceptionPxssh(message.format(self.before, self.PROMPT))
        return True
Example #2
0
    def login(self, server, username, password='', login_timeout=10,
              auto_prompt_reset=True, sync_multiplier=1, port=23):
        args = ['telnet']
        if username is not None:
            args += ['-l', username]
        args += [server, str(port)]
        cmd = ' '.join(args)

        spawn._spawn(self, cmd)  # pylint: disable=protected-access

        if password is None:
            i = self.expect([self.original_prompt, 'Login timed out'], timeout=login_timeout)
        else:
            i = self.expect('(?i)(?:password)', timeout=login_timeout)
            if i == 0:
                self.sendline(password)
                i = self.expect([self.original_prompt, 'Login incorrect'], timeout=login_timeout)
            else:
                raise pxssh.ExceptionPxssh('could not log in: did not see a password prompt')

            if i:
                raise pxssh.ExceptionPxssh('could not log in: password was incorrect')

        if not self.sync_original_prompt(sync_multiplier):
            self.close()
            raise pxssh.ExceptionPxssh('could not synchronize with original prompt')

        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                message = 'could not set shell prompt (recieved: {}, expected: {}).'
                raise pxssh.ExceptionPxssh(message.format(self.before, self.PROMPT))
        return True
Example #3
0
 def adbLogin(self, device_id, original_prompt=r"[#$]"):
     """login process for android devices over adb"""
     adb_id = get_adb_id(device_id)
     subprocess.call(["adb", "-s", adb_id, "root"])
     time.sleep(2)
     subprocess.call(["adb", "-s", adb_id, "wait-for-device"])
     spawn._spawn(self, "adb -s " + adb_id + " shell")
     index = self.expect([original_prompt, TIMEOUT, EOF])
     if index == 1 or index == 2:
         return False
     return True
Example #4
0
    def login(self,
              server,
              username,
              password='',
              login_timeout=10,
              auto_prompt_reset=True,
              sync_multiplier=1,
              port=23):
        args = ['telnet']
        if username is not None:
            args += ['-l', username]
        args += [server, str(port)]
        cmd = ' '.join(args)

        spawn._spawn(self, cmd)  # pylint: disable=protected-access

        try:
            i = self.expect('(?i)(?:password)', timeout=login_timeout)
            if i == 0:
                self.sendline(password)
                i = self.expect([self.original_prompt, 'Login incorrect'],
                                timeout=login_timeout)
            if i:
                raise pxssh.ExceptionPxssh(
                    'could not log in: password was incorrect')
        except TIMEOUT:
            if not password:
                # No password promt before TIMEOUT & no password provided
                # so assume everything is okay
                pass
            else:
                raise pxssh.ExceptionPxssh(
                    'could not log in: did not see a password prompt')

        if not self.sync_original_prompt(sync_multiplier):
            self.close()
            raise pxssh.ExceptionPxssh(
                'could not synchronize with original prompt')

        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                message = 'could not set shell prompt (recieved: {}, expected: {}).'
                raise pxssh.ExceptionPxssh(
                    message.format(self.before, self.PROMPT))
        return True
Example #5
0
    def login(self, host, auto_prompt_reset=True):  # pylint: disable=arguments-differ
        """ Radically simplified login without the 'New certificate -- always accept it.' stuff."""

        self._original_host = host

        spawn._spawn(self, 'ssh', args=[host])  # pylint: disable=protected-access
        if not self.sync_original_prompt():
            self.close()
            raise pxssh.ExceptionPxssh('could not synchronize with original prompt')

        # We appear to be in.
        # Set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise pxssh.ExceptionPxssh('could not set shell prompt')

        return True
    def login(self,
              server,
              username,
              password='',
              original_prompt=r'[#$]',
              login_timeout=10,
              auto_prompt_reset=True,
              sync_multiplier=1,
              port=23):
        cmd = 'telnet -l {} {} {}'.format(username, server, port)

        spawn._spawn(self, cmd)  # pylint: disable=protected-access
        try:
            i = self.expect('(?i)(?:password)', timeout=login_timeout)
            if i == 0:
                self.sendline(password)
                i = self.expect([original_prompt, 'Login incorrect'],
                                timeout=login_timeout)
            if i:
                raise pxssh.ExceptionPxssh(
                    'could not log in: password was incorrect')
        except TIMEOUT:
            if not password:
                # There was no password prompt before TIMEOUT, and we didn't
                # have a password to enter. Assume everything is OK.
                pass
            else:
                raise pxssh.ExceptionPxssh(
                    'could not log in: did not see a password prompt')

        if not self.sync_original_prompt(sync_multiplier):
            self.close()
            raise pxssh.ExceptionPxssh(
                'could not synchronize with original prompt')

        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                message = 'could not set shell prompt (recieved: {}, expected: {}).'
                raise pxssh.ExceptionPxssh(
                    message.format(self.before, self.PROMPT))
        return True
Example #7
0
 def login(self,server,username,passwd,timeout=30):
     host=username+"@"+server
     cmd="sftp "+host
     spawn._spawn(self, cmd)
     try:
         i=self.expect(["Are you sure you want to continue connecting","Permanently added","password"],5)
         if i==0:
             self.sendline("yes")
             self.expect(["Are you sure you want to continue connecting","Permanently added","password"],5)
         if i==1:
             self.sendline("yes")
             self.expect(["Are you sure you want to continue connecting","Permanently added","password"],5)
         if i==2:
             self.sendline(passwd)
             self.expect(self.PROMPT,5)
     except pexpect.TIMEOUT:
         self.err_str=self.before 
         return Sftp.LOGIN_ERROR
     self.logined=True
     return Sftp.OP_OK
Example #8
0
    async def login(self,
                    host: str,
                    username=None,
                    password="",
                    login_timeout=10) -> bool:
        """Log into the Ruckus device."""
        spawn._spawn(self, f"ssh {host}")

        login_regex_array = [
            "Please login: "******"(?i)are you sure you want to continue connecting",
            EOF,
            TIMEOUT,
        ]

        i = await self.expect(login_regex_array,
                              timeout=login_timeout,
                              async_=True)
        if i == 1:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = await self.expect(login_regex_array,
                                  timeout=login_timeout,
                                  async_=True)
        if i == 2:
            raise ConnectionError(CONNECT_ERROR_EOF)
        if i == 3:
            raise ConnectionError(CONNECT_ERROR_TIMEOUT)

        self.sendline(username)

        await self.expect("Password: "******"> ", "Login incorrect"], async_=True)
        if i == 1:
            raise AuthenticationError(LOGIN_ERROR_LOGIN_INCORRECT)

        return True
Example #9
0
    def login(self,
              server,
              username=None,
              password='',
              terminal_type='ansi',
              original_prompt=r"[#$]",
              login_timeout=10,
              port=None,
              auto_prompt_reset=True,
              ssh_key=None,
              quiet=True,
              sync_multiplier=1,
              check_local_ip=True,
              password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
              ssh_tunnels={},
              spawn_local_ssh=True,
              sync_original_prompt=True,
              ssh_config=None,
              cmd='ssh'):
        '''This logs the user into the given server.

        It uses 'original_prompt' to try to find the prompt right after login.
        When it finds the prompt it immediately tries to reset the prompt to
        something more easily matched. The default 'original_prompt' is very
        optimistic and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.

        Set ``password_regex`` if there is a MOTD message with `password` in it.
        Changing this is like playing in traffic, don't (p)expect it to match straight
        away.

        If you require to connect to another SSH server from the your original SSH
        connection set ``spawn_local_ssh`` to `False` and this will use your current
        session to do so. Setting this option to `False` and not having an active session
        will trigger an error.

        Set ``ssh_key`` to a file path to an SSH private key to use that SSH key
        for the session authentication.
        Set ``ssh_key`` to `True` to force passing the current SSH authentication socket
        to the desired ``hostname``.

        Set ``ssh_config`` to a file path string of an SSH client config file to pass that
        file to the client to handle itself. You may set any options you wish in here, however
        doing so will require you to post extra information that you may not want to if you
        run into issues.

        Alter the ``cmd`` to change the ssh client used, or to prepend it with network
        namespaces. For example ```cmd="ip netns exec vlan2 ssh"``` to execute the ssh in
        network namespace named ```vlan```.
        '''

        session_regex_array = [
            "(?i)are you sure you want to continue connecting",
            original_prompt, password_regex, "(?i)permission denied",
            "(?i)terminal type", TIMEOUT
        ]
        session_init_regex_array = []
        session_init_regex_array.extend(session_regex_array)
        session_init_regex_array.extend(
            ["(?i)connection closed by remote host", EOF])

        ssh_options = ''.join(
            [" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
        if quiet:
            ssh_options = ssh_options + ' -q'
        if not check_local_ip:
            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if ssh_config is not None:
            if spawn_local_ssh and not os.path.isfile(ssh_config):
                raise ExceptionPxssh(
                    'SSH config does not exist or is not a file.')
            ssh_options = ssh_options + ' -F ' + ssh_config
        if port is not None:
            ssh_options = ssh_options + ' -p %s' % (str(port))
        if ssh_key is not None:
            # Allow forwarding our SSH key to the current session
            if ssh_key == True:
                ssh_options = ssh_options + ' -A'
            else:
                if spawn_local_ssh and not os.path.isfile(ssh_key):
                    raise ExceptionPxssh(
                        'private ssh key does not exist or is not a file.')
                ssh_options = ssh_options + ' -i %s' % (ssh_key)

        # SSH tunnels, make sure you know what you're putting into the lists
        # under each heading. Do not expect these to open 100% of the time,
        # The port you're requesting might be bound.
        #
        # The structure should be like this:
        # { 'local': ['2424:localhost:22'],  # Local SSH tunnels
        # 'remote': ['2525:localhost:22'],   # Remote SSH tunnels
        # 'dynamic': [8888] } # Dynamic/SOCKS tunnels
        if ssh_tunnels != {} and isinstance({}, type(ssh_tunnels)):
            tunnel_types = {'local': 'L', 'remote': 'R', 'dynamic': 'D'}
            for tunnel_type in tunnel_types:
                cmd_type = tunnel_types[tunnel_type]
                if tunnel_type in ssh_tunnels:
                    tunnels = ssh_tunnels[tunnel_type]
                    for tunnel in tunnels:
                        if spawn_local_ssh == False:
                            tunnel = quote(str(tunnel))
                        ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(
                            tunnel)

        if username is not None:
            ssh_options = ssh_options + ' -l ' + username
        elif ssh_config is None:
            raise TypeError('login() needs either a username or an ssh_config')
        else:  # make sure ssh_config has an entry for the server with a username
            with open(ssh_config, 'rt') as f:
                lines = [l.strip() for l in f.readlines()]

            server_regex = r'^Host\s+%s\s*$' % server
            user_regex = r'^User\s+\w+\s*$'
            config_has_server = False
            server_has_username = False
            for line in lines:
                if not config_has_server and re.match(server_regex, line,
                                                      re.IGNORECASE):
                    config_has_server = True
                elif config_has_server and 'hostname' in line.lower():
                    pass
                elif config_has_server and re.match(server_regex, line,
                                                    re.IGNORECASE):
                    server_has_username = False  # insurance
                    break  # we have left the relevant section
                elif config_has_server and re.match(user_regex, line,
                                                    re.IGNORECASE):
                    server_has_username = True
                    break

            if lines:
                del line

            del lines

            if not config_has_server:
                raise TypeError('login() ssh_config has no Host entry for %s' %
                                server)
            elif not server_has_username:
                raise TypeError('login() ssh_config has no user entry for %s' %
                                server)

        cmd += " %s %s" % (ssh_options, server)
        if self.debug_command_string:
            return (cmd)

        # Are we asking for a local ssh command or to spawn one in another session?
        if spawn_local_ssh:
            spawn._spawn(self, cmd)
        else:
            self.sendline(cmd)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        i = self.expect(session_init_regex_array, timeout=login_timeout)

        # First phase
        if i == 0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect(session_regex_array)
        if i == 2:  # password or passphrase
            self.sendline(password)
            i = self.expect(session_regex_array)
        if i == 4:
            self.sendline(terminal_type)
            i = self.expect(session_regex_array)
        if i == 7:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        if i == 0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "are you sure" prompt twice.')
        elif i == 1:  # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        elif i == 2:  # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i == 3:  # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i == 4:  # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "terminal type" prompt twice.')
        elif i == 5:  # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell prompt.
            pass
        elif i == 6:  # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else:  # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if sync_original_prompt:
            if not self.sync_original_prompt(sync_multiplier):
                self.close()
                raise ExceptionPxssh(
                    'could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt '
                                     '(received: %r, expected: %r).' % (
                                         self.before,
                                         self.PROMPT,
                                     ))
        return True
Example #10
0
    def login (self, server, username, password='', terminal_type='ansi',
                original_prompt=r"[#$]", login_timeout=10, port=None,
                auto_prompt_reset=True, ssh_key=None, quiet=True,
                sync_multiplier=1, check_local_ip=True):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        '''

        ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
        if quiet:
            ssh_options = ssh_options + ' -q'
        if not check_local_ip:
            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if port is not None:
            ssh_options = ssh_options + ' -p %s'%(str(port))
        if ssh_key is not None:
            try:
                os.path.isfile(ssh_key)
            except:
                raise ExceptionPxssh('private ssh key does not exist')
            ssh_options = ssh_options + ' -i %s' % (ssh_key)
        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        spawn._spawn(self, cmd)
        i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT, "(?i)connection closed by remote host", EOF], timeout=login_timeout)

        # First phase
        if i==0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==2: # password or passphrase
            self.sendline(password)
            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==4:
            self.sendline(terminal_type)
            i = self.expect(["(?i)are you sure you want to continue connecting", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==7:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        if i==0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
        elif i==1: # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        elif i==2: # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i==3: # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i==4: # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
        elif i==5: # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell prompt.
            pass
        elif i==6: # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else: # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if not self.sync_original_prompt(sync_multiplier):
            self.close()
            raise ExceptionPxssh('could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt '
                                     '(received: %r, expected: %r).' % (
                                         self.before, self.PROMPT,))
        return True
Example #11
0
def login_host_first_time(host,
                          user,
                          password,
                          new_password,
                          expect_fail=False,
                          timeout=120):
    cmd_expected = [
        (
            # 'ssh -l {} -o UserKnownHostsFile=/dev/null {}'.format(user, host),
            # 'ssh -t -q -l {} {}'.format(user, host),
            'ssh',
            ('Are you sure you want to continue connecting (yes/no)?', ),
            ('Failed to get "continue connecting" prompt', )),
        (
            'yes',
            ("{}@{}\'s password:"******"{}={}"'.format(k, v) for k, v in SSH_OPTS.items()])

                # cmd = '{} {} -l {} {}'.format(cmd, options, user, host)
                cmd = '{} {} -l {} {}'.format(cmd, options, user, host)
                LOG.info(
                    'first time login: sending cmd:{}, \nexpected:{}\n'.format(
                        cmd, expected_output))

                spawn._spawn(connect, cmd)
                connect.force_password = True
                first_cmd = False

            else:
                LOG.info('sending cmd:{}\n'.format(cmd))
                connect.sendline(cmd)

            all_output = list(expected_output + errors)
            LOG.info('expecting outputs:{}\n'.format(all_output))

            index = connect.expect(all_output)
            LOG.info('actually got: index:{}, output:{}\n\n'.format(
                index, all_output[index]))
            LOG.info('actually got: before:\n{}\nafter:{}\n\n'.format(
                connect.before, connect.after))
            if index >= len(expected_output):
                LOG.info(
                    'error: sent:{}, returned:{}, returned-index:{}\n'.format(
                        cmd, all_output[index], index))
                LOG.info('OUTPUT:before:{}\nafter:{}\n'.format(
                    connect.before, connect.after))
                if r'\(current\) UNIX password:'******'connection broke when expecting "\(current\) UNIX password:", take as good?'
                    )
                    return True, password
                break

            time.sleep(2)

    except Exception as e:
        message = 'failed to connect to {}, got error: {}\nbefore:{}\nafter:{}\n'.format(
            message, e, connect.before, connect.after)
        LOG.info(message)
        assert expect_fail, message

    else:
        LOG.info(
            'OK, logged in for the first time, new password set:{}\n'.format(
                new_password))
        LOG.info('close the connection')
        try:
            connect.logout()
        except Exception as e:
            LOG.info('got error when closing connection:{}\n'.format(e))

        wait_time = 180
        LOG.info('Wait {} seconds after change/reset the password of sysadmin'.
                 format(wait_time))
        time.sleep(wait_time)

        return True, new_password

    finally:
        pass
        # if close_at_exit:
        #     LOG.info('close ssh connection to {}'.format(host))
        #     connect.close()
    return False, ''
Example #12
0
def log_in_raw(host, user, password, expect_fail=False):
    message = ' host:{} as user:{} with password:{}\n'.format(
        host, user, password)
    LOG.info('logging onto {}, expecting failure:{}\n'.format(
        message, expect_fail))

    connect = get_pxssh_session()
    options = ' '.join(['-o {}={}'.format(k, v) for k, v in SSH_OPTS.items()])
    cmd = 'ssh {} -l {} {}'.format(options, user, host)
    # cmd = 'ssh -q -l {} {}'.format(user, host)
    LOG.info('send cmd:{}\n'.format(cmd))
    spawn._spawn(connect, cmd)
    connect.force_password = True

    index = connect.expect(
        ['Are you sure you want to continue connecting (yes/no)?'])
    if index != 0:
        LOG.info(
            'failed to get expected result from cmd, \ncmd:{}\nindex:{}\n'.
            format(cmd, index))

    cmd = 'yes'
    LOG.info('send cmd:{}\n'.format(cmd))
    connect.sendline(cmd)
    index = connect.expect(['password:'******'failed to get expected result from cmd, \ncmd:{}\nindex:{}\n'.
            format(cmd, index))

    LOG.info('send password:{}\n'.format(password))
    connect.sendline(password)
    prompt = Prompt.CONTROLLER_PROMPT
    error = 'Permission denied, please try again.'
    index = connect.expect([prompt, error])
    if index != 0:
        msg = '{}, got index:{}'.format(message, index)
        if not expect_fail:
            LOG.info('failed to get expected prompt, {}'.format(msg))
            assert False, 'failed to get expected/login, {}'.format(msg)
        else:
            LOG.info('as expected, failed to login, {}\n'.format(msg))
            return None
    else:
        msg = 'logged in, {}\noutput before:{}, after:{}\n'.format(
            message, connect.before, connect.after)
        if expect_fail:
            LOG.info('Error, expecting to fail but actually {}'.format(msg))
            assert False, 'Error, expecting to fail but actually {}'.format(
                msg)
        else:
            LOG.info('OK, logged in, will verify it, {}\n'.format(message))

            cmd = '(date; uuid; hostname; id; ifconfig | \grep 128.224 -B1 -A7) 2>/dev/null'
            LOG.info('send cmd: {}\n'.format(cmd))
            connect.sendline(cmd)
            index = connect.expect([prompt, TIMEOUT])
            LOG.info('returned:\nbefore:{}\nafter:{}\n'.format(
                connect.before, connect.after))
            if 1 == index:
                LOG.info('timeout:')
                return None

            return connect
    def login (self, server, username, password='', terminal_type='ansi',
                original_prompt=r"[#$]", login_timeout=10, port=None,
                auto_prompt_reset=True, ssh_key=None, quiet=True,
                sync_multiplier=1, check_local_ip=True,
                password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
                ssh_tunnels={}, spawn_local_ssh=True,
                sync_original_prompt=True, ssh_config=None):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        
        Set ``password_regex`` if there is a MOTD message with `password` in it.
        Changing this is like playing in traffic, don't (p)expect it to match straight
        away.
        
        If you require to connect to another SSH server from the your original SSH
        connection set ``spawn_local_ssh`` to `False` and this will use your current
        session to do so. Setting this option to `False` and not having an active session
        will trigger an error.
        
        Set ``ssh_key`` to a file path to an SSH private key to use that SSH key
        for the session authentication.
        Set ``ssh_key`` to `True` to force passing the current SSH authentication socket
        to the desired ``hostname``.
        
        Set ``ssh_config`` to a file path string of an SSH client config file to pass that
        file to the client to handle itself. You may set any options you wish in here, however
        doing so will require you to post extra information that you may not want to if you
        run into issues.
        '''
        
        session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT]
        session_init_regex_array = []
        session_init_regex_array.extend(session_regex_array)
        session_init_regex_array.extend(["(?i)connection closed by remote host", EOF])

        ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
        if quiet:
            ssh_options = ssh_options + ' -q'
        if not check_local_ip:
            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if ssh_config is not None:
            if spawn_local_ssh and not os.path.isfile(ssh_config):
                raise ExceptionPxssh('SSH config does not exist or is not a file.')
            ssh_options = ssh_options + '-F ' + ssh_config
        if port is not None:
            ssh_options = ssh_options + ' -p %s'%(str(port))
        if ssh_key is not None:
            # Allow forwarding our SSH key to the current session
            if ssh_key==True:
                ssh_options = ssh_options + ' -A'
            else:
                if spawn_local_ssh and not os.path.isfile(ssh_key):
                    raise ExceptionPxssh('private ssh key does not exist or is not a file.')
                ssh_options = ssh_options + ' -i %s' % (ssh_key)
        
        # SSH tunnels, make sure you know what you're putting into the lists
        # under each heading. Do not expect these to open 100% of the time,
        # The port you're requesting might be bound.
        #
        # The structure should be like this:
        # { 'local': ['2424:localhost:22'],  # Local SSH tunnels
        # 'remote': ['2525:localhost:22'],   # Remote SSH tunnels
        # 'dynamic': [8888] } # Dynamic/SOCKS tunnels
        if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)):
            tunnel_types = {
                'local':'L',
                'remote':'R',
                'dynamic':'D'
            }
            for tunnel_type in tunnel_types:
                cmd_type = tunnel_types[tunnel_type]
                if tunnel_type in ssh_tunnels:
                    tunnels = ssh_tunnels[tunnel_type]
                    for tunnel in tunnels:
                        if spawn_local_ssh==False:
                            tunnel = quote(str(tunnel))
                        ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel)
        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
        if self.debug_command_string:
            return(cmd)

        # Are we asking for a local ssh command or to spawn one in another session?
        if spawn_local_ssh:
            spawn._spawn(self, cmd)
        else:
            self.sendline(cmd)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        i = self.expect(session_init_regex_array, timeout=login_timeout)

        # First phase
        if i==0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect(session_regex_array)
        if i==2: # password or passphrase
            self.sendline(password)
            i = self.expect(session_regex_array)
        if i==4:
            self.sendline(terminal_type)
            i = self.expect(session_regex_array)
        if i==7:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        if i==0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
        elif i==1: # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        elif i==2: # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i==3: # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i==4: # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
        elif i==5: # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell prompt.
            pass
        elif i==6: # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else: # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if sync_original_prompt:
            if not self.sync_original_prompt(sync_multiplier):
                self.close()
                raise ExceptionPxssh('could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt '
                                     '(received: %r, expected: %r).' % (
                                         self.before, self.PROMPT,))
        return True
Example #14
0
    def login(
            self,
            server,
            username,
            password='',
            terminal_type='ansi',
            original_prompt=r"[#$]",
            login_timeout=10,
            port=None,
            auto_prompt_reset=True,
            ssh_key=None,
            quiet=True,
            sync_multiplier=1,
            check_local_ip=True,
            password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
            ssh_tunnels={},
            spawn_local_ssh=True,
            sync_original_prompt=True,
            ssh_config=None,
            cipher=None,
            host_key_changed_regex="(?i)WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED",
            no_cipher_found_regex="(?i)no matching cipher found|(?i)Unknown cipher type",
            host_key_check_regex="(?i)are you sure you want to continue connecting",
            access_denied_regex="(?i)access denied|(?i)permission denied",
            terminal_type_regex="(?i)terminal type",
            too_many_hosts_regex="(?i)maximum number of ssh sessions are active",
            connection_closed_regex="(?i)connection closed by remote host",
            verbose_level=0,
            check_kex_only=False,
            kex_filter_regex=r'(kex:\s.*[\s\S]?)'):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        
        Set ``password_regex`` if there is a MOTD message with `password` in it.
        Changing this is like playing in traffic, don't (p)expect it to match straight
        away.
        
        If you require to connect to another SSH server from the your original SSH
        connection set ``spawn_local_ssh`` to `False` and this will use your current
        session to do so. Setting this option to `False` and not having an active session
        will trigger an error.
        
        Set ``ssh_key`` to a file path to an SSH private key to use that SSH key
        for the session authentication.
        Set ``ssh_key`` to `True` to force passing the current SSH authentication socket
        to the desired ``hostname``.
        
        Set ``ssh_config`` to a file path string of an SSH client config file to pass that
        file to the client to handle itself. You may set any options you wish in here, however
        doing so will require you to post extra information that you may not want to if you
        run into issues.
        '''
        #[JB] - added line below due to Sonicwall password prompt difference in 6.1.x vs 6.2.x and access denied regex is not a option variable
        #session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT]
        session_regex_array = [
            host_key_changed_regex, no_cipher_found_regex,
            host_key_check_regex, original_prompt, password_regex,
            access_denied_regex, terminal_type_regex, TIMEOUT
        ]
        session_init_regex_array = []
        session_init_regex_array.extend(session_regex_array)
        session_init_regex_array.extend(
            [too_many_hosts_regex, connection_closed_regex, EOF])

        ssh_options = ''.join(
            [" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
        if quiet:
            ssh_options = ssh_options + ' -q'
        if not check_local_ip:
            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if ssh_config is not None:
            if spawn_local_ssh and not os.path.isfile(ssh_config):
                raise ExceptionPxssh(
                    'SSH config does not exist or is not a file.')
            ssh_options = ssh_options + '-F ' + ssh_config
        if port is not None:
            ssh_options = ssh_options + ' -p %s' % (str(port))
        if ssh_key is not None:
            # Allow forwarding our SSH key to the current session
            if ssh_key == True:
                ssh_options = ssh_options + ' -A'
            else:
                if spawn_local_ssh and not os.path.isfile(ssh_key):
                    raise ExceptionPxssh(
                        'private ssh key does not exist or is not a file.')
                ssh_options = ssh_options + ' -i %s' % (ssh_key)

        # SSH tunnels, make sure you know what you're putting into the lists
        # under each heading. Do not expect these to open 100% of the time,
        # The port you're requesting might be bound.
        #
        # The structure should be like this:
        # { 'local': ['2424:localhost:22'],  # Local SSH tunnels
        # 'remote': ['2525:localhost:22'],   # Remote SSH tunnels
        # 'dynamic': [8888] } # Dynamic/SOCKS tunnels
        if ssh_tunnels != {} and isinstance({}, type(ssh_tunnels)):
            tunnel_types = {'local': 'L', 'remote': 'R', 'dynamic': 'D'}
            for tunnel_type in tunnel_types:
                cmd_type = tunnel_types[tunnel_type]
                if tunnel_type in ssh_tunnels:
                    tunnels = ssh_tunnels[tunnel_type]
                    for tunnel in tunnels:
                        if spawn_local_ssh == False:
                            tunnel = quote(str(tunnel))
                        ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(
                            tunnel)
        #[JB] - added cipher option for ssh
        #cmd = "ssh %s -l %s %s" % (ssh_options, username, server)
        #cmd = "ssh %s -c %s -l %s %s" % (ssh_options, cipher, username, server)
        if cipher != None:
            cmd = "ssh %s -c %s " % (ssh_options, cipher)
        else:
            cmd = "ssh %s " % (ssh_options)

        if verbose_level == 1:
            cmd = cmd + "-v "
        elif verbose_level == 2:
            cmd = cmd + "-vv "
        elif verbose_level == 3:
            cmd = cmd + "-vvv "
        cmd = cmd + "-l %s %s" % (username, server)

        if self.debug_command_string:
            return (cmd)
        logging.debug('cmd=' + cmd)

        # Are we asking for a local ssh command or to spawn one in another session?
        if spawn_local_ssh:
            spawn._spawn(self, cmd)
        else:
            self.sendline(cmd)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        if check_kex_only:
            session_init_regex_array = [host_key_changed_regex, no_cipher_found_regex, host_key_check_regex, terminal_type_regex, \
                password_regex, access_denied_regex, TIMEOUT, too_many_hosts_regex, connection_closed_regex, EOF]
            kex_output = ""
            i = self.expect(session_init_regex_array, timeout=login_timeout)
            if i == 0:
                self.close()
                raise ExceptionPxsshHostKeyChanged('Host key changed')
            if i == 1:
                self.close()
                raise ExceptionPxsshNoCipherFound('No Cipher found')
            if i == 2:
                #kex_output = self.before + self.after
                kex_output = self.before.decode() + self.after.decode()
                self.sendline("yes")
                i = self.expect(session_init_regex_array,
                                timeout=login_timeout)
            if i == 3:
                #kex_output = self.before + self.after
                kex_output = self.before.decode() + self.after.decode()
                self.sendline(terminal_type)
                i = self.expect(session_init_regex_array,
                                timeout=login_timeout)

            # Second pass
            if i == 4:
                #kex_output = kex_output + self.before + self.after
                kex_output = kex_output + self.before.decode(
                ) + self.after.decode()
                kex_output_list = re.findall(kex_filter_regex, kex_output)
                kex_output_filtered = ''.join(kex_output_list)
                self.close()
                return kex_output_filtered
            if i == 5:
                self.close()
                raise ExceptionPxsshAccessDenied('access denied')
            if i == 6:
                self.close()
                raise ExceptionPxsshLoginTimeout('timeout')
            if i == 7:
                self.close()
                raise ExceptionPxsshMaxHostsExceeded('max hosts exceeded')
            if i == 8:
                self.close()
                raise ExceptionPxssh('connection closed')
            if i == 9:
                self.close()
                raise ExceptionPxssh('Could not establish connection to host')

            self.close()
            return ''

        else:
            i = self.expect(session_init_regex_array, timeout=login_timeout)
        # First phase
        if i == 0:
            raise ExceptionPxsshHostKeyChanged('Host key changed')
        if i == 1:
            self.close()
            raise ExceptionPxsshNoCipherFound('No Cipher found')
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #if i==0:
        if i == 2:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            #[JB] - added timeout variable to expect functions due to inconsistent timeout behavior & Sonicwall login banner behavior differences for several firewalls (extended time to receive "Access denied" message)
            #i = self.expect(session_regex_array)
            i = self.expect(session_regex_array, timeout=login_timeout)
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #if i==2: # password or passphrase
        if i == 4:  # password or passphrase
            self.sendline(password)
            #[JB] - added line below due to Sonicwall login banner and password prompt difference in 6.1.x vs 6.2.x
            session_regex_array = [host_key_changed_regex, no_cipher_found_regex, host_key_check_regex, original_prompt, \
                "do not check for password prompt again and update access denied string", access_denied_regex, terminal_type_regex, TIMEOUT]
            #[JB] - added timeout variable to expect functions due to inconsistent timeout behavior & Sonicwall login banner behavior differences for several firewalls (extended time to receive "Access denied" message)
            #i = self.expect(session_regex_array)
            i = self.expect(session_regex_array, timeout=login_timeout)
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #if i==4:
        if i == 6:
            self.sendline(terminal_type)
            #[JB] - added timeout variable to expect functions due to inconsistent timeout behavior & Sonicwall login banner behavior differences for several firewalls (extended time to receive "Access denied" message)
            #i = self.expect(session_regex_array)
            i = self.expect(session_regex_array, timeout=login_timeout)
        if i == 8:
            self.close()
            raise ExceptionPxsshMaxHostsExceeded('max hosts exceeded')
        if i == 9:
            self.close()
            raise ExceptionPxssh('Connection closed by host')
        #[JB] - Increase check of i by 2 to check for Host key change at i==0 and too many hosts at i==8
        #if i==7:
        if i == 10:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #if i==0:
        if i == 2:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "are you sure" prompt twice.')
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==1: # can occur if you have a public key pair set to authenticate.
        elif i == 3:  # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==2: # password prompt again
        elif i == 4:  # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==3: # permission denied -- password was bad.
        elif i == 5:  # permission denied -- password was bad.
            self.close()
            #[JB] - added specific exception for Access Denied
            #raise ExceptionPxssh('permission denied')
            raise ExceptionPxsshAccessDenied('access denied')
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==4: # terminal type again? WTF?
        elif i == 6:  # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "terminal type" prompt twice.')
        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==5: # Timeout
        elif i == 7:  # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell prompt.

            #[JB] - added timeout variable to expect functions due to inconsistent timeout behavior & Sonicwall login banner behavior differences for several firewalls (extended time to receive "Access denied" message)
            #pass - [JB] - not commented in parent function
            #raise ExceptionPxssh('timeout') - [JB] - commented in parent function; strange that the close function was after the raise exception command in parent, but both lines are commented
            #self.close() - [JB] - commented in parent function; strange that the close function was after the raise exception command in parent, but both lines are commented
            self.close()
            raise ExceptionPxsshLoginTimeout('timeout')

        #[JB] - Increase check of i by 2 to check for Host key change (i==0) & No Cipher found (i==1)
        #elif i==6: # Connection closed by remote host
        elif i == 8:  # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else:  # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if sync_original_prompt:
            if not self.sync_original_prompt(sync_multiplier):
                self.close()
                raise ExceptionPxssh(
                    'could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt '
                                     '(received: %r, expected: %r).' % (
                                         self.before,
                                         self.PROMPT,
                                     ))
        return True
Example #15
0
    def login (self,
               executable, options='',
               username='', password='',
               login_timeout=1,
               auto_prompt_reset=True,
               sync_multiplier=1):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        '''
        print("pxshell::login(%s,%s)" % (username, password))
        # archive the options
        self.login_timeout = login_timeout
        self.sync_multiplier = sync_multiplier        

        # double check
        if executable == '':
            raise ExceptionPxShell('Unconfigured child application: %s' % executable)

        # keep this simple in here
        cmd = executable + ' ' + options

        # fire it up.
        spawn._spawn(self, cmd)

        # run the login sequence...
        self._login_state_machine(username, password)

        # try to resolve the interface
        if not self.sync_original_prompt(self.sync_multiplier):
            self.close()
            raise ExceptionPxShell('could not synchronize with original prompt')

        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxShell('could not set shell prompt '
                                        '(recieved: %r, expected: %r).' % (
                                            self.before,
                                            self.interpreter.unique_prompt(),))

        # update to the prompt
        newinfo = self.prompt(timeout=0.1)
Example #16
0
    def login (self,server,username,password='',switch_port=23,terminal_type='ansi',original_prompt=r"[#$]",login_timeout=10,port=None,auto_prompt_reset=True,ssh_key=None):


        cmd = "telnet %s %d" % (server,switch_port)
        spawn._spawn(self, cmd)
        stage=0
        # stage=1 -> get "login:"******"password:"******"(%s)|(%s)|(%s)"%(login_en,login_zh_utf8,login_zh_gbk),
                    "(?i)connection closed by (remote)|(foreign) host",
                    "(?i)Connection refused",
                    TIMEOUT,EOF ]
                i = self.expect( exp_list, timeout=login_timeout)
                if i==0:
                    stage=1 # get the login: prompt
                    self.debug('get login prompt('+self.after+')')
                else:
                    exp_msg=str(exp_list[i])
                    self.close()
                    raise ExceptionPxtelnet(exp_msg)
            elif stage==1:
                self.sendline(username)
                exp_list=[
                    "(%s)|(%s)|(%s)"%(pass_en,pass_zh_utf8,pass_zh_gbk),
                    original_prompt,
                    "(?i)connection closed by (remote)|(foreign) host",
                    "(?i)Connection refused",
                    TIMEOUT,EOF]
                i = self.expect( exp_list, timeout=login_timeout)
                if i==0:
                    stage=2 # get the passwd: prompt
                    self.debug('get passwd prompt('+self.after+')')
                elif i==1:
                    stage=3 # no passwd,into shell
                    break
                else:
                    exp_msg=str(exp_list[i])
                    self.close()
                    raise ExceptionPxtelnet(exp_msg)
            elif stage==2:
                self.sendline(password)
                exp_list=[
                    original_prompt, 
                    "(3004-300)|(Login incorrect)",
                    "(?i)terminal type", 
                    TIMEOUT]
                i = self.expect( exp_list,timeout=login_timeout)
                if i==0:
                    stage=3
                    self.debug('get shell('+self.after+')')
                    break
                elif i==2: #require teminal type
                    self.sendline('vt100')
                else:
                    exp_msg=str(exp_list[i])+'|'+self.after
                    self.close()
                    raise ExceptionPxtelnet(exp_msg)
        if not self.sync_original_prompt():
            self.close()
            raise ExceptionPxtelnet ('could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxtelnet ('could not set shell prompt\n'+self.before)
        return True
Example #17
0
    def login(self,
              executable,
              options='',
              username='',
              password='',
              login_timeout=1,
              auto_prompt_reset=True,
              sync_multiplier=1):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        '''
        print("pxshell::login(%s,%s)" % (username, password))
        # archive the options
        self.login_timeout = login_timeout
        self.sync_multiplier = sync_multiplier

        # double check
        if executable == '':
            raise ExceptionPxShell('Unconfigured child application: %s' %
                                   executable)

        # keep this simple in here
        cmd = executable + ' ' + options

        # fire it up.
        spawn._spawn(self, cmd)

        # run the login sequence...
        self._login_state_machine(username, password)

        # try to resolve the interface
        if not self.sync_original_prompt(self.sync_multiplier):
            self.close()
            raise ExceptionPxShell(
                'could not synchronize with original prompt')

        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxShell('could not set shell prompt '
                                       '(recieved: %r, expected: %r).' % (
                                           self.before,
                                           self.interpreter.unique_prompt(),
                                       ))

        # update to the prompt
        newinfo = self.prompt(timeout=0.1)
Example #18
0
File: pxssh.py Project: sikopet/wtf
    def login(self,
              server,
              username,
              password='',
              terminal_type='ansi',
              original_prompt=r"[#$]",
              login_timeout=10,
              port=None,
              auto_prompt_reset=True):
        """This logs the user into the given server. It uses the
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called "~/.hushlogin" on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an ExceptionPxssh exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, set 'auto_prompt_reset' to False to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the prompt() method. If the original prompt is
        not reset then this will disable the prompt() method unless you
        manually set the PROMPT attribute. """

        ssh_options = '-q'
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if port is not None:
            ssh_options = ssh_options + ' -p %s' % (str(port))
        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        spawn._spawn(self, cmd)
        i = self.expect([
            "(?i)are you sure you want to continue connecting",
            original_prompt, "(?i)(?:password)|(?:passphrase for key)",
            "(?i)permission denied", "(?i)terminal type", TIMEOUT,
            "(?i)connection closed by remote host"
        ],
                        timeout=login_timeout)

        # First phase
        if i == 0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect([
                "(?i)are you sure you want to continue connecting",
                original_prompt, "(?i)(?:password)|(?:passphrase for key)",
                "(?i)permission denied", "(?i)terminal type", TIMEOUT
            ])
        if i == 2:  # password or passphrase
            self.sendline(password)
            i = self.expect([
                "(?i)are you sure you want to continue connecting",
                original_prompt, "(?i)(?:password)|(?:passphrase for key)",
                "(?i)permission denied", "(?i)terminal type", TIMEOUT
            ])
        if i == 4:
            self.sendline(terminal_type)
            i = self.expect([
                "(?i)are you sure you want to continue connecting",
                original_prompt, "(?i)(?:password)|(?:passphrase for key)",
                "(?i)permission denied", "(?i)terminal type", TIMEOUT
            ])

        # Second phase
        if i == 0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "are you sure" prompt twice.')
        # can occur if you have a public key pair set to authenticate.
        elif i == 1:
            # TODO: May NOT be OK if expect() got tricked and matched a false
            # prompt.
            pass
        elif i == 2:  # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i == 3:  # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i == 4:  # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh(
                'Weird error. Got "terminal type" prompt twice.')
        elif i == 5:  # Timeout
            # This is tricky... I presume that we are at the command-line prompt.
            # It may be that the shell prompt was so weird that we couldn't match
            # it. Or it may be that we couldn't log in for some other reason. I
            # can't be sure, but it's safe to guess that we did login because if
            # I presume wrong and we are not logged in then this should be caught
            # later when I try to set the shell prompt.
            pass
        elif i == 6:  # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else:  # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if not self.synch_original_prompt():
            self.close()
            raise ExceptionPxssh('could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt\n' +
                                     self.before)
        return True
Example #19
0
    def login(
        self,
        server='',
        username='',
        password='',
        terminal_type='ansi',
        original_prompt=r'[#$]',
        login_timeout=10,
        port=None,
        auto_prompt_reset=True,
        ssh_key=None,
        quiet=True,
        sync_multiplier=1,
        check_local_ip=True,
        password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
        ssh_tunnels={},
        spawn_local_ssh=True,
        sync_original_prompt=True,
        ssh_config=None,
        remove_known_hosts=False,
        ping_before_connect=True,
        attempt=1,
    ):
        '''Overrides login from parent class, add to find the prompt after the
        ssh connection is established if auto_prompt_reset is set to False.
        Otherwise, login() function set the ssh prompt to '[PEXPECT]$' by
        default.
        '''
        self.is_logged_in = False

        # Try connecting to the server if server is specified
        if server:
            # Retry specified attempts before raising exception
            for i in range(attempt):
                output = ''
                pattern = ''
                self.pid = None  # Set pid to None to avoid AssertionError: The pid member must be None.
                if ping_before_connect:
                    # Set ping command and expected pattern
                    cmd = 'ping -c4 {}'.format(server)
                    pattern = '4 received'
                    if self.verbose:
                        if i == 0:
                            log.debug(
                                '{}/{} attempt :\t"{}"\tpattern="{}"'.format(
                                    i + 1, attempt, cmd.strip(), pattern))
                        else:
                            log.debug(
                                '{}/{} attempts:\t"{}"\tpattern="{}"'.format(
                                    i + 1, attempt, cmd.strip(), pattern))
                    output = run(cmd, timeout=10, encoding=self.encoding)
                    # output = run(cmd, timeout=10).decode('utf-8')

                # Ping to make sure host is reachable before establish ssh connection
                if pattern in output:
                    if remove_known_hosts:
                        run('rm {}'.format(
                            os.path.expanduser('~/.ssh/known_hosts')),
                            timeout=5,
                            encoding=self.encoding)
                    try:
                        if not self.is_logged_in:
                            self.is_logged_in = super(Connection, self).login(
                                server,
                                username,
                                password=password,
                                terminal_type=terminal_type,
                                original_prompt=original_prompt,
                                login_timeout=login_timeout,
                                port=port,
                                auto_prompt_reset=auto_prompt_reset,
                                ssh_key=ssh_key,
                                quiet=quiet,
                                sync_multiplier=sync_multiplier,
                                check_local_ip=check_local_ip,
                                password_regex=password_regex,
                                ssh_tunnels=ssh_tunnels,
                                spawn_local_ssh=spawn_local_ssh,
                                sync_original_prompt=sync_original_prompt,
                                ssh_config=ssh_config,
                            )
                            # Get prompt upon login and set it as default prompt
                            self.PROMPT = self._get_prompt(original_prompt)
                    except:
                        if i + 1 >= attempt:
                            # if self.verbose:
                            # print('Unable to reach host {}, make sure host is reachable!'.format(server))
                            # raise pxssh.ExceptionPxssh('Unable to reach host {}, make sure host is reachable!'.format(server))
                            # import traceback
                            # traceback.print_exc()
                            log.exception(
                                'Unable to reach host {}, make sure host is reachable!'
                                .format(server))
                        continue
                    break
                else:
                    if i + 1 >= attempt:
                        # if self.verbose:
                        # print('Unable to reach host {}, make sure host is reachable!'.format(server))
                        # raise pxssh.ExceptionPxssh('Unable to reach host {}, make sure host is reachable!'.format(server))
                        # import traceback
                        # traceback.print_exc()
                        log.warning(
                            'Unable to reach host {}, make sure host is reachable!'
                            .format(server))
        # If server not specified, just run an instance of bash shell
        # Note: Useing ssh to localhost above would work in most cases, but in
        # the case where the login credential is not known, such as running in
        # another organization's environment.
        else:
            if remove_known_hosts:
                run('rm {}'.format(os.path.expanduser('~/.ssh/known_hosts')),
                    timeout=5,
                    encoding=self.encoding)

            # TODO: Try to detect and spawn the current running shell
            # current_shell = run('echo $0', timeout=10, encoding=self.encoding)
            # log.debug('Current shell: {}'.format(current_shell))
            spawn._spawn(self, 'bash')
            self.expect(original_prompt)

            # cd to home directory to ensure local session starts in the same
            # directory as ssh session, since bash does not change directory
            # when start a new session.
            self.sendline('cd', original_prompt, timeout=5, regex=True)
            self.is_logged_in = True

            # Get prompt upon login and set it as default prompt
            self.PROMPT = self._get_prompt(original_prompt)

        return self.is_logged_in
Example #20
0
    def login (self, server, username, password='', terminal_type='ansi',
                original_prompt=r"[#$]", login_timeout=10, port=None,
                password_regex=r'(?i)(?:password:)|(?:passphrase for key)',
                auto_prompt_reset=True, ssh_key=None, quiet=True,
                sync_multiplier=1, check_local_ip=True,
                sync_original_prompt=True):
        '''This logs the user into the given server.

        It uses
        'original_prompt' to try to find the prompt right after login. When it
        finds the prompt it immediately tries to reset the prompt to something
        more easily matched. The default 'original_prompt' is very optimistic
        and is easily fooled. It's more reliable to try to match the original
        prompt as exactly as possible to prevent false matches by server
        strings such as the "Message Of The Day". On many systems you can
        disable the MOTD on the remote server by creating a zero-length file
        called :file:`~/.hushlogin` on the remote server. If a prompt cannot be found
        then this will not necessarily cause the login to fail. In the case of
        a timeout when looking for the prompt we assume that the original
        prompt was so weird that we could not match it, so we use a few tricks
        to guess when we have reached the prompt. Then we hope for the best and
        blindly try to reset the prompt to something more unique. If that fails
        then login() raises an :class:`ExceptionPxssh` exception.

        In some situations it is not possible or desirable to reset the
        original prompt. In this case, pass ``auto_prompt_reset=False`` to
        inhibit setting the prompt to the UNIQUE_PROMPT. Remember that pxssh
        uses a unique prompt in the :meth:`prompt` method. If the original prompt is
        not reset then this will disable the :meth:`prompt` method unless you
        manually set the :attr:`PROMPT` attribute.
        
        Set ``password_regex`` if there is a MOTD message with `password` in it.
        Changing this is like playing in traffic, don't (p)expect it to match straight
        away.
        '''
        
        session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT]
        session_init_regex_array = []
        session_init_regex_array.extend(session_regex_array)
        session_init_regex_array.extend(["(?i)connection closed by remote host", EOF])

        ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
        if quiet:
            ssh_options = ssh_options + ' -q'
        if not check_local_ip:
            ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
        if self.force_password:
            ssh_options = ssh_options + ' ' + self.SSH_OPTS
        if port is not None:
            ssh_options = ssh_options + ' -p %s'%(str(port))
        if ssh_key is not None:
            try:
                os.path.isfile(ssh_key)
            except:
                raise ExceptionPxssh('private ssh key does not exist')
            ssh_options = ssh_options + ' -i %s' % (ssh_key)
        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        spawn._spawn(self, cmd)
        i = self.expect(session_init_regex_array, timeout=login_timeout)

        # First phase
        if i==0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect(session_regex_array)
        if i==2: # password or passphrase
            self.sendline(password)
            i = self.expect(session_regex_array)
        if i==4:
            self.sendline(terminal_type)
            i = self.expect(session_regex_array)
        if i==7:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        if i==0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
        elif i==1: # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        elif i==2: # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i==3: # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i==4: # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
        elif i==5: # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell prompt.
            pass
        elif i==6: # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else: # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        if sync_original_prompt:
            if not self.sync_original_prompt(sync_multiplier):
                self.close()
                raise ExceptionPxssh('could not synchronize with original prompt')
        # We appear to be in.
        # set shell prompt to something unique.
        if auto_prompt_reset:
            if not self.set_unique_prompt():
                self.close()
                raise ExceptionPxssh('could not set shell prompt '
                                     '(received: %r, expected: %r).' % (
                                         self.before, self.PROMPT,))
        return True
Example #21
0
    def login (self, server, username, password='', terminal_type='ansi',
                original_prompt=r"[#$]", login_timeout=10, port=None,
                auto_prompt_reset=True, ssh_key=None, quiet=True,
                sync_multiplier=1, check_local_ip=True):

    # cp ssh doesn't have an options field so ignore ALL options
        ssh_options = ''
        if port is not None:
            ssh_options = ssh_options + ' -p %s'%(str(port))
        cmd = "ssh %s -l %s %s" % (ssh_options, username, server)

        # This does not distinguish between a remote server 'password' prompt
        # and a local ssh 'passphrase' prompt (for unlocking a private key).
        spawn._spawn(self, cmd)
        i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT, "(?i)connection closed by remote host", EOF], timeout=login_timeout)

        # First phase
        if i==0:
            # New certificate -- always accept it.
            # This is what you get if SSH does not have the remote host's
            # public key stored in the 'known_hosts' cache.
            self.sendline("yes")
            i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==2: # password or passphrase
            self.sendline(password)
            i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==4:
            self.sendline(terminal_type)
            i = self.expect(["(?i)Do you trust the host key", original_prompt, "(?i)(?:password:)|(?:passphrase for key)", "(?i)permission denied", "(?i)terminal type", TIMEOUT])
        if i==7:
            self.close()
            raise ExceptionPxssh('Could not establish connection to host')

        # Second phase
        if i==0:
            # This is weird. This should not happen twice in a row.
            self.close()
            raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
        elif i==1: # can occur if you have a public key pair set to authenticate.
            ### TODO: May NOT be OK if expect() got tricked and matched a false prompt.
            pass
        elif i==2: # password prompt again
            # For incorrect passwords, some ssh servers will
            # ask for the password again, others return 'denied' right away.
            # If we get the password prompt again then this means
            # we didn't get the password right the first time.
            self.close()
            raise ExceptionPxssh('password refused')
        elif i==3: # permission denied -- password was bad.
            self.close()
            raise ExceptionPxssh('permission denied')
        elif i==4: # terminal type again? WTF?
            self.close()
            raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
        elif i==5: # Timeout
            #This is tricky... I presume that we are at the command-line prompt.
            #It may be that the shell_sample prompt was so weird that we couldn't match
            #it. Or it may be that we couldn't log in for some other reason. I
            #can't be sure, but it's safe to guess that we did login because if
            #I presume wrong and we are not logged in then this should be caught
            #later when I try to set the shell_sample prompt.
            pass
        elif i==6: # Connection closed by remote host
            self.close()
            raise ExceptionPxssh('connection closed')
        else: # Unexpected
            self.close()
            raise ExceptionPxssh('unexpected login response')
        return True