summaryrefslogtreecommitdiffstats
path: root/user_channel
diff options
context:
space:
mode:
authorSuryakanth Sekar <suryakanth.sekar@linux.intel.com>2019-01-16 10:37:57 +0530
committerVernon Mauery <vernon.mauery@linux.intel.com>2019-03-26 16:38:59 +0000
commit90b00c71067df78597db92bb60dbacf654a6f80a (patch)
tree518214e15a188a194a795dc40e2cae72fceba845 /user_channel
parent17898f625b04d4fee6c2fd0626c47c93f2c2e7bd (diff)
downloadphosphor-host-ipmid-90b00c71067df78597db92bb60dbacf654a6f80a.tar.gz
phosphor-host-ipmid-90b00c71067df78597db92bb60dbacf654a6f80a.zip
Adding Set Password API support in Userlayer
Moved the pam function from libusercommand to libuserlayer Added the setPassword API in user layer. There are modules which requires to use set password functionality (other ipmi providers-OEM),so it's better to keep the set-password abstracted in user-layer instead of user-commands. LIBS macro hold libpam and libmapper. we want to separate the libpam from lib usercommand. so,replaced LIBS with libmapper alone. Tested:Able to set the password in ipmi using userlayer. ex: ipmitool user set password <userid> <password> user password should set properly. Change-Id: I32d55ff5c042613c89805c6b9393d18cbf880461 Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
Diffstat (limited to 'user_channel')
-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
6 files changed, 141 insertions, 78 deletions
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