Python + SSH Password auth (no external libraries or public/private keys)?

1.9k views Asked by At

So I'm aware that you can use Pexpect to solve the issue but i'd like to not rely on additional libraries to solve the issue other than those supplied with Python3.

I'm also aware the generating public keys and allowing them on the remote host is ideal, but that's sort of what i intend to use this script for (setting up keys in the right place etc).

This is as far as I've gotten on "my own" with a bunch of help from the SO community. I'm sort stuck checking if the forked child pseudo terminal is done executing what it's supposed to or not. Meaning i can tell if the SSH is done executing or not because it will live on for as long as the run() function is operating.

(my pid_exists will return True for as long as it's within the run() operation. And if i exit run() to quickly the SSH session will not have enough time to do what it's supposed to do)

#!/usr/bin/python

import pty, sys
from subprocess import Popen, PIPE, STDOUT
from time import sleep
from os.path import expanduser, abspath
from os import walk, setsid, fork, waitpid, execv, read, write, kill

def pid_exists(pid):
    """Check whether pid exists in the current process table."""
    if pid < 0:
        return False
    try:
        kill(pid, 0)
    except (OSError, e):
        return e.errno == errno.EPERMRM
    else:
        return True

class ssh():
    def __init__(self, host, execute='echo "done" > /root/testing.txt', user='root', password=b'SuperPassword'):
        self.exec = execute
        self.host = host
        self.user = user
        self.password = password
        self.run()

    def run(self):
        command = [
                '/usr/bin/ssh',
                self.user+'@'+self.host,
                '-o', 'NumberOfPasswordPrompts=1',
                self.exec,
        ]

        # PID = 0 for child, and the PID of the child for the parent    
        pid, child_fd = pty.fork()

        if not pid: # Child process
            # Replace child process with our SSH process
            execv(command[0], command)

        while True:
            output = read(child_fd, 1024).strip()
            print(output)
            lower = output.lower()
            # Write the password
            if b'password:' in lower:
                write(child_fd, self.password + b'\n')
                break
            elif 'are you sure you want to continue connecting' in lower:
                # Adding key to known_hosts
                write(child_fd, b'yes\n')
            elif 'company privacy warning' in lower:
                pass # This is an understood message
            else:
                print('Error:',output)

        sleep(5)
        print(pid_exists(pid))

ssh('10.10.10.1')

I can't find much (or any) information on how to get the execution process of the pseudo-pseudo terminal which Python opens and pipes to me. Can I or should I involve subprocess as explained here: https://stackoverflow.com/a/12235442/929999 or is there another way?

1

There are 1 answers

0
Torxed On BEST ANSWER

sigh.. One more google could have spared everyone the trouble.

os.waitpid(pid, 0)

how to give subprocess a password and get stdout at the same time