第四章:Linux-PAM扩展控件和子堆栈

PAM定义了四种常见的控制语句:必需(required)、必要(requisite)、充分(sufficient)和可选(optional )(以及被广泛忽视的绑定——binding)。这些控件决定了PAM模块的成功和失败如何影响用户的身份验证。

Linux-PAM提供了额外的扩展控制语句(extended control statements),允许您微调响应,以及允许您转移策略处理的子堆栈参数。这些仅出现在Linux-PAM中。

扩展的控制

PAM模块的 yes 总是PAM_SUCCESS,但 no 有无数种含义。每个PAM模块可能会返回对查询的几个不同响应之一。使用扩展控件,您可以根据这些响应微调PAM语句处理拒绝的方式。记住,模块对每个查询只返回一个响应。

扩展控件将四个PAM控件替换为模块可能返回的每个响应的特定指令,以及您没有指定的任何响应的通用包罗万象指令。“如果此模块返回X,则阻止访问。如果模块返回Y,则足够好。如果模块返Z,则立即授予访问权限。如果有其他答案,请尝试下一个模块”。

通过在扩展控件周围使用方括号([])来标识它们。这是CentOS中pam_securetty模块的扩展控件示例:

括号内的每个条目代表一个PAM响应,去掉前导 PAM_(小写)。等号将响应与如何处理该响应的指令分隔开。此条目表示,当此模块返回PAM_USER_UNKNOWN时,策略应采取 ignore(忽略)操作。当模块返回PAM_UCCESS时,遵循名为 ok 的操作。如果响应为PAM_IGNORE,则采取 ignore 操作。当该模块用其他任何指令响应时使用的默认指令是 bad

pam_securetty 手册页面列出了五种可能的响应代码:PAM_SUCCESS 、 PAM_AUTH_ERR 、 PAM_INCOMPLETE、PAM_SERVER_ERR和PAM_USER_UNKNOWN。扩展控件定义了PAM_UCCESS和PAM_USER_UNKNOWN的自定义操作。所有其他案例都告诉PAM采取 bad 的行动

扩展的控制动作

考虑一下PAM政策。政策中的大多数声明都会影响是否允许访问的决定。在任何时候,策略都可能有一个状态,比如“如果没有其他人反对,允许访问”或“我们肯定会拒绝请求,但您以后的模块可以记账。”Linux-PAM的七个扩展控制操作旨在改变该策略的状态。

bad 操作告诉PAM身份验证请求失败。这就是为什么我们上面的例子使用它作为默认值——我们关心几个特定的故障,但对于大多数故障,我们只是说“不”。如果模块回复触发错误,就好像 required 模块失败了。PAM继续处理策略,但除非故意重置,否则身份验证最终会被拒绝。

die 操作告诉PAM身份验证请求失败,必须立即停止处理策略。遵循此模块的模块将不会被处理。当应答触发死亡时,PAM策略的行为就像一个 requisite 模块失败一样。

ok 操作告诉PAM身份验证请求成功。如果没有其他模块对象,则允许访问。它通常应用于PAM_SUCCESS返回码。ok 不能覆盖PAM策略中其他地方的错误响应。当应答触发 ok 时,PAM策略的行为就像 required 模块成功一样。

done 操作告诉PAM身份验证请求成功,PAM应该立即停止处理策略。如果策略中的早期内容没有返回错误,则策略允许访问。当应答触发 done 时,PAM策略的行为就像一个 sufficient 模块成功。

required 操作表示此响应不会改变策略的响应。较早的坏或好代表。该模块仍然可以执行其他操作,例如记录日志或运行无关的命令,但PAM不会让模块的工作或检查结果影响其访问决定。这就像 optional 控件的最常见情况。

reset 操作告诉PAM丢弃任何以前的坏结果或好结果,并继续处理策略,从剩余模块中获得新的成功或失败。这是Linux-PAM独有的。与 binding 控制一样,我从未见过在生产环境中部署 reset

最后,您可以指定一个数字作为操作。触发数字命令会告诉Linux-PAM跳过策略中的许多后续模块。数字最常用于pam_succeed_if模块,如第5章所述。

扩展格式的标准控件

每个标准PAM控件都可以用Linux-PAM扩展控件格式表示。了解这些可以提高您对扩展控件和传统控件的理解。

required 控制可以这样表示:

如果PAM模块返回PAM_UCCESS或PAM_NEW_AUTHTOK_REQD,则此控件采取 ok 操作。身份验证成功。如果模块返回PAM_IGNORE,PAM将忽略该模块。如果模块返回任何其他内容,则采取错误操作,身份验证失败。

requisite 控制看起来非常相似。

requisiterequired 之间的唯一区别是默认操作。如果 required 控件默认为bad,则 requisite 默认为die。如果具有此控件的模块发生故障,则拒绝访问并立即停止处理。

sufficient 控制看起来完全不同:

如果模块返回PAM_UCCESS或PAM_NEW_AUTHTOK_REQD,则策略立即允许访问。由于已完成的操作,没有进行进一步的处理。任何其他响应都不会影响策略的投票,尽管该模块可能会在系统上采取其他操作。

optional 控件类似于sufficient

在这里,PAM_SUCCESS或PAM_NEW_AUTHTOK_REQD使该模块表示 ok 并允许访问。任何其他结果都意味着该模块既不允许也不拒绝访问。处理仍在继续,但其他模块仍可以否决访问。

子堆栈(Substacks)

Linux PAM支持处理迂回或 substacks 。当包含将相应的规则从该文件拉入PAM策略时,PAM会单独处理子堆栈。子堆栈文件中的控件不能使整个策略停止处理,它只能终止子堆栈并返回主PAM策略。子堆栈中做出的决定确实会影响策略允许或拒绝访问的决定。

让我们来看一个常见的子堆栈示例。这是CentOS的 /etc/pam.d/login 中的身份验证策略,它规定了控制台登录:

此策略首先检查pam_securetty模块(第2章)。然后,它会落入文件系统 system-auth 中包含的子堆栈中。许多CentOS PAM配置使用 system-auth 作为子堆栈,允许跨多个服务进行通用配置。

考虑如何处理此子堆栈。第一个模块pam_env(第5章)是必需的。如果此模块失败,即使后续模块返回成功,请求也会被拒绝。然后我们有两个足够的模块。其中任何一个都可以返回成功并立即终止处理子堆栈。第四个是必要的,这意味着如果成功,策略处理将立即结束。最后一个模块pam_deny总是返回失败。

子堆栈有三个控制语句,可以立即终止身份验证策略——两个是必需的,一个是必要的。不过,如果子堆栈中的任何一个触发,处理将立即返回到主策略。也许子组批准了访问,也可能拒绝了访问。无论如何,无论子堆栈声明什么,PAM都会处理策略的其余主要部分。

返回 /etc/pam.d/login 策略。无论系统身份验证子包如何结束,PAM都会包含登录后文件并处理这些语句。由于这是一个包含而不是子堆栈,因此包含文件中的语句可以提前终止策略。

这将带您了解PAM的Linux-PAM扩展。现在让我们来看看一些流行的Linux-PAM模块。