diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | user_channel/Makefile.am | 1 | ||||
-rw-r--r-- | user_channel/user_layer.cpp | 6 | ||||
-rw-r--r-- | user_channel/user_layer.hpp | 12 | ||||
-rw-r--r-- | user_channel/user_mgmt.cpp | 111 | ||||
-rw-r--r-- | user_channel/user_mgmt.hpp | 9 | ||||
-rw-r--r-- | user_channel/usercommands.cpp | 80 |
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) { |