You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

自制PAM模块:SSH登录时pam_sm_authenticate被调用两次的原因咨询

解答:SSH登录时PAM模块的pam_sm_authenticate被调用两次的原因与解决办法

我之前开发自定义PAM模块时也碰到过一模一样的问题!这种情况其实是SSH和PAM交互的正常特性,当然也可能和你的配置有关,下面给你拆解原因和排查方案:

主要原因

  • SSH的双认证流程设计:SSH协议在登录时会优先尝试无密码认证方式(比如公钥认证),哪怕你没配置公钥登录,SSH服务端也会先走这个流程触发一次PAM调用;当无密码认证失败后,才会切换到密码认证,这时候会第二次调用PAM的authenticate函数。你可以看看sshd_config里的PasswordAuthenticationChallengeResponseAuthentication配置,这两个开关会影响认证阶段的数量。
  • PAM栈的多阶段触发:如果你的/etc/pam.d/sshd配置文件里有多个auth类型的条目,或者某些内置模块(比如pam_unix.so)带有try_first_passuse_first_pass这类选项,也可能导致PAM模块被重复调用。

排查与解决步骤

  1. 开启SSH调试日志定位触发场景
    修改sshd_config中的LogLevelDEBUG3,然后重启SSH服务:

    sudo systemctl restart sshd
    

    之后登录时查看系统日志(通常是/var/log/auth.log/var/log/secure),你会清晰看到两次调用的触发来源——比如第一次是keyboard-interactive认证阶段,第二次是password阶段。

  2. 检查PAM配置栈
    打开/etc/pam.d/sshd,查看auth段的配置。如果你的自定义模块pam_hook.so被放在了多个auth条目里,或者和其他模块的逻辑冲突,就会重复执行。建议把自定义模块放在合适的位置,比如仅在密码认证阶段触发。

  3. 在模块代码中区分调用场景
    在你的pam_sm_authenticate函数里添加日志,打印调用时的flags参数和上下文:

    #include <syslog.h>
    // ...
    PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
        pam_syslog(pamh, LOG_DEBUG, "pam_sm_authenticate called, flags: %d", flags);
        // 其他逻辑...
    }
    

    通过日志里的flags值,你可以区分两次调用的场景(比如第一次可能带有PAM_SILENT,第二次带有PAM_PASSWORD_PROMPT),然后在代码里决定是否执行核心验证逻辑——比如只在密码认证的调用中处理用户名密码验证,其他场景直接返回PAM_SUCCESS

额外提示

其实这种两次调用是符合SSH和PAM的规范设计的,如果你不需要处理无密码认证阶段的调用,完全可以在模块里通过状态标记或者flags判断来跳过重复逻辑,避免重复执行验证操作。

内容的提问来源于stack exchange,提问作者Omer Anisfeld

火山引擎 最新活动