/* * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #define BUF_SIZE 128 #define DISABLE_ECHO 0 #define ENABLE_ECHO 1 char * getpasswd(int enable_echo); int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); struct pam_conv conv = { pam_conversation, NULL }; int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int count = num_msg; char *password = 0; *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response)); /*指针备份,下面的循环需要指针后移*/ struct pam_response *tmp_save = (struct pam_response *)(*resp); memset(*resp, 0, num_msg * sizeof(struct pam_response)); while(count-- >= 1){ switch((*msg)->msg_style){ case PAM_PROMPT_ECHO_OFF: printf("%s",(*msg)->msg); password = getpasswd(DISABLE_ECHO); (*resp)->resp = password; (*resp)->resp_retcode = 0; break; case PAM_PROMPT_ECHO_ON: printf("%s",(*msg)->msg); password = getpasswd(ENABLE_ECHO); (*resp)->resp = password; (*resp)->resp_retcode = 0; break; case PAM_ERROR_MSG: printf("%s",(*msg)->msg); break; case PAM_TEXT_INFO: printf("%s",(*msg)->msg); break; default: printf("Should not reach here!\n"); } if(count != 0){ msg++; (*resp)++; } } /*指针归位 方法1*/ /* unsigned long address_value = (unsigned long)(*resp) - (num_msg -1) * sizeof(struct pam_response); (*resp) = (struct pam_response *)address_value; */ /*指针归位 方法2*/ (*resp) = tmp_save; return PAM_SUCCESS; } int main(int argc, char *argv[]) { pam_handle_t *pamh = NULL; int retval; char *user = NULL; if(argc == 2){ user = argv[1]; } else { printf("Usage: You must specify a username.\n"); exit(1); } retval = pam_start("biotest", user, &conv, &pamh); if(retval == PAM_SUCCESS){ printf("PAM started Success.\n"); } else { printf("PAM started Failed.\n"); } int auth_status = pam_authenticate(pamh,0); if(auth_status != PAM_SUCCESS){ const char * error_msg = pam_strerror(pamh, auth_status); printf("Auth Status : %s\n",error_msg); } else { printf("Authenticate Success!\n"); } if(pam_end(pamh, retval) != PAM_SUCCESS){ pamh = NULL; printf("Failed to terminate PAM."); exit(1); } return (retval == PAM_SUCCESS ? 0:1); } char * getpasswd(int enable_echo) { struct termios tp, save; char *password = (char *)malloc(BUF_SIZE * sizeof(char)); /* printf("Input Password:"); fflush(stdout); */ if (tcgetattr(STDIN_FILENO, &tp) == -1){ printf("tcgetattr error\n"); exit(1); } save = tp;/* So we can restore settings later */ if(enable_echo) ;/*Default is echo. Do nothing*/ else tp.c_lflag &= ~ECHO;/* ECHO off, other bits unchanged */ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tp) == -1){ printf("tcgetattr error\n"); exit(1); } /* Read some input */ if (fgets(password, BUF_SIZE, stdin) == NULL) printf("Got end-of-file/error on fgets()\n"); else ; /* Restore original terminal settings */ if (tcsetattr(STDIN_FILENO, TCSANOW, &save) == -1){ printf("tcgetattr error\n"); exit(1); } /*fgets读入的字符串末尾有回车符,在此替换为\0*/ password[strlen(password)-1] = '\0'; return password; }