blob: f211a29ec703fa9b5bcd27967ec43815c53839b8 [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 }
Ed Tanousf1eebf02019-03-04 15:57:09 -080017 char* appPass = reinterpret_cast<char*>(appdataPtr);
18 size_t appPassSize = std::strlen(appPass);
19 char* pass = reinterpret_cast<char*>(malloc(appPassSize + 1));
Ed Tanous39e77502019-03-04 17:35:53 -080020 if (pass == nullptr)
Ed Tanousf1eebf02019-03-04 15:57:09 -080021 {
22 return PAM_AUTH_ERR;
23 }
24
25 std::strcpy(pass, appPass);
Ed Tanousf3d847c2017-06-12 16:01:42 -070026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027 *resp = reinterpret_cast<pam_response*>(
28 calloc(numMsg, sizeof(struct pam_response)));
Ed Tanousf3d847c2017-06-12 16:01:42 -070029
Ed Tanous39e77502019-03-04 17:35:53 -080030 if (resp == nullptr)
Ed Tanousf1eebf02019-03-04 15:57:09 -080031 {
32 return PAM_AUTH_ERR;
33 }
34
Ed Tanous1abe55e2018-09-05 08:30:59 -070035 for (int i = 0; i < numMsg; ++i)
36 {
37 /* Ignore all PAM messages except prompting for hidden input */
38 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
39 {
40 continue;
41 }
42
43 /* Assume PAM is only prompting for the password as hidden input */
44 resp[i]->resp = pass;
Ed Tanous911ac312017-08-15 09:37:42 -070045 }
Ed Tanousf3d847c2017-06-12 16:01:42 -070046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 return PAM_SUCCESS;
Ed Tanousf3d847c2017-06-12 16:01:42 -070048}
49
Ed Tanous39e77502019-03-04 17:35:53 -080050inline bool pamAuthenticateUser(const std::string_view username,
51 const std::string_view password)
Ed Tanous1abe55e2018-09-05 08:30:59 -070052{
53 std::string userStr(username);
54 std::string passStr(password);
55 const struct pam_conv localConversation = {
56 pamFunctionConversation, const_cast<char*>(passStr.c_str())};
57 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070058
Ed Tanous1abe55e2018-09-05 08:30:59 -070059 if (pam_start("webserver", userStr.c_str(), &localConversation,
60 &localAuthHandle) != PAM_SUCCESS)
61 {
62 return false;
Ed Tanous911ac312017-08-15 09:37:42 -070063 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070064 int retval = pam_authenticate(localAuthHandle,
65 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
Ed Tanous911ac312017-08-15 09:37:42 -070066
Ed Tanous1abe55e2018-09-05 08:30:59 -070067 if (retval != PAM_SUCCESS)
68 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070069 pam_end(localAuthHandle, PAM_SUCCESS);
70 return false;
71 }
Ed Tanous911ac312017-08-15 09:37:42 -070072
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 /* check that the account is healthy */
74 if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
75 PAM_SUCCESS)
76 {
77 pam_end(localAuthHandle, PAM_SUCCESS);
78 return false;
79 }
Ed Tanous911ac312017-08-15 09:37:42 -070080
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
82 {
83 return false;
84 }
85
86 return true;
Ed Tanous911ac312017-08-15 09:37:42 -070087}
Ed Tanousa8408792018-09-05 16:08:38 -070088
89inline bool pamUpdatePassword(const std::string& username,
90 const std::string& password)
91{
92 const struct pam_conv localConversation = {
93 pamFunctionConversation, const_cast<char*>(password.c_str())};
94 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
95
96 if (pam_start("passwd", username.c_str(), &localConversation,
97 &localAuthHandle) != PAM_SUCCESS)
98 {
99 return false;
100 }
101 int retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
102
103 if (retval != PAM_SUCCESS)
104 {
105 pam_end(localAuthHandle, PAM_SUCCESS);
106 return false;
107 }
108
109 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
110 {
111 return false;
112 }
113
114 return true;
115}