| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #include "pam_auth.h"
- #ifdef ENABLE_PAM_AUTH
- #include <security/pam_appl.h>
- #include <security/pam_misc.h>
- #include <pwd.h>
- #include <unistd.h>
- #include <cstring>
- #include <cstdlib>
- #endif
- PamAuth::PamAuth(const std::string& serviceName)
- : m_serviceName(serviceName)
- , m_initialized(false)
- {
- }
- PamAuth::~PamAuth() {
- }
- bool PamAuth::initialize() {
- #ifdef ENABLE_PAM_AUTH
- m_initialized = true;
- return true;
- #else
- m_initialized = false;
- return false;
- #endif
- }
- PamAuthResult PamAuth::authenticate(const std::string& username, const std::string& password) {
- PamAuthResult result;
- result.success = false;
- if (!m_initialized) {
- result.errorMessage = "PAM authentication not initialized";
- result.errorCode = "PAM_NOT_INITIALIZED";
- return result;
- }
- #ifdef ENABLE_PAM_AUTH
- return authenticateInternal(username, password);
- #else
- result.errorMessage = "PAM authentication not available (compiled without PAM support)";
- result.errorCode = "PAM_NOT_AVAILABLE";
- return result;
- #endif
- }
- bool PamAuth::isAvailable() const {
- return m_initialized;
- }
- std::string PamAuth::getServiceName() const {
- return m_serviceName;
- }
- void PamAuth::setServiceName(const std::string& serviceName) {
- m_serviceName = serviceName;
- }
- #ifdef ENABLE_PAM_AUTH
- // Structure to hold authentication data for PAM conversation
- struct PamAuthData {
- std::string username;
- std::string password;
- PamAuthResult* result;
- };
- int PamAuth::conversationFunction(int num_msg, const struct pam_message** msg,
- struct pam_response** resp, void* appdata_ptr) {
- if (num_msg <= 0 || msg == NULL || resp == NULL || appdata_ptr == NULL) {
- return PAM_CONV_ERR;
- }
- PamAuthData* authData = static_cast<PamAuthData*>(appdata_ptr);
- // Allocate response array
- struct pam_response* response = static_cast<struct pam_response*>(
- calloc(num_msg, sizeof(struct pam_response)));
- if (response == NULL) {
- return PAM_CONV_ERR;
- }
- for (int i = 0; i < num_msg; i++) {
- const struct pam_message* message = msg[i];
- switch (message->msg_style) {
- case PAM_PROMPT_ECHO_OFF:
- // Password prompt - return the password
- response[i].resp = strdup(authData->password.c_str());
- response[i].resp_retcode = 0;
- break;
- case PAM_PROMPT_ECHO_ON:
- // Username prompt - return the username
- response[i].resp = strdup(authData->username.c_str());
- response[i].resp_retcode = 0;
- break;
- case PAM_ERROR_MSG:
- // Error message - log it
- if (authData->result) {
- authData->result->errorMessage = message->msg;
- }
- response[i].resp = NULL;
- response[i].resp_retcode = 0;
- break;
- case PAM_TEXT_INFO:
- // Information message - ignore
- response[i].resp = NULL;
- response[i].resp_retcode = 0;
- break;
- default:
- // Unknown message type
- for (int j = 0; j <= i; j++) {
- if (response[j].resp != NULL) {
- free(response[j].resp);
- }
- }
- free(response);
- return PAM_CONV_ERR;
- }
- }
- *resp = response;
- return PAM_SUCCESS;
- }
- PamAuthResult PamAuth::authenticateInternal(const std::string& username, const std::string& password) {
- PamAuthResult result;
- result.success = false;
- result.username = username;
- // Prepare authentication data
- PamAuthData authData;
- authData.username = username;
- authData.password = password;
- authData.result = &result;
- // PAM conversation structure
- struct pam_conv pam_conv;
- pam_conv.conv = conversationFunction;
- pam_conv.appdata_ptr = &authData;
- pam_handle_t* pamh = NULL;
- int pam_status;
- // Start PAM transaction
- pam_status = pam_start(m_serviceName.c_str(), username.c_str(), &pam_conv, &pamh);
- if (pam_status != PAM_SUCCESS) {
- result.errorMessage = pamErrorToString(pam_status);
- result.errorCode = pamErrorToErrorCode(pam_status);
- return result;
- }
- // Authenticate user
- pam_status = pam_authenticate(pamh, PAM_SILENT);
- if (pam_status != PAM_SUCCESS) {
- result.errorMessage = pamErrorToString(pam_status);
- result.errorCode = pamErrorToErrorCode(pam_status);
- pam_end(pamh, pam_status);
- return result;
- }
- // Check account validity
- pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
- if (pam_status != PAM_SUCCESS) {
- result.errorMessage = pamErrorToString(pam_status);
- result.errorCode = pamErrorToErrorCode(pam_status);
- pam_end(pamh, pam_status);
- return result;
- }
- // Get user information
- struct passwd* pw = getpwnam(username.c_str());
- if (pw != NULL) {
- // Use system UID as user ID
- result.userId = std::to_string(pw->pw_uid);
- } else {
- // Fallback: use username as ID
- result.userId = username;
- }
- result.success = true;
- result.errorMessage = "";
- result.errorCode = "";
- // End PAM transaction
- pam_end(pamh, PAM_SUCCESS);
- return result;
- }
- std::string PamAuth::pamErrorToString(int pamError) {
- switch (pamError) {
- case PAM_SUCCESS:
- return "Success";
- case PAM_ABORT:
- return "General failure";
- case PAM_AUTH_ERR:
- return "Authentication failure";
- case PAM_CRED_INSUFFICIENT:
- return "Insufficient credentials";
- case PAM_AUTHINFO_UNAVAIL:
- return "Authentication information unavailable";
- case PAM_USER_UNKNOWN:
- return "Unknown user";
- case PAM_MAXTRIES:
- return "Maximum number of tries exceeded";
- case PAM_NEW_AUTHTOK_REQD:
- return "New authentication token required";
- case PAM_ACCT_EXPIRED:
- return "User account has expired";
- case PAM_SESSION_ERR:
- return "Session error";
- case PAM_CRED_ERR:
- return "Credential error";
- case PAM_CRED_UNAVAIL:
- return "Credential unavailable";
- case PAM_CRED_EXPIRED:
- return "Credential expired";
- case PAM_NO_MODULE_DATA:
- return "No module data available";
- case PAM_CONV_ERR:
- return "Conversation error";
- case PAM_AUTHTOK_ERR:
- return "Authentication token error";
- case PAM_AUTHTOK_RECOVERY_ERR:
- return "Authentication token recovery error";
- case PAM_AUTHTOK_LOCK_BUSY:
- return "Authentication token lock busy";
- case PAM_AUTHTOK_DISABLE_AGING:
- return "Authentication token aging disabled";
- case PAM_TRY_AGAIN:
- return "Try again";
- case PAM_IGNORE:
- return "Ignore";
- case PAM_MODULE_UNKNOWN:
- return "Unknown module";
- case PAM_BAD_ITEM:
- return "Bad item";
- case PAM_CONV_AGAIN:
- return "Conversation again";
- case PAM_INCOMPLETE:
- return "Incomplete";
- default:
- return "Unknown PAM error";
- }
- }
- std::string PamAuth::pamErrorToErrorCode(int pamError) {
- switch (pamError) {
- case PAM_SUCCESS:
- return "SUCCESS";
- case PAM_AUTH_ERR:
- case PAM_CRED_INSUFFICIENT:
- return "AUTHENTICATION_FAILED";
- case PAM_USER_UNKNOWN:
- return "USER_NOT_FOUND";
- case PAM_CRED_EXPIRED:
- return "CREDENTIAL_EXPIRED";
- case PAM_ACCT_EXPIRED:
- return "ACCOUNT_EXPIRED";
- case PAM_NEW_AUTHTOK_REQD:
- return "PASSWORD_CHANGE_REQUIRED";
- case PAM_MAXTRIES:
- return "MAX_TRIES_EXCEEDED";
- case PAM_AUTHINFO_UNAVAIL:
- case PAM_CRED_UNAVAIL:
- return "AUTHENTICATION_UNAVAILABLE";
- default:
- return "PAM_ERROR";
- }
- }
- #else
- // Stub implementations when PAM is not enabled
- PamAuthResult PamAuth::authenticateInternal(const std::string& username, const std::string& password) {
- PamAuthResult result;
- result.success = false;
- result.errorMessage = "PAM authentication not available (compiled without PAM support)";
- result.errorCode = "PAM_NOT_AVAILABLE";
- return result;
- }
- std::string PamAuth::pamErrorToString(int pamError) {
- return "PAM not available";
- }
- std::string PamAuth::pamErrorToErrorCode(int pamError) {
- return "PAM_NOT_AVAILABLE";
- }
- #endif
|