1 #pragma once 2 3 #include <security/pam_appl.h> 4 #include <cstring> 5 #include <memory> 6 #include <boost/utility/string_view.hpp> 7 8 // function used to get user input 9 inline int pamFunctionConversation(int numMsg, const struct pam_message** msg, 10 struct pam_response** resp, 11 void* appdataPtr) { 12 if (appdataPtr == nullptr) { 13 return PAM_AUTH_ERR; 14 } 15 auto* pass = reinterpret_cast<char*>( 16 malloc(std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1)); 17 std::strcpy(pass, reinterpret_cast<char*>(appdataPtr)); 18 19 *resp = reinterpret_cast<pam_response*>( 20 calloc(numMsg, sizeof(struct pam_response))); 21 22 for (int i = 0; i < numMsg; ++i) { 23 /* Ignore all PAM messages except prompting for hidden input */ 24 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) { 25 continue; 26 } 27 28 /* Assume PAM is only prompting for the password as hidden input */ 29 resp[i]->resp = pass; 30 } 31 32 return PAM_SUCCESS; 33 } 34 35 inline bool pamAuthenticateUser(const boost::string_view username, 36 const boost::string_view password) { 37 std::string userStr(username); 38 std::string passStr(password); 39 const struct pam_conv localConversation = { 40 pamFunctionConversation, const_cast<char*>(passStr.c_str())}; 41 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start 42 43 if (pam_start("webserver", userStr.c_str(), &localConversation, 44 &localAuthHandle) != PAM_SUCCESS) { 45 return false; 46 } 47 int retval = 48 pam_authenticate(localAuthHandle, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK); 49 50 if (retval != PAM_SUCCESS) { 51 if (retval == PAM_AUTH_ERR) { 52 // printf("Authentication failure.\n"); 53 } else { 54 // printf("pam_authenticate returned %d\n", retval); 55 } 56 pam_end(localAuthHandle, PAM_SUCCESS); 57 return false; 58 } 59 60 /* check that the account is healthy */ 61 if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) != 62 PAM_SUCCESS) { 63 pam_end(localAuthHandle, PAM_SUCCESS); 64 return false; 65 } 66 67 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS) { 68 return false; 69 } 70 71 return true; 72 } 73