Chinaunix首页 | 论坛 | 博客
  • 博客访问: 681988
  • 博文数量: 85
  • 博客积分: 1797
  • 博客等级: 上尉
  • 技术积分: 1238
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-02 08:53
个人简介

职位:技术总监 1、精通c++(linux平台、vc++Mfc、qt)、java、php、unity3d,略懂python 2、用c++开发过嵌入式产品,用c++开发过大型银行运维产品 3、用java开发大型银行运维产品,学校教务系统 4、用php开发进销存系统(在销售中),用php开发淘宝小程序 5、用unity3d开发衣柜设计软件,在运营中

文章分类

全部博文(85)

分类: LINUX

2011-09-19 07:15:51

 

    会话函数也叫转换函数,是服务(如sshdvsftpd)中的函数。Pam模块可以取到这个函数并且使用这个函数。

        会话函数的作用就是处理与用户之间的会话。就是说,可以向用户、服务或设备显示消息,并从中收集输入内容。会话可采用多种形式,例如,文本终端设备中常见的”Login:”提示

此部分主要包括会话函数的注册、实现、获得、使用。其中注册、实现在服务(sshd服务)中完成。获得、使用在pam模块中完成。

1.1 会话函数的注册

        应用服务程序(如sshd调用 pam_start函数发起PAM会话时,将对会话函数进行注册。函数原型:

int pam_start(const char *service_name, const char *user, const struct pam_conv *pam_conversation, pam_handle_t **pamh); 

参数const struct pam_conv *pam_conversation即为要注册的会话函数。

1.2 会话函数的实现

下面是sshd服务源码中的会话函数:

  1. static int
  2. sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
  3.     struct pam_response **resp, void *data)
  4. {
  5.     Buffer buffer;
  6.     struct pam_ctxt *ctxt;
  7.     struct pam_response *reply;
  8.     int i;

  9.     debug3("PAM: %s entering, %d messages", __func__, n);
  10.     *resp = NULL;

  11.     if (data == NULL) {
  12.         error("PAM: conversation function passed a null context");
  13.         return (PAM_CONV_ERR);
  14.     }
  15.     ctxt = data;
  16.     if (n <= 0 || n > PAM_MAX_NUM_MSG)
  17.         return (PAM_CONV_ERR);

  18.     if ((reply = malloc(n * sizeof(*reply))) == NULL)
  19.         return (PAM_CONV_ERR);
  20.     memset(reply, 0, n * sizeof(*reply));

  21.     buffer_init(&buffer);
  22.     for (i = 0; i < n; ++i) {
  23.         
  24.         //会话函数的核心就是下面的代码
  25.         switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
  26.         case PAM_PROMPT_ECHO_OFF:    //用于取得密码,不回显
  27.             buffer_put_cstring(&buffer,
  28.              PAM_MSG_MEMBER(msg, i, msg));
  29.             //终端显示提示,如 Password:
  30.             if (ssh_msg_send(ctxt->pam_csock,
  31.              PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
  32.                 goto fail;
  33.             //取得密码
  34.             if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
  35.                 goto fail;
  36.             if (buffer_get_char(&buffer) != PAM_AUTHTOK)
  37.                 goto fail;
  38.             //密码存在reply[i].resp中
  39.             reply[i].resp = buffer_get_string(&buffer, NULL);
  40.             break;
  41.         case PAM_PROMPT_ECHO_ON:        //用于取得用户名,回显
  42.             buffer_put_cstring(&buffer,
  43.              PAM_MSG_MEMBER(msg, i, msg));
  44.             //终端显示提示,如 Login:
  45.             if (ssh_msg_send(ctxt->pam_csock,
  46.              PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
  47.                 goto fail;
  48.             //取得用户名
  49.             if (ssh_msg_recv(ctxt->pam_csock, &buffer) == -1)
  50.                 goto fail;
  51.             if (buffer_get_char(&buffer) != PAM_AUTHTOK)
  52.                 goto fail;
  53.             //用户名存在reply[i].resp中
  54.             reply[i].resp = buffer_get_string(&buffer, NULL);
  55.             break;
  56.         case PAM_ERROR_MSG:        //错误信息显示
  57.             buffer_put_cstring(&buffer,
  58.              PAM_MSG_MEMBER(msg, i, msg));
  59.             if (ssh_msg_send(ctxt->pam_csock,
  60.              PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
  61.                 goto fail;
  62.             break;
  63.         case PAM_TEXT_INFO:        //信息显示
  64.             buffer_put_cstring(&buffer,
  65.              PAM_MSG_MEMBER(msg, i, msg));
  66.             if (ssh_msg_send(ctxt->pam_csock,
  67.              PAM_MSG_MEMBER(msg, i, msg_style), &buffer) == -1)
  68.                 goto fail;
  69.             break;
  70.         default:
  71.             goto fail;
  72.         }
  73.         buffer_clear(&buffer);
  74.     }
  75.     buffer_free(&buffer);
  76.     *resp = reply;
  77.     return (PAM_SUCCESS);

  78.  fail:
  79.     for(i = 0; i < n; i++) {
  80.         if (reply[i].resp != NULL)
  81.             xfree(reply[i].resp);
  82.     }
  83.     xfree(reply);
  84.     buffer_free(&buffer);
  85.     return (PAM_CONV_ERR);
  86.  }



1.3 会话函数的获得

       Pam模块与终端通话,即显示信息,取得用户名、密码,都需要使用会话函数才能完成。

pam模块中,通过下面方法取得会话函数(如sshd服务的会话函数)

       pam_get_item(pamh, PAM_CONV, (const void **) &conversation);

       conversation是包含会话函数的结构体

1.4 会话函数的使用

     上面取得会话函数后,就可以通过会话函数取得密码、用户名,以及显示信息了。

    r 获取用户名:

 

  1.         message.msg = "\nPlease input authen ID: ";
  2.         int retval;
  3.         message.msg_style = PAM_PROMPT_ECHO_ON; //设置回显
  4.         retval = conversation->conv(1, &pmessage, &res, conversation->appdata_ptr);//会话函数
  5.         if (retval != PAM_SUCCESS)
  6.             LOGOUT("pam_conv error %d (%s).", retval, pam_strerror(pamh, retval));
  7.         strcpy(user, res->resp);        //保存用户名

 

获取密码:

 

       
  1.         message.msg = "Enter fixed password: ";
  2.         int retval;
  3.         message.msg_style = PAM_PROMPT_ECHO_OFF; //设置不回显
  4.         retval = conversation->conv(1, &pmessage, &res, conversation->appdata_ptr);//会话函数
  5.         if (retval != PAM_SUCCESS)
  6.             LOGOUT("error %d (%s).", retval, pam_strerror(pamh, retval));
  7.         strcpy(passwd, res->resp);

 


    pam配置好后,通过telnet登录系统,上面程序的显示结果为:
    Please input authen ID: 

    Enter fixed password:

阅读(5123) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~