4. 函数:
1. pam_conv:函数
一般,linux中,有个默认的conv函数:misc_conv。
其中,pam_response是由conv函数来申请空间的.
*resp指向的是pam_response数组,而不是一个数组指针(pam_response *).他的内存由调用者来进行释放.通过free()函数.
*msg指向的却是一个pam_message *的数组.
若调用失败,则应该由conv函数自己来释放resp所指向的内存.
PAM_PROMPT_ECHO_ON: 输出回显, PAM_PROMPT_ECHO_OFF:输出不回显,所以,前者用于用户名,后者用于密码的获得
int myconv(int num_msg, const pam_message **msg, pam_response **resp, void *appdata_ptr) {
pam_response *tresp = NULL;
tresp = (pam_response *)calloc(num_msg, sizeof(pam_response));
if (tresp == NULL) {
return PAM_CONV_ERR;
}
char* user = NULL;
const pam_message *tmsg;
for (int i = 0; i < num_msg; ++i) {
tmsg = msg[i];
switch (tmsg->msg_style) {
case PAM_PROMPT_ECHO_ON:
fprintf(stdout, "\n%s\n", tmsg->msg);
tresp[i].resp = (char *)malloc(100);
fgets(tresp[i].resp, 99, stdin);
break;
case PAM_PROMPT_ECHO_OFF:
user = getpass(tmsg->msg);
tresp[i].resp = (char *)malloc(100);
strcpy(tresp[i].resp, user);
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
default:
free(tresp[i].resp);
free(tresp);
break;
}
}
*resp = tresp;
return PAM_SUCCESS;
}
2. main函数:
调用规则:pam_start()开始,pam_end()结束 .其中,pam_start函数,第二个参数,可以为空,则可以通过,pam_conv来交互数据.
const char* sName = "";
const char* user = "";
const char* pwd = "";
if (argc < 3) {
printf("argc < 3 \n");
return 0;
}
sName = argv[1];
user = argv[2];
pwd = argv[3];
pam_conv* pConv = NULL;
pam_handle_t* pHandle = NULL;
do {
int ret = pam_start( sName, user, &stn, &pHandle);
if (ret != PAM_SUCCESS) {
myerr(pHandle, ret, "pam_start");
break;
}
ret = pam_authenticate(pHandle, 0);
if (ret != PAM_SUCCESS) {
myerr(pHandle, ret, "pam_auth");
break;
}
ret = pam_acct_mgmt(pHandle, 0);
if (ret != PAM_SUCCESS) {
myerr(pHandle, ret, "pam_acct_mgmt");
break;
}
printf("success \n");
}while (false);
pam_end(pHandle, 0);
3. PAM模块函数:
该模块是pam_authenticate被调用时,模块对应的函数.
如这种情况.pam_authenticate函数被调用,然后,找到对应的/etc/;pam.d/下的配置文件,该模块中 auth 块中,第三列后的参数,就是指 argc与argv.
该模块被编译后,成*.so文件,放在/lib/security的目录下(默认路径).
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
pam_conv* pamconv = NULL;
int ret = pam_get_item(pamh, PAM_CONV, (const void **)&pamconv);
if (ret != PAM_SUCCESS) {
return PAM_AUTH_ERR;
}
pam_message* msg[2] = {NULL};
msg[0] = new pam_message;
msg[1] = new pam_message;
msg[0]->msg = "hello , please input your name:";
msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
msg[1]->msg = "please input passwd:";
msg[1]->msg_style = PAM_PROMPT_ECHO_OFF;
pam_response *resp = NULL;
ret = pamconv->conv(2, (const pam_message **)&msg, &resp, pamconv->appdata_ptr);
if (ret != PAM_SUCCESS) {
fputs("ret is error\n", stderr);
return PAM_MAXTRIES;
}
char buf[100];
sprintf(buf, "user:(%s), pwd:(%s) \n", resp[0].resp, resp[1].resp);
fputs(buf, stdout);
free(msg[0]);
free(msg[1]);
free(resp[0].resp);
free(resp[1].resp);
free(resp);
return PAM_SUCCESS;
}
4. 配置文件;/etc/pam.d/***
auth required pam_**.so
account required pam_**.so
password required pam_**.so
session required pam_**.so