【发布时间】:2021-11-21 01:53:43
【问题描述】:
我已从圆形立方体 1.3 升级到 1.4。我无法让用于重置密码的插件正常工作。当我尝试重置密码时,我在浏览器中收到此错误:
Could not save new password.
查看服务器日志,我看到了这个错误:
[20-Nov-2021 20:32:31 -0500]: <a7o1n9il> PHP Error: Password plugin: Unable to execute sudo /usr/sbin/chpasswd-wrapper.py in /usr/share/roundcube/plugins/password/drivers/chpasswd.php on line 46 (POST /?_task=settings&_action=plugin.password-save)
我已在 chpasswd-wrapper.py 文件上临时将权限设置为 777,以排除权限问题。我已允许www-data 用户根据自述文件在我的 debian 机器上的 /etc/sudoers.d/90roundcubemail 中运行 chpasswd:
www-data ALL=NOPASSWD:/usr/sbin/chpasswd
Defaults:www-data !requiretty
当我尝试直接从命令行运行 chpasswd-wrapper.py 并向其输入 someuser:mewpass 时,我收到此错误:
Traceback (most recent call last):
File "/usr/sbin/./chpasswd-wrapper.py", line 29, in <module>
handle.communicate('%s:%s' % (username, password))
File "/usr/lib/python3.9/subprocess.py", line 1119, in communicate
self._stdin_write(input)
File "/usr/lib/python3.9/subprocess.py", line 1068, in _stdin_write
self.stdin.write(input)
TypeError: a bytes-like object is required, not 'str'
但我不确定这个命令是否可以从命令行运行,或者它是否只能从圆形 php 文件中调用。 chpasswd-wrapper.py 是从这个圆形立方体中的 php 文件中调用的:
class rcube_chpasswd_password
{
public function save($currpass, $newpass, $username)
{
$cmd = rcmail::get_instance()->config->get('password_chpasswd_cmd');
$handle = popen($cmd, "w");
fwrite($handle, "$username:$newpass\n");
if (pclose($handle) == 0) {
return PASSWORD_SUCCESS;
}
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Password plugin: Unable to execute $cmd"
), true, false);
return PASSWORD_ERROR;
}
}
这是包装脚本本身:
#!/usr/bin/python3
import sys
import pwd
import subprocess
BLACKLIST = (
# add blacklisted users here
#'user1',
)
try:
username, password = sys.stdin.readline().split(':', 1)
except ValueError:
sys.exit('Malformed input')
try:
user = pwd.getpwnam(username)
except KeyError:
sys.exit('No such user: %s' % username)
if user.pw_uid < 1000:
sys.exit('Changing the password for user id < 1000 is forbidden')
if username in BLACKLIST:
sys.exit('Changing password for user %s is forbidden (user blacklisted)' %
username)
handle = subprocess.Popen('/usr/sbin/chpasswd', stdin = subprocess.PIPE)
handle.communicate('%s:%s' % (username, password))
sys.exit(handle.returncode)
更新:这绝对不是权限问题。如果我将包装脚本更改为此,我不会收到任何错误:
#!/usr/bin/python3
import sys
import pwd
import subprocess
handle = subprocess.Popen('/usr/sbin/chpasswd', stdin = subprocess.PIPE)
sys.exit(0)
【问题讨论】:
-
"我对 python 一点也不熟悉。不知道如何弄清楚 python 脚本的内部发生了什么以及如何弄清楚它为什么会窒息" 你没有任何代码已经显示的是 Python。该错误消息在某种程度上表明该代码适用于 (very) 旧版本的 Python,它处理某些数据类型的方式与当前标准不同。您应该首先尝试阅读所有相关文档。
-
啊,对不起。两次粘贴在同一个文件中。会修复的。
-
我正在运行最新版本的稳定版 debian,bullseye。
-
您可以通过在您的
communicate调用中使用(b'%s:%s' % (username, password))来解决一个字符的“类似字节”错误,但是您如何期望sudo在非交互式环境中工作? -
我只是按照插件的自述文件告诉我的去做。查看插件的php脚本,python包装器是用
fwrite($handle, "$username:$newpass\n");调用的