blob: 12f19c0a9cd9c8983a6233abaeea53ef8e44f82f [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>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05006
Ed Tanous911ac312017-08-15 09:37:42 -07007#include <cstring>
Ed Tanouse0d918b2018-03-27 17:41:04 -07008#include <memory>
Ed Tanousf3d847c2017-06-12 16:01:42 -07009
10// function used to get user input
Ed Tanous55c7b7a2018-05-22 15:27:24 -070011inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
Ed Tanous1abe55e2018-09-05 08:30:59 -070012 struct pam_response** resp, void* appdataPtr)
13{
14 if (appdataPtr == nullptr)
15 {
16 return PAM_AUTH_ERR;
17 }
Ed Tanousf1eebf02019-03-04 15:57:09 -080018 char* appPass = reinterpret_cast<char*>(appdataPtr);
19 size_t appPassSize = std::strlen(appPass);
20 char* pass = reinterpret_cast<char*>(malloc(appPassSize + 1));
Ed Tanous39e77502019-03-04 17:35:53 -080021 if (pass == nullptr)
Ed Tanousf1eebf02019-03-04 15:57:09 -080022 {
23 return PAM_AUTH_ERR;
24 }
25
Ed Tanouseb7d3d52019-10-24 10:23:56 -070026 std::strncpy(pass, appPass, appPassSize + 1);
Ed Tanousf3d847c2017-06-12 16:01:42 -070027
Ed Tanousf23b7292020-10-15 09:41:17 -070028 void* ptr =
29 calloc(static_cast<size_t>(numMsg), sizeof(struct pam_response));
30 if (ptr == nullptr)
Ed Tanousf1eebf02019-03-04 15:57:09 -080031 {
AppaRao Puli87f171a2020-08-07 01:37:28 +053032 free(pass);
Ed Tanousf1eebf02019-03-04 15:57:09 -080033 return PAM_AUTH_ERR;
34 }
35
Ed Tanousf23b7292020-10-15 09:41:17 -070036 *resp = reinterpret_cast<pam_response*>(ptr);
37
Ed Tanous1abe55e2018-09-05 08:30:59 -070038 for (int i = 0; i < numMsg; ++i)
39 {
40 /* Ignore all PAM messages except prompting for hidden input */
41 if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
42 {
43 continue;
44 }
45
46 /* Assume PAM is only prompting for the password as hidden input */
47 resp[i]->resp = pass;
Ed Tanous911ac312017-08-15 09:37:42 -070048 }
Ed Tanousf3d847c2017-06-12 16:01:42 -070049
Ed Tanous1abe55e2018-09-05 08:30:59 -070050 return PAM_SUCCESS;
Ed Tanousf3d847c2017-06-12 16:01:42 -070051}
52
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060053/**
54 * @brief Attempt username/password authentication via PAM.
55 * @param username The provided username aka account name.
56 * @param password The provided password.
57 * @returns PAM error code or PAM_SUCCESS for success. */
58inline int pamAuthenticateUser(const std::string_view username,
59 const std::string_view password)
Ed Tanous1abe55e2018-09-05 08:30:59 -070060{
61 std::string userStr(username);
62 std::string passStr(password);
63 const struct pam_conv localConversation = {
64 pamFunctionConversation, const_cast<char*>(passStr.c_str())};
Ed Tanous99131cd2019-10-24 11:12:47 -070065 pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
Ed Tanousf3d847c2017-06-12 16:01:42 -070066
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060067 int retval = pam_start("webserver", userStr.c_str(), &localConversation,
68 &localAuthHandle);
Ed Tanous1abe55e2018-09-05 08:30:59 -070069 if (retval != PAM_SUCCESS)
70 {
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060071 return retval;
72 }
73
74 retval = pam_authenticate(localAuthHandle,
75 PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
76 if (retval != PAM_SUCCESS)
77 {
78 pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
79 return retval;
Ed Tanous1abe55e2018-09-05 08:30:59 -070080 }
Ed Tanous911ac312017-08-15 09:37:42 -070081
Ed Tanous1abe55e2018-09-05 08:30:59 -070082 /* check that the account is healthy */
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060083 retval = pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK);
84 if (retval != PAM_SUCCESS)
Ed Tanous1abe55e2018-09-05 08:30:59 -070085 {
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060086 pam_end(localAuthHandle, PAM_SUCCESS); // ignore retval
87 return retval;
Ed Tanous1abe55e2018-09-05 08:30:59 -070088 }
Ed Tanous911ac312017-08-15 09:37:42 -070089
Joseph Reynoldsd887fff2020-01-14 16:34:09 -060090 return pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanous911ac312017-08-15 09:37:42 -070091}
Ed Tanousa8408792018-09-05 16:08:38 -070092
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +000093inline int pamUpdatePassword(const std::string& username,
94 const std::string& password)
Ed Tanousa8408792018-09-05 16:08:38 -070095{
96 const struct pam_conv localConversation = {
97 pamFunctionConversation, const_cast<char*>(password.c_str())};
Ed Tanous99131cd2019-10-24 11:12:47 -070098 pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
Ed Tanousa8408792018-09-05 16:08:38 -070099
Joseph Reynolds96b39e02019-12-05 17:53:35 -0600100 int retval = pam_start("webserver", username.c_str(), &localConversation,
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000101 &localAuthHandle);
Ed Tanousa8408792018-09-05 16:08:38 -0700102
103 if (retval != PAM_SUCCESS)
104 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000105 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700106 }
107
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000108 retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
109 if (retval != PAM_SUCCESS)
Ed Tanousa8408792018-09-05 16:08:38 -0700110 {
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000111 pam_end(localAuthHandle, PAM_SUCCESS);
112 return retval;
Ed Tanousa8408792018-09-05 16:08:38 -0700113 }
114
jayaprakash Mutyala66b5ca72019-08-07 20:26:37 +0000115 return pam_end(localAuthHandle, PAM_SUCCESS);
Ed Tanousa8408792018-09-05 16:08:38 -0700116}