blob: f8afbb13e80c96f99ac2787b27eb00f09d7792f8 [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
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060050/**
51 * @brief Attempt username/password authentication via PAM.
52 * @param username The provided username aka account name.
53 * @param password The provided password.
54 * @returns PAM error code or PAM_SUCCESS for success. */
55inline int pamAuthenticateUser(const std::string_view username,
56 const std::string_view password)
Ed Tanous1abe55e2018-09-05 08:30:59 -070057{
58 std::string userStr(username);
59 std::string passStr(password);
60 const struct pam_conv localConversation = {
61 pamFunctionConversation, const_cast<char*>(passStr.c_str())};
Ed Tanous99131cd2019-10-24 11:12:47 -070062 pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070063
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060064 int retval = pam_start("webserver", userStr.c_str(), &localConversation,
65 &localAuthHandle);
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 if (retval != PAM_SUCCESS)
67 {
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060068 return retval;
69 }
70
71 retval = pam_authenticate(localAuthHandle,
72 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
73 if (retval != PAM_SUCCESS)
74 {
75 pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
76 return retval;
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 }
Ed Tanous911ac312017-08-15 09:37:42 -070078
Ed Tanous1abe55e2018-09-05 08:30:59 -070079 /* check that the account is healthy */
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060080 retval = pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK);
81 if (retval != PAM_SUCCESS)
Ed Tanous1abe55e2018-09-05 08:30:59 -070082 {
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060083 pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
84 return retval;
Ed Tanous1abe55e2018-09-05 08:30:59 -070085 }
Ed Tanous911ac312017-08-15 09:37:42 -070086
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060087 return pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanous911ac312017-08-15 09:37:42 -070088}
Ed Tanousa8408792018-09-05 16:08:38 -070089
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +000090inline int pamUpdatePassword(const std::string& username,
91 const std::string& password)
Ed Tanousa8408792018-09-05 16:08:38 -070092{
93 const struct pam_conv localConversation = {
94 pamFunctionConversation, const_cast<char*>(password.c_str())};
Ed Tanous99131cd2019-10-24 11:12:47 -070095 pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
Ed Tanousa8408792018-09-05 16:08:38 -070096
Joseph Reynolds96b39e02019-12-05 17:53:35 -060097 int retval = pam_start("webserver", username.c_str(), &localConversation,
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +000098 &localAuthHandle);
Ed Tanousa8408792018-09-05 16:08:38 -070099
100 if (retval != PAM_SUCCESS)
101 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000102 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700103 }
104
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000105 retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
106 if (retval != PAM_SUCCESS)
Ed Tanousa8408792018-09-05 16:08:38 -0700107 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000108 pam_end(localAuthHandle, PAM_SUCCESS);
109 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700110 }
111
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000112 return pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanousa8408792018-09-05 16:08:38 -0700113}