QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 756|回复: 3

关于PAM的一个验证过程,请了解PAM的进来

[复制链接]
发表于 2005-9-8 19:11:57 | 显示全部楼层 |阅读模式

我要用PAM去实现一个用户验证的过程。我看了很多文章和例子但还是有很多不明白的地方,下面是我摘抄的一个例子,但是编译不过去,缺好多代码,而且有很多地方我看不懂,请哪位高人帮我解释一下,其中不懂的地方我用编号和问号表示出来了。在此先行谢过。


#include <security/pam_appl.h>
#include <security/pam_misc.h>

#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>

/* 回调函数 */
static int login_conv(int num_msg, struct pam_message **msg, struct pam_response **response, void *appdata_ptr);
struct pam_conv pam_conv = {login_conv, NULL};
pam_handle_t *pamh;  // 进行认证的PAM句柄

/* 出错则清理现场并退出 */
static void login_exit(int exit_code)
{
   if (pamh)
       pam_end(pamh, PAM_ABORT);
   _exit(exit_code);
}

int main(int argc, char *argv[], char **renvp)
{
passwd *pwd;
   /* 初始化,并提供一个回调函数 */
   if ((pam_start("login", user, &pam_conv, &pamh)) != PAM_SUCCESS)
       login_exit(1);

   /* 设置一些参数 */
   pam_set_item(pamh, PAM_TTY, ttyn); //1、ttyn 是在哪里定义的?PAM_TTY是什么意思?
   pam_set_item(pamh, PAM_RHOST, remote_host);//2、remote_host在哪里定义的?PAM_RHOST是什么意思?

   while (!authenticated && retry < MAX_RETRIES)//3、authenticated和retry在哪里定义?这里是什么意思?
   {
       status = pam_authenticate(pamh, 0);        /* 密码认证管理,检查用户输入的密码是否正确 */
       authenticated = (status == PAM_SUCCESS);   //4、没看到有密码输入,如果检查,此处是否是交互式的
          // 如果是,能否在开始就将密码传入?
   }

   if (status != PAM_SUCCESS)
   {
       fprintf(stderr,"error: %s\n", pam_strerror(pamh, status)); /* 显示错误原因 */
       login_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)
               login_exit(1);
       }
   }

   /* 通过帐户管理检查之后则打开会话 */
   if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)
       login_exit(status);

pwd = getpwnam(user);
   /* 设置用户组 */ //5、此处设置用户组有什么用?
   setgid(pwd->pw_gid);

   /*
   * Initialize the supplementary group access list before
   * pam_setcred because PAM modules might add groups
   * during the pam_setcred call
   */
   initgroups(user, pwd->pw_gid);

   status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
   if (status != PAM_SUCCESS)
       login_exit(status);

   /* 设置真实的用户ID(或者有效的用户ID)*/
   setuid(pwd->pw_uid);

   pam_end(pamh, PAM_SUCCESS);  /* PAM事务的结束 */


   /*
   此处可用来实现与login有关的其它内容 //6、这里的其它内容指的是什么?
   */
}

/* 这个回调函数被PAM认证模块调用以便显示错误信息或者或者用来取得用户输入,采用图形界面的服务程序则应使用图形界面来取得 用户输入或显示提示信息*/
int login_conv(int num_msg, struct pam_message **msg, struct pam_response **response, void *appdata_ptr)
{
   while (num_msg--)
   {
       switch (m->msg_style)
       {
           case PAM_PROMPT_ECHO_OFF:
               r->resp = strdup(getpass(m->msg));
               break;
           case PAM_PROMPT_ECHO_ON:
               (void) fputs(m->msg, stdout);
               r->resp = malloc(PAM_MAX_RESP_SIZE);
               fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
               /* add code here to remove \n from fputs */
               break;
           case PAM_ERROR_MSG:
               (void) fputs(m->msg, stderr);
               break;
           case PAM_TEXT_INFO:
               (void) fputs(m->msg, stdout);
               break;
           default:
               log_error();
               break;
       }
   }
   return (PAM_SUCCESS);
}
发表于 2005-9-8 21:50:39 | 显示全部楼层
_pam_types.h里有PAM_TTY,PAM_RHOST的说明。
你还不如贴个完整的例子上来。
回复

使用道具 举报

 楼主| 发表于 2005-9-9 09:24:00 | 显示全部楼层
[quote:ece27267ef="mozilla"]_pam_types.h里有PAM_TTY,PAM_RHOST的说明。
你还不如贴个完整的例子上来。[/quote]

正因为我没找到完整的例子才贴的。
回复

使用道具 举报

 楼主| 发表于 2005-9-9 18:03:55 | 显示全部楼层
现在我可以利用PAM对login服务的用户进行验证了,但是对于其它的服务的验证似乎与login是一样的过程。当我用pam_start(“samba”, user, &pam_conv, &pamh);验证samba的用户时似乎还是用的login的验证过程。比如我在验证samba用户A时,A用户是系统的合法用户但不是samba的合法用户,可是验证结果也是成功。对于vsftpd也有类似的情况,这是为什么?我本来打算用一个程序去既能验证系统的用户又能验证samba、ftp等服务的用户,但我是想让这些服务都用相同的用户名和密码,可是我现在竟然连非法用户也能验证通过,这是为什么?

现在的代码如下:

#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>

/* 回调函数 */
static int login_conv(int num_msg, const struct pam_message **msg, struct pam_response **response, void *appdata_ptr);
pam_handle_t *pamh;  // 进行认证的PAM句柄

/* 出错则清理现场并退出 */
static void login_exit(int exit_code)
{
    if (pamh)
        pam_end(pamh, PAM_ABORT);
    _exit(exit_code);
}

int main(int argc, char *argv[], char **renvp)
{
        passwd *pwd;
        int status = -1;
        const char* ttyn,*p,*service;
        const char * user = argv[1];
        struct pam_conv pam_conv = {login_conv, argv[2]};

    if (argc != 4)
        {
                printf("please inpute username and passwd\n");
                _exit(0);
        }
    /* 初始化,并提供一个回调函数 */
    status = pam_start(argv[3], user, &pam_conv, &pamh);
   
    pam_get_item(pamh ,PAM_SERVICE ,(const void **)&service);
    printf("Service is %s\n",service);
        
    if (status != PAM_SUCCESS)
    {   
            fprintf(stderr,"start error: %s\n", pam_strerror(pamh, status)); /* 显示错误原因 */
        login_exit(1);
        }
        pam_get_item(pamh,PAM_USER,(const void **)&p);/*验证用户是否存在*/
        if (getpwnam(p) == NULL)
        {
                printf("user does not exist\n");
                _exit(0);
        }
    status = pam_authenticate(pamh, 0);        /* 密码认证管理,检查用户输入的密码是否正确 */
    if (status != PAM_SUCCESS)
    {
        fprintf(stderr,"authenticate error: %s\n", pam_strerror(pamh, status)); /* 显示错误原因 */
        login_exit(1);
    }
        else
                printf("authenticate success!\n");
    getchar();
    pam_end(pamh, PAM_SUCCESS);  /* PAM事务的结束 */

}

/* 这个回调函数被PAM认证模块调用以便显示错误信息或者或者用来取得用户输入,采用图形界面的服务程序则应使用图形界面来取得 用户输入或显示提示信息*/
int login_conv(int num_msg, const struct pam_message **msg,
         struct pam_response **response, void *appdata_ptr)
{
    struct pam_message  *m = (struct pam_message *)*msg;
           struct pam_response *r ;
           while (num_msg--)
    {
        switch (m->msg_style)
        {
            case PAM_PROMPT_ECHO_OFF:
                    r               = (struct pam_response *)malloc(sizeof(struct pam_response));
                            r->resp         = (char *)malloc(strlen((char*)appdata_ptr));
                            r->resp_retcode = 0;
                strcpy(r->resp,(char*)appdata_ptr);
                *response = r;
                break;
            case PAM_PROMPT_ECHO_ON:
                (void) fputs(m->msg, stdout);
                r->resp = (char*)malloc(PAM_MAX_RESP_SIZE);
                fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
                /* add code here to remove \n from fputs */
                break;
            case PAM_ERROR_MSG:
                (void) fputs(m->msg, stderr);
                break;
            case PAM_TEXT_INFO:
                (void) fputs(m->msg, stdout);
                break;
        }
    }
    return (PAM_SUCCESS);
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-5 11:51 , Processed in 0.040727 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表