文章版权归原作者所有! (www.MegaEntry.com)
可插入的认证模块(并不是Linux指的模块)用于实现应用程序的认证机制,是程序员或管理员不需要重新编写或编译程序就可以改变认证机制.在linux它已经被广泛的应用了, 例如: /etc/securitty /etc/onlogin/etc/ftpusers 实际上都是给它用的.你在登陆的时候的输入密码和你修改密码时也都用的是它./etc/pam.conf和/etc/pam/* 都是它的配置文件.它最大的优点是它的弹性和可扩充性. 你可以随意修改认证机制, 按你的实际需要来定制系统.你了解后就会非常清楚了.DESIGN GOALS(设计目标)(a) 管理员可以选择认证方式, 从简单的密码到智能卡系统.(b) 可以为不同的程序配置不同的认证机制.如 使telnet使用 S/Key认证.而本机的 login 缺使用一般的 UNIX password.文章版权归原作者所有! (www.MegaEntry.com)
(c) 支持程序的显示方式的需求. 如login 需要基于终端的显示, 而dtlogin需要 X 显示, 而`ftp ' 和 `telnet '需要透过网络来认证.(d) 支持为一个程序配置同时使用多种认证机制.(e) 可是用户在使用多种认证机制时,不必为同一个密码敲入多次.(f) 可是用户在认真时需要输入多个密码.(g) 当底层的认证机制改变时上层软件不需要修改.(h) 结构为system authentication提供一个 _pluggable_ model.(i) 必须能满足现有的服务需要.4. OVERVIEW OF THE PAM FRAMEWORK (纵览PAM的框架)文章版权归原作者所有! (www.MegaEntry.com)
其核心实际上是一些库函数. 你写的应用程序要调用它们.PAM为你提供了一套入口(the front end). 而这套函数互调用 特定认证机制所定义的模块(the back end).简单的说是这样的: 你调用一个函数仅仅告诉它你要认正,这就足够了.至于用那一种机制来认证是由配置文件规定的. 你只需要看一看返回值就知道认证是否成功了. 对于开发应用程序的人来说只需要记住几个函数.ftp telnet login (Applications)| | || | |+--------+--------+|+-----+-----+| PAM API | <-- pam.conf file+-----+-----+MegaEntry 网络社区与信息交流平台!
|+--------+--------+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.(b) Account management:文章版权归原作者所有! (www.MegaEntry.com)
包括 `pam_acct_mgmt() ' 来检查用的账号是否还有效.可以被用来检查用户是否超时或账号是否过期.(c) 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() '来取得错误信息.MegaEntry 网络社区与信息交流平台!
如何配置你的系统呢?pam.conf的一个例子:#服务名 模块类型 控制标志 模块的名字 选项#------- ----------- ------------ ----------- -------login auth required pam_unix_auth.so nowarnlogin session required pam_unix_session.sologin account required pam_unix_account.softp auth required pam_skey_auth.so debugftp session required pam_unix_session.sotelnet session required pam_unix_session.sologin password required pam_unix_passwd.sopasswd password required pam_unix_passwd.soOTHER auth required pam_unix_auth.soOTHER session required pam_unix_session.soMegaEntry 网络社区与信息交流平台!
OTHER account required pam_unix_account.so`OTHER ' 被用来为没有它数指定的服务用的.选项是随着模块的参数.为一个服务是可以指定多个auth模块的.它们一次被调用来验证用户的身份.这叫做 Stacked Modules.下面的例子为LOGIN指定了三个模块.login|+--------+--------+| | |session auth account| | |+--+--+ +--+--+ +--+--+| PAM | | PAM | | PAM |+--+--+ +--+--+ +--+--+| | |MegaEntry 网络社区与信息交流平台!
UNIX UNIX UNIXsession auth account|Kerberosauth|RSAauthFigure 2: Stacking With the PAM Architecturepam.conf中的 `控制标志 ' 实际上是指明这些 Stacked module 的工作方式.它可取的值如下:(a) `required ':该模块的让正必须通过,失败者立即返回错误信息.MegaEntry 网络社区与信息交流平台!
(b) `optional ':表示可以忽略它的错误而继续下面一个模块.(c) `sufficient ':表明该模块的让正已经是足够了,下面的模块就不用调用了.立即返回成功的消息.Password-Mapping 密码的映射多层的模块认证可能会需要多个密码. 则会使用户感到厌烦.一个简单的方法是是用户使用同一个密码而透过mapping机制来加强安全性. 其实是通过一个密码来产生另一个密码,使一个密码可被多个模块使用. 当然要保证第一个密码是强壮的.auth的模块多有下列 `选项 ':(a) `use_first_pass ':MegaEntry 网络社区与信息交流平台!
使用第一个模块要求输入的密码.不再向用户提示要密码.(b) `try_first_pass ':先试着使用第一个模块要求输入的密码, 不对再要求用户输入.(c) `use_mapped_pass ':使用 password-mapping 来得到密码, 不再向用户提示要密码.(d) `try_mapped_pass ':先试着使用 password-mapping 来得到密码, 不对再向用户提示要密码.下面的例子可以看懂了吧:pam.conflogin auth required pam_unix.so debuglogin auth required pam_kerb.so use_mapped_passlogin auth optional pam_rsa.so use_first_passMegaEntry 网络社区与信息交流平台!
这种设计使你没有办法来知道执行的具体情况. 当然它也是与应用程序无关的.Notes:在linux下, 也可以用/etc/pam.d中的文件来配置.这些文件的格式与pam.conf类似,只是没有服务名. 其服务名就是它的文件名.入上述的login也可以配置如下:/etc/pam.d/loginauth required pam_unix.so debugauth required pam_kerb.so use_mapped_passauth optional pam_rsa.so use_first_passAPPENDIX A. PAM API 'SA.1. Framework Layer API 's文章版权归原作者所有! (www.MegaEntry.com)
intpam_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中定义的函数来与应用程序通信.intpam_end(文章版权归原作者所有! (www.MegaEntry.com)
pam_handle_t *pamh,int pam_status //上一个pam函数的返回值);`pam_end() ' 结束一次PAM 事务, 释放相关的内存.intpam_set_item(pam_handle_t *pamh,int item_type,void *item);intpam_get_item(pam_handle_t *pamh,MegaEntry 网络社区与信息交流平台!
int item_type,void **item);`pam_get_item() ' 和 `pam_set_item() ' 用于一些特殊处理.读一些信息.Table 5: Possible Values for Item_typeItem Name Description--------- -----------PAM_SERVICE The service namePAM_USER The user namePAM_TTY The tty namePAM_RHOST The remote host namePAM_CONV The pam_conv structurePAM_AUTHTOK The authentication token (password)MegaEntry 网络社区与信息交流平台!
PAM_OLDAUTHTOK The old authentication tokenPAM_RUSER The remote user namechar *pam_strerror(int errnum);intpam_set_data(pam_handle_t *pamh,char *module_data_name,char *data,(*cleanup)(pam_handle_t *pamh, char *data,MegaEntry 网络社区与信息交流平台!
int error_status));intpam_get_data(pam_handle_t *pamh,char *module_data_name,void **datap);用于读取与模块相关的数据.A.2. Authentication API 'sintpam_authenticate(MegaEntry 网络社区与信息交流平台!
pam_handle_t *pamh,int flags);intpam_setcred(pam_handle_t *pamh,int flags);A.3. Account Management APIintpam_acct_mgmt(pam_handle_t *pamh,int flagsMegaEntry 网络社区与信息交流平台!
);A.4. Session Management API 'sintpam_open_session(pam_handle_t *pamh,int flags);intpam_close_session(pam_handle_t *pamh,int flags);文章版权归原作者所有! (www.MegaEntry.com)
A.5. Password Management API 'sintpam_chauthtok(pam_handle_t *pamh,int flags);APPENDIX B. SAMPLE PAM APPLICATION/*/etc/pam.confcheck_user auth required /lib/security/pam_unix_auth.socheck_user account required /lib/security/pam_unix_acct.so注意要和你的系统一致redhat是这样编译时要这样:gcc check.c -ldl -lpam -lpam_misc -o check_userMegaEntry 网络社区与信息交流平台!
*/#include#include#includestatic 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 ";MegaEntry 网络社区与信息交流平台!
if(argc == 2) {user = argv[1];}if(argc > 2) {fprintf(stderr, "Usage: check_user [username] ");exit(1);}retval = pam_start( "check_user ", user, &conv, &pamh);/* 开始 */if (retval == PAM_SUCCESS)retval = pam_authenticate(pamh, 0);/* 认证是不是该用户? 提示你输入一个密码 */MegaEntry 网络社区与信息交流平台!
if (retval == PAM_SUCCESS)retval = pam_acct_mgmt(pamh, 0);/* 账号是否有效? */if (retval == PAM_SUCCESS) {fprintf(stdout, "Authenticated ");} else {fprintf(stdout, "Not Authenticated ");}if (pam_end(pamh,retval) != PAM_SUCCESS) {/* 结束 */pamh = NULL;fprintf(stderr, "check_user: failed to release authenticator ");exit(1);文章版权归原作者所有! (www.MegaEntry.com)
}return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */}