因此,您已经仔细调整了PAM语句,但它并没有像您预期的那样工作。也许身份验证在某个地方无缘无故地失效,或者所需的模块似乎根本没有被调用。如何判断哪些PAM模块被调用,以及身份验证请求何时终止?
在任何与计算机有关的事情中,所有的调试最终都归结为某种打印语句。PAM跳过预赛,直接把你扔到那里。您可以使用系统日志、pam_echo和pam_exec通过每个策略跟踪PAM请求的进度。您还可以启动程序调试程序,如 ktrace(1)
和 truss(1)
。
当你破坏主机的PAM配置,不再拥有root权限来修复错误时,没有什么能比得上那种可爱的感觉了。每当您使用主机的PAM配置进行调整时,请确保将具有root访问权限的终端保持打开状态。彻底测试所有更改。在注销之前,确保您仍然可以从全新的会话中获得root访问权限。
这些技术中的任何一种都可能使系统将身份验证信息泄露到系统日志或终端会话中。我强烈建议在一次性虚拟机上执行测试,而不是在有实时用户的系统上。
如果你无法弄清楚为什么一个模块的行为异常,可以从日志记录开始。
系统日志中显示了基本的系统管理问题。我最常见的配置文件错误是忘记PAM模块名称末尾的 .so ,即使在PAM大喊了几十年真正卑鄙的脏话之后也是如此。PAM搜索不存在的文件 pam_unix 而不是 pam_unix.so ,语句失败,策略拒绝访问。这些错误会出现在系统日志中,通常只对 root 用户可见。请先检查这些记录的错误。
PAM模块使用设施身份验证通过 syslog(3)
执行例行日志记录。这些通常会保存在一个只有 root 才能访问的受限日志文件中,比如CentOS上的 /var/log/secure 或FreeBSD和Debian上的 /var/log/auth.log 。
许多模块接受 debug 参数,使模块更加冗长。信息的内容和数量完全取决于模块。PAM模块开发人员都选择记录不同的内容,甚至——或者特别是——在打开调试的情况下,因此一些PAM模块提供了比其他模块更好的调试输出。
但有时,你甚至无法进入模块…
pam_echo模块将内容打印给进行身份验证的用户。并非所有程序都会将这些消息传递给用户,但当它工作时,它很有启发性,也很容易。
pam_echo接受一个文本字符串作为参数,即要传递回的消息:
xxxxxxxxxx
auth optional pam_echo PAM auth policy starting
如果应用程序将PAM消息传递回用户,则当策略点击此语句时,将显示文本PAM认证策略开始。
以下是最近FreeBSD系统中的 /etc/pam.d/system 。(我在这里使用FreeBSD是因为系统身份验证策略比普通Linux短得多。)我在每个模块之前都添加了对pam_echo的调用:
xxxxxxxxxx
auth required pam_echo checking OPIE
auth sufficient pam_opie.so no_warn no_fake_prompts
auth required pam_echo checking opieaccess
auth requisite pam_opieaccess.so no_warn allow_local
auth required pam_echo checking UNIX auth
auth required pam_unix.so no_warn try_first_pass nullok
当用户尝试使用 su(1)
这样的程序进行身份验证时,她将收到pam_echo消息:
xxxxxxxxxx
$ su -m
checking OPIE
checking opieaccess
checking UNIX auth
Password:
虽然这很嘈杂,但我们知道身份验证请求一直持续到策略的末尾。它还可能会破坏不期望额外输出的shell脚本。如果一个自动化过程在你放入调试回声(debugging echoes)的时候开始喷出错误,你就知道发生了什么。
您可以通过在pam_echo语句中使用转义符来显示PAM项的内容。pam_echo转义序列是%字符,后跟一个字母:
使用这些工具可以像这样吐出PAM内部项目:
xxxxxxxxxx
auth required pam_echo checking UNIX auth RUSER=%U USER=%u TTY=%t SERVICE=%s RHOST=%H
这些项目的一个问题是,任何以百分号开头的两个字符串都会被去掉百分号。百分号不是用户名、主机名和服务名中的典型字符,但如果您是少数特殊字符之一,请注意这一点。
Linux-PAM允许您通过单独的文本文件向pam_echo提供文本。使用 file= 选项和文件名,如下所示:
xxxxxxxxxx
auth optional pam_echo.so file=/etc/message
当用户进行身份验证时, /etc/message 中的文本会传递回她。将这种配置添加到身份验证过程中,可以向系统添加通用的法律警告。您可以在文本文件中使用pam_echo项,就像这样:
xxxxxxxxxx
Your access to this host as %u has been logged.
Unauthorized users will be mercilessly trampled by angry Luggage.
这不一定适用于所有服务——记住,有些程序不会将此文本交还给用户。但它可以为您处理许多情况,并且不将文本传递回用户的程序通常有单独的方法来显示这些消息。
如果pam_echo无法访问您需要的所有内容,或者客户端程序不会返回其输出,请尝试使用pam_exec从pam策略中提取更多信息。
如果您正在调试的软件无法将pam_echo消息传递给用户,或者pam_echo无法访问您要检查的值,请使用pam_exec。
我们在第3章中使用pam_exec来捕获pam会话的环境变量。第7章更详细地介绍了pam_exec。现在,我们将使用它将有关PAM会话的信息发送到系统日志。在这里,pamexec调用脚本 pamdebug.sh ,为脚本提供即将被调用的模块的参数。
xxxxxxxxxx
auth optional pam_exec.so /usr/local/scripts/pamdebug.sh pam_opie
auth sufficient pam_opie.so no_warn no_fake_prompts
auth optional pam_exec.so /usr/local/scripts/pamdebug.sh pam_opieaccess
auth requisite pam_opieaccess.so no_warn allow_local
auth optional pam_exec.so /usr/local/scripts/pamdebug.sh pam_unix
auth required pam_unix.so no_warn try_first_pass nullok
pamdebug.sh 脚本记录将要调用的内容:
xxxxxxxxxx
logger "process $PPID calling $1"
您还可以将任何其他调试添加到此脚本中,例如捕获内部PAM变量。但事实上,该脚本创建了类似这样的日志消息:
xxxxxxxxxx
Mar 14 08:52:21 testhost mwl: process 1314 calling pam_opie
您已经捕获了用户、进程ID和调用的模块。有了这些信息,您可以找出策略停止处理的位置,然后使用模块特定的功能来确定该语句是如何失败的。
许多Linux发行版都提供 pam_warn 用于调试。pam_warn模块不影响身份验证过程,但会将服务、终端、用户、远程用户和远程主机发送到系统日志。将pam_warn添加到要调试的任何身份验证策略的开头。在这里,我想使用pam_warn在CentOS上调试 su(1)
:
xxxxxxxxxx
auth optional pam_warn.so
auth sufficient pam_rootok.so
auth substack system-auth
auth include postlogin
由于pam_warn总是返回pam_IGNORE,因此您可以使用可选或必需的控件。
当用户尝试使用 su(1)
时,策略中的每个模块都会向系统日志发送消息。
xxxxxxxxxx
Aug 2 00:52:39 centos su: pam_warn(su-l:auth): function=[pam_sm_authenticate] flags=0 service=[su-l] terminal=[pts/3] user=[root] ruser=[mwl] rhost=[<unknown>]
Aug 2 00:52:41 centos su: pam_warn(su-l:setcred): function=[pam_sm_setcred] flags=0x2 service=[su-l] terminal=[pts/3] user=[root] ruser=[mwl] rhost=[<unknown>]
Aug 2 00:52:41 centos su: pam_systemd(su-l:session): Cannot create session: Already running in a session
Aug 2 00:52:41 centos su: pam_unix(su-l:session): session opened for user root by (uid=500)
如果需要进一步调试,可以查看pam_debug以在pam策略中专门设置值。
在pam_warn、pam_exec、pam_echo和系统日志之间,您可以从pam中提取几乎任何信息。如果一种方法不起作用,试试另一种。下一章你需要这种灵活性…