Chinaunix首页 | 论坛 | 博客
  • 博客访问: 521878
  • 博文数量: 120
  • 博客积分: 3991
  • 博客等级: 中校
  • 技术积分: 1113
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-31 15:57
文章分类

全部博文(120)

文章存档

2011年(3)

2010年(6)

2009年(111)

我的朋友

分类: 网络与安全

2009-10-21 11:49:21

  介绍

  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, RedHat,RedFlag)都是这样做的。

老系统通常使用单个/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堆栈中的第二个认证模块联合起来。

实践

具有调用PAM的应用程序可以用来认证用户,登录服务,屏保,密码工具,可以和其他任何认证工具交互。
要实现这些功能,你需要配置或者是标准的/etc/passwd文件,或者是LDAP服务,或者是windows域控制器,或者是其他任何PAM支持的东西。

虽然,配置标准的PAM看上去比较简单,但是PAM却是非常灵活的,他可以把一个正在工作的系统折腾的不知所以然,所以我们在配置的时候还是要格外小心。接下来,希望给出一些例子,结合上一篇文章,更加全面的了解PAM。

在开始之前,你必须意识到修改PAM文件会有潜在的风险,如果修改不当,有可能无法登录,因此修复起来比较麻烦。所以修改之前备份相关的配置文件, 还有即使任何时候保留一个root已经登录的终端,防止出现问题后,还有一个登录终端可以操作。有点罗嗦,但绝对不是危言耸听。

一般性PAM配置

大部分Linux发行版本的PAM配置文件都在/etc/pam.d目录下, 每一个文件--包括cups,gdm,imap,login,passwd,samba,sshd,su,sudo,system- auth,useradd,xdm,xscreensave等--指定一个或多个PAM堆栈来告诉PAM如何为特定的程序或服务认证用户。

一个重要的文件便是/etc/pam.d/system-auth,他是pam_stack.so模块的标准控制文件,后面给给出描述。

现在给出一个PAM配置文件的例子,内容如下(list one):

#%PAM-1.0
auth requisite pam_unix2.so nullok
auth required pam_securetty.so
auth required pam_nologin.so
auth required pam_env.so
auth required pam_mail.so

account required pam_unix2.so

password required pam_pwcheck.so nullok
password required pam_unix2.so nullok use_first_pass use_authtok

session required pam_unix2.so none
session required pam_limits.so

上面这个文件来自SuSE Linux的/etc/pam.d/login文件。这里面的有些模块只是为了方便而不是去执行认证的任务。举个例子,上面的auth堆栈中调用的 pam_mail.so模块并不执行认证操作,pam_mail.so只是检查新邮件然后告诉当前的用户。
上面例子中大部分的模块在上一篇文章中 都已经简单介绍了。不过一个新的模块pam_nologin.so似乎没有介绍。pam_nologin.so模块检查/etc/nologin文件。如 果这个文件存在,这个模块将会拒绝所有的用户登录,并显示/etc/nologin的内容,但是root除外(root总是有例外和特权)

上面例子的一个关键点是pam_unix2.so模块是做为requisite模块在auth堆栈中被调用的,而剩余的模块采用的是 required。上次的帖子说道,如果是requisite类型的模块失败(比如输入错误的密码),PAM将绕过这个堆栈后面剩余的模块。与此相反,一 个required模块在这种情况会要求剩余的模块继续执行,尽管整个堆栈最终仍然是以失败退出。
那么上面的这个例子,就会导致这样的一个情况发生,如果用户输入错误的密码,非认证的auth模块将会忽略,这有时候是有用的,万一这些模块中的某一个做了不应该做的事情,在一次认证失败的事情驱动过程中。虽然不是所有的认证堆栈都会这样预防。

有些发行版本的/etc/pam.d/login文件的结构可能和我们上面举的例子完全不同。许多发行版本是调用pam_unix.so而不是 pam_unix2.so,另外模块的调用顺序也不同。有些发行版本更喜欢使用required控制方式,但是更常见的是requisite。

使用pam_stack.so模块

许多发行版本会大量使用pam_stack.so模块,
下面这个例子显示了一个典型的login配置文件是如何调用这个模块的(来自Gentoo)(list two)

#%PAM-1.0

auth required pam_securetty.so
auth required pam_stack.so service=system-auth
auth required pam_nologin.so

account required pam_stack.so service=system-auth

password required pam_stack.so service=system-auth

session required pam_stack.so service=system-auth
session optional pam_console.so

这个例子采用的是调用pam_stack.so模块而不是pam_unix.so模块或pam_unix2.so模块,通过service选项将配 置文件的名字传递给该模块(pam_stack.so)。这个传递过去的配置文件(system-auth)的内如如下(list three):

#%PAM-1.0

auth required pam_env.so
auth required pam_unix.so likeauth nullok

account required pam_unix.so

password required pam_cracklib.so retry=3
password required pam_unix.so nullok md5 shadow use_authtok

session required pam_limits.so
session required pam_unix.so use_first_pass

例子中pam_stack.so模块返回成功与否依赖于模块定义的配置文件的返回值(典型的是system-auth)。如果你仅仅只是配置一个服 务,那么这种方式可能没有什么好处。但是显然,你的系统肯定运行比较多的这些服务器程序,因此采用这种模式的好处就显而易见了:你仅仅只需要修改一个配置 文件就能使整个调用该配置文件的服务发生改变。

例子2中(/etc/pam.d/login)在调用了pam_stack.so模块后,调用了pam_nologin.so模块。 pam_nologin.so模块阻止非root用户登录,如果/etc/nologin文件存在,你可能考虑把它当成一个安全措施而应用在shell登 录服务上,但是不会应用在POP邮件获取上(仅举这个例子)。因此把这个调用放到login服务的文件本身里比放到auth-system文件里更有意 思。

增加网络认证工具

一种典型的修改PAM认证方式的案例是增加一些模块,使得系统能够使用类似LDAP服务或者Windows 域控制器服务等来认证用户。(我的这篇""里就是用的这个方法。)

为了做到这点,首先你要你的系统是否使用pam_stack.so模块。如果没有,你可以直接修改登录服务所使用的配置文件来增加新的认证工具。这 意味着你可能需要修改一个到几个文件;反过来,如果使用pam_stack.so模块,那你可以修改服务对应的配置文件来达到你的目的,或者你修改 /etc/pam.d/system-auth 来改变整个认证服务。
为了增加一个新的认证模块,你必须增加一个对该模块的引用 (reference)到相关的堆栈中去。很明显,auth堆栈是肯定需要修改的,而account堆栈对认证来说也是重要的。如果你准备修改/etc /pam.d/system-auth文件,你也应该增加新认证模块的引用到session堆栈和password堆栈中,作为可选方案,你可以修改这个 新的认证工具的配置文件,使得他本身能够从新协议中使用这些服务,比如为passwd工具服务的passwd文件。

一个大问题是,尽管你知道如何修改堆栈。但是修改的细节而因为不同的系统版本,不同的配置方式而不同。一般来说,你应该做这么几件事情:

  • 在已经存在的模块(pam_unix.so or pam_unix2.so)前增加新的模块引用。
  • 把新模块引用设置为sufficient标志。这样一来,如果新模块工作,他认证成功后,堆栈停止执行,忽略老的认证模块。如果新模块失败,老的模块仍然能够调用。(顺便说一句,对于帐号而言,使用本地管理可能更便利,比如root.)
  • 增加try_first_pass或者use_first_pass选项给老的(pam_unix.so or pam_unix2.so)模块。这样可以防止用户不再新认证工具列表中时,系统显示两次密码提示。

还是举个例子,考虑例子3(list three)的auth堆栈。你如果想增加一个LDAP服务来认证用户,那么你应该这样加入pam_ldap.so模块到堆栈中:

auth required pam_env.so
auth sufficient pam_ldap.so
auth required pam_unix.so likeauth   nullok try_first_pass
因为这是一个system-auth配置方式,他将影响所有依赖PAM认证的程序。新的系统首先会去尝试LDAP认证,如果成功,pam_stack.so模块成功,pam_unix.so模块不会被调用;如果LDAP认证失败,pam_unix.so将被调用,他的结果决定了pam_stack.so模块的成功与否。

任何情况下,你都应该记得修改auth堆栈和account堆栈,为了那些主要使用PAM认证的工具(login,pop,sshd,xdm,gdm,etc).其他工具,比如passwd配置文件,还要求有别的改变或者说出了除此之外的其他改变(后面会提到)。

同时你也要记得改变那些并不是PAM需求的配置文件,最明显的,如果你使用了网络认证工具,你可能需要修改名字服务交换(Name Service Switch,NSS)配置文件,他校验帐号的存在性。至于如何配置就依赖于你使用的网络认证工具了。

增加有用的登录模块

另外一种类型的PAM修改方式根本就不会改变登录认证,相反,他调用增加的模块来执行额外的任务。上次的帖子总结了这些模块中的几个,他们会执行各种有用的任务,比如创建用户主目录,执行密码强度检查。

增加这样的模块一般都简单明了:把需要的模块加入到已经存在的堆栈中去。(确定放到了正确的堆栈上,有些模块仅仅在某种堆栈上工作。)在大部分情况 下,把这些模块配置为required类型。这些模块不会设计成用来授权或者拒绝用户访问系统,他们通常情况下返回成功代码,因此他不会导致认证出现失 败。

应该把模块加在正确认证模块之前还是之后呢?大部分情况下,两种方式都工作,至少如果你仅仅获得一个认证模块,把这些附加模块放到认证模块的前面会更好。


Password堆栈的特殊考虑

密码服务,比如passwd程序,值得多关注一下。典型的,当增加一个新的认证方式时,你必须在/etc/pam.d/passwd文件中修改 auth,account,password堆栈。auth和account堆栈设计为required用来获得对密码设置的访问,即,他们控制了你输入 存在的密码的认证方式。

改变password堆栈有点不同,具体来说,通常你增加新的一行来提供新的服务,比如对auth,account堆栈的修改,但是你应该把新的服务设置为optional而不是sufficient.
这种配置方式的结果是即使某个用户是在本地定义而不是在远程定义,也会返回成功。
以前的默认的行(pam_unix.so or pam_unix2.so),你应该保留不动(除了增加use_first_pass选项外,如果默认没有的话);可能是觉得required标志的规则可能会导致问题发生,当帐号不再本地存在的时候,实际上,它不会。

阅读(7534) | 评论(0) | 转发(0) |
0

上一篇:tcpdump

下一篇:单用户模式维护 /目录

给主人留下些什么吧!~~