127 lines
3.6 KiB
C++
127 lines
3.6 KiB
C++
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
**/
|
|
#include "pam.h"
|
|
|
|
extern "C" {
|
|
#include <security/pam_appl.h>
|
|
#include <security/pam_misc.h>
|
|
#include <signal.h>
|
|
}
|
|
|
|
#define TO_AUTHCHILD_RD_SHIFT 16
|
|
#define TO_PARENT_WR_SHIFT 0
|
|
#define PIPE_FD_MASK ((1 << TO_AUTHCHILD_RD_SHIFT) - 1)
|
|
|
|
void authenticate(int toParent[2], int toAuthChild[2])
|
|
{
|
|
pam_handle_t *pamh = NULL;
|
|
char *username;
|
|
int retval;
|
|
int auth_status;
|
|
struct pam_conv conv;
|
|
unsigned long fd = 0;
|
|
fd = fd | toAuthChild[0] << TO_AUTHCHILD_RD_SHIFT
|
|
| toParent[1] << TO_PARENT_WR_SHIFT;
|
|
/* authentication child process */
|
|
username=getenv("USER");
|
|
conv.conv = pam_conversation;
|
|
conv.appdata_ptr = (void *)fd;
|
|
retval = pam_start("ukui-screensaver-qt", username, &conv, &pamh);
|
|
if(retval == PAM_SUCCESS)
|
|
qDebug("PAM started successfully.");
|
|
else
|
|
qDebug("PAM started unsuccessfully.");
|
|
qDebug("Invoke pam authentication.");
|
|
auth_status = pam_authenticate(pamh, 0);
|
|
qDebug("Complete pam authentication.");
|
|
if(pam_end(pamh, retval) != PAM_SUCCESS){
|
|
qDebug("Failed to terminate PAM.");
|
|
_exit(1);
|
|
}
|
|
qDebug("PAM ended successfully.");
|
|
kill(getppid(), SIGUSR1);
|
|
char buffer[16];
|
|
sprintf(buffer, "%d", auth_status);
|
|
PIPE_OPS_SAFE(
|
|
write(toParent[1], buffer, strlen(buffer) + 1)
|
|
);
|
|
qDebug("Auth status has been written to pipe.");
|
|
::close(toParent[1]);
|
|
::close(toAuthChild[0]);
|
|
qDebug("Authenticate child process now exits.");
|
|
_exit(0);
|
|
}
|
|
|
|
#define MAX_PASSWORD_LENGTH 1024
|
|
int pam_conversation(int num_msg, const struct pam_message **msg,
|
|
struct pam_response **resp, void *appdata_ptr)
|
|
{
|
|
unsigned long fd;
|
|
int read_from_parent;
|
|
int write_to_parent;
|
|
int count;
|
|
char *password;
|
|
struct pam_response *tmp_save;
|
|
|
|
qDebug("Into pam_conversation");
|
|
|
|
fd = (unsigned long)appdata_ptr;
|
|
read_from_parent = (fd >> TO_AUTHCHILD_RD_SHIFT) & PIPE_FD_MASK;
|
|
write_to_parent = (fd >> TO_PARENT_WR_SHIFT) & PIPE_FD_MASK;
|
|
count = num_msg;
|
|
password = (char *)malloc(MAX_PASSWORD_LENGTH);
|
|
*resp = (struct pam_response *)malloc(num_msg *
|
|
sizeof(struct pam_response));
|
|
tmp_save = (struct pam_response *)(*resp);
|
|
memset(*resp, 0, num_msg * sizeof(struct pam_response));
|
|
qDebug("Resolve PAM messages.");
|
|
while(count-- >= 1){
|
|
struct pam_message_object pam_msg_obj;
|
|
pam_msg_obj.msg_style = (*msg)->msg_style;
|
|
strncpy(pam_msg_obj.msg, (*msg)->msg, MAX_MSG_LENGTH);
|
|
PIPE_OPS_SAFE(
|
|
write(write_to_parent, &pam_msg_obj, sizeof(pam_msg_obj));
|
|
);
|
|
qDebug("PAM message has been written to pipe.");
|
|
kill(getppid(), SIGUSR1);
|
|
|
|
if ((*msg)->msg_style == PAM_PROMPT_ECHO_OFF
|
|
|| (*msg)->msg_style == PAM_PROMPT_ECHO_ON){
|
|
int n;
|
|
PIPE_OPS_SAFE(
|
|
n = read(read_from_parent, password, MAX_PASSWORD_LENGTH);
|
|
);
|
|
qDebug("%d bytes response received from pipe.", n);
|
|
(*resp)->resp = password;
|
|
(*resp)->resp_retcode = 0;
|
|
} else {
|
|
;
|
|
}
|
|
if(count != 0){
|
|
msg++;
|
|
(*resp)++;
|
|
}
|
|
}
|
|
|
|
(*resp) = tmp_save;
|
|
|
|
qDebug("Out pam_conversation.");
|
|
return PAM_SUCCESS;
|
|
}
|
|
|