blob: 68ce64a2ef2139232c4491ecdaa59ed8be20ad33 [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*>(
Ed Tanousb01bf292019-03-25 19:25:26 +000028 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,
Joseph Reynolds8fd315a2019-09-12 12:02:33 -050051 const std::string_view password,
52 bool& passwordChangeRequired)
Ed Tanous1abe55e2018-09-05 08:30:59 -070053{
54 std::string userStr(username);
55 std::string passStr(password);
Joseph Reynolds8fd315a2019-09-12 12:02:33 -050056 passwordChangeRequired = false;
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 const struct pam_conv localConversation = {
58 pamFunctionConversation, const_cast<char*>(passStr.c_str())};
59 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070060
Ed Tanous1abe55e2018-09-05 08:30:59 -070061 if (pam_start("webserver", userStr.c_str(), &localConversation,
62 &localAuthHandle) != PAM_SUCCESS)
63 {
64 return false;
Ed Tanous911ac312017-08-15 09:37:42 -070065 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 int retval = pam_authenticate(localAuthHandle,
67 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
Ed Tanous911ac312017-08-15 09:37:42 -070068
Ed Tanous1abe55e2018-09-05 08:30:59 -070069 if (retval != PAM_SUCCESS)
70 {
Ed Tanous1abe55e2018-09-05 08:30:59 -070071 pam_end(localAuthHandle, PAM_SUCCESS);
72 return false;
73 }
Ed Tanous911ac312017-08-15 09:37:42 -070074
Joseph Reynolds8fd315a2019-09-12 12:02:33 -050075 /* check if the account is healthy */
76 switch (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK))
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 {
Joseph Reynolds8fd315a2019-09-12 12:02:33 -050078 case PAM_SUCCESS:
79 break;
80 case PAM_NEW_AUTHTOK_REQD:
81 passwordChangeRequired = true;
82 break;
83 default:
84 pam_end(localAuthHandle, PAM_SUCCESS);
85 return false;
86 break;
Ed Tanous1abe55e2018-09-05 08:30:59 -070087 }
Ed Tanous911ac312017-08-15 09:37:42 -070088
Ed Tanous1abe55e2018-09-05 08:30:59 -070089 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
90 {
91 return false;
92 }
93
94 return true;
Ed Tanous911ac312017-08-15 09:37:42 -070095}
Ed Tanousa8408792018-09-05 16:08:38 -070096
97inline bool pamUpdatePassword(const std::string& username,
98 const std::string& password)
99{
100 const struct pam_conv localConversation = {
101 pamFunctionConversation, const_cast<char*>(password.c_str())};
102 pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
103
104 if (pam_start("passwd", username.c_str(), &localConversation,
105 &localAuthHandle) != PAM_SUCCESS)
106 {
107 return false;
108 }
109 int retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
110
111 if (retval != PAM_SUCCESS)
112 {
113 pam_end(localAuthHandle, PAM_SUCCESS);
114 return false;
115 }
116
117 if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
118 {
119 return false;
120 }
121
122 return true;
123}