blob: f51f9aaddb2fd5182190a17124f8758fa3151e44 [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 Tanous1abe55e2018-09-05 08:30:59 -07004
5#include <boost/utility/string_view.hpp>
Ed Tanous911ac312017-08-15 09:37:42 -07006#include <cstring>
Ed Tanouse0d918b2018-03-27 17:41:04 -07007#include <memory>
Ed Tanousf3d847c2017-06-12 16:01:42 -07008
9// function used to get user input
Ed Tanous55c7b7a2018-05-22 15:27:24 -070010inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
Ed Tanous1abe55e2018-09-05 08:30:59 -070011 struct pam_response** resp, void* appdataPtr)
12{
13 if (appdataPtr == nullptr)
14 {
15 return PAM_AUTH_ERR;
16 }
17 auto* pass = reinterpret_cast<char*>(
18 malloc(std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1));
19 std::strcpy(pass, reinterpret_cast<char*>(appdataPtr));
Ed Tanousf3d847c2017-06-12 16:01:42 -070020
Ed Tanous1abe55e2018-09-05 08:30:59 -070021 *resp = reinterpret_cast<pam_response*>(
22 calloc(numMsg, sizeof(struct pam_response)));
Ed Tanousf3d847c2017-06-12 16:01:42 -070023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024 for (int i = 0; i < numMsg; ++i)
25 {
26 /* Ignore all PAM messages except prompting for hidden input */
27 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
28 {
29 continue;
30 }
31
32 /* Assume PAM is only prompting for the password as hidden input */
33 resp[i]->resp = pass;
Ed Tanous911ac312017-08-15 09:37:42 -070034 }
Ed Tanousf3d847c2017-06-12 16:01:42 -070035
Ed Tanous1abe55e2018-09-05 08:30:59 -070036 return PAM_SUCCESS;
Ed Tanousf3d847c2017-06-12 16:01:42 -070037}
38
Ed Tanous55c7b7a2018-05-22 15:27:24 -070039inline bool pamAuthenticateUser(const boost::string_view username,
Ed Tanous1abe55e2018-09-05 08:30:59 -070040 const boost::string_view password)
41{
42 std::string userStr(username);
43 std::string passStr(password);
44 const struct pam_conv localConversation = {
45 pamFunctionConversation, const_cast<char*>(passStr.c_str())};
46 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070047
Ed Tanous1abe55e2018-09-05 08:30:59 -070048 if (pam_start("webserver", userStr.c_str(), &localConversation,
49 &localAuthHandle) != PAM_SUCCESS)
50 {
51 return false;
Ed Tanous911ac312017-08-15 09:37:42 -070052 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 int retval = pam_authenticate(localAuthHandle,
54 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
Ed Tanous911ac312017-08-15 09:37:42 -070055
Ed Tanous1abe55e2018-09-05 08:30:59 -070056 if (retval != PAM_SUCCESS)
57 {
58 if (retval == PAM_AUTH_ERR)
59 {
60 // printf("Authentication failure.\n");
61 }
62 else
63 {
64 // printf("pam_authenticate returned %d\n", retval);
65 }
66 pam_end(localAuthHandle, PAM_SUCCESS);
67 return false;
68 }
Ed Tanous911ac312017-08-15 09:37:42 -070069
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 /* check that the account is healthy */
71 if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
72 PAM_SUCCESS)
73 {
74 pam_end(localAuthHandle, PAM_SUCCESS);
75 return false;
76 }
Ed Tanous911ac312017-08-15 09:37:42 -070077
Ed Tanous1abe55e2018-09-05 08:30:59 -070078 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
79 {
80 return false;
81 }
82
83 return true;
Ed Tanous911ac312017-08-15 09:37:42 -070084}