PAM是 PLUGGABLE AUTHENTICATION MODULES 的缩写.
可插入的认证模块(并不是Linux指的模块)用于实现应用程序的认证机制,
是程序员或管理员不需要重新编写或编译程序就可以改变认证机制.
在linux它已经被广泛的应用了, 例如: /etc/securitty /etc/onlogin
/etc/ftpusers 实际上都是给它用的.你在登陆的时候的输入密码和你修改密码
时也都用的是它./etc/pam.conf和/etc/pam/* 都是它的配置文件.
它最大的优点是它的弹性和可扩充性. 你可以随意修改认证机制, 按你的实
际需要来定制系统.你了解后就会非常清楚了.
DESIGN GOALS(设计目标)
(a) 管理员可以选择认证方式, 从简单的密码到智能卡系统.
(
可以为不同的程序配置不同的认证机制.如 使telnet使用 S/Key认证.
而本机的 login 缺使用一般的 UNIX password.
© 支持程序的显示方式的需求. 如login 需要基于终端的显示, 而dtlogin
需要 X 显示, 而`ftp\" 和 `telnet\"需要透过网络来认证.
(d) 支持为一个程序配置同时使用多种认证机制.
(e) 可是用户在使用多种认证机制时,不必为同一个密码敲入多次.
(f) 可是用户在认真时需要输入多个密码.
(g) 当底层的认证机制改变时上层软件不需要修改.
(h) 结构为system authentication提供一个 _pluggable_ model.
(i) 必须能满足现有的服务需要.
4. OVERVIEW OF THE PAM FRAMEWORK (纵览PAM的框架)
其核心实际上是一些库函数. 你写的应用程序要调用它们.PAM为你提供
了一套入口(the front end). 而这套函数互调用 特定认证机制所定义的模块
(the back end).
简单的说是这样的: 你调用一个函数仅仅告诉它你要认正,这就足够了.至于
用那一种机制来认证是由配置文件规定的. 你只需要看一看返回值就知道认证是
否成功了. 对于开发应用程序的人来说只需要记住几个函数.
ftp telnet login (Applications)
| | |
| | |
+--------+--------+
|
+-----+-----+
| PAM API | <-- pam.conf file
+-----+-----+
|
+--------+--------+
UNIX Kerberos Smart Cards (Mechanisms)
Figure 1: 基本的 PAM 结构
PAM的功能被分为四个部分: (1) authentication(认证), (2)account
(账号管理), (3) session (对话管理), 和 (4) password (密码管理).
这四个东东都是什么呢?
(a) Authentication management:
包括 `pam_authenticate()\" 来认证用户, `pam_setcred()\" 来
设置 刷新和销毁用户的 credentials.
(
Account management:
包括 `pam_acct_mgmt()\" 来检查用的账号是否还有效.可以被用来
检查用户是否超时或账号是否过期.
© Session management:
包括 `pam_open_session()\" 和 `pam_close_session()\" 用于对话
过程的管理. 例如: 可以用来纪录用户的连接时间. 一次telnet过程
实际上也是一个session.
(d) Password management:
`pam_chauthtok()\" 用来修该密码.
程序通过调用 `pam_start()\"和 `pam_end()\" 来开始或结束一次PAM 事务.
`pam_get_item()\" 和 `pam_set_item()\" 读写有关事务的信息.
可以用`pam_strerror()\"来取得错误信息.
如何配置你的系统呢?
pam.conf的一个例子:
#服务名 模块类型 控制标志 模块的名字 选项
#------- ----------- ------------ ----------- -------
login auth required pam_unix_auth.so nowarn
login session required pam_unix_session.so
login account required pam_unix_account.so
ftp auth required pam_skey_auth.so debug
ftp session required pam_unix_session.so
telnet session required pam_unix_session.so
login password required pam_unix_passwd.so
passwd password required pam_unix_passwd.so
OTHER auth required pam_unix_auth.so
OTHER session required pam_unix_session.so
OTHER account required pam_unix_account.so
`OTHER\" 被用来为没有它数指定的服务用的.
选项是随着模块的参数.为一个服务是可以指定多个auth模块的.它们一次被调用
来验证用户的身份.这叫做 Stacked Modules.
下面的例子为LOGIN指定了三个模块.
login
|
+--------+--------+
| | |
session auth account
| | |
+--+--+ +--+--+ +--+--+
| PAM | | PAM | | PAM |
+--+--+ +--+--+ +--+--+
| | |
UNIX UNIX UNIX
session auth account
|
Kerberos
auth
|
RSA
auth
Figure 2: Stacking With the PAM Architecture
pam.conf中的 `控制标志\" 实际上是指明这些 Stacked module 的工作方式.
它可取的值如下:
(a) `required\":
该模块的让正必须通过,失败者立即返回错误信息.
(
`optional\":
表示可以忽略它的错误而继续下面一个模块.
© `sufficient\":
表明该模块的让正已经是足够了,下面的模块就不用调用了.立即
返回成功的消息.
Password-Mapping 密码的映射
多层的模块认证可能会需要多个密码. 则会使用户感到厌烦.一个简单的方法是
是用户使用同一个密码而透过mapping机制来加强安全性. 其实是通过一个密码来产
生另一个密码,使一个密码可被多个模块使用. 当然要保证第一个密码是强壮的.
auth的模块多有下列 `选项\":
(a) `use_first_pass\":
使用第一个模块要求输入的密码.不再向用户提示要密码.
(
`try_first_pass\":
先试着使用第一个模块要求输入的密码, 不对再要求用户输入.
© `use_mapped_pass\":
使用 password-mapping 来得到密码, 不再向用户提示要密码.
(d) `try_mapped_pass\":
先试着使用 password-mapping 来得到密码, 不对再向用户提示要密码.
下面的例子可以看懂了吧:
pam.conf
login auth required pam_unix.so debug
login auth required pam_kerb.so use_mapped_pass
login auth optional pam_rsa.so use_first_pass
这种设计使你没有办法来知道执行的具体情况. 当然它也是与应用程序无关的.
Notes:
在linux下, 也可以用/etc/pam.d中的文件来配置.这些文件的格式与pam.conf
类似,只是没有服务名. 其服务名就是它的文件名.
入上述的login也可以配置如下:
/etc/pam.d/login
auth required pam_unix.so debug
auth required pam_kerb.so use_mapped_pass
auth optional pam_rsa.so use_first_pass
APPENDIX A. PAM API\"S
A.1. Framework Layer API\"s
int
pam_start(
char *service_name, // pam.conf中的服务的名字
char *user, // 用户名
struct pam_conv *pam_conversation,
// 一个用于互交的函数
pam_handle_t **pamh // 一个句柄
);
`pam_start()\" 用于初始化一次pam事务
PAM modules 透过struct pam_conv *pam_conversation中定义的函数来与应用程序
通信.
int
pam_end(
pam_handle_t *pamh,
int pam_status //上一个pam函数的返回值
);
`pam_end()\" 结束一次PAM 事务, 释放相关的内存.
int
pam_set_item(
pam_handle_t *pamh,
int item_type,
void *item
);
int
pam_get_item(
pam_handle_t *pamh,
int item_type,
void **item
);
`pam_get_item()\" 和 `pam_set_item()\" 用于一些特殊处理.读一些信息.
Table 5: Possible Values for Item_type
Item Name Description
--------- -----------
PAM_SERVICE The service name
PAM_USER The user name
PAM_TTY The tty name
PAM_RHOST The remote host name
PAM_CONV The pam_conv structure
PAM_AUTHTOK The authentication token (password)
PAM_OLDAUTHTOK The old authentication token
PAM_RUSER The remote user name
char *
pam_strerror(
int errnum
);
int
pam_set_data(
pam_handle_t *pamh,
char *module_data_name,
char *data,
(*cleanup)(pam_handle_t *pamh, char *data,
int error_status)
);
int
pam_get_data(
pam_handle_t *pamh,
char *module_data_name,
void **datap
);
用于读取与模块相关的数据.
A.2. Authentication API\"s
int
pam_authenticate(
pam_handle_t *pamh,
int flags
);
int
pam_setcred(
pam_handle_t *pamh,
int flags
);
A.3. Account Management API
int
pam_acct_mgmt(
pam_handle_t *pamh,
int flags
);
A.4. Session Management API\"s
int
pam_open_session(
pam_handle_t *pamh,
int flags
);
int
pam_close_session(
pam_handle_t *pamh,
int flags
);
A.5. Password Management API\"s
int
pam_chauthtok(
pam_handle_t *pamh,
int flags
);
APPENDIX B. SAMPLE PAM APPLICATION
/*
/etc/pam.conf
check_user auth required /lib/security/pam_unix_auth.so
check_user account required /lib/security/pam_unix_acct.so
注意要和你的系统一致redhat是这样
编译时要这样:
gcc check.c -ldl -lpam -lpam_misc -o check_user
*/
#include
#include
#include
static struct pam_conv conv = {
misc_conv, //定义在pam_misc.h中, 方便你编程
NULL
};
int main(int argc, char *argv[])
{
pam_handle_t *pamh=NULL;
int retval;
const char *user=\"nobody\";
if(argc == 2) {
user = argv[1];
}
if(argc > 2) {
fprintf(stderr, \"Usage: check_user [username]\\n\");
exit(1);
}
retval = pam_start(\"check_user\", user, &conv, &pamh);
/* 开始 */
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
/* 认证是不是该用户? 提示你输入一个密码 */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
/* 账号是否有效? */
if (retval == PAM_SUCCESS) {
fprintf(stdout, \"Authenticated\\n\");
} else {
fprintf(stdout, \"Not Authenticated\\n\");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) {
/* 结束 */
pamh = NULL;
fprintf(stderr, \"check_user: failed to release authenticator\\n\");
exit(1);
}
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
}
PAM中的模块
模块导引, 这里对最常用的10个模块做了描述.
想知道更多的信息, 你可以察看/usr/doc/pam* 下的文件.
1) Chroot
pam_chroot
Management groups provided:
account; session; authentication
为用户提供了一伪造的文件系统.
2) Cracklib pluggable password strength-checker
pam_cracklib
Management groups provided:
password
需要库libcrack 和议本系统字典/usr/lib/cracklib_dict.
检查密码的可靠性
对下列问题进行检查:
Palindrome - 回文 速度和倒读都一样
Case Change Only - 仅仅是大小写的变化
Similar - 过于相似
Simple - 太简单了
Rotated - 是旧密码的循环
Password component
可识别的参数
debug; type=XXX; retry=N; difok=N; minlen=N; dcredit=N;
ucredit=N; lcredit=N; ocredit=N;
Description:
提示用户输入密码,并检查密码是否可靠.
debug - 透过syslogd来写信息.
type=XXX - 系统的名字
retry=N - 可重试的次数
difok=N - 至少要有多少个字符不同
minlen=N - 新密码的长度加一的最小值
dcredit=N ucredit=N lcredit=N ocredit=N -
最少要有多少的数字,大写字母,小写字母和其它字母.
3) Deny
pam_deny
Management groups provided:
account; authentication; password; session
用于拒绝提供服务.
Account component
仅仅是返回一个错误 PAM_ACCT_EXPIRED.
#
# add this line to your other login entries to disable all accounts
#
login account required pam_deny.so
Authentication component
仅仅是返回一个错误 PAM_AUTH_ERR. 当调用 pam_authenticate()时.
返回 PAM_CRED_UNAVAIL, 当调用 pam_setcred() 时.
#
# add this line to your existing OTHER entries to prevent
# authentication succeeding with default applications.
#
OTHER auth required pam_deny.so
Password component
Recognized arguments:
Description:
拒绝用户修改密码.返回PAM_AUTHTOK_ERR.
Examples/suggested usage:
#
# add this line to your other login entries to prevent the login
# application from being able to change the user\"s password.
#
login password required pam_deny.so
Session component
阻止用户在主机上开始一个session.
Examples/suggested usage:
#
# An example to see how to configure login to refuse the user a
# session (politely)
#
login session required pam_motd.so file=/etc/system_time
login session required pam_deny.so
4) Anonymous access module
pam_ftp.so
Management groups provided:
authentication
Overview of module
提供了匿名ftp认证.
Authentication component
参数:
debug; users=XXX,YYY,...; ignore
丹用户名为ftp或anonymous时,将密码安@分为 PAM_RUSER 和 PAM_RHOST;
相应的设置pam-items. 用户名被设为 ftp.
debug - syslog
users=XXX,YYY,...- 允许的用户名.
ignore - 不关心用户的email地址.
The group access module
pam_group
Management groups provided:
authentication
System dependencies:
需要设置 /etc/security/group.conf
Network aware:
需要正确设置PAM_TTY item.
Overview of module
基于用户名和它们使用的终端来决定是否提供服务.
Authentication component
5) The last login module
pam_lastlog
Management groups provided:
auth
System dependencies:
所用的信息包含在/var/log/wtmp中.
Overview of module
这个模块维护 /var/log/wtmp . 增加打开的一项当调用 pam_open_seesion()
当pam_close_session()时关闭该项.它也显示一条信息表示用户上次何时登陆.
``Last login on ...\"\" 该模块维护 /var/log/wtmp.
Authentication component
Recognized arguments:
debug; nodate; noterm; nohost; silent; never
Description:
debug - write more information to syslog(3).
nodate - 不显示上次登陆的时间
noterm - 不显示上次登陆的终端.
nohost - 不显示上次登陆的主机.
silent - 不显示上次登陆的信息,值更新 /var/log/wtmp.
never - 如果/var/log/wtmp 不包含上次登陆的信息. 显示``welcome...\"
Examples/suggested usage:
这个木块可以用来显示该用户收到了new mail,当它们登陆到系统中时.
#
# do we have any mail?
#
login session optional pam_lastlog.so
6) The resource limits module
pam_limits
Management groups provided:
session
/etc/security/limits.conf内核支持 resource limits.
Overview of module
通过 Linux-PAM open-session hook 设置用户的session可使用的系统资源上限
Session component
Recognized arguments:
debug; conf=/path/to/file.conf
root不受限制
conf=/path/to/file.conf 指定替代缺省的配置文件的文件名
例如:
为了使用这个模块 /etc/security/limits.conf 必须是root只读的
The fields listed above should be filled as follows...
可以是用户名,用户组名(@group) 或统配符 * 表示缺省规则
可以是 hard soft
hard 强制实行 由管理员设置 由Linux Kernel执行 . 用户无权改变.
soft 非强制执行. 用户可以改变 在之前存在的 hard limits 允许下.
可以是下列值:
core - core 文件的大小 (KB)
data - 最大的data大小 (KB)
fsize - maximum filesize (KB)
memlock - max locked-in-memory address space (KB)
nofile - max number of open files
rss - max resident set size (KB)
stack - max stack size (KB)
cpu - max CPU time (MIN)
nproc - max number of processes
as - address space limit
maxlogins - max number of logins for this user.
通过加一个(-)来完全取消限制 (Example: ``bin -\"\", ``@admin -\"\").
注意用户的优先级比组的优先级要高.
下面是一个例子:
# EXAMPLE /etc/security/limits.conf file:
# =======================================
#
* soft core 0
* hard rss 10000
@student hard nproc 20
@faculty soft nproc 20
@faculty hard nproc 50
ftp hard nproc 0
@student - maxlogins 4
7) The no-login module
pam_nologin
Management groups provided:
authentication
Overview of module
提供了标准的unix nologin服务.
Authentication component
Recognized arguments:
Description:
当/etc/nologin文件存在时就拒绝login.
8) The Password-Database module
pam_pwdb
Management groups provided:
account; authentication; password; session
Overview of module
用于取代 pam_unix_* 模块. 它使用了通用的 Password Database
library 接口函数.
Account component
Recognized arguments:
debug
例如:
/etc/pam.d/login 一定会有下面一行.
#
# Ensure users account and password are still active
#
login account required pam_pwdb.so
Authentication component
可用的阐述:
debug; use_first_pass; try_first_pass; nullok; nodelay
debug就没什么好说的了.
use_first_pass try_first_pass 在我的另一篇文章中已经所得很清楚了.
nullok时所允许空密码登陆.
nodelay在失败后不停留. 这一延时是为了抵挡基于字典的暴力入侵.
Password component
Recognized arguments:
debug; nullok; not_set_pass; use_authtok; try_first_pass;
use_first_pass; md5; bigcrypt; shadow; radius; unix
Description:
not_set_pass 不为栈中的其它模块保留密码.
md5是所用MD5算法来代替标准的算法.
bigcrypt是指处理长度超过8个字符的密码.
unix使用标准的加密方式.
shadow使用shadow文件.
radius:使用远程拨入用户服务器.
Session component
它只是通过 syslog(3) 来纪录一下.
例如:
#
# pwdb - unix like session opening and closing
#
login session required pam_pwdb.so
9) The rhosts module
pam_rhosts_auth
Management groups provided:
authentication
对使用 rlogin 和 rsh 进行安全性检查.
Authentication component
可用参数:
no_hosts_equiv; no_rhosts; debug;
no_warn; privategroup; promiscuous; suppress
Description:
它通过 /etc/hosts.equiv 和 ~/.rhosts 来确认.
no_hosts_equiv 忽略 /etc/hosts.equiv 的内容.
no_rhosts 忽略 ~/.rhosts的内容.
privategroup 通常~/.rhost必须只有宿主才能写否则就失败. 这一选项
是同组可写的 ~/.rhosts 也被使用.
promiscuous 不使用这一选项 配置文件中的 \"+\" 项 将被忽略.
suppress 禁止模块用 syslog(3) 来发警告信息.
10) The securetty module
pam_securetty
Management groups provided:
authentication
Overview of module
提供了标准的安全终端的检查(使用/etc/securitty)
(http://www.fanqiang.com)