Fix password update
There is a regression issue found with this commit in password update
https://gerrit.openbmc.org/c/openbmc/bmcweb/+/73605
This commit fixes PAM conversation for password update
Tested by:
PATCH https://${bmc}/redfish/v1/AccountService/Accounts/root -d
'{"Password":"0penBmc1"}'
Change-Id: Ifcede67364c35ced899a3f726f67253cdb51002e
Signed-off-by: Ed Tanous <etanous@nvidia.com>
Signed-off-by: Ravi Teja <raviteja28031990@gmail.com>
diff --git a/include/pam_authenticate.hpp b/include/pam_authenticate.hpp
index 36d307e..fbb3f61 100644
--- a/include/pam_authenticate.hpp
+++ b/include/pam_authenticate.hpp
@@ -134,13 +134,77 @@
return pam_end(localAuthHandle, PAM_SUCCESS);
}
+inline int pamUpdatePasswordFunctionConversation(
+ int numMsg, const struct pam_message** msgs, struct pam_response** resp,
+ void* appdataPtr)
+{
+ if ((appdataPtr == nullptr) || (msgs == nullptr) || (resp == nullptr))
+ {
+ return PAM_CONV_ERR;
+ }
+
+ if (numMsg <= 0 || numMsg >= PAM_MAX_NUM_MSG)
+ {
+ return PAM_CONV_ERR;
+ }
+ auto msgCount = static_cast<size_t>(numMsg);
+
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
+ auto responseArrPtr = std::make_unique<pam_response[]>(msgCount);
+ auto responses = std::span(responseArrPtr.get(), msgCount);
+ auto messagePtrs = std::span(msgs, msgCount);
+ for (size_t i = 0; i < msgCount; ++i)
+ {
+ const pam_message& msg = *(messagePtrs[i]);
+
+ pam_response& response = responses[i];
+ response.resp_retcode = 0;
+ response.resp = nullptr;
+
+ switch (msg.msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ {
+ // Assume PAM is only prompting for the password as hidden input
+ // Allocate memory only when PAM_PROMPT_ECHO_OFF is encounterred
+ char* appPass = static_cast<char*>(appdataPtr);
+ size_t appPassSize = std::strlen(appPass);
+
+ if ((appPassSize + 1) > PAM_MAX_RESP_SIZE)
+ {
+ return PAM_CONV_ERR;
+ }
+ // Create an array for pam to own
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
+ auto passPtr = std::make_unique<char[]>(appPassSize + 1);
+ std::strncpy(passPtr.get(), appPass, appPassSize + 1);
+
+ responses[i].resp = passPtr.release();
+ }
+ break;
+ case PAM_ERROR_MSG:
+ BMCWEB_LOG_ERROR("Pam error {}", msg.msg);
+ break;
+ case PAM_TEXT_INFO:
+ BMCWEB_LOG_ERROR("Pam info {}", msg.msg);
+ break;
+ default:
+ return PAM_CONV_ERR;
+ }
+ }
+ *resp = responseArrPtr.release();
+ return PAM_SUCCESS;
+}
+
inline int pamUpdatePassword(const std::string& username,
const std::string& password)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
char* passStrNoConst = const_cast<char*>(password.c_str());
- const struct pam_conv localConversation = {pamFunctionConversation,
- passStrNoConst};
+ const struct pam_conv localConversation = {
+ pamUpdatePasswordFunctionConversation, passStrNoConst};
pam_handle_t* localAuthHandle = nullptr; // this gets set by pam_start
int retval = pam_start("webserver", username.c_str(), &localConversation,