Pluggable Authentication Modules(可插入验证模块,简称PAM)
Linux-PAM(Pluggable Authentication Modules for Linux,基于Linux的插入式验证模块)是一组共享库,使用这些模块,系统管理者可以自由选择应用程序使用的验证机制。也就是说。勿需重新编译应用程序就可以切换应用程序使用的验证机制。将系统提供的服务和该服务的认证方式分开,使得系统管理员可以灵活地根据需要给不同的服务配置不同的认证方式而无需更改服务程序,同时也便于向系统中添加新的认证手段。应用程序通过libpam函数库来提供服务,应用程序与PAM的结合通过配置文件来完成。
使用ldd命令查看有哪些程序使用pam验证,并非所有的程序都是用PAM
[root@localhost ~]# ldd `which login` | grep pam.so libpam.so.0 => /lib64/libpam.so.0 (0x00007ff2566cc000) [root@localhost ~]# ldd `which sshd` | grep pam.so libpam.so.0 => /lib64/libpam.so.0 (0x00007f83bdf05000) [root@localhost ~]#
这些功能模块存放在/lib/security/目录里,应用程序通过libpam函数库来动态加载所需要的模块,实现认证方式,每一个认证模块都会返回pass和fail结果,从而决定验证的成功与否。通过配置文件来定制服务使用那些模块,一般来说它们都存放在/etc/pam.d/目录下,
/etc/pam.d/login /etc/pam.d/sshd
注意:pam产生的日志记录会在/var/log/secure
以字符终端验证程序login为例,来初步了解一下pam的验证过程
[root@localhost ~]# cat /etc/pam.d/login #%PAM-1.0 auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth substack system-auth auth include postlogin account required pam_nologin.so account include system-auth password include system-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session required pam_loginuid.so session optional pam_console.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open session required pam_namespace.so session optional pam_keyinit.so force revoke session include system-auth session include postlogin -session optional pam_ck_connector.so [root@localhost ~]#
PAM验证类型:
*auth验证使用者身份,提示输入账号和密码 *account基于时间或者密码有效期来决定是否允许访问 *password禁止用户反复尝试登陆,在变更密码时进行密码复杂性控制 *session进行日志记录,或者限制用户登录的次数,资源使用
PAM控制类型:
required必要条件,表示本模块必须返回成功才能通过认证;如果返回成功,继续后续验证,最后是否成功由有序验证决定;
但是如果该模块返回失败的话,失败结果也不会立即通知用户,二十要等所有模块全部执行完毕再将失败结果返回给应用程序。
requisite必要条件与required类型,该模块必须返回成功才能通过认证;如果返回成功,继续后续验证,最后是否成功由后续验证决定;
但是一旦该模块返回失败,将不再执行任何模块,而是直接将控制权返回给应用程序。
sufficient:
充分条件,表名本模块返回成功已经足以通过身份认证的请求,不必再执行其他的模块;如果验证成功,就立刻返回成;
但是如果本模块返回失败的话可以忽略。
optional可选条件,表明本模块是可选的,它的成功与否一般不会对身份认证起关键作用,其返回值一般被忽略。
include包含,后边是一个文件
[root@localhost ~]# cat /etc/pam.d/system-auth #%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_faildelay.so delay=2000000 auth sufficient pam_fprintd.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 1000 quiet_success auth required pam_deny.so account required pam_unix.so account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 1000 quiet account required pam_permit.so password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_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 optional pam_systemd.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so [root@localhost ~]#
*pam_securetty.so
pam_securetty root可以登录的tty
[root@localhost ~]# cat /etc/securetty console vc/1 vc/2 vc/3 vc/4 vc/5 vc/6 vc/7 vc/8 vc/9 vc/10 vc/11 tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8 tty9 tty10 tty11 ttyS0 ttysclp0 sclp_line0 3270/tty1 hvc0 hvc1 hvc2 hvc3 hvc4 hvc5 hvc6 hvc7 hvsi0 hvsi1 hvsi2 xvc0
删除tty3看看是否root还能在tty3登录(不能)
*pam_env.so登录时选择是否设置环境变量
[root@localhost ~]# cat /etc/security/pam_env.conf # # This is the configuration file for pam_env, a PAM module to load in # a configurable list of environment variables for a # # The original idea for this came from Andrew G. Morgan ... #<quote> # Mmm. Perhaps you might like to write a pam_env module that reads a # default environment from a file? I can see that as REALLY # useful... Note it would be an "auth" module that returns PAM_IGNORE # for the auth part and sets the environment returning PAM_SUCCESS in # the setcred function... #</quote> # # What I wanted was the REMOTEHOST variable set, purely for selfish # reasons, and AGM didn't want it added to the SimpleApps login # program (which is where I added the patch). So, my first concern is # that variable, from there there are numerous others that might/would # be useful to be set: NNTPSERVER, LESS, PATH, PAGER, MANPAGER ..... # # Of course, these are a different kind of variable than REMOTEHOST in # that they are things that are likely to be configured by # administrators rather than set by logging in, how to treat them both # in the same config file? # # Here is my idea: # # Each line starts with the variable name, there are then two possible # options for each variable DEFAULT and OVERRIDE. # DEFAULT allows and administrator to set the value of the # variable to some default value, if none is supplied then the empty # string is assumed. The OVERRIDE option tells pam_env that it should # enter in its value (overriding the default value) if there is one # to use. OVERRIDE is not used, "" is assumed and no override will be # done. # # VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]] # # (Possibly non-existent) environment variables may be used in values # using the ${string} syntax and (possibly non-existent) PAM_ITEMs may # be used in values using the @{string} syntax. Both the $ and @ # characters can be backslash escaped to be used as literal values # values can be delimited with "", escaped " not supported. # Note that many environment variables that you would like to use # may not be set by the time the module is called. # For example, HOME is used below several times, but # many PAM applications don't make it available by the time you need it. # # # First, some special variables # # Set the REMOTEHOST variable for any hosts that are remote, default # to "localhost" rather than not being set at all #REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST} # # Set the DISPLAY variable if it seems reasonable #DISPLAY DEFAULT=${REMOTEHOST}:0.0 OVERRIDE=${DISPLAY} # # # Now some simple variables # #PAGER DEFAULT=less #MANPAGER DEFAULT=less #LESS DEFAULT="M q e h15 z23 b80" #NNTPSERVER DEFAULT=localhost #PATH DEFAULT=${HOME}/bin:/usr/local/bin:/bin #:/usr/bin:/usr/local/bin/X11:/usr/bin/X11 # # silly examples of escaped variables, just to show how they work. # #DOLLAR DEFAULT=$ #DOLLARDOLLAR DEFAULT= OVERRIDE=$${DOLLAR} #DOLLARPLUS DEFAULT=${REMOTEHOST}${REMOTEHOST} #ATSIGN DEFAULT="" OVERRIDE=@ [root@localhost ~]#
*pam_unix.so系统中核心的一个pam模块,专门研制下面两个文件,验证用户密码/etc/passwd,/etc/shadow
[root@localhost ~]# cat /etc/pam.d/system-auth #%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_faildelay.so delay=2000000 auth sufficient pam_fprintd.so auth sufficient pam_unix.so nullok try_first_pass auth requisite pam_succeed_if.so uid >= 1000 quiet_success auth required pam_deny.so account required pam_unix.so account sufficient pam_localuser.so account sufficient pam_succeed_if.so uid < 1000 quiet account required pam_permit.so password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_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 optional pam_systemd.so session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid session required pam_unix.so [root@localhost ~]#
*pam_seccesed_if.so uid <500
uid < 500立刻成功
*pam_permit.so 永远返回成功
*pam_nologin.so
/etc/nolog这个文件只要存在,非root用户不能登录系统,但是已经登录的没有影响。在这个文件中还可以随意写一些信息,root用户登录可以看到
*pam_access.so 限制用户user不能通过ttyx登录
[root@localhost ~]# cat /etc/pam.d/login #%PAM-1.0 auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth substack system-auth auth include postlogin account required pam_nologin.so account include system-auth password include system-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session required pam_loginuid.so session optional pam_console.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open session required pam_namespace.so session optional pam_keyinit.so force revoke session include system-auth session include postlogin -session optional pam_ck_connector.so [root@localhost ~]#
*pam_echo.so
[root@localhost ~]# cat /etc/pam.d/passwd #%PAM-1.0 auth include system-auth account include system-auth password substack system-auth -password optional pam_gnome_keyring.so use_authtok password substack postlogin [root@localhost ~]#
[root@localhost ~]# cat /etc/pam.d/sshd #%PAM-1.0 auth required pam_sepermit.so auth substack password-auth auth include postlogin # Used with polkit to reauthorize users in remote sessions -auth optional pam_reauthorize.so prepare 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 session include postlogin # Used with polkit to reauthorize users in remote sessions -session optional pam_reauthorize.so prepare [root@localhost ~]#
*pam_time.so允许的时间范围(Only the account service is supported)
[root@localhost ~]# cat /etc/security/time.conf # this is an example configuration file for the pam_time module. Its syntax # was initially based heavily on that of the shadow package (shadow-960129). # # the syntax of the lines is as follows: # # services;ttys;users;times # # white space is ignored and lines maybe extended with '\n' (escaped # newlines). As should be clear from reading these comments, # text following a '#' is ignored to the end of the line. # # the combination of individual users/terminals etc is a logic list # namely individual tokens that are optionally prefixed with '!' (logical # not) and separated with '&' (logical and) and '|' (logical or). # # services # is a logic list of PAM service names that the rule applies to. # # ttys # is a logic list of terminal names that this rule applies to. # # users # is a logic list of users or a netgroup of users to whom this # rule applies. # # NB. For these items the simple wildcard '*' may be used only once. # # times # the format here is a logic list of day/time-range # entries the days are specified by a sequence of two character # entries, MoTuSa for example is Monday Tuesday and Saturday. Note # that repeated days are unset MoMo = no day, and MoWk = all weekdays # bar Monday. The two character combinations accepted are # # Mo Tu We Th Fr Sa Su Wk Wd Al # # the last two being week-end days and all 7 days of the week # respectively. As a final example, AlFr means all days except Friday. # # each day/time-range can be prefixed with a '!' to indicate "anything # but" # # The time-range part is two 24-hour times HHMM separated by a hyphen # indicating the start and finish time (if the finish time is smaller # than the start time it is deemed to apply on the following day). # # for a rule to be active, ALL of service+ttys+users must be satisfied # by the applying process. # # # Here is a simple example: running blank on tty* (any ttyXXX device), # the users 'you' and 'me' are denied service all of the time # #blank;tty* & !ttyp*;you|me;!Al0000-2400 # Another silly example, user 'root' is denied xsh access # from pseudo terminals at the weekend and on mondays. #xsh;ttyp*;root;!WdMo0000-2400 # # End of example file. # [root@localhost ~]#