PAM详解html
1 简介
Linux-PAM(Pluggable Authentication Modules for Linux.基于Linux的插入式验证模块)是一组共享库,使用这些模块,系统管理者能够自由选择应用程序使用的验证机制。也就是说,勿需从新编译应用程序就能够切换应用程序使用的验证机制。甚至,没必要触动应用程序就能够彻底升级系统使用的验证机制。
在历史上,须要对用户进行验证的应用程序,必须同某种验证机制编译到一块儿。例如,传统的UN*X系统是使用密码对用户进行校验的。用户输入的密码通过crypt加密后,而后和/etc /passwd文件中的密文进行比较。在这种系统中,若是优先级授予的形式不是基于这种单一方式,就须要经过用户识别符和用户组识别符对优先权进行验证。服务和应用程序可使用基于用户和用户组识别的验证方式。一般,用户组的成员关系已经基于/etc/group指定了。
Linux- PAM工程的目的就是分离应用软件和验证机制的开发。经过验证函数库能够实现上述目的,一个应用程序可使用这些函数库去进行用户的认证。PAM库由本地的系统配置文件 /etc/pam.conf或者/etc/pam.d/目录下的一些配置文件来设置。而模块以动态可加载目标文件(使用dloptn(3)函数打开)的形式保存在 /lib/security和 /lib64/security
2 关于本文的一些说明
在开始阅读本文时,你应该清楚本文假定特定的文件是在特定的目录中。咱们遵守RFC-86的约定。若是你使用的linux发行版或其余支持PAM的系统以不一样的方式发布这些文件的话,那么你应该谨慎使用本文提供的例子。
例如,本文假设PAM可加载目标文件(模块)是在/lib/security/和/lib64/security/目录下,这是符合 HFS(Filesystem Hierarchy Standard)标准的。在 Solaris中,他们有属于 Solaris本身的PAM版本,在其余的UN*X中,你可能会在/usr/lib/security中看到这些文件。所以,使用本文的例子时应该注意进行必要的转换。
3 综述
咱们从一个例子开始讨论。首先找一个可以为用户提供服务的应用程序,login就是一个这样的程序。login要作两件事,首先确认发出请求的这个用户是否是该用户自己,而后为用户提供所需服务:在这里提供的是以一个以用户身份的运行的shell(bash, tcsh, zsh, etc.)
一般,login所作的前面的步骤只是提示用户输入密码并与验证是否与系统本地中存储的密码一致,而后对用户身份的验证,就是Linux-PAM的工做了。
从一个程序开发人员的角度看(在这个例子中,就是login程序的开发人员),Linux-PAM的工做就是校验--验证用户的身份。
Linux-PAM具备很大的灵活性,系统管理者能够经过它自由选择使用的验证方式。你也能够自由的为部分或全部PAM-aware的应用程序选择所使用的验证方式。Linux-PAM可以提供的验证方式多种多样,从绝对信任(pam_permit)到视网膜扫描、音频分析以及一次性口令,不一而足。
为了描述Linux-PAM的灵活性,咱们能够假想一种状况:一个系统管理者(父母)但愿提升用户(他们的子女)的数学能力。他/她就能够经过一个孩子们很是喜欢的游戏“Shoot 'em up game”达成上述目的,固然前提是这个游戏可以使用PAM提供的验证机制。验证能够设置:每次孩子们要玩游戏时,都须要回答出一组小于12的随机数的乘积。这样孩子们每次玩游戏以前均可以练习乘法运算。随着他们的成长,能够增长数字的大小。
Linux-PAM处理四种类型的任务:验证管理(auth)、账户管理(account)、会话管理(session)和口令管理 (password)。应用程序使用的管理方式经过相关的Linux-PAM配置文件设置。管理功能是有配置文件指定的模块完成的。配置文件的语法将会在下面讨论。
下图描述了Linux-PAM组织架构:
+----------------+
| application: X |
+----------------+ / +----------+ +================+
| authentication-[---->--\--] Linux- |--<--| PAM config file|
| + [----<--/--] PAM | |================|
|[conversation()][--+ \ | | | X auth .. a.so |
+----------------+ | / +-n--n-----+ | X auth .. b.so |
| | | __| | | _____/
| service user | A | | |____,-----'
| | | V A
+----------------+ +------|-----|---------+ -----+------+
+---u-----u----+ | | |
| auth.... |--[ a ]--[ b ]--[ c ]
+--------------+
| acct.... |--[ b ]--[ d ]
+--------------+
| password |--[ b ]--[ c ]
+--------------+
| session |--[ e ]--[ c ]
+--------------+
上图中,左边的应用程序X,它经过一些接口调用Linux-PAM库,而本身并不知道使用的验证方法。中间的Linux-PAM库参照图右边配置文件中的内容,加载应用程序X所适用的模块。这些模块进入某个管理组,并按照配置文件里的配置层叠在一块儿。在这些模块被Linux-PAM调用时,会对应用程序执行不一样的验证工做。应用程序和用户之间的信息交换能够经过 conversation函数实现。
若是一个程序想使用PAM,在程序中必须有支持PAM功能的代码。若是你有程序的源代码,你能够将合适的PAM功能代码添加进去,若是只有二进制文件,而二进制文件又不支持PAM,那就无能为力了。
4 Linux-PAM配置文件
当一个使用了PAM的应用程序启动时,它会启动于PAM-API的链接,而后去读取配置文件/etc/pam.conf,另外,配置文件也可能存在于/etc/pam.d中。若是存在/etc/pam.d,那么/etc/pam.conf将会被忽略。
这些配置文件列出了某个或某些系统服务所要求PAM验证规则,以及PAM规则失败事件发生时PAM-API的行为。
4.1 配置文件语法
下面将介绍配置文件的语法。配置文件是一个规则列表,每条规则都独占一行,但也可能因为某个规则长度过长致使溢出,可使用使用转意服符 `\<LF>'转写到下一行。 在同一行中,写在“#”后面的都是注释。
每一条规则的内容都是用空格分开的,前三个参数不区分大小写,以下:
service type control module-path module-arguments
(服务) (类型)(控制) (模块路径) (模块参数)
在/etc/pam.d目录下的配置文件,其规则内容都是不包含service部分的,即不包含服务名称,而/etc/pam.d目录下文件的名字就是服务名称。文件名必须是小写的。
PAM的一个重要特色是,许多个PAM规则叠加在一块共同起做用的来完成一个指定的验证工做。
service(服务) 一般都是相似于login或su这样的常见应用程序。为定义默认的规则,预留了service-name。
The service is typically the familiar name of the corresponding application: login and su are good examples.
The service-name, other, is reserved for giving default rules. Onmysql
ly lines that mention the current service
(or in the absence of such, the other entries) will be associated with the given service-application.
type(类型)是一个管理相近规则的管理组,他的做用就是指定后面的模块与哪个管理组相关联。包括下面四总类型:
acount 用于非验证的账户管理,它主要用来限制/容许用户对某个服务的访问时间,当前可用的系统资源(用户的最大数量),或者限制用户的位置(例如:root用户只能从控制台登陆)
auth 为用户提供了两个方面的验证,第一, 让应用程序提示用户输入密码或者其它的标记,确认用户的合法性;第二,经过它的凭证许可权限,设定组成员关系(不一样于上面讨论的/etc/groups文件)或者其它优先权。
passwd 用来升级用户验证标记
session 这类模块的主要用途是处理为用户提供服务以前/后须要作的一些事情,包括:记录打开/关闭交换数据的信息,挂载目录等。
若是在类型以前加了"-",则当模块丢失致使不能正常加载时,相关的日志将不会记录到系统日志中,对于那些不必定每次都须要安装的模块来讲,这一特性是有用的。
control(控制标志) 控制标志用来设置验证成功或者失败后PAM-API须要做出的反应,控制标志有两种语法,一种是简单的,只须要一个单独的关键字便可,另外一种复杂的方式是在方括号里面写“value=action”
简单语法以下:
required 表示即便某个模块对用户的验证失败,也要等全部的模块都执行完毕以后,PAM才返回错误信息。这样作是为了避免让用户知道被哪一个模块拒绝。若是对用户验证成功,全部的模块都会返回成功信息。
requisite 若是特定的模块对用户的验证失败,PAM立刻返回一个错误信息,把控制权交回应用程序,再也不执行其它模块进行验证。返回值与第一个fail的模块有关。
sufficient 表示若是一个用户经过这个模块的验证,PAM结构就马上返回验证成功信息(即便前面有模块fail了,也会把fail结果忽略掉),把控制权交回应用程序。后面的层叠模块即便使用requisite或者required控制标志,也再也不执行。若是验证失败,sufficient的做用和optional 相同。
optional 表示即便本行指定的模块验证失败,也容许用户享受应用程序提供的服务。使用这个标志,PAM框架会忽略这这个模块产生的验证错误,继续顺序执行下一个层叠模块。
include include all lines of given type from the configuration file specified as an argument to
this control.
substack include all lines of given type from the configuration file specified as an argument to
this control. This differs from include in that evaluation of the done and die actions in
a substack does not cause skipping the rest of the complete module stack, but only of
the substack. Jumps in a substack also can not make evaluation jump out of it, and the
whole substack is counted as one module when the jump is done in a parent stack. The
reset action will reset the state of a module stack to the state it was in as of beginning
of the substack evaluation.
还有一种比较复杂的语法来设置控制标志,它由一组value=action形式的标记组成,标记之间以空格分开:
[value1=action1 value2=action2 ...]
valueN能够是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, conv_again, incomplete, and default.最后一个(default)可以用来设置上面的返回值没法表达的行为。
actionN能够是一个无符号整数(非负整数),或者是下面的记号之一:ignore、ok、done、bad、die和reset。若是是非负整数 n,就表示须要忽略后面堆叠的n个一样类型的模块。经过这种方式,系统管理者能够更加灵活地设置层叠模块,模块的层叠路径由单个模块的反应决定。
ignore 若是使用层叠模块,这个模块的返回状态将不会对应用程序获取的返回值产生影响。
bad 它表示这个返回码应该被看做是模块验证失败。若是这个模块是层叠模块的第一个验证失败的模块,那么它的状态值就是整个层叠模块的状态值。
die 对层叠模块最终结果的影响至关于bad,而且马上反回到应用程序。
ok 告诉PAM这个模块的返回值直接做为整个层叠模块的返回值。也就是说,若是这个模块前面的模块返回状态是PAM_SUCCESS,那这个返回值就会覆盖前面的返回状态。注意:若是前面的模块的返回状态表示模块验证失败,那么这个“ok”标记的返回值将不会覆盖前面的返回值。
done 对层叠模块最终结果的影响至关于ok,而且马上反回到应用程序。
reset 清除全部层叠模块的返回状态,从下一个层叠模块从新开始。
对于简单语法的四种控制标志: required; requisite; sufficient; and optional,都有相同效果的复杂语法与其对应。
required [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
requisite [success=ok new_authtok_reqd=ok ignore=ignore default=die]
sufficient [success=done new_authtok_reqd=done default=ignore]
optional [success=ok new_authtok_reqd=ok default=ignore]
module-path(模块路径) 若是以"/"开头,则表示模块的全路径,不然就表示相对于 /lib/security/或/lib64/security/的相对路径。
module-arguments(模块参数) 一组用空格分开的变量,用来改变当前PAM模块的行为。对于当前模块无效的参数将会被忽略,并把错误信息记录到syslog中。注意,若是想在一个参数中使用空格,就要在其外面加上中括号,例子以下:
squid auth required pam_mysql.so user=passwd_query passwd=mada \
db=eminence [query=select user_name from internet_service \
where user_name='%u' and password=PASSWORD('%p') and \
service='web_proxy']
按照规则,你能够在字符串中使用字符“[”,可是若是要使用字符"]",就必须加上转移字符"\]"
配置文件中,任何一行的语法错误都会引起认证过程失败,失败信息会记录到syslog中。
4.2 基于目录的配置
比单一配置文件更灵活的配置方法是使用/etc/pam.d目录。这个目录中存放的都是以service-name(服务名称)命名的文件:每一个服务都有私有配置文件。
/etc/pam.d目录下的配置文件语法与/etc/pam.conf基本相同,由一下几部分组成:
type control module-path module-arguments
惟一不一样的是没有了service-name,service-name直接做为了文件的名字。例如 /etc/pam.d/login就是login服务的配置文件。
4.3 配置文件内容举例
本节咱们将会举一些Linux-PAM配置文件的例子。做为第一次配置你的系统,你能够按照下面的例子来配置。
一个合理的OTHER入口对于增强系统安全很是重要。下面是一个很是偏执的例子(可是以它做为开始并不坏)。
#
# default; deny access
#
other auth required pam_deny.so
other account required pam_deny.so
other password required pam_deny.so
other session required pam_deny.so
虽然这是一个最安全的策略(默认拒绝访问),可是对于一个PAM没有配置好的系统来讲,这中配置并不合理。例如:若是这个文件的其它部分编写很差,那么很容易把全部的用户挡在门外。
pam_deny.so模块并非很是完善,pam_deny模块在运行时不记录任何信息,除非用户在没法执行某个服务程序时可以与系统管理人员联系,不然系统管理者很长时间不会知道系统配置错误。
在上面例子中,以模块层叠的方式加入如下几行,系统管理者就能够得到有关的警告信息了:
#
# default; wake up! This application is not configured
#
other auth required pam_warn.so
other password required pam_warn.so
在使用/etc/pam.d目录的系统中,以other命名的配置文件内容应该是这样的:
#
# default configuration: /etc/pam.d/other
#
auth required pam_warn.so
auth required pam_deny.so
account required pam_deny.so
password required pam_warn.so
password required pam_deny.so
session required pam_deny.so
对于不熟悉Linux-PAM的系统管理者,下列几行能够做为最基本的系统配置:
#
# default; standard UN*X access
#
auth required pam_unix.so
account required pam_unix.so
password required pam_unix.so
session required pam_unix.so
5 安全问题
5.1 若是出现错误
若是发生错误,Linux-PAM可能会改变系统的安全性。这取决于你本身的选择,你能够选择不安全(开放系统)和绝对安全(拒绝任何访问)。一般,Linux-PAM在发生错误时,倾向于后者。任何的配置错误均可能致使系统整个或者部分没法访问。
配置Linux-PAM时,可能遇到最大的问题可能就是Linux-PAM的配置文件(/etc/pam.d/*或者/etc/pam.conf)被删除了。若是发生这种事情,你的系统就会被锁住。
有办法能够进行恢复,最好的方法就是用一个备份的镜像来恢复系统,或者登陆进单用户模式而后进行正确的配置。
5.2 不要使用脆弱的other文件
other文件的脆弱并非一件好事,由于支持PAM的应用程序若是没有特定的配置文件在/etc/pam.d下的话,则将会用other的配置,这样的话系统极可能受到***的威胁。
这是一个示例配置,pam_deny模块将拒绝全部的访问,而pam_warn模块将向auth.notice日志设备发送一条警告信息:
#
# The PAM configuration file for the `other' service
#
auth required pam_deny.so
auth required pam_warn.so
account required pam_deny.so
account required pam_warn.so
password required pam_deny.so
password required pam_warn.so
session required pam_deny.so
session required pam_warn.so
参考:
The Linux-PAM System Administrators' Guide(1.1.0)
Linux-PAM系统管理指南 http://doc.linuxpk.com/5214.htmllinux