在 PAM 会话中对用户进行外部验证/在 PAM 会话中对 PAM 会话进行身份验证

在 PAM 会话中对用户进行外部验证/在 PAM 会话中对 PAM 会话进行身份验证

有没有办法在自定义 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。这里有几种可能性:

    1. 首次登录:您的模块返回PAM_CRED_INSUFFICIENT。这个案例是捕捉通过 PAM(通过cred_insufficient),在这种情况下,它被配置为将链标记为成功 ( ok),但继续前进
    2. 这不是第一次登录,您完成了custom_auth()并且成功了(它返回了PAM_SUCCESS)。在这种情况下,我们结束链 ( done) :授予访问权限
    3. 这不是第一次登录,并且custom_auth()没有得到很好的结果(PAM_AUTH_ERR或其他类型的内部错误)。在这种情况下,请跳过接下来的 2 行 ( default=2)。该链直接进入pam_deny,但总是失败:拒绝访问
  • 在第一个场景中,链条继续到pam_unix。这里有两种可能性:

    1. UNIX 身份验证成功。这标志着该链成功 ( ok) 且进入下一个模块
    2. UNIX 身份验证失败。跳过下一个模块 ( default=1),链以 结束pam_deny拒绝访问
  • 如果到了第三行,就说明第一次my_module结束了,成功了。您的模块再次被调用 ( ) 作为。又是两种可能:PAM_CRED_INSUFFICIENTpam_unix// do something else here?sufficient

    1. 这次,您的模块成功了:授予访问权限
    2. 该模块再次失败,但除了凭据不足之外还有另一个原因:拒绝访问

您可能还想执行自定义代码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将传递一个参数(通过argvargc),这应该对您有帮助定位运行时链中的模块。当然,你的firstLogin条件应该足以做出这样的区分。

相关内容