/*********************************************************************** * File: pam_authtoken.c * Author: Juan Carlos Luciani (jluciani@novell.com) * * Abstract: Implements the CASA Authentication Token PAM Module. * * Copyright (C) 2005 Novell, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. ***********************************************************************/ #define _GNU_SOURCE #include #include #ifndef LINUX #include #endif #define PAM_SM_AUTH #define PAM_SM_ACCOUNT #define PAM_SM_PASSWORD #define PAM_SM_SESSION #include #include #include /* ************************************************************************ * LogError() * * Logs error to syslog. * * ************************************************************************/ static void LogError(char *pFormatStr, ... ) { va_list args; // openlog("pam_authtoken", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); va_start(args, pFormatStr); // vsyslog(LOG_USER | LOG_INFO, pFormatStr, args); printf(pFormatStr, args); va_end(args); // closelog(); } /* ************************************************************************ * pam_sm_authenticate() * * Service provider implementation for pam_authenticate(). * * This is a PAM authentication management function. * * We are going to validate the credentials using the CASA Authentication * Token Credential APIs. * * ************************************************************************/ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retStatus; CasaStatus casaStatus; char *pServicename = NULL; char *pUsername = NULL; char *pAuthToken = NULL; // Get the servicename. if (pam_get_item(pamh, PAM_SERVICE, (void*) &pServicename) == PAM_SUCCESS && pServicename != NULL) { // We got the service name, now obtain the username. // Note that we are not calling pam_get_user() because we // assume that the service has set it before calling PAM_Authenticate. if (pam_get_item(pamh, PAM_USER, (void*) &pUsername) == PAM_SUCCESS && pUsername != NULL) { struct pam_response *responses = NULL; // We got the username, now obtain the authentication token. if (pam_get_item(pamh, PAM_AUTHTOK, (void*) &pAuthToken) != PAM_SUCCESS || pAuthToken == NULL) { struct pam_conv *pConv; // The authentication token has not been set, try to obtain it from the // application through the use of the conversation function. if (pam_get_item(pamh, PAM_CONV, (void*) &pConv) == PAM_SUCCESS) { struct pam_message msg; struct pam_message *messages = &msg; // Obtained the conversation structure, now query the conversation // function for the authentication token. msg.msg_style = PAM_PROMPT_ECHO_OFF; if (pConv->conv(1, (const struct pam_message **) &messages, &responses, pConv->appdata_ptr) == PAM_SUCCESS) { // Check if we have a successful response if (responses[0].resp_retcode == PAM_SUCCESS && responses[0].resp) { // Set the authentication token with PAM if (pam_set_item(pamh, PAM_AUTHTOK, responses[0].resp) == PAM_SUCCESS) { // Use the buffer returned by the caller as the authentication token pAuthToken = responses[0].resp; } else { LogError("Unable to set the authentication token"); } } else { LogError("Response error"); } } else { LogError("Conversation function error"); } } else { LogError("Unable to obtain conversation structure"); } } // Check if we suuceeded at obtaining the authentication token if (pAuthToken) { // We got all of the information that we need, now validate the credentials. casaStatus = ValidateAuthTokenCredentials(pServicename, pUsername, strlen(pUsername), pAuthToken, strlen(pAuthToken)); if (CASA_SUCCESS(casaStatus)) { // Authentication succeded retStatus = PAM_SUCCESS; } else { LogError("Service %s failed to authenticate %s with status = %08X", pServicename, pUsername, casaStatus); retStatus = PAM_AUTH_ERR; } } else { LogError("Unable to obtain authentication token"); retStatus = PAM_CRED_INSUFFICIENT; } // Free conversation function response buffers if necessary if (responses) { if (responses[0].resp) free(responses[0].resp); free(responses); } } else { LogError("Unable to obtain username"); retStatus = PAM_CRED_INSUFFICIENT; } } else { LogError("Unable to obtain servicename"); retStatus = PAM_SYSTEM_ERR; } return retStatus; } /* ************************************************************************ * pam_sm_setcred() * * Service provider implementation for pam_setcred(). * * This is a PAM authentication management function. * * This function is here just for completedness and to protect against * PAM misconfiguration. * * ************************************************************************/ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* ************************************************************************ * pam_sm_acct_mgmt() * * Service provider implementation for pam_acct_mgmt(). * * This is a PAM account management function. * * This function is here just for completedness and to protect against * PAM misconfiguration. * * ************************************************************************/ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* ************************************************************************ * pam_sm_chauthtok() * * Service provider implementation for pam_chauthtok(). * * This is a PAM password management function. * * This function is here just for completedness and to protect against * PAM misconfiguration. * * ************************************************************************/ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* ************************************************************************ * pam_sm_open_session() * * Service provider implementation for pam_open_session(). * * This is a PAM session management function. * * This function is here just for completedness and to protect against * PAM misconfiguration. * * ************************************************************************/ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* ************************************************************************ * pam_sm_close_session() * * Service provider implementation for pam_close_session(). * * This is a PAM session management function. * * This function is here just for completedness and to protect against * PAM misconfiguration. * * ************************************************************************/ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_SUCCESS; } /* static module data */ #ifdef PAM_STATIC struct pam_module _pam_pwcapture_modstruct = { "pam_pwcapture", pam_sm_authenticate, pam_sm_setcred, pam_sm_acct_mgmt, pam_sm_chauthtok, pam_sm_open_session, pam_sm_close_session }; #endif