分类: LINUX
2009-09-27 10:49:51
PAM,即可插入式验证模块(Pluggable Authentication Module,PAM),是sun公司最早提出和开发的一套为系统登录应用程序提供验证和相关的安全服务的套件。主要功能包括提供验证、帐户管理、会话管理和口令管理。
一般认为有三种 PAM:
Linux-PAM:Linux-PAM 涵盖了本文中讨论的所有 PAM。在任何一个 Linux 平台中的 PAM 的主要结构都类似于 Linux-PAM 版本。
OpenPAM:OpenPAM 是由 NAI 实验室的 Dag-Erling Smorgrav 开发的另一个 PAM 实现,属于 DARPA-CHATS 研究项目。由于它是开源的,因此它主要由 FreeBSD、NetBSD 及应用程序(加上 Mac OS X)使用。
Java™ PAM 或 JPam:PAM 主要是支持 Linux 和 UNIX 的标准验证模块。JPam 将 Java 部分与普通 PAM 联系了起来。JPam 允许基于 Java 的应用程序使用 PAM 模块或工具(如 auth、account、passwd、session 等)。它提供了 JAAS 和直接 API,并且支持大多数 Unix OS 和架构。
在我们的linux发现版系统中使用的是linux-pam。
PAM 框架由四个部分组成:
PAM 消费方
PAM配置文件
PAM 服务模块,也称为提供者
PAM 库
PAM消费方即是请求安全验证等操作的应用程序,代表程序有:login,gdm等系统账户管理程序。
作为PAM 消费方程序必须得与 PAM 库 libpam 链接。应用程序使用模块提供的任何服务之前,必须通过调用 pam_start初始化其 PAM 库的实例。调用 pam_start() 可初始化必须传递给所有后续 PAM 调用的句柄。应用程序完成使用 PAM 服务后,系统将调用 pam_end() 以清除 PAM 库已使用的任何数据。
linux-pam中,配置文件统一存放在/etc/pam.d/目录下,每一个配置文件对应一个PAM消费方程序,对应关系通过配置文件名实现(如:login的配置文件是/etc/pam.d/login)。
/etc/pam.d/system-auth
#类型 控制标志 模块名 参数(可选)
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
account required pam_unix.so
account sufficient pam_localuser.so
password requisite pam_cracklib.so try_first_pass retry=3
password sufficient pam_unix.so
session optional pam_keyinit.so revoke
session required pam_unix.so
类型段中的4种类型对应于服务提供模块的4种实现接口,不同类型代表接入该模块中不同的验证接口,该内容在服务提供者部分再作补充。
控制标志字段控制验证过程以如何的方式进行。控制字段有如下几种:
Required:表示此验证条件必需返回真,否则验证失败,但是这条错误不会立即返回,二是继续进行下面的验证操作直到验证条件全部结束时返回此错误。
Requisite: 该标志相似于Required指标,只是它在验证失败时立即终止当前验证进程并返回错误。
Sufficient:如果标记为 sufficient 的模块成功并且先前没有 Required 或 sufficient 模块失败,则忽略堆栈中的所有其余模块并返回成功。
Optional:如果堆栈中没有一个模块是 required 并且没有任何一个 sufficient 模块成功,则服务/应用程序至少要有一个 optional 模块成功。
Include: 类似于C语言中的include操作,仅仅把后面包括的文件扩展到当前位置。
PAM 服务模块是一个共享库,用于为系统登录应用程序(如 login、gdm等)提供验证和其他安全服务。当前的发行版系统中一般已经提供了一些常用的服务模块,比如pam_unix,模块提供以传统的unix方式来验证用户密码的服务。但如果我们想使用一些更为安全或者易用方式验证用户权限,我们可以通过编写新的PAM服务模块来实现。比如我们可以写一个双因子认证服务模块来代替系统默认的验证模块。
一个PAM服务模块包含四种验证接口,如下:
验证服务模块-用于授予用户访问帐户或服务的权限。提供此服务的模块可以验证用户并设置用户凭证。
帐户管理模块-用于确定当前用户的帐户是否有效。提供此服务的模块可以检查口令或帐户的失效期以及限时访问。
会话管理模块-用于设置和终止登录会话。
口令管理模块-用于强制实施口令强度规则并执行验证令牌更新。
此部分接口可以全部实现或者根据需要选择性的仅实现其中一种,比如在上面的双因子认证模块的作用是对用户的身份权限进行验证,所以我们只需要实现它的验证服务模块接口。
一个PAM服务模块的四种接口对应PAM配置文件的四种不同的控制标志,不同的标志代表验证操作进入服务模块中不同的验证接口。对应关系如下:
控制标志 服务接口名 接口函数
auth 验证服务模块 pam_sm_authenticate
account 帐户管理模块 pam_sm_acct_mgmt
session 会话管理模块 pam_sm_open_session/pam_sm_close_sessiont
password 口令管理模块 pam_sm_setcred
PAM库(libpam)是 PAM 体系结构中的中心元素。
编写PAM消费者程序和PAM服务提供者都需要PAM库提供支持,PAM库除了提供一些接口转换功能和消息传递(控制消费方与服务提供者之间通信)之外,另外还提供了一些基础功能的接口供上层调用。
当一个PAM消费方应用程序启动时,该程序首先会载入libpam动态库,libpam 将读取/etc/pam.d/目录下的配置文件 以确定针对该服务参与操作的模块,参与验证操作的服务模块会被顺次载入并顺序执行配置文件中指定的验证操作。
配置文件中的每一行将对应当前服务模块中的下面函数中的一个:
pam_authenticate
pam_acct_mgmt
pam_setcred
pam_open_session
pam_close_session
pam_chauthtok
如果对于该服务的操作(如验证或帐户管理配置文件中仅包含一个模块,则该模块的结果将确定操作的结果。
另一方面,如果为服务操作定义了多个模块,那么这些模块就堆叠起来,即,对于该服务存在一个 PAM 堆栈。 例如login的配置文件内容如下:
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth include system-auth
account required pam_nologin.so
account include system-auth
password include system-auth
session required pam_selinux.so close
session required pam_loginuid.so
......
这些项表示 login 服务需要做的验证操作集。要确定login服务最后验证操作的结果结果,各个模块的结果代码需要进行集成处理。在集成处理中,模块按照 /etc/pam.d/login中指定的顺序执行。每个成功/失败代码都会根据模块的控制标志集成到整体结果中。控制标志会导致栈很早就终止。例如,requisite 模块可能会失败,而 sufficient 或 binding 模块则可能会成功。处理栈之后,各个结果会组合成一个整体结果并随后传送给应用程序。
Solaris 开发者安全性指南
了解和配置 PAM
http://www.ibm.com/developerworks/cn/linux/l-pam/