blob: 5d78efcfc19a8954d01f00f7bd3bdb4886db09a4 [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 Tanous271584a2019-07-09 16:24:22 -070028 calloc(static_cast<size_t>(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())};
Ed Tanous99131cd2019-10-24 11:12:47 -070057 pam_handle_t* localAuthHandle = nullptr; // 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
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +000089inline int pamUpdatePassword(const std::string& username,
90 const std::string& password)
Ed Tanousa8408792018-09-05 16:08:38 -070091{
92 const struct pam_conv localConversation = {
93 pamFunctionConversation, const_cast<char*>(password.c_str())};
Ed Tanous99131cd2019-10-24 11:12:47 -070094 pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
Ed Tanousa8408792018-09-05 16:08:38 -070095
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +000096 int retval = pam_start("passwd", username.c_str(), &localConversation,
97 &localAuthHandle);
Ed Tanousa8408792018-09-05 16:08:38 -070098
99 if (retval != PAM_SUCCESS)
100 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000101 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700102 }
103
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000104 retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
105 if (retval != PAM_SUCCESS)
Ed Tanousa8408792018-09-05 16:08:38 -0700106 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000107 pam_end(localAuthHandle, PAM_SUCCESS);
108 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700109 }
110
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000111 return pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanousa8408792018-09-05 16:08:38 -0700112}