pam会话函数详解

会话函数也叫转换函数,是服务(如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);
     }

 

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);        //保存用户名

 

r 获取密码:

 

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

 

 

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

    Enter fixed password:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值