Reputation: 11837
I'm trying to write some scripts in Python and stumbled upon the need of making something to update the password of a given user in a Linux system...
UPDATE: the objective is to achieve the script to update the password automatically from a given data/algorithm. The important thing is to have no human intervention...
is there a way to achieve that? or should I search through other means?
Thanks!
Upvotes: 6
Views: 11402
Reputation: 4958
You can use openssl
and usermod
:
#!/usr/bin/env python
import subprocess
login = 'username'
password = 'somepassword'
# OpenSSL doesn't support stronger hash functions, mkpasswd is preferred
#p = subprocess.Popen(('openssl', 'passwd', '-1', password), stdout=subprocess.PIPE)
p = subprocess.Popen(('mkpasswd', '-m', 'sha-512', password), stdout=subprocess.PIPE)
shadow_password = p.communicate()[0].strip()
if p.returncode != 0:
print 'Error creating hash for ' + login
r = subprocess.call(('usermod', '-p', shadow_password, login))
if r != 0:
print 'Error changing password for ' + login
Upvotes: 8
Reputation: 5305
I just needed to do this again today, and below is my solution. It is fully automatic, and also uses standard system passwd binary, so system policies are respected.
#!/usr/bin/python3
username = 'joe'
# generate passphrase
pw_length = 6
phrase = subprocess.check_output(['pwgen', str(pw_length), '1'])
phrase = phrase.decode('utf-8').strip()
dev_null = open('/dev/null', 'w')
passwd = subprocess.Popen(['sudo', 'passwd', user], stdin=subprocess.PIPE,
stdout=dev_null.fileno(),
stderr=subprocess.STDOUT)
passwd.communicate( ((phrase + '\n')*2).encode('utf-8') )
if passwd.returncode != 0:
raise OSError('password setting failed')
(This generated the password too. Skip the first part if not useful.)
Upvotes: 2
Reputation: 2239
You can use crypt to do the password hashing instead of using openssl passwd
(where you are passing the password in plaintext in the command line)
Adapting Juliusz script:
#!/usr/bin/env python
import subprocess,crypt,random
login = 'username'
password = 'somepassword'
ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
salt = ''.join(random.choice(ALPHABET) for i in range(8))
shadow_password = crypt.crypt(password,'$1$'+salt+'$')
r = subprocess.call(('usermod', '-p', shadow_password, login))
if r != 0:
print 'Error changing password for ' + login
This way, the password is only passed in the command line already hashed (to usermod
).
I've tested this with ubuntu+python2.6.6+pycrypto2.5.
Upvotes: 5