blob: 997c2974bdee0d8c99420084d44761abaac58c55 [file] [log] [blame]
Ed Tanous911ac312017-08-15 09:37:42 -07001#pragma once
2
Ed Tanousf3d847c2017-06-12 16:01:42 -07003#include <security/pam_appl.h>
Ed Tanous911ac312017-08-15 09:37:42 -07004#include <cstring>
Ed Tanouse0d918b2018-03-27 17:41:04 -07005#include <memory>
6#include <boost/utility/string_view.hpp>
Ed Tanousf3d847c2017-06-12 16:01:42 -07007
8// function used to get user input
9inline int pam_function_conversation(int num_msg,
10 const struct pam_message** msg,
11 struct pam_response** resp,
12 void* appdata_ptr) {
Ed Tanous911ac312017-08-15 09:37:42 -070013 if (appdata_ptr == nullptr) {
14 return PAM_AUTH_ERR;
15 }
16 auto* pass = reinterpret_cast<char*>(
17 malloc(std::strlen(reinterpret_cast<char*>(appdata_ptr)) + 1));
18 std::strcpy(pass, reinterpret_cast<char*>(appdata_ptr));
Ed Tanousf3d847c2017-06-12 16:01:42 -070019
Ed Tanous911ac312017-08-15 09:37:42 -070020 *resp = reinterpret_cast<pam_response*>(
21 calloc(num_msg, sizeof(struct pam_response)));
Ed Tanousf3d847c2017-06-12 16:01:42 -070022
Ed Tanous911ac312017-08-15 09:37:42 -070023 for (int i = 0; i < num_msg; ++i) {
Ed Tanousf3d847c2017-06-12 16:01:42 -070024 /* Ignore all PAM messages except prompting for hidden input */
Ed Tanous911ac312017-08-15 09:37:42 -070025 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) {
26 continue;
27 }
Ed Tanousf3d847c2017-06-12 16:01:42 -070028
29 /* Assume PAM is only prompting for the password as hidden input */
30 resp[i]->resp = pass;
31 }
32
33 return PAM_SUCCESS;
34}
35
Ed Tanouse0d918b2018-03-27 17:41:04 -070036inline bool pam_authenticate_user(const boost::string_view username,
37 const boost::string_view password) {
38 std::string user_str(username);
39 std::string pass_str(password);
Ed Tanous911ac312017-08-15 09:37:42 -070040 const struct pam_conv local_conversation = {
Ed Tanouse0d918b2018-03-27 17:41:04 -070041 pam_function_conversation, const_cast<char*>(pass_str.c_str())};
Ed Tanous911ac312017-08-15 09:37:42 -070042 pam_handle_t* local_auth_handle = NULL; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070043
Ed Tanouse0d918b2018-03-27 17:41:04 -070044 if (pam_start("dropbear", user_str.c_str(), &local_conversation,
Ed Tanous911ac312017-08-15 09:37:42 -070045 &local_auth_handle) != PAM_SUCCESS) {
46 return false;
Ed Tanousf3d847c2017-06-12 16:01:42 -070047 }
Ed Tanous911ac312017-08-15 09:37:42 -070048 int retval = pam_authenticate(local_auth_handle,
49 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
50
51 if (retval != PAM_SUCCESS) {
52 if (retval == PAM_AUTH_ERR) {
53 // printf("Authentication failure.\n");
54 } else {
55 // printf("pam_authenticate returned %d\n", retval);
56 }
57 pam_end(local_auth_handle, PAM_SUCCESS);
58 return false;
59 }
60
61 /* check that the account is healthy */
62 if (pam_acct_mgmt(local_auth_handle, PAM_DISALLOW_NULL_AUTHTOK) !=
63 PAM_SUCCESS) {
64 pam_end(local_auth_handle, PAM_SUCCESS);
65 return false;
66 }
67
68 if (pam_end(local_auth_handle, PAM_SUCCESS) != PAM_SUCCESS) {
69 return false;
70 }
71
72 return true;
73}