📄 1118.html
字号:
<br>
PAM的整个框架结构如下图所示:<br>
<br>
<br>
系统管理员通过PAM配置文件来制定认证策略,即指定什么服务该采用什么样的认证方法;应<br>
用程序开发者通过在服务程序中使用PAM API而实现对认证方法的调用;而PAM服务模块(se<br>
rvice module)的开发者则利用PAM SPI(Service Module API)来编写认证模块(主 要是<br>
引出一些函数pam_sm_xxxx( )供libpam调用),将不同的认证机制(比如传统的UNIX认证方<br>
法、Kerberos等)加入到系统中;PAM核 心库(libpam)则读取配置文件,以此为根据将服<br>
务程序和相应的认证方法联系起来。<br>
二、PAM支持的四种管理界面:<br>
<br>
1、认证管理(authentication management)<br>
主要是接受用户名和密码,进而对该用户的密码进行认证,并负责设置用户的一些秘密<br>
信息。<br>
2、帐户管理(account management)<br>
主要是检查帐户是否被允许登录系统,帐号是否已经过期,帐号的登录是否有时间段的<br>
限制等等。<br>
3、密码管理(password management)<br>
主要是用来修改用户的密码。<br>
4、会话管理(session management)<br>
主要是提供对会话的管理和记账(accounting)。<br>
<br>
三、PAM的文件:<br>
<br>
/usr/lib/libpam.so.* PAM核心库<br>
/etc/pam.conf或者/etc/pam.d/ PAM配置文件<br>
/usr/lib/security/pam_*.so 可动态加载的PAM service module<br>
对于RedHat,其目录不是/usr/lib,而是/lib。<br>
<br>
四、PAM的配置:<br>
<br>
PAM的配置是通过单个配置文件/etc/pam.conf。RedHat还支持另外一种配置方式,即通过配<br>
置目录/etc/pam.d/,且这种的优先级要高于单 个配置文件的方式。<br>
<br>
1、使用配置文件/etc/pam.conf<br>
<br>
该文件是由如下的行所组成的:<br>
service-name module-type control-flag module-path arguments<br>
<br>
service-name 服务的名字,比如telnet、login、ftp等,服务名字“OTHER”代表所有没有<br>
在该文件中明确配置的其它服务。<br>
module-type 模块类型有四种:auth、account、session、password,即对应PAM所支持的<br>
四种管理方式。同一个服务可以调用多个 PAM模块进行认证,这些模块构成一个stack。<br>
control-flag 用来告诉PAM库该如何处理与该服务相关的PAM模块的成功或失败情况。它有四<br>
种可能的 值:required,requisite,sufficient,optional。<br>
required 表示本模块必须返回成功才能通过认证,但是如果该模块返回失败的话,失败<br>
结果也不会立即通知用户,而是要等到同一stack 中的所有模块全部执行完毕再将失败结果<br>
返回给应用程序。可以认为是一个必要条件。<br>
requisite 与required类似,该模块必须返回成功才能通过认证,但是一旦该模块返回<br>
失败,将不再执行同一stack内的任何模块,而是直 接将控制权返回给应用程序。是一个必<br>
要条件。注:这种只有RedHat支持,Solaris不支持。<br>
sufficient 表明本模块返回成功已经足以通过身份认证的要求,不必再执行同一stack<br>
内的其它模块,但是如果本模块返回失败的话可以 忽略。可以认为是一个充分条件。<br>
optional表明本模块是可选的,它的成功与否一般不会对身份认证起关键作用,其返回<br>
值一般被忽略。<br>
对于control-flag,从Linux-PAM-0.63版本起,支持一种新的语法,具体可参看Linux <br>
PAM文档。<br>
module-path 用来指明本模块对应的程序文件的路径名,一般采用绝对路径,如果没有给出<br>
绝对路径,默认该文件在目录/usr/lib/security下 面。<br>
arguments 是用来传递给该模块的参数。一般来说每个模块的参数都不相同,可以由该模块<br>
的开发者自己定义,但是也有以下几个共同 的参数:<br>
debug 该模块应当用syslog( )将调试信息写入到系统日志文件中。<br>
no_warn 表明该模块不应把警告信息发送给应用程序。<br>
use_first_pass 表明该模块不能提示用户输入密码,而应使用前一个模块从用户那里<br>
得到的密码。<br>
try_first_pass 表明该模块首先应当使用前一个模块从用户那里得到的密码,如果该<br>
密码验证不通过,再提示用户输入新的密码。<br>
use_mapped_pass 该模块不能提示用户输入密码,而是使用映射过的密码。<br>
expose_account 允许该模块显示用户的帐号名等信息,一般只能在安全的环境下使用<br>
,因为泄漏用户名会对安全造成一定程度的威 胁。<br>
<br>
2、使用配置目录/etc/pam.d/(只适用于RedHat Linux)<br>
<br>
该目录下的每个文件的名字对应服务名,例如ftp服务对应文件/etc/pam.d/ftp。如果名为x<br>
xxx的服务所对应的配置文件/etc/pam.d/xxxx不存 在,则该服务将使用默认的配置文件/et<br>
c/pam.d/other。每个文件由如下格式的文本行所构成:<br>
module-type control-flag module-path arguments<br>
每个字段的含义和/etc/pam.conf中的相同。<br>
<br>
3、配置的例子<br>
<br>
例一:用/etc/pam.conf配置默认的认证方式。<br>
<br>
下面的例子将拒绝所有没有在/etc/pam.conf中明确配置的服务。OTHER代表没有明确配置的<br>
其它所有服务,pam_deny模块的作用只是简 单地拒绝通过认证。<br>
OTHER auth required /usr/lib/security/pam_deny.so<br>
OTHER account required /usr/lib/security/pam_deny.so<br>
OTHER password required /usr/lib/security/pam_deny.so<br>
OTHER session required /usr/lib/security/pam_deny.so<br>
<br>
<br>
例二:通过/etc/pam.d/rsh文件配置rsh服务的认证方式。<br>
<br>
rsh服务认证用户时,先使用/etc/hosts.equiv和.rhosts文件的认证方式,然后再根据/etc<br>
/nologin文件的存在与否来判断是否允许该用户使用 rsh,最后使用password database来认<br>
证用户。<br>
<br>
auth required /lib/security/pam_rhosts_auth.so<br>
auth required /lib/security/pam_nologin.so<br>
account required /lib/security/pam_pwdb.so<br>
session required /lib/security/pam_pwdb.so<br>
<br>
<br>
例三:通过/etc/pam.conf配置ftpd的认证方式。<br>
<br>
下面是ftpd服务利用PAM模块进行用户认证的三个步骤。首先用pam_ftp模块检查当前用户是<br>
否为匿名用户,如果是匿名用户,则 sufficient控制标志表明无需再进行后面的认证步骤,<br>
直接通过认证;否则继续使用pam_unix_auth模块来进行标准的unix认证,即用/etc/ passw<br>
d和/etc/shadow进行认证;通过了pam_unix_auth模块的认证之后,还要继续用pam_listfil<br>
e模块来检查该用户是否出现在文件/etc/ ftpusers中,如果是则该用户被deny掉。<br>
ftpd auth sufficient /usr/lib/security/pam_ftp.so<br>
ftpd auth required /usr/lib/security/pam_unix_auth.so use_first_pass<br>
ftpd auth required /usr/lib/security/pam_listfile.so <br>
onerr=succeed item=user sense=deny file=/etc/ftpuser<br>
s<br>
<br>
五、密码映射(password-mapping)<br>
<br>
密码映射允许用户在不同的认证机制下使用不同的密码,其中有一个主密码(primary pass<br>
word),其它密码为次密码(secondary passwords,可能有多个)。主密码用来对次密码进<br>
行加密。在主密码认证通过后,认证模块利用主密码将加密过的次密码(也称为 mapped pa<br>
ssword)解密,并对次密码进行认证。<br>
注:如果使用了一次性密码的机制,就不使用密码映射。<br>
<br>
所有服务模块必须支持如下4个映射选项(在第四部分已经简单解释过):<br>
<br>
1、use_first_pass<br>
<br>
这个选项指示本模块不能提示用户输入密码,而是使用已有的密码,即从第一个向用户提示<br>
输入密码的模块那里取得密码,并对该密码进 行认证。<br>
<br>
2、try_first_pass<br>
<br>
这个选项指示本模块首先尝试使用已有的密码,即从第一个向用户提示输入密码的模块那里<br>
取得密码,并对该密码进行认证。如果密码认 证失败,则再提示用户输入密码。<br>
<br>
3、use_mapped_pass<br>
<br>
这个选项指示本模块不能向用户提示输入密码,而应使用映射过的密码,即利用主密码将加<br>
密过的次密码解密出来并进行认证。<br>
<br>
4、try_mapped_pass<br>
<br>
这个选项指示本模块首先尝试使用映射过的密码,即利用主密码将加密过的次密码解密出来<br>
并进行认证。如果密码认证失败,则再提示用 户输入密码。<br>
<br>
密码映射的例子:<br>
<br>
下面是/etc/pam.conf中关于login服务的配置。这里login共有3种认证机制:Kerberos、UN<br>
IX和RSA认证,两个required控制标志表明用户必 须通过Kerberos认证和UNIX认证才能使用<br>
login服务,optional选项则说明RSA认证是可选的。首先用户输入主密码进行Kerberos认 证<br>
;use_mapped_pass选项指示UNIX认证模块利用主密码将用于UNIX认证的次密码解密出来并对<br>
该次密码进行认证;try_first_pass选项 指示RSA认证模块先使用第一个模块(即Kerberos<br>
模块)的密码作为进行认证的密码,当对该密码认证失败时才提示用户输入用于RSA认 证的<br>
次密码。<br>
login auth required pam_kerb_auth.so debug<br>
login auth required pam_unix_auth.so use_mapped_pass<br>
login auth optional pam_rsa_auth.so try_first_pass<br>
<br>
六、PAM API<br>
<br>
1、框架API:<br>
<br>
任何一个支持PAM的服务程序在进行认证时必须以pam_start( )开始进行初始化,最后以pam<br>
_end( )结束以便进行清理工作。<br>
<br>
2、认证管理API:<br>
<br>
pam_authenticate( )对用户名/密码进行认证。<br>
pam_setcred( )用来修改用户的秘密信息。<br>
<br>
3、帐户管理API:<br>
<br>
pam_acct_mgmt( )检查帐户本身是否有权限登录系统、帐户是否过期、帐户是否有登录时间<br>
限制等。<br>
<br>
4、密码管理API:<br>
<br>
pam_chauthtok( )修改用户的密码。<br>
<br>
5、会话管理API:<br>
<br>
一个会话以pam_open_session( )开始,最后以pam_close_session( )结束。<br>
<br>
6、其它:<br>
<br>
pam_get_item( )、pam_set_item( )用来读写PAM事务(transaction)的状态信息。<br>
pam_get_data( )、pam_set_data( )用来取得和设置PAM模块及会话的相关信息。<br>
pam_putenv( )、pam_getenv( )、pam_getenvlist( )用来读写环境变量。<br>
pam_strerror( )返回相关的错误信息。<br>
例子程序(摘自Sun的白皮书):<br>
<br>
下面的例子使用PAM API写了一个简单的login服务程序(注:这不是个完整的程序,所以省<br>
略了对pam_close_session的调用)。<br>
<br>
#include <security/pam_appl.h><br>
<br>
/* 回调函数 */<br>
static int login_conv(int num_msg, struct pam_message **msg, struct pam_response<br>
**response, void *appdata_ptr);<br>
struct pam_conv pam_conv = {login_conv, NULL};<br>
pam_handle_t *pamh; /* 进行认证的PAM句柄 */<br>
<br>
void main(int argc, char *argv[], char **renvp)<br>
{<br>
/* 初始化,并提供一个回调函数 */<br>
if ((pam_start("login", user_name, &pam_conv, &pamh)) != PAM_SUCCESS)<br>
login_exit(1);<br>
<br>
/* 设置一些参数 */<br>
pam_set_item(pamh, PAM_TTY, ttyn);<br>
pam_set_item(pamh, PAM_RHOST, remote_host);<br>
<br>
while (!authenticated && retry < MAX_RETRIES)<br>
{<br>
status = pam_authenticate(pamh, 0); /* 密码认证管理,检查用户输入<br>
的密码是否正确 */<br>
authenticated = (status == PAM_SUCCESS);<br>
}<br>
<br>
if (status != PAM_SUCCESS)<br>
{<br>
fprintf(stderr,"error: %s", pam_strerror(pamh, status)); /* 显示错误原<br>
因 */<br>
login_exit(1);<br>
}<br>
<br>
/* 通过了密码认证之后再调用帐户管理API,检查用户帐号是否已经过期 */<br>
if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)<br>
{<br>
if (status == PAM_AUTHTOK_EXPIRED)<br>
{<br>
status = pam_chauthtok(pamh, 0); /* 过期则要求用户更改密码 */<br>
if (status != PAM_SUCCESS)<br>
login_exit(1);<br>
}<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -