Linux系统的PAM模块认证⽂件含义说明总结
在Linux中执⾏有些程序时,这些程序在执⾏前⾸先要对启动它的⽤户进⾏认证,符合⼀定的要求之后才允许执⾏,例如login, su等。在Linux中进⾏⾝份或是状态的验证程序是由PAM来进⾏的,PAM(Pluggable Authentication Modules)可动态加载验证模块,因为可以按需要动态的对验证的内容进⾏变更,所以可以⼤⼤提⾼验证的灵活性。
⼀、PAM模块介绍
Linux-PAM(即linux可插⼊认证模块)是⼀套共享库,使本地系统管理员可以随意选择程序的认证⽅式。换句话说,不⽤(重新编写)重新编译⼀个包含PAM功能的应⽤程序,就可以改变它使⽤的认证机制,这种⽅式下,就算升级本地认证机制,也不⽤修改程序。
PAM使⽤配置/etc/pam.d/下的⽂件,来管理对程序的认证⽅式.应⽤程序调⽤相应的配置⽂件,从⽽调⽤本地的认证模块.模块放置
在/lib/security下,以加载动态库的形式进,像我们使⽤su命令时,系统会提⽰你输⼊root⽤户的密码.这就是su命令通过调⽤PAM模块实现的。
⼆、PAM的配置⽂件说明
PAM配置⽂件有下⾯两种写法:
1)写在/f⽂件中,但centos6之后的系统中,这个⽂件就没有了。
2)将PAM配置⽂件放到/etc/pam.d/⽬录下,其规则内容都是不包含 service 部分的,即不包含服务名称,⽽/etc/pam.d ⽬录下⽂件的名字就是服务名称。如: vsftpd,login等,只是少了最左边的服务名列。如:/etc/pam.d/sshd
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15[root@centos6-test06 ~]# cat /etc/pam.d/sshd
#%PAM-1.0
auth required pam_sepermit.so
auth include password-auth
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
由上⾯的pam模块⽂件内容看,可以将pam配置⽂件分为四列,
第⼀列代表模块类型
第⼆列代表控制标记
第三列代表模块路径
第四列代表模块参数
1)第⼀列:PAM的模块类型
Linux-PAM有四种模块类型,分别代表四种不同的任务,它们是:
认证管理(auth),账号管理(account),会话管理(session)和密码(password)管理,⼀个类型可能有多⾏,它们按顺序依次由PAM模块调⽤。
对以上四种模块类型进⼀步补充说明:
auth:表⽰鉴别类接⼝模块类型⽤于检查⽤户和密码,并分配权限;
这种类型的模块为⽤户验证提供两⽅⾯服务。让应⽤程序提⽰⽤户输⼊密码或者其他标记,确认⽤户合法性;通过他的凭证许可权限,设定组成员关系或者其他优先权。
account:表⽰账户类接⼝,主要负责账户合法性检查,确认帐号是否过期,是否有权限登录系统等;
这种模块执⾏的是基于⾮验证的帐号管理。他主要⽤于限制/允许⽤户对某个服务的访问时间,当前有
效的系统资源(最多可以多少⽤户),限制⽤户位置(例如:root只能通过控制台登录)。
多数情况下auth和account会⼀起⽤来对⽤户登录和使⽤服务的情况进⾏限制。这样的限制会更加完整。⽐如下⾯是⼀个具体的例⼦:login 是⼀个应⽤程序。Login要完成两件⼯作——⾸先查询⽤户,然后为⽤户提供所需的服务,例如提供⼀个shell程序。通常Login要求⽤户输⼊名称和密码进⾏验证。当⽤户名输⼊的时候,系统⾃然会去⽐对该⽤户是否是⼀个合法⽤户,是否在存在于本地或者远程的⽤户数据库中。如果该账号确实存在,那么是否过期。这些个⼯作是由account接⼝来负责。
如果⽤户满⾜上述登录的前提条件,那么它是否具有可登录系统的⼝令,⼝令是否过期等。这个⼯作就要由auth接⼝来负责了,他通常会将⽤户⼝令信息加密并提供给本地(/etc/shadow)或者远程的(ldap,kerberos等)⼝令验证⽅式进⾏验证。
如果⽤户能够登录成功,证明auth和account的⼯作已经完成。但整个验证过程并没有完全结束。因为还有⼀些其他的问题没有得到确认。例如,⽤户能够在服务器上同时开启多少个窗⼝登录,⽤户可以在登录之后使⽤多少终端多长时间,⽤户能够访问哪些资源和不能访问哪些资源等等。也就是说登录之后的后续验证和环境定义等还需要其他的接⼝。这就是我们下⾯要提到的两组接⼝:
session:会话类接⼝。实现从⽤户登录成功到退出的会话控制;
处理为⽤户提供服务之前/后需要做的些事情。包括:开启/关闭交换数据的信息,监视⽬录等,设置⽤户会话环境等。也就是说这是在系统正式进⾏服务提供之前的最后⼀道关⼝。
password:⼝令类接⼝。控制⽤户更改密码的全过程。也就是有些资料所说的升级⽤户验证标记。
注意:上述接⼝在使⽤的时候,每⾏只能指定⼀种接⼝类型,如果程序需要多种接⼝的话,可在多⾏中分别予以规定。
2)第⼆列:PAM的控制标记
PAM使⽤控制标记来处理和判断各个模块的返回值.(在此只说明简单的认证标记)。
规定如何处理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的语法来设置控制标志,标志之间会以空格分开。格式如下:
1value1 = 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:清除所有层叠模块的返回状态,从下⼀个层叠模块重新开始验证。
3)模块路径
模块路径.即要调⽤模块的位置. 如果是64位系统,⼀般保存在/lib64/security,如: pam_unix.so,同⼀个模块,可以出现在不同的类型中.它在不同的类型中所执⾏的操作都不相同.这是由于每个模块,针对不同的模块类型,编制了不同的执⾏函数。
4)模块参数
模块参数,即传递给模块的参数.参数可以有多个,之间⽤空格分隔开,如:password required pam_unix.so nullok obscure min=4 max=8 md5。
三、PAM模块的⼯作原理和流程
以RHEL系统为例,当pam安装之后有两⼤部分:在/lib/security⽬录下的各种pam模块以及/etc/pam.d和/etc/pam.d⽬录下的针对各种服务和应⽤已经定义好的pam配置⽂件。当某⼀个有认证需求的应⽤程序需要验证的时候,⼀般在应⽤程序中就会定义负责对其认证的PAM配置⽂件。以vsftpd为例,在它的配置⽂件/etc/f中就有这样⼀⾏定义:
1pam_service_name=vsftpd
表⽰登录FTP服务器的时候进⾏认证是根据/etc/pam.d/vsftpd⽂件定义的内容进⾏。
那么,当程序需要认证的时候已经到相关的pam配置⽂件,认证过程是如何进⾏的?下⾯我们将通过解读/etc/pam.d/system-auth⽂件予以说明。
⾸先要声明⼀点的是:system-auth是⼀个⾮常重要的pam配置⽂件,主要负责⽤户登录系统的认证⼯作。⽽且该⽂件不仅仅只是负责⽤户登录系统认证,其它的程序和服务通过include接⼝也可以调⽤到它,从⽽节省了很多重新⾃定义配置的⼯作。所以应该说该⽂件是系统安全的总开关和核⼼的pam配置⽂件。
下⾯是/etc/pam.d/system-auth⽂件的全部内容:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19[root@centos6-test06 ~]# 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_localuser.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 type=
password sufficient pam_unix.so sha512 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/f进⾏⽤户登录之后环境变量的设置。
然后通过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/f,默认情况下对每个登录⽤户都没有限制。关于该模块的配置⽅法在后⾯也会详细介绍。
可见,不同应⽤程序通过配置⽂件在认证过程中调⽤不同的pam模块来定制具体的认证流程。其中我们不难看出,其实可以根据实际的需要对pam的配置⽂件进⾏修改以满⾜不同的认证需求,例如下⾯的例⼦:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22#%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配置进⾏修改的时候务必要考虑这⼀点。
四、常⽤的PAM模块介绍
PAM模块结合管理
类型
说明
pam_unix.so
auth提⽰⽤户输⼊密码,并与/etc/shadow⽂件相⽐对.匹配返回0
account检查⽤户的账号信息(包括是否过期等).帐号可⽤时,返回0.
password修改⽤户的密码. 将⽤户输⼊的密码,作为⽤户的新密码更新shadow⽂件
pam_shells.so auth
account
如果⽤户想登录系统,那么它的shell必须是在/etc/shells⽂件中之⼀的shell
pam_deny.so account
auth
password
session
该模块可⽤于拒绝访问
pam_permit.so auth
account
password
session
模块任何时候都返回成功.
pam_securetty.so auth如果⽤户要以root登录时,则登录的tty必须在/etc/securetty之中.
pam_listfile.so auth
account
password
session
访问应⽤程的控制开关
pam_cracklib.so password这个模块可以插⼊到⼀个程序的密码栈中,⽤于检查密码的强度.
pam_limits.so session定义使⽤系统资源的上限,root⽤户也会受此限制,可以通过/etc/fshadow什么意思啊
或/etc/security/limits.d/*.conf来设定
五、PAM模式使⽤说明
1)pam_access.so模块
pam_access.so模块主要的功能和作⽤是根据主机名(包括普通主机名或者FQDN)、IP地址和⽤户实现全⾯的访问控制。pam_access.so 模块的具体⼯作⾏为根据配置⽂件/etc/f来决定。该配置⽂件的主体包含了三个字段——权限、⽤户和访问发起⽅。格式上是⼀个⽤""隔开的表。
第⼀个字段:权限(permission),使⽤"+"表⽰授予权限,⽤"-"表⽰禁⽌权限。
第⼆个字段:⽤户(user),定义了⽤户、组以及⽤"@"表⽰的在不同主机上的同名⽤户和同⼀主机上不同名⽤户。
第三个字段:访问发起⽅(origins),定义了发起访问的主机名称、域名称、终端名称。
⽽且/etc/f⽂件提供了很多范例供修改时参考,并且都给出了具体的说明,例如:
1
2
3
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48#禁⽌⾮root⽤户通过tty1访问相关服务
#-:ALL EXCEPT root:tty1
#禁⽌除了wheel、shutdown以及sync之外的所有⽤户访问相关服务
#-:ALL EXCEPT wheel shutdown sync:LOCAL
#禁⽌wheel⽤户通过.win.tue.nl之外的其它它终端访问相关服务
#-:wheel:ALL EXCEPT LOCAL .win.tue.nl
# 禁⽌下⾯的⽤户从任何主机登录。其它⽤户可以从任意地⽅访问相关服务#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL
# root⽤户允许通过cron来使⽤tty1到tty6终端访问相关服务
#+ : root : cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6
# ⽤户root允许从下⾯的地址访问相关服务
#+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
#+ : root : 127.0.0.1
# ⽤户root可以从192.168.201.⽹段访问相关服务
#+ : root : 192.168.201.
# ⽤户root可以从.中任何主机访问相关服务
#+ : root : .
# ⽤户root不允许从任何主机访问相关服务
#- : root : ALL
# ⽤户@nis_group和foo可以从任何主机访问相关服务
#+ : @nis_group foo : ALL
# ⽤户john只能从127.0.0.0/24来对本机相关服务进⾏访问
#+ : john : 127.0.0.0/24
# ⽤户john可以通过ipv4和ipv6的地址对本机相关服务进⾏访问
#+ : john : ::ffff:127.0.0.0/127
# ⽤户john可以通过ipv6的地址访问本机相关服务
#+ : john : 2001:4ca0:0:101::1
# ⽤户john可以通过ipv6的主机IP地址来访问本机
#+ : john : 2001:4ca0:0:101:0:0:0:1
# ⽤户john可以通过ipv6的IP地址和掩码来访问相关服务
#+ : john : 2001:4ca0:0:101::/64
# 开放所有⽤户对本机所有相关服务的访问
#- : ALL : ALL
⽰例说明(vsftp):
如果要在⽹络内架设⼀个FTP服务器,⽽且在该FTP服务器上需要强制地指定某个⽤户只能通过某个IP地址登录,这个时候pam_access.so 模块就派上⽤场了。假设我的FTP服务器是使⽤vsftp来构建的,具体操作是:
1
2
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论