Sending a Password Over Ssh or Scp with Subprocess.Popen

Sending a password over SSH or SCP with subprocess.Popen

The second answer you linked suggests you use Pexpect(which is usually the right way to go about interacting with command line programs that expect input). There is a fork of it which works for python3 which you can use.

SSH using subprocess.popen, unable to enter password

Sending a password over SSH or SCP with subprocess.Popen

As you want to use windows you should look at a pexpect port: https://bitbucket.org/geertj/winpexpect/wiki/Home

Use subprocess to send a password

Perhaps you should use an expect-like library instead?

For instance Pexpect (example). There are other, similar python libraries as well.

SCP via Python Subprocess Popen: Identity File not accessible

You should not combine an option and its argument in the same parameter, they need to be separate list elements.

SSH = subprocess.Popen(['scp', '-i', './id_rsa.key', '-P', '2222', './test.plan', 'root@127.0.0.1:/go/'],

Execute scp using Popen without having to enter password

When scp or ssh attempt to read a password they do not read it from stdin. Instead they open /dev/tty and read the password direct from the connected terminal.

sshpass works by creating its own dummy terminal and spawning ssh or scp in a child process controlled by that terminal. That's basically the only way to intercept the password prompt. The recommended solution is to use public key authentication, but you say you cannot do that.

If as you say you cannot install sshpass and also cannot use a secure form of authentication then about the only thing you can do is re-implement sshpass in your own code. sshpass itself is licensed under the GPL, so if you copy the existing code be sure not to infringe on its copyleft.

Here's the comment from the sshpass source which describes how it manages to spoof the input:

/*
Comment no. 3.14159
This comment documents the history of code.
We need to open the slavept inside the child process, after "setsid", so that it becomes the controlling
TTY for the process. We do not, otherwise, need the file descriptor open. The original approach was to
close the fd immediately after, as it is no longer needed.
It turns out that (at least) the Linux kernel considers a master ptty fd that has no open slave fds
to be unused, and causes "select" to return with "error on fd". The subsequent read would fail, causing us
to go into an infinite loop. This is a bug in the kernel, as the fact that a master ptty fd has no slaves
is not a permenant problem. As long as processes exist that have the slave end as their controlling TTYs,
new slave fds can be created by opening /dev/tty, which is exactly what ssh is, in fact, doing.
Our attempt at solving this problem, then, was to have the child process not close its end of the slave
ptty fd. We do, essentially, leak this fd, but this was a small price to pay. This worked great up until
openssh version 5.6.
Openssh version 5.6 looks at all of its open file descriptors, and closes any that it does not know what
they are for. While entirely within its prerogative, this breaks our fix, causing sshpass to either
hang, or do the infinite loop again.
Our solution is to keep the slave end open in both parent AND child, at least until the handshake is
complete, at which point we no longer need to monitor the TTY anyways.
*/

So what sshpass is doing is opening a pseudo terminal device (using posix_openpt), then forks and in the child process makes the slave the controlling pt for the process. Then it can exec the scp command.

I don't know if you can get this to work from Python, but the good news is the standard library does include functions for working with pseudo terminals: https://docs.python.org/3.6/library/pty.html



Related Topics



Leave a reply



Submit