![在没有 PAM 的情况下验证用户身份的正确方法是什么?](https://linux22.com/image/59586/%E5%9C%A8%E6%B2%A1%E6%9C%89%20PAM%20%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E9%AA%8C%E8%AF%81%E7%94%A8%E6%88%B7%E8%BA%AB%E4%BB%BD%E7%9A%84%E6%AD%A3%E7%A1%AE%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
由于我的相关问题似乎没有受到太多关注,这里还有另一个问题: 如今,在 Linux 中通过用户名/密码提示来验证用户身份的正确方法是什么?
原则上,我想我必须获取用户名和密码,从 中读取相应用户的盐和哈希值/etc/shadow
。然后,我将计算给定密码和存储的盐的哈希值,并检查结果是否与存储在/etc/shadow
.
通常,我可以简单地通过 PAM(例如pam_unix
)进行身份验证,PAM 已经完成了所有这些操作,但我的应用程序是一个自定义 PAM 模块,并且我发现没有方法可以从另一个 PAM 模块调用一个 PAM 模块。如果这是可能的,我很乐意采用这个解决方案。
截至目前,我发现这个教程确实过时了http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.html从 1996 年开始,显然,影子支持还没有内置到 libc 中。它提到pw_auth
和valid
作为身份验证的辅助函数。我尝试将这些植入到我的代码中并链接到libshadow.a
影子工具,但我收到pw_auth
和 的“未解析的外部引用”错误valid
。代码看起来像这样:
if ((pw->pw_passwd && pw->pw_passwd[0] == '@'
&& pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL))
|| !valid (passwd, pw)) {
return (UPAP_AUTHNAK);
}
我没有进一步检查这一点,但无论如何这不是首选解决方案,因为每次更新 Shadow-utils 时我都必须更新我的代码。
我更愿意链接到一个提供针对/etc/shadow
.有这样的东西吗,我还没找到?或者其他解决方案?
答案1
在我看来,你对 Shadow-utils 更新的恐惧是没有根据的。该 HOWTO 中描述的例程可以在我的 Ubuntu 12.04 和 Mint 17 系统上使用,无需安装任何特殊的东西。
/etc/shadow
在 C 程序中读取信息的结构可以在/usr/include/shadow.h
和 中找到man 5 shadow
,并且您需要找到例如按名称定义的影子密码条目的函数,/usr/include/shadow.h
这getspnam
也会为您提供一个手册页 ( man getspnam
) 描述该内容和所有相关功能。
基于此,您应该能够获取任何给定名称的哈希密码条目。哈希密码应该有多个“$”标记,从哈希密码中删除最后一个“$”之后的所有内容,包括最后一个“$”,并将其作为盐呈现给crypt()
,glibc 版本(根据man 3 crypt
)应该能够处理“扩展”盐表示当今更常见的 SHA512 条目。