我正在为项目创建PAM模块。 PAM模块将使用一些库,该库将被某些命令行实用程序重用(而不是每次都重写所有内容)。在这个库中,我想让它解释根据远程主机的子网成员资格区分和/或记录的策略。接近,因为我可以告诉这个值可能来自验证应用程序,但我不知道。由于共享对象无法访问libpam中的pamh结构,因此我不能只执行pam_get_item(就像我可以从PAM模块本身那样),所以我不得不求助于其他方法。
我提出的最佳解决方案是让共享对象查找已连接的TTY,如果有,则转到utmp并找到与该TTY关联的登录进程,从那里提取IP地址。如果没有TTY,则假设它是网络用户的初始登录。然后,库会遍历套接字(当你执行ls -l /proc/<pid>/fd
时,我已经定义为基本上任何带有“socket”字样的符号链接,并使用套接字inode编号与{{1进行交叉引用)并提取与该inode编号关联的远程IP地址。如果它没有在那里找到inode,那么它假定它是Unix域或tcp6(IPv6支持即将到来,并且在不久的将来不是非常重要)。如果它仍然无法找到它,假设某个守护进程已经调用了一个链接它的应用程序并将其解释为(如果它值得的话,最终可能会做一些事情,但是现在如果前两个没有,这只是一个很大的NOOP不归还任何东西。
它似乎有效但我对PAM应该如何工作有一些高级别的问题:
是否有一些管理PAM运营的官方标准?例如,它是否被某个POSIX标准覆盖?我知道有多个PAM实现(我已经发现了四个或五个),但我不知道现有的共性是法律上还是事实上的,或者我是如何配置系统的。
我从模块本身(通过/proc/net/tcp
)开始ls -l /proc/<pid>/fd > /lsOutput
之后:
[root @ hypervisor pam] #cat / lsOutput total 0
lrwx ------。 1 root root 64 Jun 15 15:09 0 - &gt; / dev / null
lrwx ------。 1 root root 64 Jun 15 15:09 1 - &gt; / dev / null
lrwx ------。 1 root root 64 Jun 15 15:09 2 - &gt;的/ dev / null的
LR-X ------。 1 root root 64 Jun 15 15:09 3 - &gt;插座:[426180]
[root @ hypervisor pam]#
在用户登录后发出手册system()
:
ls
基本上,似乎TTY和任何其他套接字都只在会话模块完成后打开(我的临时测试模块的会话处理是[root@hypervisor pam]# ls -l /proc/18261/fd
total 0
lrwx------. 1 root root 64 Jun 15 15:15 0 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 1 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 11 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 12 -> /dev/ptmx
lrwx------. 1 root root 64 Jun 15 15:15 13 -> socket:[426780]
lrwx------. 1 root root 64 Jun 15 15:15 14 -> socket:[426829]
lrwx------. 1 root root 64 Jun 15 15:15 2 -> /dev/null
lrwx------. 1 root root 64 Jun 15 15:15 3 -> socket:[426180]
lrwx------. 1 root root 64 Jun 15 15:15 4 -> socket:[426322]
lr-x------. 1 root root 64 Jun 15 15:15 5 -> pipe:[426336]
l-wx------. 1 root root 64 Jun 15 15:15 6 -> pipe:[426336]
lrwx------. 1 root root 64 Jun 15 15:15 7 -> socket:[426348]
lrwx------. 1 root root 64 Jun 15 15:15 8 -> socket:[426349]
lrwx------. 1 root root 64 Jun 15 15:15 9 -> /dev/ptmx
[root@hypervisor pam]#
服务的堆栈中的最后一个)。我一直无法得到它(或者甚至想到连接客户端不会成为描述符3的TCP套接字的时候)。
这是因为我缺乏想象力还是一定如此?我倾向于后者,因为看起来与客户沟通将是做其他任何有用的事情的先决条件。我不确定,所以我觉得我应该问别人。描述符3总是作为身份验证客户端(我的.so只假设它是编号最小的TCP套接字,并且只有在没有TTY的情况下,但似乎sshd
应始终是连接客户端的描述符) 。将第一个TCP描述符拉为建立远程客户端身份的“确定性”方式?或者是没有规定的方式应该发挥作用,这是我的系统配置或SSH如何选择与PAM接口?
3
是设置rhost值还是来自其他地方?我已尝试sshd
- 浏览SSH和libpam的源代码,但没有骰子。我可以看到libpam在调用pam_set_item时处理主机值的设置,但实际上没有调用pam_set_item来将其设置为此特定主机。任何数量的帮助都会受到赞赏,我已经用Google搜索了,但是我开始在指尖上刮下碎片的底部。
我有兴趣了解这一点的主要原因是,我不仅会以“正确”的答案结束,而且大部分时间以后我都不会有任何意外。我们可以使用一些Solaris平台,但我的主要动机是假设基于实际上将保持不变的事物。
我也意识到我可以让客户端程序/模块将主机信息提供给库,但这可能会导致代码重写两到三次(因为CLI工具从utmp和PAM模块准备会话信息)来自pam_get_item)并且可能使项目看起来比实际需要的更复杂。
答案 0 :(得分:0)
回答你的一些问题:
“是否有一些管理PAM操作的官方标准?”
显然,是的。维基百科在Pluggable_Authentication_Module上的条目说“PAM被标准化为X / Open UNIX标准化过程的一部分,导致X / Open单点登录(XSSO)标准。”我从未发现这与我与它的交易特别相关。
“这只是因为我缺乏想象力还是必然如此?”
&lt; magicEightBall&gt;“专注并再次询问”&lt; / magicEightBall&gt; (提到“这个”的含糊不清 - 也许你可以澄清一下?
“描述符3是否始终是验证客户端?”
这是应用程序的行为,而不是PAM。
拉第一个TCP描述符是否是建立远程客户端身份的“确定性”方式?
也是应用程序的行为。
“sshd是设置rhost值还是来自其他地方?”
设置rhost值的是sshd。在openssh的文件auth-pam.c中,函数sshpam_init(),你会发现:
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
一些一般性说明: