使用Python脚本更改Linux用户名或密码

时间:2014-10-27 19:27:03

标签: python linux

我正在编写一个更改Linux帐户用户的用户名和密码的Python脚本 - 它是更大的内部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语句仅用于临时调试。这样运行正常并且不会报告任何错误 - outerr上没有任何内容;但由于某种原因,实际的UNIX密码只是没有改变

调用此函数的脚本正在侦听本地绑定的TCP套接字。当它收到更改密码请求(以user:password的形式 - 稍后加密但现在是纯文本)时,它会将其添加到队列中,然后调用chpasswd函数。

因此,典型的用法是:

# telnet localhost 7001
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
jsmith:mynewpassword

当服务器在bash窗口(而不是守护进程)中运行时,它会输出:

# python chpasswd.py
Starting Password Server
New connection from: 127.0.0.1
Changing: jsmith:mynewpassword

您可以看到,最后一条语句是print函数中的chpasswd语句。

但在完成上述操作后,当我尝试使用新密码以用户身份登录时,我得到:

$ su jsmith
Password: 
su: Authentication failure

我在这里做错了吗?我的怀疑是,与Popen的连接实际上并未关闭,或者单行user:password文本未被传输。所以我尝试做了类似的事情:

out, err = proc.communicate(user + ':' + passwd + '\x04')

注意结尾处的额外\x04字符,表示传输结束。添加它仍然没有使它工作 - 但密码保持不变。

我在Debian Wheezy上运行它,以防它有任何区别。

更新

进一步调查,我可以看到我的chpasswd函数实际 更改了密码 - 如果cat /etc/shadow文件在连接到我之前和之后密码服务器,我看到有一个不同的哈希。

只是当我尝试使用明文密码进行身份验证时,它不起作用。因此,我怀疑是,不知何故,与Popen的通信要么添加额外的字符,要么以某种方式丢失字符。当然,由于/etc/shadow是一个哈希,我无法确切地知道这里发生了什么。

1 个答案:

答案 0 :(得分:1)

此特定实例中的问题是,在输入文本时按回车键后,telnet会添加"\r\n"。由于您的服务器没有剥离空白数据,因此在更改密码时会保留该数据。

通过使用传输结束字符(EOT)结束一行,可以使telnet不发送回车符和换行符。您可以按Ctrl-D。

来完成此操作

例如

$ telnet localhost 7001
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
jsmith:mynewpassword^DChanging: jsmith:mynewpassword

或者,您可以将该行传输到telnet

echo -n jsmith:mynewpassword | telnet localhost 7001

显然,您只想进行测试,否则新密码将在您的shell历史记录中结束。 (-n参数禁止按echo

打印换行符

或者您可能希望完全取消telnet并改为使用netcat

echo -n jsmith:mynewpassword | netcat localhost 7001