如何让 PAM 仅在首次登录时检查条件?

如何让 PAM 仅在首次登录时检查条件?

如同配置 pam_mount 仅在初次登录时提示,但推荐的答案不适用于 RHEL 9(并且显然不适用于最初提出问题的人)。

我需要在 Red Hat Enterprise Linux 9 上设置 DUO 双因素身份验证。指示在供应商网站上的设置会导致每次用户输入密码时都需要回答 2FA 质询,例如sudo.我想修改此设置,以便仅在首次登录时提示进行 2FA 质询。

我在 /etc/authselect/password-auth 包含以下内容的行之后添加了以下内容pam_unix.so

auth    [success=1 default=ignore]    pam_succeed_if.so service = systemd-user quiet
auth    sufficient                    pam_duo.so

pam_succeed_if 条件在链接的问题和 Arch wiki(本身链接在该问题中)上都有建议。然而,pam_succeed_if条件每次都失败,现在每次系统解锁时,DUO都会提示进行2FA。如果用户已经登录,如何可靠地跳过 DUO?

答案1

如果您希望仅在初始登录时进行 2FA 质询,则必须pam_duo.so仅引用处理初始登录的服务。

出于谨慎考虑,您可能希望明确列出以下服务:允许跳过 2FA,因此您不会意外地在您没有意识到需要 2FA 的服务上留下无 2FA 的“漏洞”。

线路

auth    [success=1 default=ignore]    pam_succeed_if.so service = systemd-user quiet

意思是:“如果条件“service = systemd-user”匹配,则跳过下一个auth配置行,否则继续执行,就好像该行根本不存在一样。”

systemd-user要为两个服务(例如和)提供类似的跳过sudo,您可以这样做:

auth    [success=2 default=ignore]    pam_succeed_if.so service = sudo quiet
auth    [success=1 default=ignore]    pam_succeed_if.so service = systemd-user quiet
auth    sufficient                    pam_duo.so

如果第一行匹配,我们就已经知道请求身份验证的服务是sudo,因此我们不必检查它是否是systemd-user。因此我们跳过两行:systemd-user检查和pam_duo.so身份验证模块。

如果您还想允许 2FA-less su(仅作为示例),您可以添加第三行:

auth    [success=3 default=ignore]    pam_succeed_if.so service = su quiet
auth    [success=2 default=ignore]    pam_succeed_if.so service = sudo quiet
auth    [success=1 default=ignore]    pam_succeed_if.so service = systemd-user quiet
auth    sufficient                    pam_duo.so

等等。

与往常一样,修改 PAM 配置时,明智的做法是不注销测试更改后:如果您通过 SSH 连接进行更改,请打开第二个 SSH 连接进行测试,而不是注销第一个连接。如果您在本地进行更改,请打开第二个终端窗口并在其中成为 root 用户,或者切换到不同的虚拟控制台并以同样的方式以文本模式登录。您需要一个已经以完全 root 权限登录的会话,以便在发现您犯了严重错误时撤消您的更改。

在生产系统上,我个人会首先登录第二SSH 连接并在进行 PAM 更改之前将其切换到 root,只是为了防止意外的“手指比大脑更快”注销。

答案2

我能够使用其他一些答案中的信息来使其发挥作用。首先,仅使用 PAM 模块无法区分登录和解锁,至少在 GNOME 上是这样的这个答案。该问题的其他答案建议使用pam_script作为解决方法,但我并不热衷于在我的 PAM 堆栈中使用某人的 github 项目。幸运的是,内置函数pam_exec可以完成相同的工作。

首先,修改脚本这个答案用于pam_exec

#!/bin/sh

SESSION_ID=$(loginctl session-status | head -1 | cut -d' ' -f1)

if [ -z "$SESSION_ID" ]; then
    exit 1
fi
if ! loginctl show-session "$SESSION_ID" | grep '^LockedHint=yes$' > /dev/null; then
    exit 1
fi

# Current session is locked, return success
exit 0

保存在或者任何你想要的地方,只要相应修改/etc/pam.d/is-current-session-locked传递到的路径即可。pam_exec确保使脚本可执行。

使用存储在SESSION_ID而不是的命令XDG_SESSION_ID是因为 GNOME(至少在 RHEL 9 上)不会将任何内容存储到XDG_SESSION_ID.返回值更改为退出值,因为pam_exec检查命令的退出值,而退出值本身取决于 PAM 堆栈逻辑。

接下来,我在 for 行之前添加了以下行pam_duo.so

auth    sufficient    pam_exec.so quiet /etc/pam.d/is-current-session-locked/pam_script_auth.sh

既然pam_duo也够了,反正处理完之后就什么也没有了。

当然,正如另一个答案中提到的,最好登录并在另一个会话中拥有 root shell。在解决这个问题时,我把自己锁在外面好几次,但因为我打开了 root shell,所以我可以切换到该会话并修复 PAM 文件,以便能够解锁图形会话。

相关内容