有没有办法在自定义 PAM 会话中正确验证用户身份?
我目前正在编写自己的 PAM 身份验证模块,该模块允许用户通过外部令牌登录。必须先生成此令牌,然后用户才能使用我的模块登录。因此,当不存在令牌时,我想回退到默认的 PAM 身份验证,并在用户通过身份验证后立即继续使用我的代码。
这有可能吗?在伪代码中,我的模块如下所示:
pam_sm_authenticate() {
if (first_login) {
code_copied_from_pam_unix_to_authenticate_user();
// do something else here?
} else {
custom_auth();
}
}
作为快速修复,我将 Linux 的 pam_unix 模块中的代码复制到我自己的模块中,并且它可以工作。然而,这并不是很令人满意,因为它需要大量额外的库,并且只有在 pam_unix 不改变的情况下才有效。我更愿意在我的会话中打开另一个 PAM 会话,但尚未使其正常工作。
答案1
不要让您的代码执行所有逻辑:首先使用 PAM 及其配置来确保您的模块在最佳条件下运行(即不需要复制pam_unix
代码)。
首先,让我为您的模块建议另一个伪代码:
pam_sm_authenticate() {
if (first_login) return PAM_CRED_INSUFFICIENT;
else custom_auth();
}
在这里,我认为首次登录是凭证不足的情况。我告诉 PAM 该模块失败了,因为它没有完全验证用户身份所需的一切。现在,假设您的模块被称为my_module
,可能的配置是:
auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1] pam_unix.so
auth sufficient my_module.so
auth requisite pam_deny.so
详细信息如下:
首先,请求经过
my_module
。这里有几种可能性:- 首次登录:您的模块返回
PAM_CRED_INSUFFICIENT
。这个案例是捕捉通过 PAM(通过cred_insufficient
),在这种情况下,它被配置为将链标记为成功 (ok
),但继续前进。 - 这不是第一次登录,您完成了
custom_auth()
并且成功了(它返回了PAM_SUCCESS
)。在这种情况下,我们结束链 (done
) :授予访问权限。 - 这不是第一次登录,并且
custom_auth()
没有得到很好的结果(PAM_AUTH_ERR
或其他类型的内部错误)。在这种情况下,请跳过接下来的 2 行 (default=2
)。该链直接进入pam_deny
,但总是失败:拒绝访问。
- 首次登录:您的模块返回
在第一个场景中,链条继续到
pam_unix
。这里有两种可能性:- UNIX 身份验证成功。这标志着该链成功 (
ok
) 且进入下一个模块。 - UNIX 身份验证失败。跳过下一个模块 (
default=1
),链以 结束pam_deny
:拒绝访问。
- UNIX 身份验证成功。这标志着该链成功 (
如果到了第三行,就说明第一次
my_module
结束了,成功了。您的模块再次被调用 ( ) 作为。又是两种可能:PAM_CRED_INSUFFICIENT
pam_unix
// do something else here?
sufficient
- 这次,您的模块成功了:授予访问权限。
- 该模块再次失败,但除了凭据不足之外还有另一个原因:拒绝访问。
您可能还想执行自定义代码UNIX 身份验证后,即使失败了。为此,请将第二行更改为:
auth [success=ok default=bad] pam_unix.so
my_module
无论如何,这都会使该链再经历一次,但该链将被标记为失败的。即使您的模块最终在这里成功,该链也会失败。
您可能还想让您的模块知道我们在链中调用了它多少次:区分第一次调用my_module
和第二次调用。这可以通过参数轻松完成:
auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1] pam_unix.so
auth sufficient my_module.so second_time
auth requisite pam_deny.so
在这里,第二次调用pam_sm_authenticate
将传递一个参数(通过argv
和argc
),这应该对您有帮助定位运行时链中的模块。当然,你的firstLogin
条件应该足以做出这样的区分。