PAM(4)

有了前面的知识,今天将和大家一起写一个简单的PAM模块

好了废话不说了直接写吧(文件为 pam_test.c)

[cpp]  view plain  copy
  1. #define PAM_SM_AUTH  
  2. #include <security/pam_modules.h>  
  3. #include <security/pam_appl.h>  
  4. #include <stdio.h>  
  5. #include <string.h>  
  6. #include <stdarg.h>  
  7.   
  8. #define MODULE_NAME "pam_sample"  
  9. #define SAMPLE_PROMPT "Extra Password for root:"  
  10. #define PAM_DEBUG_ARG      1  
  11.   
  12. #define DPRINT if (ctrl & PAM_DEBUG_ARG) sample_syslog  
  13.   
  14. #define PAM_RET_CHECK(ret) if(PAM_SUCCESS != ret) \  
  15.                            {                        \  
  16.                                 return ret;         \  
  17.                            }  
  18.   
  19.   
  20.   
  21. //if debug is setting this function can write log information /var/log/message  
  22. static void sample_syslog(int err, const char *format, ...)  
  23. {  
  24.     va_list args;  
  25.     char buffer[1024];  
  26.   
  27.     va_start(args, format);  
  28.     vsprintf(buffer, format, args);  
  29.     /* don't do openlog or closelog, but put our name in to be friendly */  
  30.     syslog(err, "%s: %s", MODULE_NAME, buffer);  
  31.     va_end(args);  
  32. }  
  33.   
  34. //get the paramters  
  35. static int sample_parse(int argc, const char **argv, char *szconf)  
  36. {  
  37.   int ctrl=0;  
  38.     
  39.   /* 
  40.    *  If either is not there, then we can't parse anything. 
  41.    */  
  42.   if ((argc == 0) || (argv == NULL)) {  
  43.     return ctrl;  
  44.   }  
  45.     
  46.   /* step through arguments */  
  47.   for (ctrl=0; argc-- > 0; ++argv)   
  48.   {  
  49.       
  50.     /* generic options */  
  51.     if (!strcmp(*argv, "debug"))   
  52.     {  
  53.       ctrl |= PAM_DEBUG_ARG;  
  54.     }  
  55.     else   
  56.     {  
  57.      sample_syslog(LOG_WARNING, "unrecognized option '%s'", *argv);  
  58.     }  
  59.   }  
  60.   return ctrl;  
  61. }  
  62.   
  63. //callback function to release a buffer  
  64. void sample_pam_free(pam_handle_t *pamh, void *pbuf, int error_status)  
  65. {  
  66.     free(pbuf);  
  67. }  
  68. //conversation function  
  69. //这个是做了封装的对话函数,每次只允许你向应用程序请求一个"问题"  
  70. int sample_converse(pam_handle_t *pamh, int msg_style, char *message, char **password)  
  71. {  
  72.     const struct pam_conv *conv;  
  73.       
  74.     struct pam_message resp_message;  
  75.     const struct pam_message *msg[1];  
  76.     struct pam_response *resp = NULL;  
  77.       
  78.     int retval;  
  79.   
  80.     resp_message.msg_style = msg_style;  
  81.     resp_message.msg = message;  
  82.     msg[0] = &resp_message;  
  83.     //之前老提到对话函数,我们说过对话函数由应用程序提供,这里可以看到在模块中怎么获得对话函数  
  84. //通过pam_get_item 可以获得pam_conv这个结构的一个指针(第二个参数是PAM_CONV表示类型)  
  85. //然后就想下面的调用方式,你可以在你的模块中调用这个对话函数,和应用程序交互  
  86.     retval = pam_get_item(pamh, PAM_CONV, (const void **)&conv);  
  87.     PAM_RET_CHECK(retval)  
  88.           
  89.     retval = conv->conv(1, msg, &resp, conv->appdata_ptr);  
  90.     PAM_RET_CHECK(retval)  
  91.     if(password)  
  92.     {  
  93.         *password = resp->resp;  
  94.         free(resp);  
  95.     }  
  96.       
  97.     return PAM_SUCCESS;  
  98. }   
  99.   
  100.   
  101. #ifdef PAM_SM_AUTH  
  102. PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)  
  103. {  
  104.     char *puser, *ppwd;  
  105.     int nret;  
  106.     int nloop;  
  107.     int nChallenge;  
  108.     int nValidrsp;  
  109.     char szbuf[256];  
  110.     char szconf[256];  
  111.     char *resp2challenge = NULL;  
  112.   
  113.     int ctrl = 0;  
  114.     memset(szconf, 0, 256);  
  115. //通过这个函数获得用户名  
  116.     nret = pam_get_user(pamh, &puser, "UserName:");  
  117.     if(PAM_SUCCESS != nret)  
  118.     {  
  119.         int *pret = (int *)malloc(sizeof(int));  
  120.         //makelog("get username failed");  
  121.         DPRINT(LOG_DEBUG, "Get user name failed");  
  122.         *pret = nret;  
  123.         pam_set_data(pamh, "sample_setcred_return", (void *)pret, sample_pam_free);  
  124.         return PAM_SYSTEM_ERR;  
  125.     }  
  126.     else  
  127.     {  
  128.         //username  
  129. //如果用户名为root,请用户输入附加密码 "123456"  
  130.         if(!strcasecmp("root", puser))  
  131. {  
  132. //如果为root 和应用程序交互,让用户输入密码  
  133. //如果为root 和应用程序交互,让用户输入密码  
  134. nret = sample_converse(pamh, PAM_PROMPT_ECHO_OFF, SAMPLE_PROMPT, &ppwd);  
  135. if(PAM_SUCCESS != nret)  
  136. {  
  137.     int *pret = (int *)malloc(sizeof(int));  
  138.      *pret = nret;  
  139.      DPRINT(LOG_DEBUG, "Get extra password failed");  
  140.      pam_set_data(pamh, "sample_setcred_return", (void *)pret, sample_pam_free);  
  141.       return nret;  
  142. }  
  143. //you have get the extra password  
  144. if(strcasecmp("123456", ppwd))  
  145. {  
  146.     int *pret = (int *)malloc(sizeof(int));                          *pret = PAM_AUTH_ERR;                          DPRINT(LOG_DEBUG, "Invalid extra password");                          pam_set_data(pamh, "sample_setcred_return", (void *)pret, sample_pam_free);                          return PAM_AUTH_ERR;  
  147. }  
  148. }  
  149. }  
  150.     return PAM_SUCCESS;  
  151. }  
  152.   
  153. PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)  
  154. {  
  155.     int nret = PAM_SUCCESS, *pret;  
  156.     pret = &nret;  
  157.     pam_get_data(pamh, "sample_setcred_return", (void **)&pret);  
  158.     return *pret;  
  159. }  
  160.   
  161. #endif//PAM_SM_AUTH  


 

编译 gcc -o pam_test.so -shared -fPIC ./pam_test.c -lpam

将pam_test.so 拷贝到/lib/security/下(平台不同有差异)

配置 vim /etc/pam.d/login (如果想为login使用这个模块) 

在你希望的位置添加 auth sufficient pam_test.so

sufficient 还可以为 required 等具体请参照http://www.ibm.com/developerworks/cn/linux/l-pam/index.html?ca=drs-#resources

至此一个简单的PAM模块就写好了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值