From 282e79b49e6b36dac304b72ed0e9d065fb5b818c Mon Sep 17 00:00:00 2001 From: Richard Marian Thomaiyar Date: Tue, 13 Nov 2018 19:00:58 +0530 Subject: Add test & user enabled state in set user password Support for test password and user enabled state in Set user password command Unit Test: 1. Performed user enabled & disabled and verified the state change 2. Performed test user password - both pass & fail condition Change-Id: I0eb91ad849e43072b1d9e90d777304fabdfb40bc Signed-off-by: Richard Marian Thomaiyar --- user_channel/user_layer.cpp | 5 +++++ user_channel/user_layer.hpp | 9 +++++++++ user_channel/user_mgmt.cpp | 27 +++++++++++++++++++++++++++ user_channel/user_mgmt.hpp | 10 ++++++++++ user_channel/usercommands.cpp | 39 ++++++++++++++++++++++++++++----------- user_channel/usercommands.hpp | 6 ++++++ 6 files changed, 85 insertions(+), 11 deletions(-) diff --git a/user_channel/user_layer.cpp b/user_channel/user_layer.cpp index 3e4490c..5a4d7ad 100644 --- a/user_channel/user_layer.cpp +++ b/user_channel/user_layer.cpp @@ -109,6 +109,11 @@ ipmi_ret_t ipmiUserGetAllCounts(uint8_t& maxChUsers, uint8_t& enabledUsers, return IPMI_CC_OK; } +ipmi_ret_t ipmiUserUpdateEnabledState(const uint8_t& userId, const bool& state) +{ + return getUserAccessObject().setUserEnabledState(userId, state); +} + ipmi_ret_t ipmiUserCheckEnabled(const uint8_t& userId, bool& state) { if (!UserAccess::isValidUserId(userId)) diff --git a/user_channel/user_layer.hpp b/user_channel/user_layer.hpp index 5136e86..8c81188 100644 --- a/user_channel/user_layer.hpp +++ b/user_channel/user_layer.hpp @@ -146,6 +146,15 @@ ipmi_ret_t ipmiUserGetUserName(const uint8_t& userId, std::string& userName); ipmi_ret_t ipmiUserGetAllCounts(uint8_t& maxChUsers, uint8_t& enabledUsers, uint8_t& fixedUsers); +/** @brief function to update user enabled state + * + * @param[in] userId - user id + *..@param[in] state - state of the user to be updated, true - user enabled. + * + * @return IPMI_CC_OK for success, others for failure. + */ +ipmi_ret_t ipmiUserUpdateEnabledState(const uint8_t& userId, const bool& state); + /** @brief determines whether user is enabled * * @param[in] userId - user id diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp index e320e3f..e90bff6 100644 --- a/user_channel/user_mgmt.cpp +++ b/user_channel/user_mgmt.cpp @@ -631,6 +631,33 @@ bool UserAccess::isValidUserName(const char* userNameInChar) return true; } +ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t& userId, + const bool& enabledState) +{ + if (!isValidUserId(userId)) + { + return IPMI_CC_PARM_OUT_OF_RANGE; + } + boost::interprocess::scoped_lock + userLock{*userMutex}; + UserInfo* userInfo = getUserInfo(userId); + std::string userName; + userName.assign(reinterpret_cast(userInfo->userName), 0, + ipmiMaxUserName); + if (userName.empty()) + { + log("User name not set / invalid"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + if (userInfo->userEnabled != enabledState) + { + std::string userPath = std::string(userObjBasePath) + "/" + userName; + setDbusProperty(bus, getUserServiceName().c_str(), userPath.c_str(), + usersInterface, userEnabledProperty, enabledState); + } + return IPMI_CC_OK; +} + ipmi_ret_t UserAccess::setUserPrivilegeAccess(const uint8_t& userId, const uint8_t& chNum, const UserPrivAccess& privAccess, diff --git a/user_channel/user_mgmt.hpp b/user_channel/user_mgmt.hpp index 16dbd31..5755fa0 100644 --- a/user_channel/user_mgmt.hpp +++ b/user_channel/user_mgmt.hpp @@ -183,6 +183,16 @@ class UserAccess */ ipmi_ret_t setUserName(const uint8_t& userId, const char* userNameInChar); + /** @brief to set user enabled state + * + * @param[in] userId - user id + * @param[in] enabledState - enabled state of the user + * + * @return IPMI_CC_OK for success, others for failure. + */ + ipmi_ret_t setUserEnabledState(const uint8_t& userId, + const bool& enabledState); + /** @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 0ed5b8f..84e9456 100644 --- a/user_channel/usercommands.cpp +++ b/user_channel/usercommands.cpp @@ -429,25 +429,42 @@ ipmi_ret_t ipmiSetUserPassword(ipmi_netfn_t netfn, ipmi_cmd_t cmd, if (!std::regex_match(passwd.c_str(), std::regex("[a-zA-z_0-9][a-zA-Z_0-9,?:`!\"]*"))) { - log("Invalid password fields", - entry("USER-ID:%d", (uint8_t)req->userId)); + log("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("Failed to update password", - entry("USER-ID:%d", (uint8_t)req->userId)); - return IPMI_CC_UNSPECIFIED_ERROR; + log("Failed to update password", + entry("USER-ID:%d", (uint8_t)req->userId)); + return IPMI_CC_INVALID_FIELD_REQUEST; } + return IPMI_CC_OK; } - else + else if (req->operation == enableUser || req->operation == disableUser) { - // TODO: test the password by reading the encrypted file - log( - "Other operations not implemented - TODO yet to implement"); - return IPMI_CC_INVALID_FIELD_REQUEST; + return ipmiUserUpdateEnabledState(req->userId, + static_cast(req->operation)); } - return IPMI_CC_OK; + else if (req->operation == testPassword) + { + auto password = ipmiUserGetPassword(userName); + std::string testPassword( + reinterpret_cast(req->userPassword), 0, + passwordLength); + // Note: For security reasons password size won't be compared and + // wrong password size completion code will not be returned if size + // doesn't match as specified in IPMI specification. + if (password != testPassword) + { + log("Test password failed", + entry("USER-ID:%d", (uint8_t)req->userId)); + return static_cast( + IPMISetPasswordReturnCodes::ipmiCCPasswdFailMismatch); + } + return IPMI_CC_OK; + } + return IPMI_CC_INVALID_FIELD_REQUEST; } void registerUserIpmiFunctions() diff --git a/user_channel/usercommands.hpp b/user_channel/usercommands.hpp index ee33b5a..afbe67a 100644 --- a/user_channel/usercommands.hpp +++ b/user_channel/usercommands.hpp @@ -29,6 +29,12 @@ enum ipmi_netfn_user_cmds IPMI_CMD_SET_USER_PASSWORD = 0x47, }; +enum class IPMISetPasswordReturnCodes +{ + ipmiCCPasswdFailMismatch = 0x80, + ipmiCCPasswdFailWrongSize = 0x81, +}; + static constexpr uint8_t userIdEnabledViaSetPassword = 0x1; static constexpr uint8_t userIdDisabledViaSetPassword = 0x2; -- cgit v1.2.1