问题描述
我正在研究由PAM模块和NSS模块组成的半径认证解决方案。
流程如下:
- 用户
ben
登录(通过login
命令) - 用户输入用户名:
ben
- 使用该用户名查询我的NSS模块,并返回默认的非特权用户
radius
,其行为与libnss-ato - 用户键入密码
- 将调用我的PAM模块,并将查询Radius服务器,如果接受了身份验证,则PAM模块将使用Radius供应商属性来选择将Radius用户映射到的本地用户名,此映射将写入数据库,以用于示例
ben
->admin
- 现在,我的NSS模块将读取该数据库并为Radius用户返回正确的本地用户名
- 使用
login
命令,将用户登录到正确的映射用户admin
现在,我的问题如下。 OpenSSH服务器将在PAM之前读取NSS。
这意味着流程如下:
- 用户
ben
的ssh输入 - SSH查询NSS并将
ben
映射到默认帐户radius
- 向用户显示密码提示并输入密码
- 调用了我的PAM模块,并映射了
ben
->admin
- SSH将以
radius
而不是admin
的形式生成会话,因为它使用在调用PAM之前从NSS获得的值
现在,此错误仅在第一次登录时发生,因为在第二次登录时,NSS将缓存数据并在第一次调用时返回正确的用户。
但这仍然是一个问题,首先是因为我不希望每次都将第一个登录名落入错误的用户,其次,如果ben
失去了管理员权限,那么他的下一个登录名仍将映射为admin由于我的NSS模块的NSS缓存而通过SSH进行访问。
我无法在第一个NSS调用上查询映射,因为从radius查询映射需要成功登录。
我的线索是:
- 让
radius
用户使用特殊的root setuid外壳,该外壳将读取我的NSS数据库并更改用户,然后执行真正的外壳,问题是我需要知道哪个半径用户已登录我可以在我的PAM模块中编写env var,但是由于外壳将是setuid,因此我需要一种安全机制来确保var是可信任的。我唯一看到的是在var中具有加密签名,并让setuid shell使用根0600中的私钥进行验证。 - 在PAM模块中致电
setuid
,但这听起来很可疑
解决方法
我最终将用户的外壳更改为setuid包装器,该包装器将特权授予了目标用户。