1、PAM应用程序端(PAM API)
PAM应用程序端需要注册实现pam_conv回调函数,通过pam_message用于接收服务端的认证提示信息(如:登录用户名输入提示、密码输入提示、指纹登录系统中的指纹按压提示等)、pam_response用于向后端反馈用户的输入的交互信息(如:密码),如下是应用程序端的交互的核心代码示例:
#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 应用程序端的会话函数 */
int converse(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr) {
struct pam_response *aresp;
char buf[PAM_MAX_RESP_SIZE];
if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
return PAM_CONV_ERR;
aresp = calloc(num_msg, sizeof(struct pam_response));
if (!aresp) return PAM_BUF_ERR;
for (int i = 0; i < num_msg; i++) {
aresp[i].resp_retcode = 0;
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
printf("%s", msg[i]->msg);
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\n")] = '\0'; // 去除换行符
aresp[i].resp = strdup(buf);
break;
case PAM_PROMPT_ECHO_ON:
printf("%s", msg[i]->msg);
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\n")] = '\0';
aresp[i].resp = strdup(buf);
break;
case PAM_ERROR_MSG:
fprintf(stderr, "ERROR: %s\n", msg[i]->msg);
break;
case PAM_TEXT_INFO:
printf("%s\n", msg[i]->msg);
break;
default:
free(aresp);
return PAM_CONV_ERR;
}
}
*resp = aresp;
return PAM_SUCCESS;
}
2、PAM服务程序端(PAM SPI)
PAM服务端程序端需要使用pam_get_item函数获取pam_conv结构体,该结构体包含pam_conv会话函数,通过调用会话函数实现pam_message认证提示信息(如:登录用户名输入提示、密码输入提示、指纹登录系统中的指纹按压提示等)的发送、pam_response交互信息(如:密码)的接收,如下是服务程序端的交互的核心代码示例:
#include <security/pam_modules.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* PAM模块端的认证函数 */
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv) {
int retval;
const char *username;
struct pam_conv *conv;
struct pam_message msg;
const struct pam_message *msgp;
struct pam_response *resp = NULL;
/* 获取会话函数 */
retval = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
if (retval != PAM_SUCCESS) return retval;
/* 构造用户名提示消息 */
msg.msg_style = PAM_PROMPT_ECHO_ON;
msg.msg = "Username: ";
msgp = &msg;
/* 发送消息并获取响应 */
retval = conv->conv(1, &msgp, &resp, conv->appdata_ptr);
if (retval != PAM_SUCCESS || resp == NULL || resp->resp == NULL) {
return PAM_AUTH_ERR;
}
username = resp->resp;
/* 构造密码提示消息 */
msg.msg_style = PAM_PROMPT_ECHO_OFF;
msg.msg = "Password: ";
/* 发送消息并获取响应 */
retval = conv->conv(1, &msgp, &resp, conv->appdata_ptr);
if (retval != PAM_SUCCESS) return retval;
/* 此处应添加实际认证逻辑 */
printf("Authenticating user: %s\n", username);
/* 清理响应内存(由PAM自动完成)*/
return PAM_SUCCESS;
}
相关核心关键字:pam_conv、pam_message、pam_response、pam交互机制

1万+

被折叠的 条评论
为什么被折叠?



