blob: 643c8043e47030bf1b895a5877910c9cfe6e5488 [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 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 pam_end(localAuthHandle, PAM_SUCCESS);
59 return false;
60 }
Ed Tanous911ac312017-08-15 09:37:42 -070061
Ed Tanous1abe55e2018-09-05 08:30:59 -070062 /* check that the account is healthy */
63 if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
64 PAM_SUCCESS)
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 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
71 {
72 return false;
73 }
74
75 return true;
Ed Tanous911ac312017-08-15 09:37:42 -070076}
Ed Tanousa8408792018-09-05 16:08:38 -070077
78inline bool pamUpdatePassword(const std::string& username,
79 const std::string& password)
80{
81 const struct pam_conv localConversation = {
82 pamFunctionConversation, const_cast<char*>(password.c_str())};
83 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
84
85 if (pam_start("passwd", username.c_str(), &localConversation,
86 &localAuthHandle) != PAM_SUCCESS)
87 {
88 return false;
89 }
90 int retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
91
92 if (retval != PAM_SUCCESS)
93 {
94 pam_end(localAuthHandle, PAM_SUCCESS);
95 return false;
96 }
97
98 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
99 {
100 return false;
101 }
102
103 return true;
104}