Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a password over SSH or SCP with subprocess.Popen

I'm trying to run an scp (secure copy) command using subprocess.Popen. The login requires that I send a password:

from subprocess import Popen, PIPE

proc = Popen(['scp', "[email protected]:/foo/bar/somefile.txt", "."], stdin = PIPE)
proc.stdin.write(b'mypassword')
proc.stdin.flush()

This immediately returns an error:

[email protected]'s password:
Permission denied, please try again.

I'm certain the password is correct. I easily verify it by manually invoking scp on the shell. So why doesn't this work?

Note, there are many similar questions to this, asking about subprocess.Popen and sending a password for automated SSH or FTP login:

How can I set a users password in linux from a python script?
Use subprocess to send a password

The answer(s) to these questions don't work and/or don't apply because I am using Python 3.

like image 807
Channel72 Avatar asked Mar 01 '13 21:03

Channel72


1 Answers

Here's a function to ssh with a password using pexpect:

import pexpect
import tempfile

def ssh(host, cmd, user, password, timeout=30, bg_run=False):                                                                                                 
    """SSH'es to a host using the supplied credentials and executes a command.                                                                                                 
    Throws an exception if the command doesn't return 0.                                                                                                                       
    bgrun: run command in the background"""                                                                                                                                    
                                                                                                                                                                               
    fname = tempfile.mktemp()                                                                                                                                                  
    fout = open(fname, 'w')                                                                                                                                                    
                                                                                                                                                                               
    options = '-q -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no'                                                                         
    if bg_run:                                                                                                                                                         
        options += ' -f'                                                                                                                                                       
    ssh_cmd = 'ssh %s@%s %s "%s"' % (user, host, options, cmd)                                                                                                                 
    child = pexpect.spawn(ssh_cmd, timeout=timeout)  #spawnu for Python 3                                                                                                                          
    child.expect(['[pP]assword: '])                                                                                                                                                                                                                                                                                               
    child.sendline(password)                                                                                                                                                   
    child.logfile = fout                                                                                                                                                       
    child.expect(pexpect.EOF)                                                                                                                                                  
    child.close()                                                                                                                                                              
    fout.close()                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                        
    fin = open(fname, 'r')                                                                                                                                                     
    stdout = fin.read()                                                                                                                                                        
    fin.close()                                                                                                                                                                
                                                                                                                                                                               
    if 0 != child.exitstatus:                                                                                                                                                  
        raise Exception(stdout)                                                                                                                                                
                                                                                                                                                                               
    return stdout

Something similar should be possible using scp.

like image 131
sjbx Avatar answered Oct 10 '22 06:10

sjbx