本文作者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布。
本文作者十分愿意与他人分享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有的作品集:
由于作者水平有限,因此不能保证作品内容准确无误。如果你发现了作品中的错误(哪怕是错别字也好),请来信指出,任何提高作品质量的建议我都将虚心接纳。
PAM 是 Pluggable Authentication Modules 的缩写,意为"可插拔认证模块"。它将各种不同的底层认证机制统一到一组高层API中,从而省去了在每个应用程序中分别设计和实现各种认证机制的麻烦。Linux PAM 就是一种 Linux 平台上的 PAM 实现。[注意]官网的文档已经过时且不再更新,最新的文档在 Linux-PAM-GitHub {Linux-PAM-*-docs.tar.xz (doc/sag/html), Linux-PAM-*.tar.xz (modules/*/*.[58])}
以常见的 su 命令来说,它可以实现用户切换,从 root 切换至其他用户不需要密码、从非 root 用户切换至其他用户则需要验证目标用户的密码,一旦认证成功就以目标用户身份启动 shell 以供使用。本质上,su 只做两件事:(1)认证;(2)启动 shell 。按照传统思路,两件事都很容易实现,例如认证逻辑可以用伪代码这样简单的描述:
if ( uid == 0 ) 认证成功 elseif ( 输入的密码 == 目标用户的密码 ) 认证成功 else 认证失败
但是,认证需求不是一成不变的。例如:(1)为了方便运维团队成员(也就是 wheel 组),希望 wheel 组中的用户无需输入密码也能直接进行用户切换;(2)为了加强安全性,希望额外验证手机短信;(3)为了避免频繁输入难记的用户密码,希望可以选用指纹方式进行验证;(4)为了方便某个特定的用户测试,希望仅凭手机短信也能完成验证 ...... 这样一来, su 的开发者将会被迫不断更改 su 的源代码,然后再重新调试、编译、分发,非常辛苦。这种情况下,PAM 就可以对 su 开发者说:"认证的事交给我,能不能通过认证由我说了算,你只需做好其他事情(启动 shell)即可";同时又对用户(系统管理员)说:"只要学会了 PAM 配置语法,就可以利用各种 PAM 模块,编写出千变万化的认证策略。无需打扰 su 开发者,就能立即得到想要的效果"。通过把与认证相关的脏活累活都交给 PAM 来干, su 的开发者与用户之间实现了解耦,彼此皆大欢喜。
推而广之,如果一个应用程序想要使用 PAM 进行认证,只需在源代码中嵌入 PAM 支持即可(也就是引入相应的头文件)。然后开发者无需再为认证部分操心(是否通过认证交给 PAM 决定),只需专注程序的其他部分即可。也就是说,无需修改应用程序就可以切换、修改、升级应用程序使用的认证机制。当然,如果只有一个不支持 PAM 的二进制文件,那就没有办法改造了。
简单来说,PAM 能够完成如下四种类型(type)的任务:
上述所有任务都通过位于 /lib/security/ 或 /lib64/security/ 中的各个 PAM 模块来实现,模块文件名一般都符合 pam_*.so 格式。
系统管理员维护的配置文件统一放置在 /etc/pam.d/ 目录中(高优先级),软件包自带的默认配置文件统一放置在 /usr/lib/pam.d/ 目录中(低优先级),对同时存在于两个目录中的同名文件来说,前者会覆盖后者。注意,文件名中的字母只能小写,并且拥有特殊的含义,文件名必须等于应用程序内部硬编码的"服务名"(同一个应用程序可以拥有多个不同的"服务名")。例如: su 总是读取 /etc/pam.d/su (若运行"su -l"则读取 /etc/pam.d/su-l )、 sudo 总是读取 /etc/pam.d/sudo (若运行"sudo -i"则读取 /etc/pam.d/sudo-i )、 sshd 总是读取 /etc/pam.d/sshd 。
名为"other"的特殊配置文件,表示当应用程序未能找到所需的配置文件(例如"su"或"sudo")时,应该使用的默认配置(一般是拒绝一切请求)。除"other"之外,还有其他一些配置文件也比较特别,这些配置文件并不对应某个"服务名",而是专用于被其他配置文件引用,例如"password-auth"以及"system-auth"等等。
配置文件的语法非常简单,一看便知,具体说来就是:以"#"号开头的行表示注释,空行将被忽略,其余每行表示一条策略,每条策略都有四个字段(第四个字段为可选字段),字段之间用空格分隔。下面是一个示例:
#类型(type) 控制标志(control-flag) 模块路径(module-path) 模块参数(module-arguments) auth substack password-auth auth sufficient pam_unix.so nullok try_first_pass auth required pam_deny.so account include system-auth account sufficient pam_succeed_if.so uid=0 use_uid quiet account required pam_deny.so -password optional pam_gnome_keyring.so use_authtok password include password-auth password requisite pam_pwquality.so try_first_pass local_users_only password required pam_deny.so -session optional pam_systemd.so session optional pam_xauth.so session include postlogin session [success=1 default=ignore] pam_succeed_if.so service !~ gdm* service !~ su* quiet session required pam_deny.so
第一个字段"类型"(type)就是"Linux PAM 能做什么?"小节中所述的四种类型(auth,account,password,session)之一。若在类型前加上"-"(减号)前缀,则表示即使模块不存在,也不会影响认证结果,更不会将此事件记录到日志中,对于那些可有可无的模块来说,这一特性非常有用。
第二个字段"控制标志"(control-flag)用于控制模块在流程栈中的行为。该字段有两种语法,一种是简单语法,一种是复杂语法,用于描述 PAM 认证流程的执行规则。详见后文的"流程栈"小节。
第三个字段"模块路径"(module-path)表示模块的文件系统路径,既可以是绝对路径,也可以是相对路径(相对于 /lib/security/ 或 /lib64/security/ 目录),模块文件名一般都符合 pam_*.so 格式。注意,当第二个字段(控制标志)的值是"include"或"substack"时,相对路径表示相对于 /etc/pam.d/ 或 /usr/lib/pam.d/ 目录的路径。
第四个字段"模块参数"(module-arguments)用于控制模块的行为,它是一组用空格分隔的参数列表,每个模块能够使用的参数各不相同,详见后文"常用模块"小节。如果想在某个参数中使用空格,那么必须在该参数外围加上中括号(字符串中的"["无需转义,但"]"必须转义为"\]")。例如 passwd=mada [query=select user_name from internet_service where user_name='%u' and password=PASSWORD('%p')]
注意,配置文件中的任何语法错误都会导致认证过程失败,同时,失败信息将会被记录到系统日志(syslog)中。
所谓"流程栈"是指执行步骤和规则,非常类似于程序逻辑的概念,它体现在配置文件自上而下的执行顺序中。"栈"就像是一段可以嵌套的程序逻辑,通过"substack"关键字,可以在一个栈(父栈)中嵌入另一个栈(子栈)。 PAM 流程栈的执行规则由配置文件中的第二个字段"控制标志"(control-flag)决定,你可以把"控制标志"想象成逻辑控制语法。该字段有两种语法,一种是简单语法,一种是复杂语法。
通常使用简单语法,表现为一组关键字:
复杂语法,表现为用中括号包围的一组以空格分隔的"value=action"列表,形如 [value1=action1 value2=action2 ...] 。由于很少使用,这里就略过此种语法的介绍。
为防止配置文件缺失可能导致的隐蔽故障与安全漏洞,应该确保存在一个严苛的默认配置(/etc/pam.d/other)。
因为配置文件中的任何语法错误都会导致认证过程失败,所以务必确保语法正确。
严苛的默认配置(/etc/pam.d/other)对于加强系统安全是非常重要的,它可以预防丢失或忘记配置所导致的安全漏洞。但因为 pam_deny.so 在运行时不记录任何信息,所以除非用户在无法执行某个应用的认证时能够与系统管理员联系,否则系统管理员可能很长时间都不知道系统存在配置错误。为了解决这个问题,可以额外加入 pam_warn.so 模块,以确保系统管理员可以从系统日志(syslog)中获得警告信息(auth.notice)。具体内容如下:
#默认拒绝一切请求并发出警告(/etc/pam.d/other) 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
如果你对 Linux PAM 不熟悉,并且也不想使用复杂的认证策略,而应用程序又使用了 PAM 认证,那么一个偷懒的做法是使用下面的配置来模拟传统的 UNIX 认证方式:
#模拟传统认证方式 auth required pam_unix.so account required pam_unix.so password required pam_unix.so session required pam_unix.so
在实践中,把这个配置用作复杂认证策略的配置起点也是一个不错的选择。
除了 Linux PAM 自身附带的模块之外,还存在许多第三方模块(例如 Google Authenticator),本小节并不打算、也不可能介绍所有模块,而是仅选取一些常用模块进行介绍。[提示]每一个模块标题行末尾的小括号表示该模块的适用类型(对应于配置文件中的"类型"(type)字段)。
pam_access.so [ debug ] [ nodefgroup ] [ noaudit ] [ accessfile=配置文件 ] [ fieldsep=分隔符 ] [ listsep=分隔符 ]
此模块能够基于账号与来源(主机/网络/终端/$DISPLAY/服务名)的组合执行访问控制。访问控制策略保存在主配置文件(accessfile)(默认=/etc/security/access.conf)与配置片段(/etc/security/access.d/*.conf)中,所有配置片段按顺序依次解析,一旦匹配成功就立即停止继续解析。为了给不同的服务分别指定不同的访问控制策略,可以明确指定 accessfile 参数,这将导致仅解析指定的主配置文件(忽略所有配置片段)。因为配置片段的优先级低于主配置文件且容易被忽略,所以不建议使用配置片段。
此模块能够通过几种不同的组合决定允许或拒绝访问,具体如下:(1)首先,按照 (user, 主机名/域名) 或 (user, IP地址/IP网段) 组合进行匹配;(2)其次,如果用户通过终端访问,那么按照 (user, tty) 组合进行匹配;(3)否则,按照 (user, $DISPLAY) 或 (user, 服务名) 组合进行匹配。一旦找到第一个匹配,就立即停止解析并返回允许或拒绝的结果。
#按照从上到下的顺序依次匹配,并且一旦匹配成功就立即返回,所以策略的顺序非常重要。 #允许 root 用户从特定服务以及特定终端(其中":0"是X终端[键盘+鼠标+屏幕])访问 +:root:cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6 #允许 root 用户从特定的IP地址与网段访问 +:root:127.0.0.0/24 ::ffff:127.0.0.0/127 192.168.200.4 192.168.200.9 192.168.201.0/24 2001:4ca0:0:101::1 2001:4ca0:0:101::/64 #允许 remote 组从非本地登录 +:(remote):ALL EXCEPT LOCAL #允许 root 组、 nis_admins 网络用户组、 admin 用户从任意来源登录 +:(root) @nis_admins admin:ALL #允许 wheel 组从本地登录 +:(wheel):LOCAL #允许 wheel 组中除 john 之外的其他成员从 localhost 与 localhost.localdomain 与 foo.bar.org 主机访问 +:(wheel) EXCEPT john:localhost localhost.localdomain foo.bar.org #允许 wheel 组中除 john 与 tommy 之外的其他成员从 www.bar.org 域名访问 +:(wheel) EXCEPT john tommy:.www.bar.org #允许 assistants 组从"192.168.5.0/24"网段内除"192.168.5.97-99"之外的其他IP地址访问 +:(assistants):192.168.5.0/24 EXCEPT 192.168.5.97 192.168.5.98 192.168.5.99 #默认兜底策略(拒绝所有来源的所有用户) -:ALL:ALL
从上面的实例可知,配置语法非常简单,具体说来就是:以"#"号开头的行表示注释,空行将被忽略,其余每行表示一条策略,每条策略都有三个字段,字段之间的分隔符由 fieldsep 参数决定(默认为冒号":")。[提示]不要在字段分隔符两边添加空白。
第一个字段(权限)必须是"+"或"-"字符之一,分别表示允许(+)与拒绝(-)。
第二个字段(账号)有三种不同的语法:(1)关键字,"ALL"表示任意用户;(2)包含列表,表现为以 listsep 参数(默认=空格/水平制表符/逗号)作为分隔符的一系列登录名、常规用户组[用小括号包围,例如"(group)"]、网络用户组[带有"@"前缀,例如"@nis_group"];(3)排除列表,表现为 EXCEPT 表达式。[注意]为兼容老版本配置文件,默认情况下,没有使用小括号包围的登录名会在未能匹配成功时被当作用户组再次匹配。为避免这种含混不清的语法,强烈建议使用 nodefgroup 选项关闭这个坑爹的兼容性。
第三个字段(来源)有三种不同的语法:(1)关键字,"ALL"表示任意来源、"LOCAL"表示本地登录[匹配所有不含"."的字符串];(2)包含列表,表现为以 listsep 参数(默认=空格/水平制表符/逗号)作为分隔符的一系列来源,可以识别的来源形式如下:(a)终端设备名[剥除"/dev/"前缀]、(b) $DISPLAY 变量值、(c)服务名、(d)主机名与域名[域名以"."开头,例如".www.example.com"]、(e)网络主机组[以"@"开头,例如"@nis_hostgroup"]、(f)IP地址与IP网段[IP网段用"network/mask"表示,例如"192.168.5.0/24"];(3)排除列表,表现为 EXCEPT 表达式。
如果在编译 Linux PAM 时开启了审计支持,此模块还将通过系统日志(syslog)报告所有被拒绝的访问(除非使用 noaudit 选项强制关闭审计)。另外,也可以使用 debug 选项在系统日志(syslog)中输出详细的调试信息。
pam_deny.so
此模块没有任何选项或参数,用于无条件的拒绝访问,常用于默认配置(other)之中。
pam_echo.so [file=消息文件]
此模块在流程栈中一般用作 optional 条件,用于显示一些提示消息。文本中的百分号(%)是替换标记,可以识别的替换标记如下:
所有其他不能识别的替换标记都只简单的去掉前导百分号(例如"%%"将被替换为"%")。
pam_env.so [debug] [conffile=配置文件] [envfile=变量文件] [readenv=0|1]
此模块用于设置与撤销环境变量(也包括PAM变量,例如"PAM_RHOST")。首先,执行配置文件(conffile)(默认=/etc/security/pam_env.conf)中的指令;然后,根据 readenv 的指示(1=是[默认]|0=否)决定是否继续加载变量文件(envfile)(默认=/etc/environment)。
配置文件(conffile)用于变量的设置/撤销/修改。配置文件的语法非常简单,以井号(#)开头的行表示注释、空行将被忽略、其余的行必须符合如下格式:
变量名 [DEFAULT=[默认值]] [OVERRIDE=[指定值]]
行首的"变量名"一般使用全大写字母且不能有前导空白,可选的 DEFAULT 关键字用于设置变量的默认值(默认为空字符串)(不会覆盖变量的原有值),可选的 OVERRIDE 关键字用于强制覆盖变量的原有值。可以在"默认值/指定值"中使用 ${XXX} 语法引用(可能不存在的)环境变量、使用 @{XXX} 语法引用(可能不存在的)PAM变量。 HOME 与 SHELL 是两个特例,它们既可以是环境变量也可以是PAM变量,当用作PAM变量时, @{HOME} 与 @{SHELL} 的值实际上来源于该用户在 /etc/passwd 中登记的值(可能不等于环境变量 ${HOME} 与 ${SHELL} 的值)。注意,因为应用程序在调用此模块时,有可能尚未设置所需的环境变量,所以某些环境变量在调用此模块时可能尚不存在,例如 ${HOME} 就经常用 @{HOME} 来代替。下面是一个配置文件(conffile)实例:
#/etc/security/pam_env.conf #为远程主机设置 REMOTEHOST 变量,并将默认值设为"localhost" REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST} #为 DISPLAY 变量设置一个合理的值 DISPLAY DEFAULT=${REMOTEHOST}:0.0 OVERRIDE=${DISPLAY} #其他一些常规变量 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 XDG_DATA_HOME DEFAULT=@{HOME}/share/ #一些针对特殊字符的例子(仅支持对 $ 与 @ 的转义,不支持对引号的转义) DOLLAR DEFAULT=\$ DOLLARDOLLAR DEFAULT= OVERRIDE=\$${DOLLAR} DOLLARPLUS DEFAULT=\${REMOTEHOST}${REMOTEHOST} ATSIGN DEFAULT="" OVERRIDE=\@
变量文件(envfile)仅用于环境变量的设置。变量文件的语法非常简单,以井号(#)开头的行表示注释、空行将被忽略、其余的行必须符合 KEY=VAL 格式(若想兼容bash脚本也可以添加可选的 export 指令前缀)。
注意,因为设置PAM变量会影响其他PAM模块的行为,所以应该将此模块放在流程栈的末尾。另外,出于调试目的,还可以使用 debug 选项在系统日志(syslog)中输出详细的调试信息。
pam_exec.so [ debug ] [ expose_authtok ] [ seteuid ] [ quiet ] [ quiet_log ] [ stdout ] [ log=日志文件 ] [ type=模块类型 ] 外部命令 [ 参数 ... ]
此模块用于调用外部命令。子进程(外部命令)除了继承当前进程的环境变量之外,还能使用下列PAM变量:PAM_RHOST, PAM_RUSER, PAM_SERVICE, PAM_TTY, PAM_USER, PAM_TYPE(account, auth, password, open_session, close_session 之一)。注意,父进程的用户决定了外部命令(子进程)能够看到的环境变量。
使用 debug 选项可以在系统日志(syslog)中输出详细的调试信息。使用 expose_authtok 选项表示被调用的外部命令可以从标准输入(STDIN)读取密码。使用 seteuid 选项表示以调用进程(父进程)的 EUID(effective UID) 身份调用外部命令(默认=调用进程的实际UID[real UID])。使用 quiet 选项表示在外部命令出错(退出码≠0)时不显示退出状态(默认=外部命令出错时显示退出状态)。使用 quiet_log 选项表示在外部命令出错(退出码≠0)时不在日志中记录退出状态(默认=外部命令出错时在日志中记录退出状态)。当未使用 stdout 选项时,外部命令的标准输出(STDOUT)将会被记录到 log= 参数指定的日志文件(默认=/dev/null)中;当使用 stdout 选项时,则忽略 log= 参数,并将外部命令的标准输出(STDOUT)重定向至调用进程(父进程),由调用进程负责处理。可以使用 type= 参数限定仅在当前模块的类型与给定的类型(auth,account,password,session 之一)匹配时才调用外部命令。下面是一个实例:
#可用于向 /etc/pam.d/passwd 中添加的行 #在本地密码被修改的同时重建NIS数据库(以EUID身份执行 make -C /var/yp 命令) password optional pam_exec.so seteuid /usr/bin/make -C /var/yp
pam_unix.so [nullresetok|nullok] [try_first_pass|use_first_pass] [nodelay] [use_authtok] [shadow] [sha256|sha512] [rounds=N] [minlen=N] [no_pass_expiry] [debug|audit] [quiet]
标准的传统UNIX密码验证(基于 /etc/passwd 与 /etc/shadow 验证和设置帐户信息)。"auth"组件用于验证密码(默认拒绝空密码访问)。"account"组件用于验证账户与密码的有效性、建议更改即将过期的密码、拒绝失效的账户与密码。"password"组件用于更新密码(默认哈希算法取决于 /etc/login.defs 文件中的 ENCRYPT_METHOD 变量)。"session"组件用于记录用户的登录与退出(/var/log/[uwb]tmp)。此模块支持下列选项:
下面是一个 /etc/pam.d/login 实例:
#验证密码 auth required pam_unix.so #确保账号和密码仍然处于有效期 account required pam_unix.so #在更改密码前首先用 pam_passwdqc 确保新密码符合复杂性要求 password required pam_passwdqc.so config=/etc/passwdqc.conf password required pam_unix.so use_authtok nullresetok sha512 #建立会话 session required pam_unix.so
模块 | 类型 | 简介 |
---|---|---|
pam_access.so | auth,account,password,session | 基于来源(主机/网络/终端/$DISPLAY/服务名)的访问控制 |
pam_debug.so | auth,account,password,session | 调试PAM栈 |
pam_deny.so | auth,account,password,session | 无条件的拒绝访问 |
pam_echo.so | auth,account,password,session | 显示文本消息 |
pam_env.so | auth,session | 设置与撤销环境变量(也包括PAM变量) |
pam_exec.so | auth,account,password,session | 调用外部命令 |
pam_faildelay.so | auth | 设置认证失败时的阻塞延迟 |
pam_faillock.so | auth,account | 锁定连续认证失败的账户 |
pam_filter.so | auth,account,password,session | 在用户与应用程序之间建立输入输出(STDIN/STDOUT)过滤器 |
pam_ftp.so | auth | 可插拔的匿名FTP访问模式(不安全) |
pam_group.so | auth | 将用户额外添加到特定组中 |
pam_issue.so | auth | 更改用户的提示文件(issue) |
pam_keyinit.so | session | 在默认内核会话密钥环之外额外创建新的内核会话密钥环 |
pam_lastlog.so | auth,account,session | 显示账户的上次登录时间、锁定长期不登录的帐户 |
pam_limits.so | session | 设置会话的资源限制 |
pam_listfile.so | auth,account,password,session | 基于各种属性(tty|user|rhost|ruser|group|shell)执行访问控制 |
pam_localuser.so | auth,account,password,session | 仅允许本地用户(/etc/passwd)访问 |
pam_loginuid.so | session | 设置进程的 loginuid 属性(主要用于审计目的) |
pam_mail.so | auth,session | 提示用户有新邮件 |
pam_mkhomedir.so | session | 在开始会话前创建用户的家目录 |
pam_motd.so | session | 显示"今日消息"(motd) |
pam_namespace.so | session | 为会话设置私有名字空间 |
pam_nologin.so | auth,account | 禁止非 root 账户登录 |
pam_permit.so | auth,account,password,session | 无条件的允许访问(小心使用) |
pam_pwhistory.so | password | 防止重复使用旧密码 |
pam_rhosts.so | auth | 使用 rlogin/rsh 网络访问认证(/etc/hosts.equiv 与 ~/.rhosts) |
pam_rootok.so | auth,account,password | 仅在 UID=0 时验证成功 |
pam_securetty.so | auth | 仅允许 root 从指定的"安全"设备登录 |
pam_selinux.so | session | 设置默认的 SELinux 安全上下文 |
pam_sepermit.so | auth,account | 根据 SELinux 的开关状态决定是否通过认证 |
pam_setquota.so | session | 在开始会话时设置或修改磁盘限额 |
pam_shells.so | auth,account | 检查登录shell的有效性(是否列于 /etc/shells 之中) |
pam_stress.so | auth,account,password,session | 模拟失败表现 |
pam_succeed_if.so | auth,account,password,session | 测试账号自身的属性以实现条件分支逻辑 |
pam_time.so | account | 根据时间段决定是否允许访问 |
pam_timestamp.so | auth,session | 缓存成功的认证以避免频繁的反复认证 |
pam_tty_audit.so | session | 开启或关闭TTY审计(内核默认不审计TTY上的输入) |
pam_umask.so | session | 设置本次会话中的 umask 值 |
pam_unix.so | auth,account,password,session | 传统UNIX密码验证(/etc/passwd 与 /etc/shadow) |
pam_userdb.so | auth,account | 使用 Berkeley DB 数据库验证用户名/密码 |
pam_usertype.so | auth,account,password,session | 根据 /etc/login.defs 中的设置检查已认证用户的类型(系统账户/普通账户) |
pam_warn.so | auth,account,password,session | 向系统日志中记录详细的PAM信息(服务名,终端,用户,远程用户,远程主机) |
pam_wheel.so | auth,account | 仅允许 wheel 组成员获得 root 权限 |
pam_xauth.so | session | 在用户之间转发 xauth 密钥(cookies) |
模块 | RHEL(rpm) | Debian(deb) | 关键词 |
---|---|---|---|
pam_fprintd.so | fprintd-pam | libpam-fprintd | 指纹 |
pam_gdm.so | gdm | gdm3 | GDM(GNOME显示管理器) |
pam_gnome_keyring.so | gnome-keyring-pam | libpam-gnome-keyring | gnome-keyring(GNOME密钥管理器) |
pam_cap.so | libcap | libpam-cap | Linux Capabilities |
pam_pwquality.so | libpwquality | libpam-pwquality | 密码复杂度 |
pam_user_map.so | mariadb-pam | mariadb-server | MariaDB |
pam_oddjob_mkhomedir.so | oddjob-mkhomedir | oddjob-mkhomedir | 创建家目录 |
pam_cifscreds.so | pam_cifscreds | cifs-utils | NTLM(NT LAN Manager) |
pam_oath.so | pam_oath | libpam-oath | OATH(一次性密码) |
pam_ssh_agent_auth.so | pam_ssh_agent_auth | libpam-ssh-agent-auth | ssh-agent |
pam_winbind.so | samba-winbind-modules | libpam-winbind | Winbind |
pam_sss.so | sssd-client | libpam-sss | System Security Services Daemon |
pam_systemd.so | systemd-pam | libpam-systemd | systemd-logind |