How To Change A Linux User Password From Python
Solution 1:
Try using the '--stdin' option to the passwd command in your pipes. To quote from the man page:
--stdin This option is used to indicate that passwd should read the new password from standard input, which can be a pipe.
Another option, if your Linux has the usermod command, as root (or via sudo) you can explicitly set the (encrypted) password using the '-p' option.
Solution 2:
The user you are running this as must have sudo permission to run the passwd
command without a password.
>>>from subprocess import Popen>>>proc = Popen(['/usr/bin/sudo', '/usr/bin/passwd', 'test', '--stdin'])>>>proc.communicate('newpassword')
Solution 3:
I ran accross the same problem today and I wrote a simple wrapper around subprocess
to call the passwd
command and feed stdin
with the new password. This code is not fool proof and only works when running as root which does not prompt for the old password.
import subprocess
from time import sleep
PASSWD_CMD='/usr/bin/passwd'defset_password(user, password):
cmd = [PASSWD_CMD, user]
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
p.stdin.write(u'%(p)s\n%(p)s\n' % { 'p': password })
p.stdin.flush()
# Give `passwd` cmd 1 second to finish and kill it otherwise.for x inrange(0, 10):
if p.poll() isnotNone:
break
sleep(0.1)
else:
p.terminate()
sleep(1)
p.kill()
raise RuntimeError('Setting password failed. ''`passwd` process did not terminate.')
if p.returncode != 0:
raise RuntimeError('`passwd` failed: %d' % p.returncode)
If you need the output of passwd you can also pass stdout=subprocess.PIPE
to the Popen
call and read from it. In my case I was only interested if the operation succeeded or not so I simply skipped that part.
Security consideration: Do not use something like echo -n 'password\npassword\n | passwd username'
as this will make the password visible in the process list.
SUDO
Since you seam to want to be using sudo passwd <username>
I would recommend adding a new line to your /etc/sudoers
(use visudo
for that!)
some_user ALL = NOPASSWD: /usr/bin/passwd
Sudo will not ask for the password for some_user
and the script will run as expected.
Alternatively simply add an extra p.stdin.write(u'%s\n' % SUDO_PASSWORD)
line. That way sudo
will receive the user password first and then passwd
receives the new user password.
Solution 4:
usermod
-based version:
#!/usr/bin/env pythonfrom crypt import crypt
from getpass import getpass
from subprocess import Popen, PIPE
sudo_password_callback = lambda: sudo_password # getpass("[sudo] password: ")
username, username_newpassword = 'testaccount', '$2&J|5ty)*X?9+KqODA)7'# passwd has no `--stdin` on my system, so `usermod` is used instead# hash password for `usermod`try:
hashed = crypt(username_newpassword) # use the strongest available methodexcept TypeError: # Python < 3.3
p = Popen(["mkpasswd", "-m", "sha-512", "-s"], stdin=PIPE, stdout=PIPE,
universal_newlines=True)
hashed = p.communicate(username_newpassword)[0][:-1] # chop '\n'assert p.wait() == 0assert hashed == crypt(username_newpassword, hashed)
# change password
p = Popen(['sudo', '-S', # read sudo password from the pipe# XXX: hashed is visible to other users'usermod', '-p', hashed, username],
stdin=PIPE, universal_newlines=True)
p.communicate(sudo_password_callback() + '\n')
assert p.wait() == 0
Solution 5:
For those that --stdin isn't an option:
import subprocess
cmd ="bash -c \"echo -e 'NewPassword\\nNewPassword' | passwd root\""
subprocess.check_call(cmd, shell=True)
Post a Comment for "How To Change A Linux User Password From Python"