summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--user_channel/Makefile.am1
-rw-r--r--user_channel/user_layer.cpp6
-rw-r--r--user_channel/user_layer.hpp12
-rw-r--r--user_channel/user_mgmt.cpp111
-rw-r--r--user_channel/user_mgmt.hpp9
-rw-r--r--user_channel/usercommands.cpp80
7 files changed, 142 insertions, 79 deletions
diff --git a/Makefile.am b/Makefile.am
index 492f452..d1ced8f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -126,7 +126,7 @@ libusercmds_la_SOURCES = \
user_channel/usercommands.cpp
libusercmds_la_LDFLAGS = \
$(PHOSPHOR_LOGGING_LIBS) \
- $(LIBS) \
+ $(libmapper_LIBS) \
-version-info 0:0:0 -shared
libusercmds_la_CXXFLAGS = $(COMMON_CXX)
diff --git a/user_channel/Makefile.am b/user_channel/Makefile.am
index 460b18e..3860a39 100644
--- a/user_channel/Makefile.am
+++ b/user_channel/Makefile.am
@@ -24,6 +24,7 @@ libuserlayer_la_LDFLAGS = \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
-lstdc++fs \
$(CRYPTO_LIBS) \
+ -lpam_misc \
-version-info 0:0:0 -shared
libuserlayer_la_CXXFLAGS = \
-I$(top_srcdir) \
diff --git a/user_channel/user_layer.cpp b/user_channel/user_layer.cpp
index 4dfed1f..b241564 100644
--- a/user_channel/user_layer.cpp
+++ b/user_channel/user_layer.cpp
@@ -82,6 +82,12 @@ ipmi_ret_t ipmiUserGetUserName(const uint8_t userId, std::string& userName)
return getUserAccessObject().getUserName(userId, userName);
}
+ipmi_ret_t ipmiUserSetUserPassword(const uint8_t userId,
+ const char* userPassword)
+{
+ return getUserAccessObject().setUserPassword(userId, userPassword);
+}
+
ipmi_ret_t ipmiUserGetAllCounts(uint8_t& maxChUsers, uint8_t& enabledUsers,
uint8_t& fixedUsers)
{
diff --git a/user_channel/user_layer.hpp b/user_channel/user_layer.hpp
index 6c8c683..5f3567a 100644
--- a/user_channel/user_layer.hpp
+++ b/user_channel/user_layer.hpp
@@ -35,6 +35,8 @@ static constexpr uint8_t reservedUserId = 0x0;
static constexpr uint8_t ipmiMaxUserName = 16;
static constexpr uint8_t ipmiMaxUsers = 15;
static constexpr uint8_t ipmiMaxChannels = 16;
+static constexpr uint8_t maxIpmi20PasswordSize = 20;
+static constexpr uint8_t maxIpmi15PasswordSize = 16;
/** @struct PrivAccess
*
@@ -126,6 +128,16 @@ uint8_t ipmiUserGetUserId(const std::string& userName);
*/
ipmi_ret_t ipmiUserSetUserName(const uint8_t userId, const char* userName);
+/** @brief set user password
+ *
+ * @param[in] userId - user id
+ * @param[in] userPassword - New Password
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ipmi_ret_t ipmiUserSetUserPassword(const uint8_t userId,
+ const char* userPassword);
+
/** @brief get user name
*
* @param[in] userId - user id
diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp
index 86f51da..f0cd7ad 100644
--- a/user_channel/user_mgmt.cpp
+++ b/user_channel/user_mgmt.cpp
@@ -17,6 +17,7 @@
#include "apphandler.hpp"
+#include <security/pam_appl.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -635,6 +636,116 @@ bool UserAccess::isValidUserName(const char* userNameInChar)
return true;
}
+/** @brief Information exchanged by pam module and application.
+ *
+ * @param[in] numMsg - length of the array of pointers,msg.
+ *
+ * @param[in] msg - pointer to an array of pointers to pam_message structure
+ *
+ * @param[out] resp - struct pam response array
+ *
+ * @param[in] appdataPtr - member of pam_conv structure
+ *
+ * @return the response in pam response structure.
+ */
+
+static int pamFunctionConversation(int numMsg, const struct pam_message** msg,
+ struct pam_response** resp, void* appdataPtr)
+{
+ if (appdataPtr == nullptr)
+ {
+ return PAM_AUTH_ERR;
+ }
+ size_t passSize = std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1;
+ char* pass = reinterpret_cast<char*>(malloc(passSize));
+ std::strncpy(pass, reinterpret_cast<char*>(appdataPtr), passSize);
+
+ *resp = reinterpret_cast<pam_response*>(
+ calloc(numMsg, sizeof(struct pam_response)));
+
+ for (int i = 0; i < numMsg; ++i)
+ {
+ if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
+ {
+ continue;
+ }
+ resp[i]->resp = pass;
+ }
+ return PAM_SUCCESS;
+}
+
+/** @brief Updating the PAM password
+ *
+ * @param[in] username - username in string
+ *
+ * @param[in] password - new password in string
+ *
+ * @return status
+ */
+
+bool pamUpdatePasswd(const char* username, const char* password)
+{
+ const struct pam_conv localConversation = {pamFunctionConversation,
+ const_cast<char*>(password)};
+ pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
+
+ if (pam_start("passwd", username, &localConversation, &localAuthHandle) !=
+ PAM_SUCCESS)
+ {
+ return false;
+ }
+ int retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
+
+ if (retval != PAM_SUCCESS)
+ {
+ if (retval == PAM_AUTHTOK_ERR)
+ {
+ log<level::DEBUG>("Authentication Failure");
+ }
+ else
+ {
+ log<level::DEBUG>("pam_chauthtok returned failure",
+ entry("ERROR=%d", retval));
+ }
+ pam_end(localAuthHandle, retval);
+ return false;
+ }
+ if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
+ {
+ return false;
+ }
+ return true;
+}
+
+ipmi_ret_t UserAccess::setUserPassword(const uint8_t userId,
+ const char* userPassword)
+{
+ std::string userName;
+ if (ipmiUserGetUserName(userId, userName) != IPMI_CC_OK)
+ {
+ log<level::DEBUG>("User Name not found",
+ entry("USER-ID:%d", (uint8_t)userId));
+ return IPMI_CC_PARM_OUT_OF_RANGE;
+ }
+ std::string passwd;
+ passwd.assign(reinterpret_cast<const char*>(userPassword), 0,
+ maxIpmi20PasswordSize);
+ if (!std::regex_match(passwd.c_str(),
+ std::regex("[a-zA-z_0-9][a-zA-Z_0-9,?:`!\"]*")))
+ {
+ log<level::DEBUG>("Invalid password fields",
+ entry("USER-ID:%d", (uint8_t)userId));
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ if (!pamUpdatePasswd(userName.c_str(), passwd.c_str()))
+ {
+ log<level::DEBUG>("Failed to update password",
+ entry("USER-ID:%d", (uint8_t)userId));
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ return IPMI_CC_OK;
+}
+
ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t userId,
const bool& enabledState)
{
diff --git a/user_channel/user_mgmt.hpp b/user_channel/user_mgmt.hpp
index 643ca93..9ea9f6b 100644
--- a/user_channel/user_mgmt.hpp
+++ b/user_channel/user_mgmt.hpp
@@ -208,6 +208,15 @@ class UserAccess
ipmi_ret_t setUserEnabledState(const uint8_t userId,
const bool& enabledState);
+ /** @brief to set user password
+ *
+ * @param[in] userId - user id
+ * @param[in] userPassword - new password of the user
+ *
+ * @return IPMI_CC_OK for success, others for failure.
+ */
+ ipmi_ret_t setUserPassword(const uint8_t userId, const char* userPassword);
+
/** @brief to set user privilege and access details
*
* @param[in] userId - user id
diff --git a/user_channel/usercommands.cpp b/user_channel/usercommands.cpp
index 90aadb1..d0ea29f 100644
--- a/user_channel/usercommands.cpp
+++ b/user_channel/usercommands.cpp
@@ -31,8 +31,6 @@ namespace ipmi
using namespace phosphor::logging;
-static constexpr uint8_t maxIpmi20PasswordSize = 20;
-static constexpr uint8_t maxIpmi15PasswordSize = 16;
static constexpr uint8_t disableUser = 0x00;
static constexpr uint8_t enableUser = 0x01;
static constexpr uint8_t setPassword = 0x02;
@@ -352,65 +350,6 @@ ipmi_ret_t ipmiGetUserName(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return IPMI_CC_OK;
}
-int pamFunctionConversation(int numMsg, const struct pam_message** msg,
- struct pam_response** resp, void* appdataPtr)
-{
- if (appdataPtr == nullptr)
- {
- return PAM_AUTH_ERR;
- }
- size_t passSize = std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1;
- char* pass = reinterpret_cast<char*>(malloc(passSize));
- std::strncpy(pass, reinterpret_cast<char*>(appdataPtr), passSize);
-
- *resp = reinterpret_cast<pam_response*>(
- calloc(numMsg, sizeof(struct pam_response)));
-
- for (int i = 0; i < numMsg; ++i)
- {
- if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
- {
- continue;
- }
- resp[i]->resp = pass;
- }
- return PAM_SUCCESS;
-}
-
-bool pamUpdatePasswd(const char* username, const char* password)
-{
- const struct pam_conv localConversation = {pamFunctionConversation,
- const_cast<char*>(password)};
- pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
-
- if (pam_start("passwd", username, &localConversation, &localAuthHandle) !=
- PAM_SUCCESS)
- {
- return false;
- }
- int retval = pam_chauthtok(localAuthHandle, PAM_SILENT);
-
- if (retval != PAM_SUCCESS)
- {
- if (retval == PAM_AUTHTOK_ERR)
- {
- log<level::DEBUG>("Authentication Failure");
- }
- else
- {
- log<level::DEBUG>("pam_chauthtok returned failure",
- entry("ERROR=%d", retval));
- }
- pam_end(localAuthHandle, retval);
- return false;
- }
- if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
- {
- return false;
- }
- return true;
-}
-
/** @brief implementes the set user password command
* @param[in] netfn - specifies netfn.
* @param[in] cmd - specifies cmd number.
@@ -462,23 +401,8 @@ ipmi_ret_t ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
}
if (req->operation == setPassword)
{
- std::string passwd;
- passwd.assign(reinterpret_cast<const char*>(req->userPassword), 0,
- maxIpmi20PasswordSize);
- if (!std::regex_match(passwd.c_str(),
- std::regex("[a-zA-z_0-9][a-zA-Z_0-9,?:`!\"]*")))
- {
- log<level::ERR>("Invalid password fields",
- entry("USER-ID:%d", (uint8_t)req->userId));
- return IPMI_CC_INVALID_FIELD_REQUEST;
- }
- if (!pamUpdatePasswd(userName.c_str(), passwd.c_str()))
- {
- log<level::ERR>("Failed to update password",
- entry("USER-ID:%d", (uint8_t)req->userId));
- return IPMI_CC_INVALID_FIELD_REQUEST;
- }
- return IPMI_CC_OK;
+ return ipmiUserSetUserPassword(
+ req->userId, reinterpret_cast<const char*>(req->userPassword));
}
else if (req->operation == enableUser || req->operation == disableUser)
{
OpenPOWER on IntegriCloud