写点什么

Linux 可插拔认证模块(PAM)的配置文件、工作原理与流程

  • 2012-04-27
  • 本文字数:7056 字

    阅读完需:约 23 分钟

在上一篇文章《 Linux 可插拔认证模块的基本概念与架构》中,我们讲到了 PAM 的一些基本概念和相关架构,接下来我们看看 PAM 的配置文件如何使用。

PAM 的配置文件:

我们注意到,配置文件也放在了在应用接口层中,他与 PAM API 配合使用,从而达到了在应用中灵活插入所需鉴别模块的目的。他的作用主要是为应用选定具体的鉴别模块,模块间的组合以及规定模块的行为。下面是一个示例配置文件:

复制代码
# cat /etc/pam.d/system-auth:
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth required /lib/security/$ISA/pam_deny.so
account required /lib/security/$ISA/pam_unix.so
account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
account required /lib/security/$ISA/pam_permit.so
password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow nis
password required /lib/security/$ISA/pam_deny.so
session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so

我们可以看到, 配置文件有许多配置项 (每行对应一个配置项) 组成,每一行又分为四列 (每列对应一栏):

第一栏,认证鉴别接口类型:

指明程序所使用的 PAM 的认证接口类型,其实对应了刚才所说的四类接口:

auth:表示鉴别类接口模块类型用于检查用户和密码,并分配权限;

这种类型的模块为用户验证提供两方面服务。让应用程序提示用户输入密码或者其他标记,确认用户合法性;通过他的凭证许可权限,设定组成员关系或者其他优先权。

account:表示账户类接口,主要负责账户合法性检查,确认帐号是否过期,是否有权限登录系统等;

这种模块执行的是基于非验证的帐号管理。他主要用于限制 / 允许用户对某个服务的访问时间,当前有效的系统资源(最多可以多少用户),限制用户位置(例如:root 只能通过控制台登录)。

多数情况下 auth 和 account 会一起用来对用户登录和使用服务的情况进行限制。这样的限制会更加完整。比如下面是一个具体的例子:login 是一个应用程序。Login 要完成两件工作——首先查询用户,然后为用户提供所需的服务,例如提供一个 shell 程序。通常 Login 要求用户输入名称和密码进行验证。当用户名输入的时候,系统自然会去比对该用户是否是一个合法用户,是否在存在于本地或者远程的用户数据库中。如果该账号确实存在,那么是否过期。这些个工作是由 account 接口来负责。

如果用户满足上述登录的前提条件,那么他是否具有可登录系统的口令,口令是否过期等。这个工作就要由 auth 接口来负责了,他通常会将用户口令信息加密并提供给本地(/etc/shadow)或者远程的 (ldap,kerberos 等) 口令验证方式进行验证。

如果用户能够登录成功,证明 auth 和 account 的工作已经完成。但整个验证过程并没有完全结束。因为还有一些其他的问题没有得到确认。例如,用户能够在服务器上同时开启多少个窗口登录,用户可以在登录之后使用多少终端多长时间,用户能够访问哪些资源和不能访问哪些资源等等。也就是说登录之后的后续验证和环境定义等还需要其他的接口。这就是我们下面要提到的两组接口:

session:会话类接口。实现从用户登录成功到退出的会话控制;

处理为用户提供服务之前 / 后需要做的些事情。包括:开启 / 关闭交换数据的信息,监视目录等,设置用户会话环境等。也就是说这是在系统正式进行服务提供之前的最后一道关口。

password:口令类接口。控制用户更改密码的全过程。也就是有些资料所说的升级用户验证标记。

注意,上述接口在使用的时候,每行只能指定一种接口类型,如果程序需要多种接口的话,可在多行中分别予以规定。

第二栏,control_flag 控制位:

规定如何处理 PAM 模块鉴别认证的结果,简而言之就是鉴别认证成功或者失败之后会发生什么事,如何进行控制。单个应用程序可以调用多种底层模块,通常称为“堆叠”。对应于某程序按照配置文件中出现顺序执行的所有模块成为“堆”,堆中的各模块的地位与出错时的处理方式由 control_flag 栏的取值决定,他的四种可能的取值分别为 required、Requisite、sufficient 或 _optional:

required:表示该行以及所涉及模块的成功是用户通过鉴别的必要条件。换句话说,只有当对应于应用程序的所有带 required 标记的模块全部成功后,该程序才能通过鉴别。同时,如果任何带 required 标记的模块出现了错误,PAM 并不立刻将错误消息返回给应用程序,而是在所有模块都调用完毕后才将错误消息返回调用他的程序。 反正说白了,就是必须将所有的模块都执行一次,其中任何一个模块验证出错,验证都会继续进行,并在执行完成之后才返回错误信息。这样做的目的就是不让用户知道自己被哪个模块拒绝,通过一种隐蔽的方式来保护系统服务。就像设置防火墙规则的时候将拒绝类的规则都设置为 drop 一样,以致于用户在访问网络不成功的时候无法准确判断到底是被拒绝还是目标网络不可达。

requisite:与 required 相仿,只有带此标记的模块返回成功后,用户才能通过鉴别。不同之处在于其一旦失败就不再执行堆中后面的其他模块,并且鉴别过程到此结束,同时也会立即返回错误信息。与上面的 required 相比,似乎要显得更光明正大一些。

sufficient:表示该行以及所涉及模块验证成功是用户通过鉴别的充分条件。也就是说只要标记为 sufficient 的模块一旦验证成功,那么 PAM 便立即向应用程序返回成功结果而不必尝试任何其他模块。即便后面的层叠模块使用了 requisite 或者 required 控制标志也是一样。当标记为 sufficient 的模块失败时,sufficient 模块会当做 optional 对待。因此拥有 sufficient 标志位的配置项在执行验证出错的时候并不会导致整个验证失败,但执行验证成功之时则大门敞开。所以该控制位的使用务必慎重。

optional:他表示即便该行所涉及的模块验证失败用户仍能通过认证。在 PAM 体系中,带有该标记的模块失败后将继续处理下一模块。也就是说即使本行指定的模块验证失败,也允许用户享受应用程序提供的服务。使用该标志,PAM 框架会忽略这个模块产生的验证错误,继续顺序执行下一个层叠模块。

include:表示在验证过程中调用其他的 PAM 配置文件。在 RHEL 系统中有相当多的应用通过完整调用 /etc/pam.d/system-auth 来实现认证而不需要重新逐一去写配置项。这也就意味着在很多时候只要用户能够登录系统,针对绝大多数的应用程序也能同时通过认证。

另外还有一种比较复杂的格式为 value = action 的语法来设置控制标志,标志之间会以空格分开。格式如下:

复制代码
value1 = action1 value2 = action2 ……

其中 value 可以是下列 Linux PAM 库的返回值:

success、open_err、symbol_err、service_err、 system_err、buf_err、perm_denied、auth_err、cred_insufficient、authinfo_unavail、user_unknown、maxtries、new_authtok_reqd、acct_expired、 session_err、cred_unavail、cred_expired、cred_err、no_module_data、conv_err、 authtok_err、authtok_recover_err、authtok_lock_busy、authtok_disable_aging、 try_again、ignore、abort、authtok_expired、module_unknown、bad_item 和 default。

最后一个 (default) 能够用来设置上面的返回值无法表达的行为。

actionN 可以是一个非负整数或者是下面的记号之一:ignore、ok、done、bad、die 和 reset。如果是非负整数 J,就表示需要忽略后面 J 个同样类型的模块。通过这种方式,系统管理者可以更加灵活地设置层叠模块,模块的层叠路径由单个模块的反应决定。

关于这几个记号的详细解释:

ignore:如果使用层叠模块,那么这个模块的返回值将被忽略,不会被应用程序知道。

bad:他表示这个返回码应该被看作是模块验证失败的标志。如果这个模块是层叠模块的第一个验证失败的模块,那么他的状态值就是整个层叠模块验证的状态值和结果。

die:终止层叠模块验证过程,立刻返回到应用程序。

ok:告诉 PAM 这个模块的返回值将直接作为所有层叠模块的返回值。也就是说,如果这个模块前面的模块返回状态是 PAM_SUCCESS,那这个返回值就会覆盖前面的返回状态。注意:如果前面的模块的返回状态表示模块验证失败,那么不能使用这个返回值再加以覆盖。

done:终止后续层叠模块的验证,把控制权立刻交回应用程序。

reset:清除所有层叠模块的返回状态,从下一个层叠模块重新开始验证。

第三栏,module_path 即所使用模块的全路径名称。

以 Red Hat Enterprise Linux(RHEL)为例,值得注意的是在 i368/i686 和 x86_64 系统中模块的全路径名称是不一样的。所以当有的时候用户将一些 PAM 的配置文件从原来系统复制到新的系统时,如果两种系统架构不同,那么不修改模块路径名称则可能导致 PAM 报错。

第四栏,options 用于向特定模块传递相关的选项,然后由模块分析解释这些选项。

比如使用此栏打开模块调试模式,或向某模块传递诸如超时值之类的参数等。另外他还用于支持下文所述的口令映射技术。

如果任一栏出现错误或某模块没有找到,那么所在行被忽略并将其作为严重错误进行记录。

到此为止,PAM 的基本架构和 PAM 配置文件的基本格式已经做了比较详细的介绍。下一篇文章我们将介绍 PAM 是如何工作的。

到此为止,PAM 的基本架构和 PAM 配置文件的基本格式已经做了比较详细的介绍。下面我们需要看看 PAM 是如何工作的。

PAM 的工作原理与流程:

以 RHEL 系统为例,当 pam 安装之后有两大部分:在 /lib/security 目录下的各种 pam 模块以及 /etc/pam.d 和 /etc/pam.d 目录下的针对各种服务和应用已经定义好的 pam 配置文件。当某一个有认证需求的应用程序需要验证的时候,一般在应用程序中就会定义负责对其认证的 PAM 配置文件。以 vsftpd 为例,在它的配置文件 /etc/vsftpd/vsftpd.conf 中就有这样一行定义:

复制代码
pam_service_name=vsftpd

表示登录 FTP 服务器的时候进行认证是根据 /etc/pam.d/vsftpd 文件定义的内容进行。

那么,当程序需要认证的时候已经找到相关的 pam 配置文件,认证过程是如何进行的?下面我们将通过解读 /etc/pam.d/system-auth 文件予以说明。

首先要声明一点的是:system-auth 是一个非常重要的 pam 配置文件,主要负责用户登录系统的认证工作。而且该文件不仅仅只是负责用户登录系统认证,其它的程序和服务通过 include 接口也可以调用到它,从而节省了很多重新自定义配置的工作。所以应该说该文件是系统安全的总开关和核心的 pam 配置文件。

下面是 /etc/pam.d/system-auth 文件的全部内容:

复制代码
# grep -v ^# /etc/pam.d/system-auth
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password requisite pam_cracklib.so try_first_pass retry=3
password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so

第一部分表示,当用户登录的时候,首先会通过 auth 类接口对用户身份进行识别和密码认证。所以在该过程中验证会经过几个带 auth 的配置项。

其中的第一步是通过 pam_env.so 模块来定义用户登录之后的环境变量, pam_env.so 允许设置和更改用户登录时候的环境变量,默认情况下,若没有特别指定配置文件,将依据 /etc/security/pam_env.conf 进行用户登录之后环境变量的设置。

然后通过 pam_unix.so 模块来提示用户输入密码,并将用户密码与 /etc/shadow 中记录的密码信息进行对比,如果密码比对结果正确则允许用户登录,而且该配置项的使用的是“sufficient”控制位,即表示只要该配置项的验证通过,用户即可完全通过认证而不用再去走下面的认证项。不过在特殊情况下,用户允许使用空密码登录系统,例如当将某个用户在 /etc/shadow 中的密码字段删除之后,该用户可以只输入用户名直接登录系统。

下面的配置项中,通过 pam_succeed_if.so 对用户的登录条件做一些限制,表示允许 uid 大于 500 的用户在通过密码验证的情况下登录,在 Linux 系统中,一般系统用户的 uid 都在 500 之内,所以该项即表示允许使用 useradd 命令以及默认选项建立的普通用户直接由本地控制台登录系统。

最后通过 pam_deny.so 模块对所有不满足上述任意条件的登录请求直接拒绝,pam_deny.so 是一个特殊的模块,该模块返回值永远为否,类似于大多数安全机制的配置准则,在所有认证规则走完之后,对不匹配任何规则的请求直接拒绝。

第二部分的三个配置项主要表示通过 account 账户类接口来识别账户的合法性以及登录权限。

第一行仍然使用 pam_unix.so 模块来声明用户需要通过密码认证。第二行承认了系统中 uid 小于 500 的系统用户的合法性。之后对所有类型的用户登录请求都开放控制台。

第三部分会通过 password 口另类接口来确认用户使用的密码或者口令的合法性。第一行配置项表示需要的情况下将调用 pam_cracklib 来验证用户密码复杂度。如果用户输入密码不满足复杂度要求或者密码错,最多将在三次这种错误之后直接返回密码错误的提示,否则期间任何一次正确的密码验证都允许登录。需要指出的是,pam_cracklib.so 是一个常用的控制密码复杂度的 pam 模块,关于其用法举例我们会在之后详细介绍。之后带 pam_unix.so 和 pam_deny.so 的两行配置项的意思与之前类似。都表示需要通过密码认证并对不符合上述任何配置项要求的登录请求直接予以拒绝。不过用户如果执行的操作是单纯的登录,则这部分配置是不起作用的。

第四部分主要将通过 session 会话类接口为用户初始化会话连接。其中几个比较重要的地方包括,使用 pam_keyinit.so 表示当用户登录的时候为其建立相应的密钥环,并在用户登出的时候予以撤销。不过该行配置的控制位使用的是 optional,表示这并非必要条件。之后通过 pam_limits.so 限制用户登录时的会话连接资源,相关 pam_limit.so 配置文件是 /etc/security/limits.conf,默认情况下对每个登录用户都没有限制。关于该模块的配置方法在后面也会详细介绍。

可见,不同应用程序通过配置文件在认证过程中调用不同的 pam 模块来定制具体的认证流程。其中我们不难看出,其实可以根据实际的需要对 pam 的配置文件进行修改以满足不同的认证需求,例如下面的例子:

复制代码
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth required pam_tally.so onerr=fail deny=5
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password requisite pam_cracklib.so try_first_pass retry=3 minlen=10 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 difok=6
password requisite pam_passwdqc.so use_first_pass enforce=everyone
password sufficient pam_unix.so md5 remember=6 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session required pam_unix.so

在其中就增加了对用户密码修改时复杂度的限制,用户多次错误输入密码之后的锁定限制以及用户使用密码历史等限制选项。

所以我们通过对上述 system-auth 配置文件的修改,模块的增加和选项的变化,从很大的程度上增加了用户登录验证的安全性要求。我们会在之后的文章中对该配置进行详细说明。

另外也一定需要注意,在整个的 PAM 配置文件当中,配置项以及模块调用的逻辑顺序非常关键。因为 PAM 是按照配置项的先后顺序来进行验证。错误的模块调用顺序很可能导致严重的安全问题甚至系统错误。所以对 PAM 配置进行修改的时候务必要考虑这一点。

关于作者

王基立,现工作于红帽软件(北京)有限公司,具备多年的售前解决方案规划与售后技术支持经验,熟悉红帽所有平台类产品和解决方案。现常驻深圳任红帽软件华南区解决方案架构师一职,主要负责红帽解决方案在华为、中兴等大型电信企业用户环境中的设计、规划、应用以及相关售前工作。同时也为包括各高级分销商以及金融、政府、教育等各方面在内的管道和区域用户提供相关解决方案、技术咨询、技术培训、现场实施、技术支持等服务。


给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2012-04-27 00:0020911

评论

发布
暂无评论

数字人民币是现有世界上最完整设计最灵活的央行数字货币

CECBC

结语:Apache Spark 3_0(十二)

数据与智能

sql spark API

Windows Service 小品

喵叔

7月日更

安装 Druid 安装的时候提示 JAVA 版本的问题

HoneyMoose

Python OpenCV 图像处理之直方图相关知识细节,学点细的

梦想橡皮擦

7月日更

带你走进“华为链”

华为云开发者联盟

区块链 高性能 华为链 自研区块链平台 自主可控

音视频延时和抖动问题分析和解决

hanaper

讲的是切片,但好像又不只是切片?

Gopher指北

Go 语言

模块三

Winston

网络攻防学习笔记 Day89

穿过生命散发芬芳

网络攻防 7月日更

教你如何成为解决问题的高手

孙叫兽

高手 解决问题

如何激发责任心

escray

学习 极客时间 朱赟的技术管理课 7月日更

倒数第二天

IT蜗壳-Tango

7月日更

在线常用crontab表达式大全验证解析

入门小站

工具

充满科技感的农业,是年轻人的『菜』吗?

百度大脑

人工智能

云图说 | 华为云医疗智能体,智联大健康,AI药物研发

华为云开发者联盟

AI 药物研发 医疗智能体

腾讯被罚了!!!

Jackpop

全是蓝光,太狠了!

Jackpop

如何对抗信息茧房?

caiyongji

程序员 信息茧房

如何在二三线城市月薪过万(一)看完这篇后端简历优化,包你面试不断

小鲍侃java

面试 后端

被下架三次了,手慢无,23w字中高级Java面试题库!

Java架构师迁哥

ES6中的生成器函数是什么?

devpoint

ES6 JavaScrip 7月日更

数字人民币专利数量井喷 智能合约成新方向

CECBC

Druid 如何开启查询日志

HoneyMoose

模块三作业

河马先生

架构实战营

程序员如何快速成长为IT精英

孙叫兽

程序员 成长 IT职场

硬核!一套基于SpringBoot + Vue 的开源物联网智能家居系统!

编程菌

Java 编程 程序员 项目 计算机

一文搞定,轻松掌握,进程的内存消耗和泄漏

奔着腾讯去

内存泄露 Linux Kenel 进程管理 内存消耗 VMA

今晚拿下PHP反序列化的一系列操作

网络安全学海

php 网络安全 信息安全 渗透测试 漏洞分析

Linux之top命令

入门小站

Linux

坐下来谈谈如何写好一份简历?

童欧巴

面试 大前端 简历

Linux可插拔认证模块(PAM)的配置文件、工作原理与流程_Linux_王基立_InfoQ精选文章