ukui-screensaver/src/pam.cpp

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;
}