【问题标题】:PHP error when trying to use password reset plugin in roundcube尝试在roundcube中使用密码重置插件时出现PHP错误
【发布时间】: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");调用的

标签: python roundcube


【解决方案1】:

这似乎是包装脚本中的一个错误。

变化:

handle = subprocess.Popen('/usr/sbin/chpasswd', stdin = subprocess.PIPE)

到:

handle = subprocess.Popen('/usr/sbin/chpasswd', stdin = subprocess.PIPE, text=True)

注意text=True 参数添加到POpen。这会强制communicate() 方法将参数作为字符串处理。详情请见https://docs.python.org/3/library/subprocess.html

注意:我正在运行 3.9 版的 python。这个损坏的脚本版本可能仍然适用于旧版本的 python,但我不确定。

【讨论】:

    猜你喜欢
    • 2019-06-28
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 2018-06-27
    相关资源
    最近更新 更多