How to pass a variable to subprocess communicate - python

I am new to python and have done several searches on SO and google regarding this question.
How can I pass a variable pw, which is the user's password, to the input for popen.communicate?
Here is the code involved:
pw = getpass.getpass()
from subprocess import Popen, PIPE, STDOUT
ssh_conn = Popen(["ssh", "-t", server, "sudo -S cp /etc/"+map, "/etc/"+map + "." +fulltime], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
ssh_conn.communicate(input='pw\n')[0]
The code above appears to send the string 'pw' to standard input, instead I would like the value of the variable pw to be sent.
I realize that this approach is less than ideal and that there are other python modules that could do the job more simply, but I am not in a position to install any additional modules.

Use str.format to insert the password into the string:
pw = getpass.getpass()
from subprocess import Popen, PIPE, STDOUT
ssh_conn = Popen(["ssh", "-t", server, "sudo -S cp /etc/"+map, "/etc/"+map + "." +fulltime], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
ssh_conn.communicate(input='{0}\n'.format(pw))[0]

Related

Python Expect Like Behavior to capture /dev/tty (Provide passphrase to ssh / ssh-add)

I would like to respond to ssh / ssh-add password prompt when launched using Python subprocess, but since ssh reads password directly from /dev/ttyXX and not stdin, standards PIPEs do not work.
Is there a way to wrap subprocess with a virtual tty that I can control in Python so that I can send a password to the vty programmatically (like Expect seems to be able to do)? I would rather not use an Expect like module for Python if possible.
# Does not work, still grabs tty
my_env = os.environ.copy()
my_env['SSH_ASKPASS'] = my_env['HOME'] + '/bin/foo'
keyfile = './id_rsa'
keypass = b'password\n'
proc = subprocess.Popen('/usr/bin/ssh-add -t 86400 ' + keyfile,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=my_env)
# Always results in timeout as keypass is sent to stdin NOT /dev/ttyXX
stdout_data, stderr = result.communicate(input=keypass, timeout=60)
if stderr:
print("#LOG ERROR - Could not add password to ssh-agent [" + keyfile + "].")
sys.exit(1)

How can I read the error content outputs of mysql command executed from python

bash_fc = rf"mysql -u {source_user_name} -h {source_ipv4_addr} --password={source_db_password}"
When I use the following functions for the above command,
from subprocess import PIPE,run
def cons_r(cmd):
response = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True)
return response.stdout
response = os.popen(bash_fc)
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql: Unknown OS character set 'cp857'.
mysql: Switching to the default character set 'utf8mb4'.
ERROR 1045 (28000): Access denied for user 'root'#'pc.mshome.net' (using password: YES)
I can't read the output, is there a method you know of so I can read it?
You can read errors from standard error
import subprocess as sp
ret = sp.run(['ls', '*.bad'], stderr=sp.PIPE,
stdout=sp.PIPE, shell=True, encoding="cp857")
if ret.returncode == 0:
print(ret.stdout)
else:
print(ret.stderr)
This change fixed the problem
from subprocess import PIPE, run, STDOUT
def cons_r(cmd):
response = run(cmd, stdout=PIPE, stderr=STDOUT, universal_newlines=True, shell=True)
return response.stdout

How can I use Python to automate setting a password using the Unix pass command line program

I'm trying to automate setting new passwords using the Unix pass program.
I understand that there is a Python library, pexpect, that might help, but I would like to avoid using third-party libraries.
When using a terminal, the flow looks like this:
$ pass insert --force gmail
>> Enter password for gmail: <type in password using masked prompt>
>> Retype password for gmail: <reenter password>
What I would like my function to do:
Run the command pass insert --force {entry_name}
Capture the output (and echo it for testing)
Check output for the presence of 'password for gmail', and if True
write '{password}\n' to stdin
write '{password}\n' to stdin again
Echo any errors or messages for testing
Issues:
I'm stuck on step 2. The subprocess either hangs indefinitely, times out with an error, or produces no output.
Attempts:
I've tried configurations of Popen(), using both stdin.write() and communicate().
I've set wait() calls at various points.
I've tried both the shell=True and shell=False options (prefer False for security reasons)
Code:
def set_pass_password(entry_name, password):
from subprocess import Popen, PIPE
command = ['pass', 'insert', '--force', entry_name]
sub = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
# At this point I assume that the command has run, and that there is an "Enter password..." message
message = sub.stdout.read() # also tried readline() and readlines()
print(message) # never happens, because process hangs on stdout.read()
if 'password for {}'.format(entry_name) in message:
err, msg = sub.communicate(input='{p}\n{p}\n'.format(p=password))
print('errors: {}\nmessage: {}'.format(err, msg))
Edit: the original answer was about passwd, which is what's used to set passwords. I noticed late that you use pass, which is a keystore (doesn't actually change the Unix password). The pass program works differently and will not print a prompt if stdin is not a tty. Therefore the following very simple program works:
def set_pass_password(entry_name, password):
from subprocess import Popen, PIPE
command = ['pass', 'insert', '--force', entry_name]
sub = Popen(command, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE)
err, msg = sub.communicate(input='{p}\n{p}\n'.format(p=password))
print('errors: {}\nmessage: {}'.format(err, msg))
if __name__ == "__main__":
set_pass_password("ttt", "ttt123asdqwe")
(you will see that both stderr and stdout are empty, if the command succeeded).
For the passwd command:
FYI: the passwd command outputs the prompt to stderr, not stdout.
NOTE: rather than sending the password twice in the same 'write', you might need to wait for the second prompt before sending the password again.
For this simple case, code similar to yours should work, but in general you should use select on all the pipes and send/receive data when the other side is ready, so you don't get deadlocks.

Python users creation script

For training reasons im trying to write a python script that creates and sets user accounts and passwords :
import subprocess
from subprocess import Popen
users = ["user1"]
default_passwd = 'password'
for user in users:
p1 = subprocess.Popen(["useradd" ,user])
proc = Popen(['echo' ,default_passwd , '|' , 'passwd', user, '--stdin'])
proc.communicate()
While the user is created , the passwd process fails.
Any help would be appreciated.
Why don't you pass password along with command useradd?
so that it creates a user with password without prompting!!
import os
import crypt
password ="your-password"
crypted_password = crypt.crypt(password,"22")
os.system("useradd -p "+ crypted_password +" student")
#Naren answer is neat and much more readable; but for the purpose of answering your subprocess question, it should be like this
import subprocess
users = ["user1"]
default_passwd = 'password'
for user in users:
p1 = subprocess.Popen(['useradd', user, '-p'])
proc = subprocess.Popen(['echo', default_passwd], stdout=subprocess.PIPE)
p1.communicate(proc.stdout)
proc.communicate()
p1 opens a subshell with useradd user1 command executed and waits for input
proc then executes echo default_passwd, but instead of sending output to sys.stdout, it pipes it to subprocess.PIPE
The communicate on p1 sends the output of proc.stdout to the stdin of p1 and waits for it completion
The last commands wait for proc process to finish and exit

How to send the password after user name in command prompt using python

Trying to run some windows application in a specific user mode. After passing the command, it will ask for password. So passing the password using proc.communicate() but its not working, Please help
from subprocess import Popen, PIPE
import time
cmd = "runas /user:administrator notepad.exe"
proc = Popen(cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE)
print proc.stdout.read()
proc.communicate('password')
Are you open to using Pexpect instead? If yes, you can use the following:
import pexpect
cmd = "runas /user:administrator notepad.exe"
child_process = pexpect.spawn(cmd)
child_process.expect('assword')
child_process.sendline(password)

Categories

Resources