// rdpam.cpp // // Authenticate a PAM name. // // (C) Copyright 2010-2025 Fred Gleason <fredg@paravelsystems.com> // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // 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, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #include <syslog.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <pwd.h> #include <security/pam_appl.h> #include <qstringlist.h> #include "rdapplication.h" #include "rdpam.h" int RDPamCallback(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { RDPam *pam=(RDPam *)appdata_ptr; int ret=PAM_SUCCESS; *resp=(struct pam_response *)malloc(sizeof(struct pam_response)*num_msg); memset(*resp,0,sizeof(struct pam_response)*num_msg); for(int i=0;i<num_msg;i++) { resp[i]->resp=(char *)malloc(256); memset(resp[i]->resp,0,256); switch(msg[i]->msg_style) { case PAM_PROMPT_ECHO_OFF: case PAM_PROMPT_ECHO_ON: strncpy(resp[i]->resp,pam->system_token.toUtf8(),255); break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: rda->syslog(LOG_INFO,"PAM message: %s",msg[i]->msg); break; } } return ret; } RDPam::RDPam(const QString &pam_service) { system_pam_service=pam_service; } bool RDPam::authenticate(const QString &username,const QString &token) { pam_handle_t *pamh=NULL; struct pam_conv conv; int err; system_token=token; memset(&conv,0,sizeof(conv)); conv.conv=RDPamCallback; conv.appdata_ptr=(RDPam *)this; if((err=pam_start(system_pam_service.toUtf8(),username.toUtf8(),&conv,&pamh))!=PAM_SUCCESS) { rda->syslog(LOG_WARNING,"PAM error [%s]",pam_strerror(pamh,err)); pam_end(pamh,err); return false; } if((err=pam_authenticate(pamh,0))!=PAM_SUCCESS) { rda->syslog(LOG_WARNING,"PAM authentication failed [%s]", pam_strerror(pamh,err)); pam_end(pamh,err); return false; } pam_end(pamh,err); return true; }