[ 2007/04/05 15:45 | by ]
PAM(Pluggable Authentication Modules)是一个好东西,在现代的Linux系统中已经必不可少了。以前也接触过,也修改过他的一些配置,不过都是依葫芦画瓢,没有仔细看过有关说明文档。今天在linux-mag上看到了这样的文章,正好可以仔细阅读一番。介绍分为两篇,这篇是介绍PAM的基本常识和配置文件的规则,下一篇是利用这些规则做一些联系。下面是阅读后的一些笔记:
PAM 配置文件
大部分现代Linux发行版本都使用/etc/pam.d/下面的文件来配置PAM。这个目录下的每一个文件是以程序提供的服务命名的,有些软件包提供了缺省的PAM配置文件,你也可以自己选择配置,特别是采用不同的协议来实现认证手段,比如你可以使用本地认证工具来配置su程序,而采用LDAP的方式来认证SSH登录。
配置文件的目的是用来创建一个或多个模块堆栈来为每一个程序服务。一个模块堆栈是一系列PAM模块,他们被调用以和特定的程序进行交互。每一个模块执行一个特定的任务,比如为网络服务娇艳密码,坚持用户是否有新邮件。作为登录过程的一部分,模块也可以执行用来执行一些非认证的任务,有时会显得比较方便。
/etc/pam.d/下的配置文件格式都是由很多行组成,每行有下面四个域:
management_group control_flag module[options]
每一个域都有其特定的含义,解释如下:
- management_group PAM服务的标识代码: auth 表示认证(典型的就是校验密码), account 表示帐号管理(无密码帐号访问规则,比如检查该用户是否有有权访问请求的服务), session 表示会话管理(处理灯入登出相关的内部事物), password 表示密码维护(比如修改密码)。
- control_flag 这个域表述了PAM应该如何应答模块的返回代码。可能的值有 requisite, required, sufficient, 和 optional. 这些值的详细描述清参考接下来的“PAM模块堆栈”
- module 模块的名字,可以是独立的模块名,也可以是绝对路径。如果没有提供完整路径,PAM通常在/etc/security/目录下寻找对应的模块。一些通用的模块介绍,可以参考后面的“通用PAM模块”
- options 可选项,一般是包括传递给模块的一些参数,详细描述请参考“通用模块选项”
- 大部分PAM使用的服务都有自己的PAM配置文件,因此你需要对该对一个的配置文件。有一个文件特别要注意,就是/etc/pam.d/system-auth。这个文件定义了一套标准的模块堆栈,他们能被pam_stack.so模块调用,其意图是想为PAM修改提供一站式服务。通过修改system-auth,你可以改变绝大部分或者全部服务的应答方式。当然,不是所有的发行版本都使用这个配置文件,不过很多(包括 Fedora, Gentoo, Mandrake, ,)都是这样做的。
老系统通常使用单个/etc/pam.conf配置文件。这个文件的工作方式就等同于现在的/etc/pam.d/下的配置文件,除了每行开头需要一个引导入口来表示这个配置应用在哪个程序上之外。
因为这个基本都很少见了,所以这里也就不详细介绍了。
PAM模块堆栈(PAM Module Stacks)一个PAM配置文件有一系列模块堆栈组成,他们安装相同的管理组集合在一起。当一个程序通过管理组来寻求处理时,PAM依次调用每一个模块,最终根据每一个模块的返回值以及与此相关连的control_flag域来返回一个代码。
一个典型的认证堆栈类似下面这样
auth required pam_env.so
auth required pam_unix.so likeauth nullok这个配置我文件意味着pam_env.so和pam_unix.so将依次调用,当PAM被要求认证用户的时候。
每一个模块有自己特定的任务来执行,后面会描述。
堆栈里的每一个模块返回成功或者失败代码,这些代码和模块的control_flag表示合作,用来最终返回一个结果,下面给出control_flag的总结:
模块控制标识以及返回值表
控制标志 成功结果 失败结果
----------------------------------------------
requisite 堆栈继续执行 堆栈立刻以失败方式中断
required 堆栈继续执行 堆栈继续执行,但是以失败方式中断
sufficient 堆栈立刻以成功方式中断,除非之前模块失败了 堆栈继续执行
optional 堆栈继续执行 堆栈继续执行,只有当模块丢失或者给出一个非决定性结果才失败。
理想情况下,不同模块的结果不会发生冲突,如果冲突了,那么规则能拒绝。比如,假设你想配置一个计算机使用本地密码数据(用pam_unix.so表达)或通过Kerberos(用pam_krb5.so表达)服务来认证用户。你可能会这样写配置文件。
auth required pam_env.so
auth required pam_unix.so likeauth nullok
auth sufficient pam_krb5.so try_first_pass(这个堆栈也包括了pam_env.so,pam_deny.so,现在你可以忽略)。这个例子指定pam_krb5.so是sufficient的。其目标是当Kerberos服务宕了胡或者帐号没有存储在这里时,通过本地数据库也可以登录。 但问题就出在pam_unix.so的控制标识required上。他表示用户必须通过本地认证。也就没有达到我们预期的目的,因为Kerberos模块没有起到作用。为了达到期望目标,我们应该把所有的模块的控制标志改成sufficient的。
auth required pam_env.so
auth sufficient pam_unix.so likeauth nullok
auth sufficient pam_krb5.so try_first_pass但是,问题又来了,当一个模块成功后,他会忽略其后的任何一个模块。在这个例子中,不会有这个问题,但是一些缺省的配置会在认证堆栈中包括额外的模块。有时候忽略接下里的模块不是问题,但有时候却是(下一篇会提到多认证方式)。
大部分使用PAM的服务要求多堆栈的帮助。典型的就是登录服务,他使用auth,account,session堆栈,有时候甚至定义至少一个password模块。
通用PAM模块(Common PAM Modules)PAM提供了非常多样的模块来帮助实现很多功能特征,另外,一些程序也提供了自己的PAM模块来扩展PAM功能。大部分模块可以在一个或多个管理组中工作。特命执行一项任务当他们作为一个堆栈的一部分被调用时同时也可以执行另外一项任务当作为另外一个管理组堆栈的一部分被调用时。
下面的表给出了一些重要的PAM模块的解释,虽然这个表远不够完整。
通用PAM模块
模块名称 管理组 效果
-------------------------------------------------
pam_unix.so auth, account, session, password 基于/etc/passwd和/etc/shadow认证用户
pam_unix2.so auth, account, session, password pam_unix.so变体,提供额外的一些功能
pam_securetty.so auth 阻止root登录,除非在/etc/securetty文件中设置PAM_TTY环境变量
pam_env.so auth 从/etc/security/pam_env.conf 文件中设置环境变量
pam_mail.so auth,session 根据指定的dir=diretory选项来检查邮件和给用户提供检查结果。
pam_lastlog.so auth 显示用户最后登录的消息
pam_deny.so auth, account, session, password 总是表示失败。
pam_limits.so session 用来设置用户对CPU,内存等资源的消耗限制,配置文件是 /etc/security/limits.conf
pam_mkhomedir.so session 为用户创建一个家目录,如果它已经不存在了。这为那些通过 网络登录服务器验证而登录的用户创造了便利。
pam_pwcheck.so password 根据/etc/login.defs文件规则来检查用户密码,以便用户在修 改密码时提高安全度。
pam_cracklib.so password 根据字典来检查密码,以确保密码至少显得显得比较安全和随机。
pam_stack.so auth, account, session, password 调用在system-auth的堆栈,返回其结果。
如果你仔细研究你的PAM配置文件,你应该可以看到上面的绝大部分模块。你也可以来确定这些模块的效果,比如我增加pam_mail.so模块看是否能达到上面说的作用。
通用模块选项(Common Module Options)大多数PAM模块接受可选项,而这些可选现对很多模块是非常有帮助的。更多的通用的可选现包括:
- debug. 这个选项创建而外的调式输出,典型的是将其发送给系统日志。
- try_first_pass. 大多数auth模块接受这个选项,它使得这个模块会去尝试堆栈里以前模块请求到的密码,如果这个密码不正确,这个模块会给出要求新密码的提示。
- use_first_pass. 这个选项工作方式和try_first_pass非常相似,除了它不会显示需要第二次密码的提示。实际上,在这种情况下,这个模块返回一个失败代码。
- use_authtok. 这个选项使得auth堆栈里的模块把密码当成令牌(token)传递给下一行。
- nullok. 通常,处理密码的模块拒绝空(empty,null)密码。这个选项告诉他们接受这样的密码。
- shadow. 接受这个选项的模块需要密切注意shadow文件的一些特征,比如密码年龄和过期时间。
大部分情况下,你不用管这些选项,尽管有时你可以想使用他,特别是在增加认证工具的时候。比如try_first_pass 或 use_first_pass经常用来和auth堆栈中的第二个认证模块联合起来。