分享
 
 
 

PAM的应用开发和内部实现源码分析

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

1 引言

身份认证是操作系统安全的重要机制之一,系统通过认证机制核查用户的身份证明,并作为用户进入系统的判定条件,是防止恶意用户进入系统的第一道门槛。近年来认证理论和技术得到了迅速发展,产生了各种认证机制,如口令机制,RSA, DCE, kerberos认证体制,S/Key和基于智能卡的身份认证等。然而,当系统中引入新的认证机制时,一些系统入口登录服务如login, rlogin和telnet等应用程序就必须改写以适应新的认证机制。为了解决这个问题,1995年Sun公司的Vipin Samar和 Charlie Lai提出了PAM(Pluggable Authentication Modules),并将其应用在Solaris系统上。PAM框架将应用程序与具体的认证机制分离,使得系统改变认证机制时,不再需要修改采用认证机制的应用程序,而只要由管理员配置应用程序的认证服务模块,极大地提高了认证机制的通用性与灵活性。

现在大多数操作系统都采用PAM实现身份认证,有Linux系统的Linux-PAM和FreeBSD5.x采用的OpenPAM(FreeBSD 4.x采用的是Linux-PAM)等。它们的实现原理一样,只有实现细节不同而已。下面从PAM的应用开发开始介绍。

2 PAM的应用开发

2.1 PAM框架概览

PAM即可插拔认证模块。它提供了对所有服务进行认证的中央机制,适用于login,远程登录(telnet,rlogin,fsh,ftp,点对点协议(PPP)),su等应用程序中。系统管理员通过PAM配置文件来制定不同应用程序的不同认证策略;应用程序开发者通过在服务程序中使用PAM API(pam_xxxx( ))来实现对认证方法的调用;而PAM服务模块的开发者则利用PAM SPI来编写模块(主要是引出一些函数pam_sm_xxxx( )供PAM接口库调用),将不同的认证机制加入到系统中;PAM接口库(libpam)则读取配置文件,将应用程序和相应的PAM服务模块联系起来。PAM框架结构如图所示。

其中,pamh是一个pam_handle类型的结构,它是一个非常重要的处理句柄,是PAM与应用程序通信的唯一数据结构,也是调用PAM接口库API的唯一句柄。pam_handle数据结构将在下面的源代码分析一节的介绍。

另外,如上图所示的服务模块分auth(认证管理)、account(账号管理)、session(会话管理)、passwd(口令管理)四种类型,各个类型模块的作用以及配置文件的四个组成部分模块类型、控制标志、模块路径、模块参数等在很多讲PAM的配置管理的文章里都有介绍,这里就不再赘述了。

2.2 在应用程序中使用PAM认证

每个使用PAM认证的应用程序都以pam_start开始,pam_end结束。PAM还提供了pam_get_item和pam_set_item共享有关认证会话的某些公共信息,例如用户名,服务名,密码和会话函数。应用程序在调用了pam_start ()后也能够用这些APIs来改变状态信息。实际做认证工作的API函数有六个(以下将这六个函数简称为认证API):

认证管理--包括pam_authenticate ()函数认证用户,pam_setcred ()设置,刷新,或销毁用户证书。

账号管理--包括pam_acc_mgmt ()检查认证的用户是否可以访问他们的账户,该函数可以实现口令有效期,访问时间限制等。

会话管理--包括pam_open_session ()和pam_close_session ()函数用来管理会话和记账。例如,系统可以存储会话的全部时间。

口令管理--包括pam_chauthok ()函数用来改变密码。

下面看一个简单的login模拟程序:

/* 使用PAM所必需的两个头文件*/

#include

#include

void main(int argc, char *argv[], char **renvp)

{

/* 初始化,并提供一个回调函数 */

if ((pam_start("login", user_name, &pam_conv, &pamh)) != PAM_SUCCESS)

exit(1);

/* 设置一些关于认证用户信息的参数 */

pam_set_item(pamh, PAM_TTY, ttyn);

pam_set_item(pamh, PAM_RHOST, remote_host);

while (!authenticated && retry

{

status = pam_authenticate(pamh, 0);/* 认证,检查用户输入的密码是否正确 */

}

/* 认证失败则应用程序退出*/

if (status != PAM_SUCCESS)

{

……

exit(1);

}

/*

通过了密码认证之后再调用帐号管理API,检查用户帐号是否已经过期 */

if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)

{

if (status == PAM_AUTHTOK_EXPIRED)

{

status = pam_chauthtok(pamh, 0);

/* 过期则要求用户更改密码 */

if (status != PAM_SUCCESS)

exit(1);

}

}

/* 通过帐户管理检查之后则打开会话 */

if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)

exit(status);

……

/* 建立认证服务的用户证书*/

status = pam_setcred(pamh, PAM_ESTABLISH_CRED);

if (status != PAM_SUCCESS)

exit(status);

……

pam_end(pamh, PAM_SUCCESS);

/* PAM事务的结束 */

……

}

从上面程序中,我们可以了解到使用PAM认证的一般流程,同时也可以看出PAM API使得使用认证的应用程序不仅不用关心底层使用的服务模块,而且编写起来简洁明了得多。

有关开发使用PAM的应用程序更加详细完整的阐述请参考The Linux-PAM Application Developers' Guide。

2.3 怎样开发PAM服务模块

首先在编写的服务模块的源程序里要包含下列头文件:

#include

PAM的服务模块是一个一个的动态链接库文件(也可以是静态库),PAM接口库通过dlopen来装载这些库。假设源程序名为pam_module-name.c,则需要用下列命令将其编译成动态链接库:

gcc -fPIC -c pam_module-name.c

ld -x --shared -o pam_module-name.so pam_module-name.o

选项-fPIC是指位置无关代码(Position Independent Code),这类代码支持大偏移。使用--shared选项将目标代码放进共享目标库中。

四种类型的模块各自要实现的函数如下表所示:

当然同一个服务模块可以同时属于多种类型,只要这些类型模块要实现的函数都实现了就可以,比如PAM自带的经典口令认证机制模块pam_unix.so 就可以支持四种模块类型。

下面来看一个最简单的pam_deny模块的源程序pam_deny.c:

1.#define PAM_SM_AUTH

2.#define PAM_SM_ACCOUNT

3.#define PAM_SM_SESSION

4.#define PAM_SM_PASSWORD

5.#include "../../libpam/include/security/pam_modules.h"

6./* --- 认证管理函数的实现--- */

7.PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc

8.,const char **argv)

9.{

10.return PAM_AUTH_ERR;

11.}

12.PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc

13.const char **argv)

14.{

15.return PAM_CRED_UNAVAIL;

16.}

17./* --- 账号管理函数的实现 --- */

18.PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc

19.,const char **argv)

20.{

21.return PAM_ACCT_EXPIRED;

22.}

23./* --- 口令管理函数的实现 --- */

24.PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc

25.const char **argv)

26.{

27.return PAM_AUTHTOK_ERR;

28.}

29./* --- 会话管理函数的实现 --- */

30.PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc

31.const char **argv)

32.{

33.return PAM_SYSTEM_ERR;

34.}

35.PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc

36.,const char **argv)

37.{

38.return PAM_SYSTEM_ERR;

39.}

40./* 模块定义结束 */

41./* 静态模块数据 */

42.#ifdef PAM_STATIC

43.struct pam_module _pam_deny_modstruct = {

44."pam_deny",

45.pam_sm_authenticate,

46.pam_sm_setcred,

47.pam_sm_acct_mgmt,

48.pam_sm_open_session,

49.pam_sm_close_session,

50.pam_sm_chauthtok

51.};

52.#endif

很容易看出,pam_deny模块支持四种模块类型。前4行包含静态模块的一些原型申明,第37-39行实现了四种模块类型的函数,因为这只是一个简单的拒绝服务的模块,所以这些函数只是简单地返回认证错或系统错等PAM错误。最后几行定义了该程序被编译成静态模块所需的一个模块数据结构。

因此,PAM SPI使得服务模块的开发也相当简单和专一,因为服务模块不再需要考虑和应用程序的交互,只要将自己采用的算法实现好就可以了。

模块源程序可用的flags参数值和返回值的定义这里不作全面介绍,有兴趣者请参考The Linux-PAM Module Writers' Guide。

3 PAM接口库源代码分析

上面我们介绍了怎样使用PAM和怎样开发PAM服务模块,要想对PAM的内部机制有个透彻的理解,还需要进一步分析PAM接口库的代码。下面基于Linux 的pam-0.75-40.src.rpm包所得的源

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有