blob: 65e47402f71673fd0075b8977beb61d984a729b7 [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
Ed Tanous55c7b7a2018-05-22 15:27:24 -07009inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
10 struct pam_response** resp,
11 void* appdataPtr) {
12 if (appdataPtr == nullptr) {
Ed Tanous911ac312017-08-15 09:37:42 -070013 return PAM_AUTH_ERR;
14 }
15 auto* pass = reinterpret_cast<char*>(
Ed Tanous55c7b7a2018-05-22 15:27:24 -070016 malloc(std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1));
17 std::strcpy(pass, reinterpret_cast<char*>(appdataPtr));
Ed Tanousf3d847c2017-06-12 16:01:42 -070018
Ed Tanous911ac312017-08-15 09:37:42 -070019 *resp = reinterpret_cast<pam_response*>(
Ed Tanous55c7b7a2018-05-22 15:27:24 -070020 calloc(numMsg, sizeof(struct pam_response)));
Ed Tanousf3d847c2017-06-12 16:01:42 -070021
Ed Tanous55c7b7a2018-05-22 15:27:24 -070022 for (int i = 0; i < numMsg; ++i) {
Ed Tanousf3d847c2017-06-12 16:01:42 -070023 /* Ignore all PAM messages except prompting for hidden input */
Ed Tanous911ac312017-08-15 09:37:42 -070024 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) {
25 continue;
26 }
Ed Tanousf3d847c2017-06-12 16:01:42 -070027
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
Ed Tanous55c7b7a2018-05-22 15:27:24 -070035inline 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
Ed Tanousf3d847c2017-06-12 16:01:42 -070042
Ed Tanous55c7b7a2018-05-22 15:27:24 -070043 if (pam_start("webserver", userStr.c_str(), &localConversation,
44 &localAuthHandle) != PAM_SUCCESS) {
Ed Tanous911ac312017-08-15 09:37:42 -070045 return false;
Ed Tanousf3d847c2017-06-12 16:01:42 -070046 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -070047 int retval =
48 pam_authenticate(localAuthHandle, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
Ed Tanous911ac312017-08-15 09:37:42 -070049
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 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -070056 pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanous911ac312017-08-15 09:37:42 -070057 return false;
58 }
59
60 /* check that the account is healthy */
Ed Tanous55c7b7a2018-05-22 15:27:24 -070061 if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
Ed Tanous911ac312017-08-15 09:37:42 -070062 PAM_SUCCESS) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070063 pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanous911ac312017-08-15 09:37:42 -070064 return false;
65 }
66
Ed Tanous55c7b7a2018-05-22 15:27:24 -070067 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS) {
Ed Tanous911ac312017-08-15 09:37:42 -070068 return false;
69 }
70
71 return true;
72}