165 lines
4.0 KiB
C
165 lines
4.0 KiB
C
/*
|
||
* Copyright (C) 2023 KylinSoftCo., 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 <http://www.gnu.org/licenses/>.
|
||
*
|
||
**/
|
||
#include<security/pam_appl.h>
|
||
#include<security/pam_misc.h>
|
||
#include<stdio.h>
|
||
#include<string.h>
|
||
#include <termios.h>
|
||
#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;
|
||
}
|