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模块的扩展控件示例:
xxxxxxxxxx
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
括号内的每个条目代表一个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 控制可以这样表示:
xxxxxxxxxx
[success=ok new_authtok_reqd=ok ignore=ignore default=bad]
如果PAM模块返回PAM_UCCESS或PAM_NEW_AUTHTOK_REQD,则此控件采取 ok 操作。身份验证成功。如果模块返回PAM_IGNORE,PAM将忽略该模块。如果模块返回任何其他内容,则采取错误操作,身份验证失败。
requisite 控制看起来非常相似。
xxxxxxxxxx
[success=ok new_authtok_reqd=ok ignore=ignore default=die]
requisite 和 required 之间的唯一区别是默认操作。如果 required 控件默认为bad,则 requisite 默认为die。如果具有此控件的模块发生故障,则拒绝访问并立即停止处理。
sufficient 控制看起来完全不同:
xxxxxxxxxx
[success=done new_authtok_reqd=done default=ignore]
如果模块返回PAM_UCCESS或PAM_NEW_AUTHTOK_REQD,则策略立即允许访问。由于已完成的操作,没有进行进一步的处理。任何其他响应都不会影响策略的投票,尽管该模块可能会在系统上采取其他操作。
optional 控件类似于sufficient :
xxxxxxxxxx
[success=ok new_authtok_reqd=ok default=ignore]
在这里,PAM_SUCCESS或PAM_NEW_AUTHTOK_REQD使该模块表示 ok 并允许访问。任何其他结果都意味着该模块既不允许也不拒绝访问。处理仍在继续,但其他模块仍可以否决访问。
Linux PAM支持处理迂回或 substacks 。当包含将相应的规则从该文件拉入PAM策略时,PAM会单独处理子堆栈。子堆栈文件中的控件不能使整个策略停止处理,它只能终止子堆栈并返回主PAM策略。子堆栈中做出的决定确实会影响策略允许或拒绝访问的决定。
让我们来看一个常见的子堆栈示例。这是CentOS的 /etc/pam.d/login 中的身份验证策略,它规定了控制台登录:
xxxxxxxxxx
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth substack system-auth
auth include postlogin
此策略首先检查pam_securetty模块(第2章)。然后,它会落入文件系统 system-auth 中包含的子堆栈中。许多CentOS PAM配置使用 system-auth 作为子堆栈,允许跨多个服务进行通用配置。
xxxxxxxxxx
auth required pam_env.so
auth sufficient pam_fprintd.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 1000 quiet_success
auth required pam_deny.so
考虑如何处理此子堆栈。第一个模块pam_env(第5章)是必需的。如果此模块失败,即使后续模块返回成功,请求也会被拒绝。然后我们有两个足够的模块。其中任何一个都可以返回成功并立即终止处理子堆栈。第四个是必要的,这意味着如果成功,策略处理将立即结束。最后一个模块pam_deny总是返回失败。
子堆栈有三个控制语句,可以立即终止身份验证策略——两个是必需的,一个是必要的。不过,如果子堆栈中的任何一个触发,处理将立即返回到主策略。也许子组批准了访问,也可能拒绝了访问。无论如何,无论子堆栈声明什么,PAM都会处理策略的其余主要部分。
返回 /etc/pam.d/login 策略。无论系统身份验证子包如何结束,PAM都会包含登录后文件并处理这些语句。由于这是一个包含而不是子堆栈,因此包含文件中的语句可以提前终止策略。
这将带您了解PAM的Linux-PAM扩展。现在让我们来看看一些流行的Linux-PAM模块。