1 #pragma once 2 3 #include <security/pam_appl.h> 4 #include <memory> 5 #include <cstring> 6 7 // function used to get user input 8 inline int pam_function_conversation(int num_msg, 9 const struct pam_message** msg, 10 struct pam_response** resp, 11 void* appdata_ptr) { 12 if (appdata_ptr == nullptr) { 13 return PAM_AUTH_ERR; 14 } 15 auto* pass = reinterpret_cast<char*>( 16 malloc(std::strlen(reinterpret_cast<char*>(appdata_ptr)) + 1)); 17 std::strcpy(pass, reinterpret_cast<char*>(appdata_ptr)); 18 19 *resp = reinterpret_cast<pam_response*>( 20 calloc(num_msg, sizeof(struct pam_response))); 21 22 for (int i = 0; i < num_msg; ++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 pam_authenticate_user(const std::string& username, 36 const std::string& password) { 37 const struct pam_conv local_conversation = { 38 pam_function_conversation, const_cast<char*>(password.c_str())}; 39 pam_handle_t* local_auth_handle = NULL; // this gets set by pam_start 40 41 if (pam_start("dropbear", username.c_str(), &local_conversation, 42 &local_auth_handle) != PAM_SUCCESS) { 43 return false; 44 } 45 int retval = pam_authenticate(local_auth_handle, 46 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK); 47 48 if (retval != PAM_SUCCESS) { 49 if (retval == PAM_AUTH_ERR) { 50 // printf("Authentication failure.\n"); 51 } else { 52 // printf("pam_authenticate returned %d\n", retval); 53 } 54 pam_end(local_auth_handle, PAM_SUCCESS); 55 return false; 56 } 57 58 /* check that the account is healthy */ 59 if (pam_acct_mgmt(local_auth_handle, PAM_DISALLOW_NULL_AUTHTOK) != 60 PAM_SUCCESS) { 61 pam_end(local_auth_handle, PAM_SUCCESS); 62 return false; 63 } 64 65 if (pam_end(local_auth_handle, PAM_SUCCESS) != PAM_SUCCESS) { 66 return false; 67 } 68 69 return true; 70 } 71