diff options
Diffstat (limited to 'user_channel/user_mgmt.cpp')
-rw-r--r-- | user_channel/user_mgmt.cpp | 495 |
1 files changed, 395 insertions, 100 deletions
diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp index f0cd7ad..102f990 100644 --- a/user_channel/user_mgmt.cpp +++ b/user_channel/user_mgmt.cpp @@ -16,6 +16,7 @@ #include "user_mgmt.hpp" #include "apphandler.hpp" +#include "channel_layer.hpp" #include <security/pam_appl.h> #include <sys/stat.h> @@ -31,6 +32,7 @@ #include <regex> #include <sdbusplus/bus/match.hpp> #include <sdbusplus/server/object.hpp> +#include <variant> #include <xyz/openbmc_project/Common/error.hpp> #include <xyz/openbmc_project/User/Common/error.hpp> @@ -103,13 +105,10 @@ static std::array<std::string, (PRIVILEGE_OEM + 1)> ipmiPrivIndex = { "priv-custom" // PRIVILEGE_OEM - 5 }; -namespace variant_ns = sdbusplus::message::variant_ns; - using namespace phosphor::logging; using Json = nlohmann::json; -using PrivAndGroupType = - sdbusplus::message::variant<std::string, std::vector<std::string>>; +using PrivAndGroupType = std::variant<std::string, std::vector<std::string>>; using NoResource = sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource; @@ -198,12 +197,13 @@ UserAccess& getUserAccessObject() int getUserNameFromPath(const std::string& path, std::string& userName) { - static size_t pos = strlen(userObjBasePath) + 1; - if (path.find(userObjBasePath) == std::string::npos) + constexpr size_t length = strlen(userObjBasePath); + if (((length + 1) >= path.size()) || + path.compare(0, length, userObjBasePath)) { return -EINVAL; } - userName.assign(path, pos, path.size()); + userName.assign(path, length + 1, path.size()); return 0; } @@ -308,7 +308,7 @@ void userUpdatedSignalHandler(UserAccess& usrAccess, { static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); std::string signal = msg.get_member(); - std::string userName, update, priv, newUserName; + std::string userName, priv, newUserName; std::vector<std::string> groups; bool enabled = false; UserUpdateEvent userEvent = UserUpdateEvent::reservedEvent; @@ -376,17 +376,17 @@ void userUpdatedSignalHandler(UserAccess& usrAccess, std::string member = prop.first; if (member == userPrivProperty) { - priv = variant_ns::get<std::string>(prop.second); + priv = std::get<std::string>(prop.second); userEvent = UserUpdateEvent::userPrivUpdated; } else if (member == userGrpProperty) { - groups = variant_ns::get<std::vector<std::string>>(prop.second); + groups = std::get<std::vector<std::string>>(prop.second); userEvent = UserUpdateEvent::userGrpUpdated; } else if (member == userEnabledProperty) { - enabled = variant_ns::get<bool>(prop.second); + enabled = std::get<bool>(prop.second); userEvent = UserUpdateEvent::userStateUpdated; } // Process based on event type. @@ -472,43 +472,8 @@ UserAccess::UserAccess() : bus(ipmid_get_sd_bus_connection()) userMutex = std::make_unique<boost::interprocess::named_recursive_mutex>( boost::interprocess::open_or_create, ipmiUserMutex); - initUserDataFile(); + cacheUserDataFile(); getSystemPrivAndGroups(); - sigHndlrLock = boost::interprocess::file_lock(ipmiUserDataFile); - // Register it for single object and single process either netipimd / - // host-ipmid - if (userUpdatedSignal == nullptr && sigHndlrLock.try_lock()) - { - log<level::DEBUG>("Registering signal handler"); - userUpdatedSignal = std::make_unique<sdbusplus::bus::match_t>( - bus, - sdbusplus::bus::match::rules::type::signal() + - sdbusplus::bus::match::rules::interface(dBusObjManager) + - sdbusplus::bus::match::rules::path(userMgrObjBasePath), - [&](sdbusplus::message::message& msg) { - userUpdatedSignalHandler(*this, msg); - }); - userMgrRenamedSignal = std::make_unique<sdbusplus::bus::match_t>( - bus, - sdbusplus::bus::match::rules::type::signal() + - sdbusplus::bus::match::rules::interface(userMgrInterface) + - sdbusplus::bus::match::rules::path(userMgrObjBasePath), - [&](sdbusplus::message::message& msg) { - userUpdatedSignalHandler(*this, msg); - }); - userPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>( - bus, - sdbusplus::bus::match::rules::type::signal() + - sdbusplus::bus::match::rules::path_namespace(userObjBasePath) + - sdbusplus::bus::match::rules::interface( - dBusPropertiesInterface) + - sdbusplus::bus::match::rules::member(propertiesChangedSignal) + - sdbusplus::bus::match::rules::argN(0, usersInterface), - [&](sdbusplus::message::message& msg) { - userUpdatedSignalHandler(*this, msg); - }); - signalHndlrObject = true; - } } UserInfo* UserAccess::getUserInfo(const uint8_t userId) @@ -683,33 +648,64 @@ static int pamFunctionConversation(int numMsg, const struct pam_message** msg, * @return status */ -bool pamUpdatePasswd(const char* username, const char* password) +int 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) + int retval = + pam_start("passwd", username, &localConversation, &localAuthHandle); + + if (retval != PAM_SUCCESS) { + return retval; + } + + retval = pam_chauthtok(localAuthHandle, PAM_SILENT); + if (retval != PAM_SUCCESS) + { + pam_end(localAuthHandle, retval); + return retval; + } + + return pam_end(localAuthHandle, PAM_SUCCESS); +} + +bool pamUserCheckAuthenticate(std::string_view username, + std::string_view password) +{ + const struct pam_conv localConversation = { + pamFunctionConversation, const_cast<char*>(password.data())}; + + pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start + + if (pam_start("dropbear", username.data(), &localConversation, + &localAuthHandle) != PAM_SUCCESS) + { + log<level::ERR>("User Authentication Failure"); return false; } - int retval = pam_chauthtok(localAuthHandle, PAM_SILENT); + + int retval = pam_authenticate(localAuthHandle, + PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK); 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)); - } + log<level::DEBUG>("pam_authenticate returned failure", + entry("ERROR=%d", retval)); + pam_end(localAuthHandle, retval); return false; } + + if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) != + PAM_SUCCESS) + { + pam_end(localAuthHandle, PAM_SUCCESS); + return false; + } + if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS) { return false; @@ -717,33 +713,51 @@ bool pamUpdatePasswd(const char* username, const char* password) return true; } +ipmi_ret_t UserAccess::setSpecialUserPassword(const std::string& userName, + const std::string& userPassword) +{ + if (pamUpdatePasswd(userName.c_str(), userPassword.c_str()) != PAM_SUCCESS) + { + log<level::DEBUG>("Failed to update password"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + return IPMI_CC_OK; +} + ipmi_ret_t UserAccess::setUserPassword(const uint8_t userId, const char* userPassword) { std::string userName; - if (ipmiUserGetUserName(userId, userName) != IPMI_CC_OK) + if (ipmiUserGetUserName(userId, userName) != ipmi::ccSuccess) { log<level::DEBUG>("User Name not found", - entry("USER-ID:%d", (uint8_t)userId)); - return IPMI_CC_PARM_OUT_OF_RANGE; + entry("USER-ID=%d", (uint8_t)userId)); + return ipmi::ccParmOutOfRange; } 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())) + + int retval = pamUpdatePasswd(userName.c_str(), passwd.c_str()); + + switch (retval) { - log<level::DEBUG>("Failed to update password", - entry("USER-ID:%d", (uint8_t)userId)); - return IPMI_CC_UNSPECIFIED_ERROR; + case PAM_SUCCESS: + { + return ipmi::ccSuccess; + } + case PAM_AUTHTOK_ERR: + { + log<level::DEBUG>("Bad authentication token"); + return ipmi::ccInvalidFieldRequest; + } + default: + { + log<level::DEBUG>("Failed to update password", + entry("USER-ID=%d", (uint8_t)userId)); + return ipmi::ccUnspecifiedError; + } } - return IPMI_CC_OK; } ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t userId, @@ -783,6 +797,60 @@ ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t userId, return IPMI_CC_OK; } +ipmi_ret_t UserAccess::setUserPayloadAccess(const uint8_t chNum, + const uint8_t operation, + const uint8_t userId, + const PayloadAccess& payloadAccess) +{ + constexpr uint8_t enable = 0x0; + constexpr uint8_t disable = 0x1; + + if (!isValidChannel(chNum)) + { + return IPMI_CC_INVALID_FIELD_REQUEST; + } + if (!isValidUserId(userId)) + { + return IPMI_CC_PARM_OUT_OF_RANGE; + } + if (operation != enable && operation != disable) + { + return IPMI_CC_INVALID_FIELD_REQUEST; + } + // Check operation & payloadAccess if required. + boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> + userLock{*userMutex}; + UserInfo* userInfo = getUserInfo(userId); + + if (operation == enable) + { + userInfo->payloadAccess[chNum].stdPayloadEnables1 |= + payloadAccess.stdPayloadEnables1; + + userInfo->payloadAccess[chNum].oemPayloadEnables1 |= + payloadAccess.oemPayloadEnables1; + } + else + { + userInfo->payloadAccess[chNum].stdPayloadEnables1 &= + ~(payloadAccess.stdPayloadEnables1); + + userInfo->payloadAccess[chNum].oemPayloadEnables1 &= + ~(payloadAccess.oemPayloadEnables1); + } + + try + { + writeUserData(); + } + catch (const std::exception& e) + { + log<level::ERR>("Write user data failed"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + return IPMI_CC_OK; +} + ipmi_ret_t UserAccess::setUserPrivilegeAccess(const uint8_t userId, const uint8_t chNum, const UserPrivAccess& privAccess, @@ -878,6 +946,26 @@ ipmi_ret_t UserAccess::getUserName(const uint8_t userId, std::string& userName) return IPMI_CC_OK; } +bool UserAccess::isIpmiInAvailableGroupList() +{ + if (std::find(availableGroups.begin(), availableGroups.end(), + ipmiGrpName) != availableGroups.end()) + { + return true; + } + if (availableGroups.empty()) + { + // available groups shouldn't be empty, re-query + getSystemPrivAndGroups(); + if (std::find(availableGroups.begin(), availableGroups.end(), + ipmiGrpName) != availableGroups.end()) + { + return true; + } + } + return false; +} + ipmi_ret_t UserAccess::setUserName(const uint8_t userId, const char* userNameInChar) { @@ -923,6 +1011,10 @@ ipmi_ret_t UserAccess::setUserName(const uint8_t userId, { try { + if (!isIpmiInAvailableGroupList()) + { + return IPMI_CC_UNSPECIFIED_ERROR; + } // Create new user auto method = bus.new_method_call( getUserServiceName().c_str(), userMgrObjBasePath, @@ -990,6 +1082,98 @@ static constexpr const char* jsonAccCallbk = "access_callback"; static constexpr const char* jsonUserEnabled = "user_enabled"; static constexpr const char* jsonUserInSys = "user_in_system"; static constexpr const char* jsonFixedUser = "fixed_user_name"; +static constexpr const char* payloadEnabledStr = "payload_enabled"; +static constexpr const char* stdPayloadStr = "std_payload"; +static constexpr const char* oemPayloadStr = "OEM_payload"; + +/** @brief to construct a JSON object from the given payload access details. + * + * @param[in] stdPayload - stdPayloadEnables1 in a 2D-array. (input) + * @param[in] oemPayload - oemPayloadEnables1 in a 2D-array. (input) + * + * @details Sample output JSON object format : + * "payload_enabled":{ + * "OEM_payload0":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload1":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload2":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload3":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload4":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload5":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload6":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "OEM_payload7":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload0":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload1":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload2":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload3":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload4":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload5":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload6":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * "std_payload7":[false,...<repeat 'ipmiMaxChannels - 1' times>], + * } + */ +static const Json constructJsonPayloadEnables( + const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& + stdPayload, + const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& + oemPayload) +{ + Json jsonPayloadEnabled; + + for (auto payloadNum = 0; payloadNum < payloadsPerByte; payloadNum++) + { + std::ostringstream stdPayloadStream; + std::ostringstream oemPayloadStream; + + stdPayloadStream << stdPayloadStr << payloadNum; + oemPayloadStream << oemPayloadStr << payloadNum; + + jsonPayloadEnabled.push_back(Json::object_t::value_type( + stdPayloadStream.str(), stdPayload[payloadNum])); + + jsonPayloadEnabled.push_back(Json::object_t::value_type( + oemPayloadStream.str(), oemPayload[payloadNum])); + } + return jsonPayloadEnabled; +} + +void UserAccess::readPayloadAccessFromUserInfo( + const UserInfo& userInfo, + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& stdPayload, + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& oemPayload) +{ + for (auto payloadNum = 0; payloadNum < payloadsPerByte; payloadNum++) + { + for (auto chIndex = 0; chIndex < ipmiMaxChannels; chIndex++) + { + stdPayload[payloadNum][chIndex] = + userInfo.payloadAccess[chIndex].stdPayloadEnables1[payloadNum]; + + oemPayload[payloadNum][chIndex] = + userInfo.payloadAccess[chIndex].oemPayloadEnables1[payloadNum]; + } + } +} + +void UserAccess::updatePayloadAccessInUserInfo( + const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& + stdPayload, + const std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte>& + oemPayload, + UserInfo& userInfo) +{ + for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) + { + // Ensure that reserved/unsupported payloads are marked to zero. + userInfo.payloadAccess[chIndex].stdPayloadEnables1.reset(); + userInfo.payloadAccess[chIndex].oemPayloadEnables1.reset(); + userInfo.payloadAccess[chIndex].stdPayloadEnables2Reserved.reset(); + userInfo.payloadAccess[chIndex].oemPayloadEnables2Reserved.reset(); + // Update SOL status as it is the only supported payload currently. + userInfo.payloadAccess[chIndex] + .stdPayloadEnables1[static_cast<uint8_t>(ipmi::PayloadType::SOL)] = + stdPayload[static_cast<uint8_t>(ipmi::PayloadType::SOL)][chIndex]; + } +} void UserAccess::readUserData() { @@ -1013,6 +1197,7 @@ void UserAccess::readUserData() throw std::runtime_error( "Corrupted IPMI user data file - invalid user count"); } + // user index 0 is reserved, starts with 1 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) { @@ -1036,6 +1221,48 @@ void UserAccess::readUserData() userInfo[jsonLinkAuthEnabled].get<std::vector<bool>>(); std::vector<bool> accessCallback = userInfo[jsonAccCallbk].get<std::vector<bool>>(); + + // Payload Enables Processing. + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte> + stdPayload = {}; + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte> + oemPayload = {}; + try + { + const auto jsonPayloadEnabled = userInfo.at(payloadEnabledStr); + for (auto payloadNum = 0; payloadNum < payloadsPerByte; + payloadNum++) + { + std::ostringstream stdPayloadStream; + std::ostringstream oemPayloadStream; + + stdPayloadStream << stdPayloadStr << payloadNum; + oemPayloadStream << oemPayloadStr << payloadNum; + + stdPayload[payloadNum] = + jsonPayloadEnabled[stdPayloadStream.str()] + .get<std::array<bool, ipmiMaxChannels>>(); + oemPayload[payloadNum] = + jsonPayloadEnabled[oemPayloadStream.str()] + .get<std::array<bool, ipmiMaxChannels>>(); + + if (stdPayload[payloadNum].size() != ipmiMaxChannels || + oemPayload[payloadNum].size() != ipmiMaxChannels) + { + log<level::ERR>("Error in reading IPMI user data file - " + "payload properties corrupted"); + throw std::runtime_error( + "Corrupted IPMI user data file - payload properties"); + } + } + } + catch (Json::out_of_range& e) + { + // Key not found in 'userInfo'; possibly an old JSON file. Use + // default values for all payloads, and SOL payload default is true. + stdPayload[static_cast<uint8_t>(ipmi::PayloadType::SOL)].fill(true); + } + if (privilege.size() != ipmiMaxChannels || ipmiEnabled.size() != ipmiMaxChannels || linkAuthEnabled.size() != ipmiMaxChannels || @@ -1058,6 +1285,8 @@ void UserAccess::readUserData() usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback = accessCallback[chIndex]; } + updatePayloadAccessInUserInfo(stdPayload, oemPayload, + usersTbl.user[usrIndex]); usersTbl.user[usrIndex].userEnabled = userInfo[jsonUserEnabled].get<bool>(); usersTbl.user[usrIndex].userInSystem = @@ -1078,15 +1307,6 @@ void UserAccess::writeUserData() boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> userLock{*userMutex}; - static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"}; - std::ofstream oUsrData(tmpFile, std::ios::out | std::ios::binary); - if (!oUsrData.good()) - { - log<level::ERR>("Error in creating temporary IPMI user data file"); - throw std::ios_base::failure( - "Error in creating temporary IPMI user data file"); - } - Json jsonUsersTbl = Json::array(); // user index 0 is reserved, starts with 1 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) @@ -1099,6 +1319,12 @@ void UserAccess::writeUserData() std::vector<bool> ipmiEnabled(ipmiMaxChannels); std::vector<bool> linkAuthEnabled(ipmiMaxChannels); std::vector<bool> accessCallback(ipmiMaxChannels); + + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte> + stdPayload; + std::array<std::array<bool, ipmiMaxChannels>, payloadsPerByte> + oemPayload; + for (size_t chIndex = 0; chIndex < ipmiMaxChannels; chIndex++) { privilege[chIndex] = @@ -1118,12 +1344,35 @@ void UserAccess::writeUserData() jsonUserInfo[jsonUserEnabled] = usersTbl.user[usrIndex].userEnabled; jsonUserInfo[jsonUserInSys] = usersTbl.user[usrIndex].userInSystem; jsonUserInfo[jsonFixedUser] = usersTbl.user[usrIndex].fixedUserName; + + readPayloadAccessFromUserInfo(usersTbl.user[usrIndex], stdPayload, + oemPayload); + Json jsonPayloadEnabledInfo = + constructJsonPayloadEnables(stdPayload, oemPayload); + jsonUserInfo[payloadEnabledStr] = jsonPayloadEnabledInfo; + jsonUsersTbl.push_back(jsonUserInfo); } - oUsrData << jsonUsersTbl; - oUsrData.flush(); - oUsrData.close(); + static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"}; + int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) + { + log<level::ERR>("Error in creating temporary IPMI user data file"); + throw std::ios_base::failure( + "Error in creating temporary IPMI user data file"); + } + const auto& writeStr = jsonUsersTbl.dump(); + if (write(fd, writeStr.c_str(), writeStr.size()) != + static_cast<ssize_t>(writeStr.size())) + { + close(fd); + log<level::ERR>("Error in writing temporary IPMI user data file"); + throw std::ios_base::failure( + "Error in writing temporary IPMI user data file"); + } + close(fd); if (std::rename(tmpFile.c_str(), ipmiUserDataFile) != 0) { @@ -1252,13 +1501,11 @@ void UserAccess::getSystemPrivAndGroups() auto key = t.first; if (key == allPrivProperty) { - availablePrivileges = - variant_ns::get<std::vector<std::string>>(t.second); + availablePrivileges = std::get<std::vector<std::string>>(t.second); } else if (key == allGrpProperty) { - availableGroups = - variant_ns::get<std::vector<std::string>>(t.second); + availableGroups = std::get<std::vector<std::string>>(t.second); } } // TODO: Implement Supported Privilege & Groups verification logic @@ -1285,15 +1532,15 @@ void UserAccess::getUserProperties(const DbusUserObjProperties& properties, std::string key = t.first; if (key == userPrivProperty) { - usrPriv = variant_ns::get<std::string>(t.second); + usrPriv = std::get<std::string>(t.second); } else if (key == userGrpProperty) { - usrGrps = variant_ns::get<std::vector<std::string>>(t.second); + usrGrps = std::get<std::vector<std::string>>(t.second); } else if (key == userEnabledProperty) { - usrEnabled = variant_ns::get<bool>(t.second); + usrEnabled = std::get<bool>(t.second); } } return; @@ -1312,7 +1559,7 @@ int UserAccess::getUserObjProperties(const DbusUserObjValue& userObjs, return -EIO; } -void UserAccess::initUserDataFile() +void UserAccess::cacheUserDataFile() { boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> userLock{*userMutex}; @@ -1331,10 +1578,49 @@ void UserAccess::initUserDataFile() { usersTbl.user[userIndex].userPrivAccess[chIndex].privilege = privNoAccess; + usersTbl.user[userIndex] + .payloadAccess[chIndex] + .stdPayloadEnables1[static_cast<uint8_t>( + ipmi::PayloadType::SOL)] = true; } } writeUserData(); } + sigHndlrLock = boost::interprocess::file_lock(ipmiUserDataFile); + // Register it for single object and single process either netipimd / + // host-ipmid + if (userUpdatedSignal == nullptr && sigHndlrLock.try_lock()) + { + log<level::DEBUG>("Registering signal handler"); + userUpdatedSignal = std::make_unique<sdbusplus::bus::match_t>( + bus, + sdbusplus::bus::match::rules::type::signal() + + sdbusplus::bus::match::rules::interface(dBusObjManager) + + sdbusplus::bus::match::rules::path(userMgrObjBasePath), + [&](sdbusplus::message::message& msg) { + userUpdatedSignalHandler(*this, msg); + }); + userMgrRenamedSignal = std::make_unique<sdbusplus::bus::match_t>( + bus, + sdbusplus::bus::match::rules::type::signal() + + sdbusplus::bus::match::rules::interface(userMgrInterface) + + sdbusplus::bus::match::rules::path(userMgrObjBasePath), + [&](sdbusplus::message::message& msg) { + userUpdatedSignalHandler(*this, msg); + }); + userPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>( + bus, + sdbusplus::bus::match::rules::type::signal() + + sdbusplus::bus::match::rules::path_namespace(userObjBasePath) + + sdbusplus::bus::match::rules::interface( + dBusPropertiesInterface) + + sdbusplus::bus::match::rules::member(propertiesChangedSignal) + + sdbusplus::bus::match::rules::argN(0, usersInterface), + [&](sdbusplus::message::message& msg) { + userUpdatedSignalHandler(*this, msg); + }); + signalHndlrObject = true; + } std::map<DbusUserObjPath, DbusUserObjValue> managedObjs; try { @@ -1351,7 +1637,7 @@ void UserAccess::initUserDataFile() entry("PATH=%s", userMgrObjBasePath)); return; } - + bool updateRequired = false; UsersTbl* userData = &usersTbl; // user index 0 is reserved, starts with 1 for (size_t usrIdx = 1; usrIdx <= ipmiMaxUsers; ++usrIdx) @@ -1361,7 +1647,6 @@ void UserAccess::initUserDataFile() { std::vector<std::string> usrGrps; std::string usrPriv; - bool usrEnabled; std::string userName( reinterpret_cast<char*>(userData->user[usrIdx].userName), 0, @@ -1372,12 +1657,15 @@ void UserAccess::initUserDataFile() auto usrObj = managedObjs.find(usersPath); if (usrObj != managedObjs.end()) { + bool usrEnabled = false; + // User exist. Lets check and update other fileds getUserObjProperties(usrObj->second, usrGrps, usrPriv, usrEnabled); if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) == usrGrps.end()) { + updateRequired = true; // Group "ipmi" is removed so lets remove user in IPMI deleteUserIndex(usrIdx); } @@ -1393,6 +1681,7 @@ void UserAccess::initUserDataFile() .userPrivAccess[getUsrMgmtSyncIndex()] .privilege != priv) { + updateRequired = true; for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) { @@ -1403,6 +1692,7 @@ void UserAccess::initUserDataFile() } if (userData->user[usrIdx].userEnabled != usrEnabled) { + updateRequired = true; userData->user[usrIdx].userEnabled = usrEnabled; } } @@ -1412,6 +1702,7 @@ void UserAccess::initUserDataFile() } else { + updateRequired = true; deleteUserIndex(usrIdx); } } @@ -1423,7 +1714,7 @@ void UserAccess::initUserDataFile() { std::vector<std::string> usrGrps; std::string usrPriv, userName; - bool usrEnabled; + bool usrEnabled = false; std::string usrObjPath = std::string(usrObj.first); if (getUserNameFromPath(usrObj.first.str, userName) != 0) { @@ -1435,6 +1726,7 @@ void UserAccess::initUserDataFile() if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) != usrGrps.end()) { + updateRequired = true; // CREATE NEW USER if (true != addUserEntry(userName, usrPriv, usrEnabled)) { @@ -1443,8 +1735,11 @@ void UserAccess::initUserDataFile() } } - // All userData slots update done. Lets write the data - writeUserData(); + if (updateRequired) + { + // All userData slots update done. Lets write the data + writeUserData(); + } return; } |