【问题标题】:Some high level questions about how PAM is designed关于如何设计 PAM 的一些高级问题
【发布时间】:2013-06-15 20:22:27
【问题描述】:

我正在为一个项目创建一个 PAM 模块。 PAM 模块将使用一个库,该库将被某些命令行实用程序重用(而不是每次都重写所有内容)。在这个库中,我想让它解释根据远程主机的子网成员身份区分和/或记录的策略。据我所知,这个值可能来自身份验证应用程序,但我不知道。由于共享对象无法从 libpam 访问 pamh 结构,因此我不能只执行 pam_get_item(就像我可以从 PAM 模块本身一样)所以我不得不求助于其他方式。

我想出的最佳解决方案是让共享对象查找已连接的 TTY,如果存在,请转到 utmp 并找到与该 TTY 关联的登录进程,然后从那里提取 IP 地址。如果没有 TTY,则假设它是网络用户的初始登录。然后该库遍历套接字(当您执行ls -l /proc/<pid>/fd 时,我基本上将其定义为目标文件名中带有单词“socket”的任何符号链接)并使用套接字inode 编号与/proc/net/tcp 交叉引用并提取与该 inode 号关联的远程 IP 地址。如果它在那里没有找到一个 inode,那么它假定它是 Unix 域或 tcp6(IPv6 支持即将到来,并且在不久的将来并不是非常重要)。如果它仍然无法找到它,假设某个守护进程调用了一个链接它的应用程序并将其解释为这样(最终可能会做一些事情,如果它是值得的,但现在它只是一个很大的 NOOP 如果前两个不'不返回任何东西。

它似乎有效,但我对 PAM 应该如何工作有一些高级别的问题:

  1. 是否有一些管理 PAM 操作的官方标准?例如,它是否被某个地方的 POSIX 标准所覆盖?我知道有多个 PAM 实现(到目前为止我发现了四个或五个),但我不知道现有的共同点是法律上的还是事实上的,或者我碰巧是如何配置我的系统的。

    李>
  2. 在我从模块本身执行ls -l /proc/<pid>/fd > /lsOutput 之后(通过system()):

[root@hypervisor pam]# cat /lsOutput total 0

lrwx------。 1 根 64 Jun 15 15:09 0 -> /dev/null

lrwx------。 1 根 64 Jun 15 15:09 1 -> /dev/null

lrwx------。 1 根 64 Jun 15 15:09 2 -> /dev/null

lr-x-----。 1 根 64 Jun 15 15:09 3 -> 套接字:[426180]

[root@hypervisor pam]#

并在用户登录后发布手册ls

[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]#

所以基本上,似乎 TTY 和任何其他套接字都只有在会话模块完成后才打开(我的临时测试模块的会话处理是 sshd 服务堆栈中的最后一个)。我一直无法让它成为其他情况(或者甚至想到连接客户端 不会 是描述符 3 处的 TCP 套接字的时候)。

这只是因为我缺乏想象力还是必然如此?我倾向于后者,因为与客户沟通似乎是做任何其他有用的事情的先决条件。我不确定,所以我觉得我应该问问别人。描述符 3 是否始终是身份验证客户端(我的 .so 仅假设它是编号最小的 TCP 套接字,并且仅在没有 TTY 的情况下,但似乎 3 应该始终是连接客户端的描述符)。提取第一个 TCP 描述符会是建立远程客户端身份的“确定性”方式吗?还是没有规定的方式应该发挥作用,而这正是我的系统的配置方式或 SSH 选择与 PAM 交互的方式?

  1. sshd 设置了 rhost 值还是来自其他地方?我已经在 SSH 和 libpam 的源代码上尝试了grep-ing,但没有骰子。当调用 pam_set_item 时,我可以看到 libpam 在哪里处理主机值的设置,但实际上并没有调用 pam_set_item 来将其设置为这个或那个特定的主机。

如果能提供任何帮助,我将不胜感激,我在谷歌上搜索过,但我开始在我的指尖上刮伤桶底。

我有兴趣知道这一点的主要原因是,我不仅会得到“正确”的答案,而且主要是为了以后不会有任何惊喜。我们可以在一些 Solaris 平台上执行此操作,但我的主要动机是基于实际不变的事物进行假设。

我也意识到我可以让客户端程序/模块将主机信息提供给库,但这可能涉及代码重写两到三次(因为 CLI 工具从 utmp 和 PAM 模块准备会话信息来自 pam_get_item) 并可能使项目看起来比实际需要的更复杂。

【问题讨论】:

标签: linux solaris pam


【解决方案1】:

回答您的一些问题:

“是否有一些管理 PAM 操作的官方标准?”

显然,是的。维基百科在Pluggable_Authentication_Module上的条目说“PAM 被标准化为 X/Open UNIX 标准化过程的一部分,从而产生了 X/Open 单点登录 (XSSO) 标准。”我从来没有发现这与我处理它特别相关。

“这只是我缺乏想象力还是必然如此?”

“集中注意力,再问一遍”(“这个”指的是哪个含糊不清——也许你可以澄清一下?

“描述符 3 是否始终是身份验证客户端?”

这是应用程序的行为,而不是 PAM。

提取第一个 TCP 描述符是否是建立远程客户端身份的“确定性”方式?

也是应用程序的一种行为。

“是 sshd 设置了 rhost 值还是来自其他地方?”

设置 rhost 值的是 sshd。在openssh的文件auth-pam.c中,函数sshpam_init(),你会发现:

sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);

一些一般说明:

  • 而不是关闭 TTY - 正如您稍后发现的那样 - 您可以通过 getppid() 和 /proc 遍历进程沿袭。
  • 不要相信 PAM 模块中的 system() - 它使用用户的环境,可能不是您所期望的。请改用 fork()/execlp()。

【讨论】:

  • 遍历进程树如何获得 IP 地址?我正在关闭 TTY,因为这告诉我我还没有回溯到可能捕获与非会话(或更糟糕的是,其他会话)相关的 IP 地址。此外,XSSO 是另一种 PAM 实现(由 Open Group 指定),它将 Kerberos/SSO 混合在一起(不是总体标准)。 XSSO 与 OpenPAM 或 Solaris 的 libpam 类似。例如,没有其他 PAM 实现具有 XSSO 的凭据缓存、辅助登录或用户名映射。
  • fwiw,我最终发现实际上并没有 PAM 的总体标准(这让我感到惊讶),但是作为 LSB 的一部分存在的 Linux-PAM 实现存在一些模糊的描述,但它基本上只是给出了一堆关于模块倾向于做什么以及常见约定是什么的空话陈述。随后是对 SPI 和 API Linux-PAM 支持的基本描述。有可能在某个时候他们会充实它并确保不同的组件提供更多的保证,但现在它模糊得令人不安。
  • 我已经决定硬着头皮做一个类似 setRemoteAddress() 的解决方案,它设置一个内部值,只有在库在 utmp 中找不到任何东西时才会查看该值。我已经决定没有可靠的方法来以编程方式确定远程地址。我希望它的设置类似于 loginuid 或其他东西的设置方式(即通过 PAM-SPI,甚至通过核心 libpam 会更好),但事实并非如此,因此您必须等待应用程序执行 utmp。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-25
  • 2011-08-05
  • 1970-01-01
相关资源
最近更新 更多