# 1、PAM认证机制简介
Linux 通常会通过 login 进程完成登陆,最开始时只是简单的提示用户输入用户名和密码,然后校验用户是否存在、密码是否正确,如果都正常,那么就会直接完成登陆,进入到 Shell 程序运行。
PAM(Pluggable Authentication Modules
,可插拔认证模块) 提供了一整套的鉴权、授权、密码管理、会话管理机制等,只需要程序支持 PAM 框架,用户就可以在完全不修改程序的条件下,动态修改鉴权机制,例如除了常规的用户名密码登陆,还可以使用指纹、One-Time-Password 等机制。
如果一个应用程序 (例如 login) 想使用 PAM 提供的机制,那么需要链接到 libpam.so
库,否则就不支持 PAM 机制,可以通过如下命令查看:
|
|
PAM相关模块包括:
libpam.so.0
:核心库,使用 PAM 机制的应用会链接到该库上。/etc/pam.conf
与/etc/pam.d/*
:配置文件,配置内容基本类似,前者为全局配置,通过第一列标识应用程序,而后者则以文件名标识应用程序,结构层次更加明确,也更常见。pam_*.so
:可以动态加载的模块,在配置文件中可以直接通过文件名引用,在Debian发行版下位于/lib/x86_64-linux-gnu/security/
目录。
PAM认证一般遵循这样的顺序:Service(服务)→PAM(配置文件)→pam_*.so
,PAM配置文件在/etc/pam.d/
目录下,原理图如下:
# 2、PAM配置文件
#
2.1 /etc/pam.conf
该文件的格式为:
|
|
该文件当前默认为空。通常使用/etc/pam.d/
目录下的配置文件。
#
2.2 /etc/pam.d/
该目录下为具体服务的配置文件,如login
、sshd
等。
在配置文件中包含了四列,分别为:模块类型
、 控制模式
、模块名称
、模块参数
。
与/etc/pam.conf
文件的格式的区别是没有服务名称这一列了,因为服务名称已经是/etc/pam.d/
目录下的文件名了。
# 2.2.1 模块类型
PAM 有四种模块类型,代表不同的任务,一个类型可能有多行,按顺序依次由 PAM 模块调用
auth
:认证管理,用来对用户的身份进行识别,如提示用户输入密码、判断用户是否为 root 等。account
:账号管理,对帐号的各项属性进行检查,如用户帐户是否已过期、是否允许登录、是否达到最大用户数、root 用户是否允许在这个终端登录等。session
:配置和管理用户会话,定义用户登录前的及用户退出后所要进行的操作,如登录连接信息、用户数据的打开与关闭、挂载文件系统等。password
:密码管理,使用用户信息来更新,如修改用户密码。
如果在模块类型的开头有个短横线 -
,意味着,如果找不到这个模块导致无法加载,这一事件不会被记录在日志中,适用于那些非必须的验证功能。
# 2.2.2 控制模式
通过控制标记来处理和判断各个模块的返回值。
required
:如果本条目没有被满足,那最终本次认证一定失败,但认证过程不因此打断,也要等所有的模块都执行完毕后才返回错误信息。requisite
:模块结果必须成功才能继续身份验证,如果某个模块返回失败,则立刻返回失败,不再进行同类型后面的操作。sufficient
:如果验证通过,且本条目之前没有任何required
条目失败,则立即返回验证成功消息,而且也不再执行后面模块。如果验证失败,不对结果造成影响,此时sufficient 的作用和 optional 相同 。optional
:该条目仅在整个栈中只有这一个条目时才有决定性作用。即使指定的模块验证失败,也允许用户接受应用程序提供的服务,一般返回PAM_IGNORE
。include
:将其他配置文件中的流程栈包含在当前的位置,就好像将其他配置文件中的内容复制粘贴到这里一样。substack
:运行其他配置文件中的流程,并将整个运行结果作为该行的结果进行输出。该模式和include
的不同点在于认证结果的作用域:如果某个流程栈include
了一个带requisite
的栈,这个requisite
失败将直接导致认证失败,同时退出栈;而某个流程栈substack
了同样的栈时,requisite
的失败只会导致这个子栈返回失败信号,母栈并不会在此退出。[value1=action1 value2=action2 ….]
:valueN
的值是各个认证模块执行之后的返回值,有success
、user_unknown
、new_authtok_reqd
、default
等等数十种。流程栈中很可能有多个验证规则,每条验证的返回值可能不尽相同,那么到底哪一个验证规则能作为最终的结果呢?这就需要actionN
的值来决定了。actionN
的值有以下几种:ok
:在一个栈的运行过程中,如果ok
前面没有返回值,或者前面的返回值为PAM_SUCCESS
,那么这个标记了ok
的返回值将覆盖前面的返回值。但如果前面执行过的验证中有最终将导致失败的返回值,那ok
标记的值将不会起作用。done
:在前面没有bad
值被命中的情况下,done
值被命中之后将马上被返回,并退出整个栈。bad
:标记bad
的返回值被命中时,最终的认证结果注定会失败。此外,如果这条bad
的返回值是整个栈的第一个失败项,那么整个栈的返回值一定是这个返回值,后面的认证无论结果怎样都改变不了现状了。die
:标记die
的返回值被命中时,马上退出栈并宣告失败。整个返回值为这个die
的返回值。ignore
:在一个栈中有多个认证条目的情况下,如果标记ignore
的返回值被命中,那么这条返回值不会对最终的认证结果产生影响。N
(一个自然数):功效和ok
类似,并且会跳过接下来的 N 个验证步骤。如果N = 0
则和ok
完全相同。reset
:清空之前生效的返回值,并且从下面的验证起重新开始。
实际上控制模式
的“关键字”模式可以等效地用“返回值=行为
”模式来表示。具体的对应如下:
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]