我正在编写一个Python脚本来更改Linux帐户用户的用户名和密码-这是一个更大的内部web gui系统的一部分,它将来自apache2
(不能作为root用户运行)的密码更改请求排队,然后更改密码本身。python脚本本身显然必须以root用户身份运行才能更改密码。在
密码更改功能非常简单:
def chpasswd(user, passwd):
if os.getuid() != 0:
syslog.syslog("Error: chpasswd.py must be run as root")
return
proc = Popen(
['/usr/sbin/chpasswd'],
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
print "Changing: " + user + ':' + passwd
out, err = proc.communicate(user + ':' + passwd)
proc.wait()
print out
if proc.returncode != 0:
print "Error: Return code", proc.returncode, ", stderr: ", out, err
if out:
syslog.syslog("stdout: " + out)
if err:
syslog.syslog("stderr: " + err)
print
语句只是用于临时调试。它运行良好,不报告任何错误-out
或err
上没有任何内容;但是由于某些原因,实际的UNIX密码没有被更改。在
调用此函数的脚本正在侦听本地绑定的TCP套接字。当它接收到一个更改密码请求(格式为user:password
-稍后将被加密,但现在是纯文本)时,它将其添加到队列中,然后调用chpasswd
函数。在
因此,典型用法是:
^{pr2}$当服务器在bash窗口中运行时(不是作为守护程序),它会输出:
# python chpasswd.py
Starting Password Server
New connection from: 127.0.0.1
Changing: jsmith:mynewpassword
您可以看到,最后一个语句是我的chpasswd
函数中的print
语句。在
但在完成上述操作后,当我实际尝试使用新密码以用户身份登录时,我得到:
$ su jsmith
Password:
su: Authentication failure
我有什么明显的错误吗?我的怀疑是,不知何故,与Popen
的连接实际上并没有结束,或者也许单行user:password
文本没有被传输。所以我试着做一些类似的事情:
out, err = proc.communicate(user + ':' + passwd + '\x04')
请注意结尾处额外的\x04
字符,表示传输结束。但是,添加这个仍然不能使它工作-密码保持不变。在
我在Debian Wheezzy上运行这个,以防有什么不同。在
更新:
进一步研究,我可以看到我的chpasswd
函数实际上是在更改密码-如果我在连接密码服务器之前和之后cat
文件,我会发现有一个不同的哈希。在
只是当我尝试使用明文密码进行身份验证时,它不起作用。因此,我怀疑,与Popen
的通信要么添加额外的字符,要么以某种方式丢失字符。当然,由于/etc/shadow
是一个散列,所以我不能确切地知道这里到底发生了什么。在
这个特定实例中的问题是,telnet在输入文本时按return后添加
"\r\n"
。由于您的服务器没有剥离空白数据,因此在更改密码时会保留这一点。在通过用传输结束字符(EOT)结束一行,可以使telnet不发送回车符和换行符。您可以按Ctrl-D来执行此操作
例如
或者,您可以将线路连接到telnet
^{pr2}$显然,您只想在测试时这样做,否则新密码将出现在shell历史记录中。(
-n
参数通过echo
禁止打印换行符)或者您可能想完全取消}。在
telnet
,而改用{相关问题 更多 >
编程相关推荐