有没有一种使用Python脚本在Linux中更改用户密码的方法?如果有,怎么做?

6

我正在尝试用Python编写一些脚本,并遇到了需要更新Linux系统中给定用户密码的需求...

更新:目标是通过给定的数据/算法自动更新密码。重要的是不需要人工干预...

有没有办法实现这个?还是我应该通过其他方式搜索?

谢谢!

4个回答

8
您可以使用opensslusermod
#!/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

好的!几乎做到了!问题是我仍然需要与脚本间接交互:我需要使用sudo运行它,要求我输入用户密码执行脚本,即使登录变量与运行脚本的用户名称相同。我猜这与usermod有关,对吧? - Javier Novoa C.
是的,看起来是这样。我不知道是否有办法绕过这个问题。运行usermod的用户需要有修改/etc/passwd/etc/shadow的权限。您需要检查一下passwd如何在不需要权限的情况下更改密码。 - Juliusz Gonera
非常感谢。由于我想在特定时刻自动修改某个用户的密码,我设法通过使用root的crontab(可以通过sudo crontab -e访问)来绕过它,然后脚本按照我的要求运行... - Javier Novoa C.
1
不幸的是,openssl-passwd 只支持 crypt、md5 和 apr1 哈希,而不支持现在更常用的 blowfish 或 sha1。此外,它也不会检查密码强度等方面的内容。 - zbyszek
@zbyszek,我想你是对的。看起来mkpasswd能够生成更强的哈希值。我已经更新了答案。 - Juliusz Gonera

5
你可以使用 crypt 来进行密码哈希,而不是使用 openssl passwd(在命令行中传递明文密码)。
修改 Juliusz 脚本:
#!/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

这样,密码只会以已经哈希过的形式(通过usermod命令)在命令行中传递。
我已经在ubuntu+python2.6.6+pycrypto2.5上进行了测试。


2

今天我需要再次执行此操作,以下是我的解决方案。它完全自动化,并且还使用标准的系统passwd二进制文件,因此尊重系统策略。

#!/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')

(如果不需要,可以跳过第一部分。)这也生成了密码。

0
使用subprocess调用passwd

谢谢回答,但我真正需要的是在没有人工干预的情况下完成它,据我所知,passwd需要人工输入... - Javier Novoa C.
你尝试过手册中给出的选项吗?特别是 --stdin - Ignacio Vazquez-Abrams
考虑同时调用“usermod”。 - ulidtko
1
passwd --stdin 不是一个选项,因为该参数并不总是存在于所有发行版中,或者我已经注意到了。在我的测试系统中,Debian(也几乎显然地在Ubuntu上找到了相同的问题),没有--stdin选项。我已经注意到在CentOS中它是存在的,但问题仍然存在:并非所有发行版都支持它... - Javier Novoa C.
我会看一下usermod,之前不知道它的存在,但是我手动测试后发现,由于usermod将密码“按照加密方式返回”(根据man页面),系统不允许我使用经过usermod修改的密码登录,所以我必须su并手动重新设置密码...需要再做些研究... - Javier Novoa C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接