How to pass password part on linux -subprocess-os - python

I'm trying to make a program that allows me whenever the user want, shutdown or restart the computer. I'll send this to my friends so I don't know which operating system. I'm using tkinter too,here is an example codes;
import subprocess
import os
time = "10"
if os.name == "posix":
subprocess.call(["shutdown", "-h", time])
elif os.name == "nt":
subprocess.call(["shutdown", "-s", "-t", time])
However, on linux, it's asking password to user before shutting down. So this program is useless if asking password before shutting down. I tried to use %admin ALL = NOPASSWD: /sbin/shutdown after if statement but it doesn't work either. How to pass this password thing on linux?

I don' t think that's possible, you do have to disable the password or your program is like you said going to be useless. But I could be wrong ;)

A direct call of subprocess or Popen could NOT possibly handle this, as this is an interactive to wait for the user input, you can use pexepct for this kind of interactive mode. http://pexpect.readthedocs.org/en/latest/examples.html

You should configure a passwordless /sbin/shutdown via your sudoers settings instead of hardcoding the password in your script.
It is not recommended but you can pass the password to sudo (based on sudo mount example):
#!/usr/bin/env python
from getpass import getpass
from subprocess import Popen, PIPE
command = 'shutdown -P now'.split()
sudo_password = getpass('Sudo password: ')
p = Popen(['sudo', '--stdin'] + command, stdin=PIPE, stderr=PIPE,
universal_newlines=True)
sudo_prompt = p.communicate(sudo_password + '\n')[1]
# should not get here
print('sudo return code = {}'.format(p.returncode))
print('sudo stderr = ' + sudo_prompt)

Related

Execute mysqldump with python and set the password via stdin

I want to execute a mysqldump in python and provide the password when it is requested from the mysqldump.
Adding the password in the command line is not an option, it must be provided via stdin.
This is what I've done so far:
command = [
'mysqldump',
'-h', mysqlhost,
'-P', mysqlport,
'-u', mysqluser,
'-p',
mysqldb
]
mysqlfile = mysqlpath + "/" + mysqldb + ".sql"
with open(mysqlfile, "w+") as file:
p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=file)
p.communicate(input=mysqlpass)
p.wait()
But when I execute the code the terminal hangs requesting the password.
Thank you.
You can use pexpect for that. This is modified code as I had to test it, but you get the idea:
import pexpect
command2 = 'mysqldump -h localhost -u root -p xyzzy'
mysqlfile = "/tmp/foo.sql"
with open(mysqlfile, "w+") as file:
p = pexpect.spawn(command2)
p.expect("Enter password: ")
p.sendline("foobar")
q = p.read()
p.wait()
file.write(q)
here "foobar" is my database password.
Hannu
For me, the accepted answer did not solve the problem. Presumably it is related to the python version I am using, which is 3.5.
The difficulties I had:
p.read() was blocking the process (I always killed the script at some point)
The chunk-approach by David Rojo did not block, but .read(1024) returned integers, where strings where expected by file.write(...). I assume this is related to differences in the way unicode is handled in Python 2 and 3, since adding the parameter encoding='utf-8' to pexpect.spawn() gave me the proper results. However, then I had to adapt the writing of the file, s.t. it supports unicode as well.
Another problem with the for chunk in p.read(1024):-approach is, that I experienced the reading to finish before mysqldump finished writing the dump to stdout. I guess that in this case mysqldump was too slow to deliver. I changed my solution, s.t. it waits for EOF.
Note: I just started learning python a couple of days ago, please correct me if my assumptions or conclusions are wrong or misleading.
Code example
The script below is my minimal working example for calling mysqldump and providing the password when mysqldump asks for it:
#!/usr/bin/env python3
import pexpect
import io
cmd = 'mysqldump -u MYSQL_USER -p DATABASES(S)'
sqlfile = "/home/user/test-database-dump.sql"
password = 'secret'
with io.open(sqlfile, 'w', encoding="utf-8") as file:
print('Calling mysqldump...')
p = pexpect.spawn(cmd,encoding='utf-8')
p.expect("Enter password: ")
# Send password to mysqldump
p.sendline(password)
# Capture the dump
print('Reading dump from process and writing it to file...')
while not p.eof():
chunk = p.readline()
file.write(chunk)
print('Finished.')
p.close()
print(p.exitstatus, p.signalstatus)

Using pexpect to get output of 'ls' command

I am trying to login as a user using pexpect and trying to print all the crons available :
import pexpect
import os, time
passwd = "mypass"
child = pexpect.spawn('su myuser')
child.expect('Password:')
child.sendline(passwd)
child.expect('$')
child.sendline('crontab -l')
i =child.expect(['%','.*$', '$' ])
print i # prints 1 here so, the shell is expected.
print child.before # this doesn't print anything though.
This code doesn't seem to be working and prints empty line.
Couldn't figure out the issue with this code
If there is any better way to list cron job of other user, given username and password
Any pointers or suggestions would be much appreciated.
If you can arrange to configure password-less sudo access, then the above simply becomes:
import subprocess
output = subprocess.check_output('sudo -u myuser crontab -l', shell=True)
If you need to continue using su, then you can pass it a command and avoid trying to parse shell prompts:
import pexpect
passwd = "mypass"
child = pexpect.spawn('su myuser -c "crontab -l"')
child.expect('Password:')
child.sendline(passwd)
child.expect(pexpect.EOF)
print child.before

Enter an ssh password using the standard python library (not pexpect)

Related questions that are essentially asking the same thing, but have answers that don't work for me:
Make python enter password when running a csh script
How to interact with ssh using subprocess module
How to execute a process remotely using python
I want to ssh into a remote machine and run one command. For example:
ssh <user>#<ipv6-link-local-addr>%eth0 sudo service fooService status
The problem is that I'm trying to do this through a python script with only the standard libraries (no pexpect). I've been trying to get this to work using the subprocess module, but calling communicate always blocks when requesting a password, even though I supplied the password as an argument to communicate. For example:
proc = subprocess.Popen(
[
"ssh",
"{testUser1}#{testHost1}%eth0".format(**locals()),
"sudo service cassandra status"],
shell=False,
stdin=subprocess.PIPE)
a, b = proc.communicate(input=testPasswd1)
print "a:", a, "b:", b
print "return code: ", proc.returncode
I've tried a number of variants of the above, as well (e.g., removing "input=", adding/removing subprocess.PIPE assignments to stdout and sterr). However, the result is always the same prompt:
ubuntu#<ipv6-link-local-addr>%eth0's password:
Am I missing something? Or is there another way to achieve this using the python standard libraries?
This answer is just an adaptation of this answer by Torxed, which I recommend you go upvote. It simply adds the ability to capture the output of the command you execute on the remote server.
import pty
from os import waitpid, execv, read, write
class ssh():
def __init__(self, host, execute='echo "done" > /root/testing.txt',
askpass=False, user='root', password=b'SuperSecurePassword'):
self.exec_ = execute
self.host = host
self.user = user
self.password = password
self.askpass = askpass
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)
## if we havn't setup pub-key authentication
## we can loop for a password promt and "insert" the password.
while self.askpass:
try:
output = read(child_fd, 1024).strip()
except:
break
lower = output.lower()
# Write the password
if b'password:' in lower:
write(child_fd, self.password + b'\n')
break
elif b'are you sure you want to continue connecting' in lower:
# Adding key to known_hosts
write(child_fd, b'yes\n')
else:
print('Error:',output)
# See if there's more output to read after the password has been sent,
# And capture it in a list.
output = []
while True:
try:
output.append(read(child_fd, 1024).strip())
except:
break
waitpid(pid, 0)
return ''.join(output)
if __name__ == "__main__":
s = ssh("some ip", execute="ls -R /etc", askpass=True)
print s.run()
Output:
/etc:
adduser.conf
adjtime
aliases
alternatives
apm
apt
bash.bashrc
bash_completion.d
<and so on>

Script cannot read password

Python script is designed to run with elevated credentials, unfortunately
it still prompts me for password
when I enter the correct password it doesn't work
Here is script1, which calls script2 with elevated credentials
import os
import sys, subprocess, socket, string
import wmi, win32api, win32con
import win32com.shell.shell as sh
ASADMIN = '/user:DOMAIN\username'
os.system('"runas /user:DOMAIN\username "D:/Python27/python.exe script2.py sender-ip=10.10.10.10 < password.txt""')
sys.exit(0)
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ''.join([ASADMIN] + ['D:\Python27\python.exe',script] + sys.argv[1:])
sh.ShellExecuteEx(lpVerb='runas',lpFile=sys.executable,lpParameters=params)
sys.exit(0)
Here is script2
import sys, subprocess, socket, string
import wmi, win32api, win32con
for args in [item.strip('sender-ip=') for item in sys.argv[1:]]:
userIP = args
userloggedon = ""
# perform system lookup of IP address
userIP = "\\\\" + userIP
pst = subprocess.Popen(
["D:\pstools\psloggedon.exe", "-l", "-x", userIP],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = pst.communicate()
userLoggedOn = out.split('\n')[1].strip()
print 'userId={}'.format(userLoggedOn)
f = open('D:\SymantecDLP\Protect\plugins\output.txt', 'w')
f.write('userId={}'.format(userLoggedOn))
output.txt is not created
Any ideas?
EDIT
I also read this thread, How to supply password to runas command when executing it from java
but no matter what I try I keep getting the error
Attempting to start c:\test.bat as user "DOMAIN\username" ...
RUNAS ERROR: Unable to run - c:\test.bat
1326: Logon failure: unknown user name or bad password.
Let's talk about your problems one at the time.
1. It still prompts me for password
In the line
os.system('"runas /user:DOMAIN\username "D:/Python27/python.exe script2.py sender-ip=10.10.10.10 < password.txt""')
you're providing the password to script2. runas command still need a password since is trying to run a program as another user.
2. When I enter the correct password it doesn't work
Well ... The code does'n work that's clear. But, you have to be more specific when asking a question. Right now a look to your code and I can see that you're trying to do ping on a remote machine.
Might the remote machine has a firewall?
Have you tryed doing ping manually?
Edit: The output.txt file is not created, and running the script don't tell you nothing about error writting the file, obviously your code is hitting one of the sys.exit() lines.
You can use PsExec
https://learn.microsoft.com/en-us/sysinternals/downloads/psexec
You can supply a username and password and executing does not need to be elevated to admin:
psexec [\computer[,computer2[,...] | #file]]\ [-u user [-p psswd] [-n s][-r servicename][-h][-l][-s|-e][-x][-i [session]][-c [-f|-v]][-w directory][-d][-][-a n,n,...] cmd [arguments]
Use the -e switch to give the same results as Runas /netonly:
-e Does not load the specified account’s profile.

os.setuid doesn't change current user

I wanted to change current user for script execution. I did this
import os
newuid = pwd.getpwnam('newuser').pw_uid
os.setuid(newuid)
print('User :' + getpass.getuser());
I am still getting root. Is there better way than this? I want switch user once and then continue rest of the commands execution in the script with that new user.
getpass.getuser() doesn't use getuid() or geteuid() to get the current user.
http://docs.python.org/3/library/getpass.html#getpass.getuser
This function checks the environment variables LOGNAME, USER, LNAME and USERNAME, in order, and returns the value of the first one which is set to a non-empty string. If none are set, the login name from the password database is returned on systems which support the pwd module, otherwise, an exception is raised.
After trying modules os, subprocess, getpass, I realised that the problem is not whether the user is set. The user gets set or gets changed using os.setuid, however, the methods from modules to get username like os.getlogin(), getpass.getuser(), actually does not get username properly. If you run a shell command whoami or idusing subprocess.Popen() or os.system(), you will get the changed user. These are little puzzled outputs for me. Below is script which shows all these weird behaviours.
import os
import subprocess
import pwd
import getpass
#os.chdir("/tmp")
#uid = pwd.getpwnam('newuser').pw_uid
os.setuid(500) # newuser's id found from shell cmd line
print os.getuid()
p = subprocess.Popen(['id'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
# print os.system('useradd newuser1') # Try this commenting, it will not create, and then try commenting above line of setuid. i.e. it will become root, and then see the change.
# print os.getcwd()
print out,err
p = subprocess.Popen(['whoami'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
print out,err
print getpass.getuser()
print os.getlogin()
print os.system('whoami')

Categories