1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #include "user_mgmt.hpp" 17 18 #include "apphandler.hpp" 19 20 #include <sys/stat.h> 21 #include <unistd.h> 22 23 #include <boost/interprocess/sync/named_recursive_mutex.hpp> 24 #include <boost/interprocess/sync/scoped_lock.hpp> 25 #include <cerrno> 26 #include <fstream> 27 #include <host-ipmid/ipmid-host-cmd.hpp> 28 #include <nlohmann/json.hpp> 29 #include <phosphor-logging/elog-errors.hpp> 30 #include <phosphor-logging/log.hpp> 31 #include <regex> 32 #include <sdbusplus/bus/match.hpp> 33 #include <sdbusplus/server/object.hpp> 34 #include <xyz/openbmc_project/Common/error.hpp> 35 #include <xyz/openbmc_project/User/Common/error.hpp> 36 37 namespace ipmi 38 { 39 40 // TODO: Move D-Bus & Object Manager related stuff, to common files 41 // D-Bus property related 42 static constexpr const char* dBusPropertiesInterface = 43 "org.freedesktop.DBus.Properties"; 44 static constexpr const char* getAllPropertiesMethod = "GetAll"; 45 static constexpr const char* propertiesChangedSignal = "PropertiesChanged"; 46 static constexpr const char* setPropertiesMethod = "Set"; 47 48 // Object Manager related 49 static constexpr const char* dBusObjManager = 50 "org.freedesktop.DBus.ObjectManager"; 51 static constexpr const char* getManagedObjectsMethod = "GetManagedObjects"; 52 // Object Manager signals 53 static constexpr const char* intfAddedSignal = "InterfacesAdded"; 54 static constexpr const char* intfRemovedSignal = "InterfacesRemoved"; 55 56 // Object Mapper related 57 static constexpr const char* objMapperService = 58 "xyz.openbmc_project.ObjectMapper"; 59 static constexpr const char* objMapperPath = 60 "/xyz/openbmc_project/object_mapper"; 61 static constexpr const char* objMapperInterface = 62 "xyz.openbmc_project.ObjectMapper"; 63 static constexpr const char* getSubTreeMethod = "GetSubTree"; 64 static constexpr const char* getObjectMethod = "GetObject"; 65 66 static constexpr const char* ipmiUserMutex = "ipmi_usr_mutex"; 67 static constexpr const char* ipmiMutexCleanupLockFile = 68 "/var/lib/ipmi/ipmi_usr_mutex_cleanup"; 69 static constexpr const char* ipmiUserDataFile = "/var/lib/ipmi/ipmi_user.json"; 70 static constexpr const char* ipmiGrpName = "ipmi"; 71 static constexpr size_t privNoAccess = 0xF; 72 static constexpr size_t privMask = 0xF; 73 74 // User manager related 75 static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user"; 76 static constexpr const char* userObjBasePath = "/xyz/openbmc_project/user"; 77 static constexpr const char* userMgrInterface = 78 "xyz.openbmc_project.User.Manager"; 79 static constexpr const char* usersInterface = 80 "xyz.openbmc_project.User.Attributes"; 81 static constexpr const char* deleteUserInterface = 82 "xyz.openbmc_project.Object.Delete"; 83 84 static constexpr const char* createUserMethod = "CreateUser"; 85 static constexpr const char* deleteUserMethod = "Delete"; 86 static constexpr const char* renameUserMethod = "RenameUser"; 87 // User manager signal memebers 88 static constexpr const char* userRenamedSignal = "UserRenamed"; 89 // Mgr interface properties 90 static constexpr const char* allPrivProperty = "AllPrivileges"; 91 static constexpr const char* allGrpProperty = "AllGroups"; 92 // User interface properties 93 static constexpr const char* userPrivProperty = "UserPrivilege"; 94 static constexpr const char* userGrpProperty = "UserGroups"; 95 static constexpr const char* userEnabledProperty = "UserEnabled"; 96 97 static std::array<std::string, (PRIVILEGE_OEM + 1)> ipmiPrivIndex = { 98 "priv-reserved", // PRIVILEGE_RESERVED - 0 99 "priv-callback", // PRIVILEGE_CALLBACK - 1 100 "priv-user", // PRIVILEGE_USER - 2 101 "priv-operator", // PRIVILEGE_OPERATOR - 3 102 "priv-admin", // PRIVILEGE_ADMIN - 4 103 "priv-custom" // PRIVILEGE_OEM - 5 104 }; 105 106 namespace variant_ns = sdbusplus::message::variant_ns; 107 108 using namespace phosphor::logging; 109 using Json = nlohmann::json; 110 111 using PrivAndGroupType = 112 sdbusplus::message::variant<std::string, std::vector<std::string>>; 113 114 using NoResource = 115 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource; 116 117 using InternalFailure = 118 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 119 120 std::unique_ptr<sdbusplus::bus::match_t> userUpdatedSignal(nullptr); 121 std::unique_ptr<sdbusplus::bus::match_t> userMgrRenamedSignal(nullptr); 122 std::unique_ptr<sdbusplus::bus::match_t> userPropertiesSignal(nullptr); 123 124 // TODO: Below code can be removed once it is moved to common layer libmiscutil 125 std::string getUserService(sdbusplus::bus::bus& bus, const std::string& intf, 126 const std::string& path) 127 { 128 auto mapperCall = bus.new_method_call(objMapperService, objMapperPath, 129 objMapperInterface, getObjectMethod); 130 131 mapperCall.append(path); 132 mapperCall.append(std::vector<std::string>({intf})); 133 134 auto mapperResponseMsg = bus.call(mapperCall); 135 136 std::map<std::string, std::vector<std::string>> mapperResponse; 137 mapperResponseMsg.read(mapperResponse); 138 139 if (mapperResponse.begin() == mapperResponse.end()) 140 { 141 throw sdbusplus::exception::SdBusError( 142 -EIO, "ERROR in reading the mapper response"); 143 } 144 145 return mapperResponse.begin()->first; 146 } 147 148 void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service, 149 const std::string& objPath, const std::string& interface, 150 const std::string& property, 151 const DbusUserPropVariant& value) 152 { 153 try 154 { 155 auto method = 156 bus.new_method_call(service.c_str(), objPath.c_str(), 157 dBusPropertiesInterface, setPropertiesMethod); 158 method.append(interface, property, value); 159 bus.call(method); 160 } 161 catch (const sdbusplus::exception::SdBusError& e) 162 { 163 log<level::ERR>("Failed to set property", 164 entry("PROPERTY=%s", property.c_str()), 165 entry("PATH=%s", objPath.c_str()), 166 entry("INTERFACE=%s", interface.c_str())); 167 throw; 168 } 169 } 170 171 static std::string getUserServiceName() 172 { 173 static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 174 static std::string userMgmtService; 175 if (userMgmtService.empty()) 176 { 177 try 178 { 179 userMgmtService = 180 ipmi::getUserService(bus, userMgrInterface, userMgrObjBasePath); 181 } 182 catch (const sdbusplus::exception::SdBusError& e) 183 { 184 userMgmtService.clear(); 185 } 186 } 187 return userMgmtService; 188 } 189 190 UserAccess& getUserAccessObject() 191 { 192 static UserAccess userAccess; 193 return userAccess; 194 } 195 196 int getUserNameFromPath(const std::string& path, std::string& userName) 197 { 198 static size_t pos = strlen(userObjBasePath) + 1; 199 if (path.find(userObjBasePath) == std::string::npos) 200 { 201 return -EINVAL; 202 } 203 userName.assign(path, pos, path.size()); 204 return 0; 205 } 206 207 void userUpdateHelper(UserAccess& usrAccess, const UserUpdateEvent& userEvent, 208 const std::string& userName, const std::string& priv, 209 const bool& enabled, const std::string& newUserName) 210 { 211 UsersTbl* userData = usrAccess.getUsersTblPtr(); 212 if (userEvent == UserUpdateEvent::userCreated) 213 { 214 if (usrAccess.addUserEntry(userName, priv, enabled) == false) 215 { 216 return; 217 } 218 } 219 else 220 { 221 // user index 0 is reserved, starts with 1 222 size_t usrIndex = 1; 223 for (; usrIndex <= ipmiMaxUsers; ++usrIndex) 224 { 225 std::string curName( 226 reinterpret_cast<char*>(userData->user[usrIndex].userName), 0, 227 ipmiMaxUserName); 228 if (userName == curName) 229 { 230 break; // found the entry 231 } 232 } 233 if (usrIndex > ipmiMaxUsers) 234 { 235 log<level::DEBUG>("User not found for signal", 236 entry("USER_NAME=%s", userName.c_str()), 237 entry("USER_EVENT=%d", userEvent)); 238 return; 239 } 240 switch (userEvent) 241 { 242 case UserUpdateEvent::userDeleted: 243 { 244 usrAccess.deleteUserIndex(usrIndex); 245 break; 246 } 247 case UserUpdateEvent::userPrivUpdated: 248 { 249 uint8_t userPriv = 250 static_cast<uint8_t>( 251 UserAccess::convertToIPMIPrivilege(priv)) & 252 privMask; 253 // Update all channels privileges, only if it is not equivalent 254 // to getUsrMgmtSyncIndex() 255 if (userData->user[usrIndex] 256 .userPrivAccess[UserAccess::getUsrMgmtSyncIndex()] 257 .privilege != userPriv) 258 { 259 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; 260 ++chIndex) 261 { 262 userData->user[usrIndex] 263 .userPrivAccess[chIndex] 264 .privilege = userPriv; 265 } 266 } 267 break; 268 } 269 case UserUpdateEvent::userRenamed: 270 { 271 std::fill( 272 static_cast<uint8_t*>(userData->user[usrIndex].userName), 273 static_cast<uint8_t*>(userData->user[usrIndex].userName) + 274 sizeof(userData->user[usrIndex].userName), 275 0); 276 std::strncpy( 277 reinterpret_cast<char*>(userData->user[usrIndex].userName), 278 newUserName.c_str(), ipmiMaxUserName); 279 ipmiRenameUserEntryPassword(userName, newUserName); 280 break; 281 } 282 case UserUpdateEvent::userStateUpdated: 283 { 284 userData->user[usrIndex].userEnabled = enabled; 285 break; 286 } 287 default: 288 { 289 log<level::ERR>("Unhandled user event", 290 entry("USER_EVENT=%d", userEvent)); 291 return; 292 } 293 } 294 } 295 usrAccess.writeUserData(); 296 log<level::DEBUG>("User event handled successfully", 297 entry("USER_NAME=%s", userName.c_str()), 298 entry("USER_EVENT=%d", userEvent)); 299 300 return; 301 } 302 303 void userUpdatedSignalHandler(UserAccess& usrAccess, 304 sdbusplus::message::message& msg) 305 { 306 static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 307 std::string signal = msg.get_member(); 308 std::string userName, update, priv, newUserName; 309 std::vector<std::string> groups; 310 bool enabled = false; 311 UserUpdateEvent userEvent = UserUpdateEvent::reservedEvent; 312 if (signal == intfAddedSignal) 313 { 314 DbusUserObjPath objPath; 315 DbusUserObjValue objValue; 316 msg.read(objPath, objValue); 317 getUserNameFromPath(objPath.str, userName); 318 if (usrAccess.getUserObjProperties(objValue, groups, priv, enabled) != 319 0) 320 { 321 return; 322 } 323 if (std::find(groups.begin(), groups.end(), ipmiGrpName) == 324 groups.end()) 325 { 326 return; 327 } 328 userEvent = UserUpdateEvent::userCreated; 329 } 330 else if (signal == intfRemovedSignal) 331 { 332 DbusUserObjPath objPath; 333 std::vector<std::string> interfaces; 334 msg.read(objPath, interfaces); 335 getUserNameFromPath(objPath.str, userName); 336 userEvent = UserUpdateEvent::userDeleted; 337 } 338 else if (signal == userRenamedSignal) 339 { 340 msg.read(userName, newUserName); 341 userEvent = UserUpdateEvent::userRenamed; 342 } 343 else if (signal == propertiesChangedSignal) 344 { 345 getUserNameFromPath(msg.get_path(), userName); 346 } 347 else 348 { 349 log<level::ERR>("Unknown user update signal", 350 entry("SIGNAL=%s", signal.c_str())); 351 return; 352 } 353 354 if (signal.empty() || userName.empty() || 355 (signal == userRenamedSignal && newUserName.empty())) 356 { 357 log<level::ERR>("Invalid inputs received"); 358 return; 359 } 360 361 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 362 userLock{*(usrAccess.userMutex)}; 363 usrAccess.checkAndReloadUserData(); 364 365 if (signal == propertiesChangedSignal) 366 { 367 std::string intfName; 368 DbusUserObjProperties chProperties; 369 msg.read(intfName, chProperties); // skip reading 3rd argument. 370 for (const auto& prop : chProperties) 371 { 372 userEvent = UserUpdateEvent::reservedEvent; 373 std::string member = prop.first; 374 if (member == userPrivProperty) 375 { 376 priv = variant_ns::get<std::string>(prop.second); 377 userEvent = UserUpdateEvent::userPrivUpdated; 378 } 379 else if (member == userGrpProperty) 380 { 381 groups = variant_ns::get<std::vector<std::string>>(prop.second); 382 userEvent = UserUpdateEvent::userGrpUpdated; 383 } 384 else if (member == userEnabledProperty) 385 { 386 enabled = variant_ns::get<bool>(prop.second); 387 userEvent = UserUpdateEvent::userStateUpdated; 388 } 389 // Process based on event type. 390 if (userEvent == UserUpdateEvent::userGrpUpdated) 391 { 392 if (std::find(groups.begin(), groups.end(), ipmiGrpName) == 393 groups.end()) 394 { 395 // remove user from ipmi user list. 396 userUpdateHelper(usrAccess, UserUpdateEvent::userDeleted, 397 userName, priv, enabled, newUserName); 398 } 399 else 400 { 401 DbusUserObjProperties properties; 402 try 403 { 404 auto method = bus.new_method_call( 405 getUserServiceName().c_str(), msg.get_path(), 406 dBusPropertiesInterface, getAllPropertiesMethod); 407 method.append(usersInterface); 408 auto reply = bus.call(method); 409 reply.read(properties); 410 } 411 catch (const sdbusplus::exception::SdBusError& e) 412 { 413 log<level::DEBUG>( 414 "Failed to excute method", 415 entry("METHOD=%s", getAllPropertiesMethod), 416 entry("PATH=%s", msg.get_path())); 417 return; 418 } 419 usrAccess.getUserProperties(properties, groups, priv, 420 enabled); 421 // add user to ipmi user list. 422 userUpdateHelper(usrAccess, UserUpdateEvent::userCreated, 423 userName, priv, enabled, newUserName); 424 } 425 } 426 else if (userEvent != UserUpdateEvent::reservedEvent) 427 { 428 userUpdateHelper(usrAccess, userEvent, userName, priv, enabled, 429 newUserName); 430 } 431 } 432 } 433 else if (userEvent != UserUpdateEvent::reservedEvent) 434 { 435 userUpdateHelper(usrAccess, userEvent, userName, priv, enabled, 436 newUserName); 437 } 438 return; 439 } 440 441 UserAccess::~UserAccess() 442 { 443 if (signalHndlrObject) 444 { 445 userUpdatedSignal.reset(); 446 userMgrRenamedSignal.reset(); 447 userPropertiesSignal.reset(); 448 sigHndlrLock.unlock(); 449 } 450 } 451 452 UserAccess::UserAccess() : bus(ipmid_get_sd_bus_connection()) 453 { 454 std::ofstream mutexCleanUpFile; 455 mutexCleanUpFile.open(ipmiMutexCleanupLockFile, 456 std::ofstream::out | std::ofstream::app); 457 if (!mutexCleanUpFile.good()) 458 { 459 log<level::DEBUG>("Unable to open mutex cleanup file"); 460 return; 461 } 462 mutexCleanUpFile.close(); 463 mutexCleanupLock = boost::interprocess::file_lock(ipmiMutexCleanupLockFile); 464 if (mutexCleanupLock.try_lock()) 465 { 466 boost::interprocess::named_recursive_mutex::remove(ipmiUserMutex); 467 } 468 mutexCleanupLock.lock_sharable(); 469 userMutex = std::make_unique<boost::interprocess::named_recursive_mutex>( 470 boost::interprocess::open_or_create, ipmiUserMutex); 471 472 initUserDataFile(); 473 getSystemPrivAndGroups(); 474 sigHndlrLock = boost::interprocess::file_lock(ipmiUserDataFile); 475 // Register it for single object and single process either netipimd / 476 // host-ipmid 477 if (userUpdatedSignal == nullptr && sigHndlrLock.try_lock()) 478 { 479 log<level::DEBUG>("Registering signal handler"); 480 userUpdatedSignal = std::make_unique<sdbusplus::bus::match_t>( 481 bus, 482 sdbusplus::bus::match::rules::type::signal() + 483 sdbusplus::bus::match::rules::interface(dBusObjManager) + 484 sdbusplus::bus::match::rules::path(userMgrObjBasePath), 485 [&](sdbusplus::message::message& msg) { 486 userUpdatedSignalHandler(*this, msg); 487 }); 488 userMgrRenamedSignal = std::make_unique<sdbusplus::bus::match_t>( 489 bus, 490 sdbusplus::bus::match::rules::type::signal() + 491 sdbusplus::bus::match::rules::interface(userMgrInterface) + 492 sdbusplus::bus::match::rules::path(userMgrObjBasePath), 493 [&](sdbusplus::message::message& msg) { 494 userUpdatedSignalHandler(*this, msg); 495 }); 496 userPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>( 497 bus, 498 sdbusplus::bus::match::rules::type::signal() + 499 sdbusplus::bus::match::rules::path_namespace(userObjBasePath) + 500 sdbusplus::bus::match::rules::interface( 501 dBusPropertiesInterface) + 502 sdbusplus::bus::match::rules::member(propertiesChangedSignal) + 503 sdbusplus::bus::match::rules::argN(0, usersInterface), 504 [&](sdbusplus::message::message& msg) { 505 userUpdatedSignalHandler(*this, msg); 506 }); 507 signalHndlrObject = true; 508 } 509 } 510 511 UserInfo* UserAccess::getUserInfo(const uint8_t userId) 512 { 513 checkAndReloadUserData(); 514 return &usersTbl.user[userId]; 515 } 516 517 void UserAccess::setUserInfo(const uint8_t userId, UserInfo* userInfo) 518 { 519 checkAndReloadUserData(); 520 std::copy(reinterpret_cast<uint8_t*>(userInfo), 521 reinterpret_cast<uint8_t*>(userInfo) + sizeof(*userInfo), 522 reinterpret_cast<uint8_t*>(&usersTbl.user[userId])); 523 writeUserData(); 524 } 525 526 bool UserAccess::isValidChannel(const uint8_t chNum) 527 { 528 return (chNum < ipmiMaxChannels); 529 } 530 531 bool UserAccess::isValidUserId(const uint8_t userId) 532 { 533 return ((userId <= ipmiMaxUsers) && (userId != reservedUserId)); 534 } 535 536 bool UserAccess::isValidPrivilege(const uint8_t priv) 537 { 538 return ((priv >= PRIVILEGE_CALLBACK && priv <= PRIVILEGE_OEM) || 539 priv == privNoAccess); 540 } 541 542 uint8_t UserAccess::getUsrMgmtSyncIndex() 543 { 544 // TODO: Need to get LAN1 channel number dynamically, 545 // which has to be in sync with system user privilege 546 // level(Phosphor-user-manager). Note: For time being chanLan1 is marked as 547 // sync index to the user-manager privilege.. 548 return static_cast<uint8_t>(EChannelID::chanLan1); 549 } 550 551 CommandPrivilege UserAccess::convertToIPMIPrivilege(const std::string& value) 552 { 553 auto iter = std::find(ipmiPrivIndex.begin(), ipmiPrivIndex.end(), value); 554 if (iter == ipmiPrivIndex.end()) 555 { 556 if (value == "") 557 { 558 return static_cast<CommandPrivilege>(privNoAccess); 559 } 560 log<level::ERR>("Error in converting to IPMI privilege", 561 entry("PRIV=%s", value.c_str())); 562 throw std::out_of_range("Out of range - convertToIPMIPrivilege"); 563 } 564 else 565 { 566 return static_cast<CommandPrivilege>( 567 std::distance(ipmiPrivIndex.begin(), iter)); 568 } 569 } 570 571 std::string UserAccess::convertToSystemPrivilege(const CommandPrivilege& value) 572 { 573 if (value == static_cast<CommandPrivilege>(privNoAccess)) 574 { 575 return ""; 576 } 577 try 578 { 579 return ipmiPrivIndex.at(value); 580 } 581 catch (const std::out_of_range& e) 582 { 583 log<level::ERR>("Error in converting to system privilege", 584 entry("PRIV=%d", static_cast<uint8_t>(value))); 585 throw std::out_of_range("Out of range - convertToSystemPrivilege"); 586 } 587 } 588 589 bool UserAccess::isValidUserName(const char* userNameInChar) 590 { 591 if (!userNameInChar) 592 { 593 log<level::ERR>("null ptr"); 594 return false; 595 } 596 std::string userName(userNameInChar, 0, ipmiMaxUserName); 597 if (!std::regex_match(userName.c_str(), 598 std::regex("[a-zA-z_][a-zA-Z_0-9]*"))) 599 { 600 log<level::ERR>("Unsupported characters in user name"); 601 return false; 602 } 603 if (userName == "root") 604 { 605 log<level::ERR>("Invalid user name - root"); 606 return false; 607 } 608 std::map<DbusUserObjPath, DbusUserObjValue> properties; 609 try 610 { 611 auto method = bus.new_method_call(getUserServiceName().c_str(), 612 userMgrObjBasePath, dBusObjManager, 613 getManagedObjectsMethod); 614 auto reply = bus.call(method); 615 reply.read(properties); 616 } 617 catch (const sdbusplus::exception::SdBusError& e) 618 { 619 log<level::ERR>("Failed to excute method", 620 entry("METHOD=%s", getSubTreeMethod), 621 entry("PATH=%s", userMgrObjBasePath)); 622 return false; 623 } 624 625 std::string usersPath = std::string(userObjBasePath) + "/" + userName; 626 if (properties.find(usersPath) != properties.end()) 627 { 628 log<level::DEBUG>("User name already exists", 629 entry("USER_NAME=%s", userName.c_str())); 630 return false; 631 } 632 633 return true; 634 } 635 636 ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t userId, 637 const bool& enabledState) 638 { 639 if (!isValidUserId(userId)) 640 { 641 return IPMI_CC_PARM_OUT_OF_RANGE; 642 } 643 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 644 userLock{*userMutex}; 645 UserInfo* userInfo = getUserInfo(userId); 646 std::string userName; 647 userName.assign(reinterpret_cast<char*>(userInfo->userName), 0, 648 ipmiMaxUserName); 649 if (userName.empty()) 650 { 651 log<level::DEBUG>("User name not set / invalid"); 652 return IPMI_CC_UNSPECIFIED_ERROR; 653 } 654 if (userInfo->userEnabled != enabledState) 655 { 656 std::string userPath = std::string(userObjBasePath) + "/" + userName; 657 setDbusProperty(bus, getUserServiceName().c_str(), userPath.c_str(), 658 usersInterface, userEnabledProperty, enabledState); 659 } 660 return IPMI_CC_OK; 661 } 662 663 ipmi_ret_t UserAccess::setUserPrivilegeAccess(const uint8_t userId, 664 const uint8_t chNum, 665 const UserPrivAccess& privAccess, 666 const bool& otherPrivUpdates) 667 { 668 if (!isValidChannel(chNum)) 669 { 670 return IPMI_CC_INVALID_FIELD_REQUEST; 671 } 672 if (!isValidUserId(userId)) 673 { 674 return IPMI_CC_PARM_OUT_OF_RANGE; 675 } 676 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 677 userLock{*userMutex}; 678 UserInfo* userInfo = getUserInfo(userId); 679 std::string userName; 680 userName.assign(reinterpret_cast<char*>(userInfo->userName), 0, 681 ipmiMaxUserName); 682 if (userName.empty()) 683 { 684 log<level::DEBUG>("User name not set / invalid"); 685 return IPMI_CC_UNSPECIFIED_ERROR; 686 } 687 std::string priv = convertToSystemPrivilege( 688 static_cast<CommandPrivilege>(privAccess.privilege)); 689 uint8_t syncIndex = getUsrMgmtSyncIndex(); 690 if (chNum == syncIndex && 691 privAccess.privilege != userInfo->userPrivAccess[syncIndex].privilege) 692 { 693 std::string userPath = std::string(userObjBasePath) + "/" + userName; 694 setDbusProperty(bus, getUserServiceName().c_str(), userPath.c_str(), 695 usersInterface, userPrivProperty, priv); 696 } 697 userInfo->userPrivAccess[chNum].privilege = privAccess.privilege; 698 699 if (otherPrivUpdates) 700 { 701 userInfo->userPrivAccess[chNum].ipmiEnabled = privAccess.ipmiEnabled; 702 userInfo->userPrivAccess[chNum].linkAuthEnabled = 703 privAccess.linkAuthEnabled; 704 userInfo->userPrivAccess[chNum].accessCallback = 705 privAccess.accessCallback; 706 } 707 try 708 { 709 writeUserData(); 710 } 711 catch (const std::exception& e) 712 { 713 log<level::DEBUG>("Write user data failed"); 714 return IPMI_CC_UNSPECIFIED_ERROR; 715 } 716 return IPMI_CC_OK; 717 } 718 719 uint8_t UserAccess::getUserId(const std::string& userName) 720 { 721 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 722 userLock{*userMutex}; 723 checkAndReloadUserData(); 724 // user index 0 is reserved, starts with 1 725 size_t usrIndex = 1; 726 for (; usrIndex <= ipmiMaxUsers; ++usrIndex) 727 { 728 std::string curName( 729 reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0, 730 ipmiMaxUserName); 731 if (userName == curName) 732 { 733 break; // found the entry 734 } 735 } 736 if (usrIndex > ipmiMaxUsers) 737 { 738 log<level::DEBUG>("User not found", 739 entry("USER_NAME=%s", userName.c_str())); 740 return invalidUserId; 741 } 742 743 return usrIndex; 744 } 745 746 ipmi_ret_t UserAccess::getUserName(const uint8_t userId, std::string& userName) 747 { 748 if (!isValidUserId(userId)) 749 { 750 return IPMI_CC_PARM_OUT_OF_RANGE; 751 } 752 UserInfo* userInfo = getUserInfo(userId); 753 userName.assign(reinterpret_cast<char*>(userInfo->userName), 0, 754 ipmiMaxUserName); 755 return IPMI_CC_OK; 756 } 757 758 ipmi_ret_t UserAccess::setUserName(const uint8_t userId, 759 const char* userNameInChar) 760 { 761 if (!isValidUserId(userId)) 762 { 763 return IPMI_CC_PARM_OUT_OF_RANGE; 764 } 765 766 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 767 userLock{*userMutex}; 768 std::string oldUser; 769 getUserName(userId, oldUser); 770 771 std::string newUser(userNameInChar, 0, ipmiMaxUserName); 772 if (oldUser == newUser) 773 { 774 // requesting to set the same user name, return success. 775 return IPMI_CC_OK; 776 } 777 bool validUser = isValidUserName(userNameInChar); 778 UserInfo* userInfo = getUserInfo(userId); 779 if (newUser.empty() && !oldUser.empty()) 780 { 781 // Delete existing user 782 std::string userPath = std::string(userObjBasePath) + "/" + oldUser; 783 try 784 { 785 auto method = bus.new_method_call( 786 getUserServiceName().c_str(), userPath.c_str(), 787 deleteUserInterface, deleteUserMethod); 788 auto reply = bus.call(method); 789 } 790 catch (const sdbusplus::exception::SdBusError& e) 791 { 792 log<level::DEBUG>("Failed to excute method", 793 entry("METHOD=%s", deleteUserMethod), 794 entry("PATH=%s", userPath.c_str())); 795 return IPMI_CC_UNSPECIFIED_ERROR; 796 } 797 deleteUserIndex(userId); 798 } 799 else if (oldUser.empty() && !newUser.empty() && validUser) 800 { 801 try 802 { 803 // Create new user 804 auto method = bus.new_method_call( 805 getUserServiceName().c_str(), userMgrObjBasePath, 806 userMgrInterface, createUserMethod); 807 method.append(newUser.c_str(), availableGroups, "", false); 808 auto reply = bus.call(method); 809 } 810 catch (const sdbusplus::exception::SdBusError& e) 811 { 812 log<level::DEBUG>("Failed to excute method", 813 entry("METHOD=%s", createUserMethod), 814 entry("PATH=%s", userMgrObjBasePath)); 815 return IPMI_CC_UNSPECIFIED_ERROR; 816 } 817 std::memcpy(userInfo->userName, userNameInChar, ipmiMaxUserName); 818 userInfo->userInSystem = true; 819 } 820 else if (oldUser != newUser && validUser) 821 { 822 try 823 { 824 // User rename 825 auto method = bus.new_method_call( 826 getUserServiceName().c_str(), userMgrObjBasePath, 827 userMgrInterface, renameUserMethod); 828 method.append(oldUser.c_str(), newUser.c_str()); 829 auto reply = bus.call(method); 830 } 831 catch (const sdbusplus::exception::SdBusError& e) 832 { 833 log<level::DEBUG>("Failed to excute method", 834 entry("METHOD=%s", renameUserMethod), 835 entry("PATH=%s", userMgrObjBasePath)); 836 return IPMI_CC_UNSPECIFIED_ERROR; 837 } 838 std::fill(static_cast<uint8_t*>(userInfo->userName), 839 static_cast<uint8_t*>(userInfo->userName) + 840 sizeof(userInfo->userName), 841 0); 842 std::memcpy(userInfo->userName, userNameInChar, ipmiMaxUserName); 843 ipmiRenameUserEntryPassword(oldUser, newUser); 844 userInfo->userInSystem = true; 845 } 846 else if (!validUser) 847 { 848 return IPMI_CC_INVALID_FIELD_REQUEST; 849 } 850 try 851 { 852 writeUserData(); 853 } 854 catch (const std::exception& e) 855 { 856 log<level::DEBUG>("Write user data failed"); 857 return IPMI_CC_UNSPECIFIED_ERROR; 858 } 859 return IPMI_CC_OK; 860 } 861 862 static constexpr const char* jsonUserName = "user_name"; 863 static constexpr const char* jsonPriv = "privilege"; 864 static constexpr const char* jsonIpmiEnabled = "ipmi_enabled"; 865 static constexpr const char* jsonLinkAuthEnabled = "link_auth_enabled"; 866 static constexpr const char* jsonAccCallbk = "access_callback"; 867 static constexpr const char* jsonUserEnabled = "user_enabled"; 868 static constexpr const char* jsonUserInSys = "user_in_system"; 869 static constexpr const char* jsonFixedUser = "fixed_user_name"; 870 871 void UserAccess::readUserData() 872 { 873 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 874 userLock{*userMutex}; 875 876 std::ifstream iUsrData(ipmiUserDataFile, std::ios::in | std::ios::binary); 877 if (!iUsrData.good()) 878 { 879 log<level::ERR>("Error in reading IPMI user data file"); 880 throw std::ios_base::failure("Error opening IPMI user data file"); 881 } 882 883 Json jsonUsersTbl = Json::array(); 884 jsonUsersTbl = Json::parse(iUsrData, nullptr, false); 885 886 if (jsonUsersTbl.size() != ipmiMaxUsers) 887 { 888 log<level::ERR>( 889 "Error in reading IPMI user data file - User count issues"); 890 throw std::runtime_error( 891 "Corrupted IPMI user data file - invalid user count"); 892 } 893 // user index 0 is reserved, starts with 1 894 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) 895 { 896 Json userInfo = jsonUsersTbl[usrIndex - 1]; // json array starts with 0. 897 if (userInfo.is_null()) 898 { 899 log<level::ERR>("Error in reading IPMI user data file - " 900 "user info corrupted"); 901 throw std::runtime_error( 902 "Corrupted IPMI user data file - invalid user info"); 903 } 904 std::string userName = userInfo[jsonUserName].get<std::string>(); 905 std::strncpy(reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 906 userName.c_str(), ipmiMaxUserName); 907 908 std::vector<std::string> privilege = 909 userInfo[jsonPriv].get<std::vector<std::string>>(); 910 std::vector<bool> ipmiEnabled = 911 userInfo[jsonIpmiEnabled].get<std::vector<bool>>(); 912 std::vector<bool> linkAuthEnabled = 913 userInfo[jsonLinkAuthEnabled].get<std::vector<bool>>(); 914 std::vector<bool> accessCallback = 915 userInfo[jsonAccCallbk].get<std::vector<bool>>(); 916 if (privilege.size() != ipmiMaxChannels || 917 ipmiEnabled.size() != ipmiMaxChannels || 918 linkAuthEnabled.size() != ipmiMaxChannels || 919 accessCallback.size() != ipmiMaxChannels) 920 { 921 log<level::ERR>("Error in reading IPMI user data file - " 922 "properties corrupted"); 923 throw std::runtime_error( 924 "Corrupted IPMI user data file - properties"); 925 } 926 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) 927 { 928 usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege = 929 static_cast<uint8_t>( 930 convertToIPMIPrivilege(privilege[chIndex])); 931 usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled = 932 ipmiEnabled[chIndex]; 933 usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled = 934 linkAuthEnabled[chIndex]; 935 usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback = 936 accessCallback[chIndex]; 937 } 938 usersTbl.user[usrIndex].userEnabled = 939 userInfo[jsonUserEnabled].get<bool>(); 940 usersTbl.user[usrIndex].userInSystem = 941 userInfo[jsonUserInSys].get<bool>(); 942 usersTbl.user[usrIndex].fixedUserName = 943 userInfo[jsonFixedUser].get<bool>(); 944 } 945 946 log<level::DEBUG>("User data read from IPMI data file"); 947 iUsrData.close(); 948 // Update the timestamp 949 fileLastUpdatedTime = getUpdatedFileTime(); 950 return; 951 } 952 953 void UserAccess::writeUserData() 954 { 955 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 956 userLock{*userMutex}; 957 958 static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"}; 959 std::ofstream oUsrData(tmpFile, std::ios::out | std::ios::binary); 960 if (!oUsrData.good()) 961 { 962 log<level::ERR>("Error in creating temporary IPMI user data file"); 963 throw std::ios_base::failure( 964 "Error in creating temporary IPMI user data file"); 965 } 966 967 Json jsonUsersTbl = Json::array(); 968 // user index 0 is reserved, starts with 1 969 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) 970 { 971 Json jsonUserInfo; 972 jsonUserInfo[jsonUserName] = std::string( 973 reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0, 974 ipmiMaxUserName); 975 std::vector<std::string> privilege(ipmiMaxChannels); 976 std::vector<bool> ipmiEnabled(ipmiMaxChannels); 977 std::vector<bool> linkAuthEnabled(ipmiMaxChannels); 978 std::vector<bool> accessCallback(ipmiMaxChannels); 979 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; chIndex++) 980 { 981 privilege[chIndex] = 982 convertToSystemPrivilege(static_cast<CommandPrivilege>( 983 usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege)); 984 ipmiEnabled[chIndex] = 985 usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled; 986 linkAuthEnabled[chIndex] = 987 usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled; 988 accessCallback[chIndex] = 989 usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback; 990 } 991 jsonUserInfo[jsonPriv] = privilege; 992 jsonUserInfo[jsonIpmiEnabled] = ipmiEnabled; 993 jsonUserInfo[jsonLinkAuthEnabled] = linkAuthEnabled; 994 jsonUserInfo[jsonAccCallbk] = accessCallback; 995 jsonUserInfo[jsonUserEnabled] = usersTbl.user[usrIndex].userEnabled; 996 jsonUserInfo[jsonUserInSys] = usersTbl.user[usrIndex].userInSystem; 997 jsonUserInfo[jsonFixedUser] = usersTbl.user[usrIndex].fixedUserName; 998 jsonUsersTbl.push_back(jsonUserInfo); 999 } 1000 1001 oUsrData << jsonUsersTbl; 1002 oUsrData.flush(); 1003 oUsrData.close(); 1004 1005 if (std::rename(tmpFile.c_str(), ipmiUserDataFile) != 0) 1006 { 1007 log<level::ERR>("Error in renaming temporary IPMI user data file"); 1008 throw std::runtime_error("Error in renaming IPMI user data file"); 1009 } 1010 // Update the timestamp 1011 fileLastUpdatedTime = getUpdatedFileTime(); 1012 return; 1013 } 1014 1015 bool UserAccess::addUserEntry(const std::string& userName, 1016 const std::string& sysPriv, const bool& enabled) 1017 { 1018 UsersTbl* userData = getUsersTblPtr(); 1019 size_t freeIndex = 0xFF; 1020 // user index 0 is reserved, starts with 1 1021 for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex) 1022 { 1023 std::string curName( 1024 reinterpret_cast<char*>(userData->user[usrIndex].userName), 0, 1025 ipmiMaxUserName); 1026 if (userName == curName) 1027 { 1028 log<level::DEBUG>("User name exists", 1029 entry("USER_NAME=%s", userName.c_str())); 1030 return false; // user name exists. 1031 } 1032 1033 if ((!userData->user[usrIndex].userInSystem) && 1034 (userData->user[usrIndex].userName[0] == '\0') && 1035 (freeIndex == 0xFF)) 1036 { 1037 freeIndex = usrIndex; 1038 } 1039 } 1040 if (freeIndex == 0xFF) 1041 { 1042 log<level::ERR>("No empty slots found"); 1043 return false; 1044 } 1045 std::strncpy(reinterpret_cast<char*>(userData->user[freeIndex].userName), 1046 userName.c_str(), ipmiMaxUserName); 1047 uint8_t priv = 1048 static_cast<uint8_t>(UserAccess::convertToIPMIPrivilege(sysPriv)) & 1049 privMask; 1050 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) 1051 { 1052 userData->user[freeIndex].userPrivAccess[chIndex].privilege = priv; 1053 userData->user[freeIndex].userPrivAccess[chIndex].ipmiEnabled = true; 1054 userData->user[freeIndex].userPrivAccess[chIndex].linkAuthEnabled = 1055 true; 1056 userData->user[freeIndex].userPrivAccess[chIndex].accessCallback = true; 1057 } 1058 userData->user[freeIndex].userInSystem = true; 1059 userData->user[freeIndex].userEnabled = enabled; 1060 1061 return true; 1062 } 1063 1064 void UserAccess::deleteUserIndex(const size_t& usrIdx) 1065 { 1066 UsersTbl* userData = getUsersTblPtr(); 1067 1068 std::string userName( 1069 reinterpret_cast<char*>(userData->user[usrIdx].userName), 0, 1070 ipmiMaxUserName); 1071 ipmiClearUserEntryPassword(userName); 1072 std::fill(static_cast<uint8_t*>(userData->user[usrIdx].userName), 1073 static_cast<uint8_t*>(userData->user[usrIdx].userName) + 1074 sizeof(userData->user[usrIdx].userName), 1075 0); 1076 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) 1077 { 1078 userData->user[usrIdx].userPrivAccess[chIndex].privilege = privNoAccess; 1079 userData->user[usrIdx].userPrivAccess[chIndex].ipmiEnabled = false; 1080 userData->user[usrIdx].userPrivAccess[chIndex].linkAuthEnabled = false; 1081 userData->user[usrIdx].userPrivAccess[chIndex].accessCallback = false; 1082 } 1083 userData->user[usrIdx].userInSystem = false; 1084 userData->user[usrIdx].userEnabled = false; 1085 return; 1086 } 1087 1088 void UserAccess::checkAndReloadUserData() 1089 { 1090 std::time_t updateTime = getUpdatedFileTime(); 1091 if (updateTime != fileLastUpdatedTime || updateTime == -EIO) 1092 { 1093 std::fill(reinterpret_cast<uint8_t*>(&usersTbl), 1094 reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0); 1095 readUserData(); 1096 } 1097 return; 1098 } 1099 1100 UsersTbl* UserAccess::getUsersTblPtr() 1101 { 1102 // reload data before using it. 1103 checkAndReloadUserData(); 1104 return &usersTbl; 1105 } 1106 1107 void UserAccess::getSystemPrivAndGroups() 1108 { 1109 std::map<std::string, PrivAndGroupType> properties; 1110 try 1111 { 1112 auto method = bus.new_method_call( 1113 getUserServiceName().c_str(), userMgrObjBasePath, 1114 dBusPropertiesInterface, getAllPropertiesMethod); 1115 method.append(userMgrInterface); 1116 1117 auto reply = bus.call(method); 1118 reply.read(properties); 1119 } 1120 catch (const sdbusplus::exception::SdBusError& e) 1121 { 1122 log<level::DEBUG>("Failed to excute method", 1123 entry("METHOD=%s", getAllPropertiesMethod), 1124 entry("PATH=%s", userMgrObjBasePath)); 1125 return; 1126 } 1127 for (const auto& t : properties) 1128 { 1129 auto key = t.first; 1130 if (key == allPrivProperty) 1131 { 1132 availablePrivileges = 1133 variant_ns::get<std::vector<std::string>>(t.second); 1134 } 1135 else if (key == allGrpProperty) 1136 { 1137 availableGroups = 1138 variant_ns::get<std::vector<std::string>>(t.second); 1139 } 1140 } 1141 // TODO: Implement Supported Privilege & Groups verification logic 1142 return; 1143 } 1144 1145 std::time_t UserAccess::getUpdatedFileTime() 1146 { 1147 struct stat fileStat; 1148 if (stat(ipmiUserDataFile, &fileStat) != 0) 1149 { 1150 log<level::DEBUG>("Error in getting last updated time stamp"); 1151 return -EIO; 1152 } 1153 return fileStat.st_mtime; 1154 } 1155 1156 void UserAccess::getUserProperties(const DbusUserObjProperties& properties, 1157 std::vector<std::string>& usrGrps, 1158 std::string& usrPriv, bool& usrEnabled) 1159 { 1160 for (const auto& t : properties) 1161 { 1162 std::string key = t.first; 1163 if (key == userPrivProperty) 1164 { 1165 usrPriv = variant_ns::get<std::string>(t.second); 1166 } 1167 else if (key == userGrpProperty) 1168 { 1169 usrGrps = variant_ns::get<std::vector<std::string>>(t.second); 1170 } 1171 else if (key == userEnabledProperty) 1172 { 1173 usrEnabled = variant_ns::get<bool>(t.second); 1174 } 1175 } 1176 return; 1177 } 1178 1179 int UserAccess::getUserObjProperties(const DbusUserObjValue& userObjs, 1180 std::vector<std::string>& usrGrps, 1181 std::string& usrPriv, bool& usrEnabled) 1182 { 1183 auto usrObj = userObjs.find(usersInterface); 1184 if (usrObj != userObjs.end()) 1185 { 1186 getUserProperties(usrObj->second, usrGrps, usrPriv, usrEnabled); 1187 return 0; 1188 } 1189 return -EIO; 1190 } 1191 1192 void UserAccess::initUserDataFile() 1193 { 1194 boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex> 1195 userLock{*userMutex}; 1196 try 1197 { 1198 readUserData(); 1199 } 1200 catch (const std::ios_base::failure& e) 1201 { // File is empty, create it for the first time 1202 std::fill(reinterpret_cast<uint8_t*>(&usersTbl), 1203 reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0); 1204 // user index 0 is reserved, starts with 1 1205 for (size_t userIndex = 1; userIndex <= ipmiMaxUsers; ++userIndex) 1206 { 1207 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex) 1208 { 1209 usersTbl.user[userIndex].userPrivAccess[chIndex].privilege = 1210 privNoAccess; 1211 } 1212 } 1213 writeUserData(); 1214 } 1215 std::map<DbusUserObjPath, DbusUserObjValue> managedObjs; 1216 try 1217 { 1218 auto method = bus.new_method_call(getUserServiceName().c_str(), 1219 userMgrObjBasePath, dBusObjManager, 1220 getManagedObjectsMethod); 1221 auto reply = bus.call(method); 1222 reply.read(managedObjs); 1223 } 1224 catch (const sdbusplus::exception::SdBusError& e) 1225 { 1226 log<level::DEBUG>("Failed to excute method", 1227 entry("METHOD=%s", getSubTreeMethod), 1228 entry("PATH=%s", userMgrObjBasePath)); 1229 return; 1230 } 1231 1232 UsersTbl* userData = &usersTbl; 1233 // user index 0 is reserved, starts with 1 1234 for (size_t usrIdx = 1; usrIdx <= ipmiMaxUsers; ++usrIdx) 1235 { 1236 if ((userData->user[usrIdx].userInSystem) && 1237 (userData->user[usrIdx].userName[0] != '\0')) 1238 { 1239 std::vector<std::string> usrGrps; 1240 std::string usrPriv; 1241 bool usrEnabled; 1242 1243 std::string userName( 1244 reinterpret_cast<char*>(userData->user[usrIdx].userName), 0, 1245 ipmiMaxUserName); 1246 std::string usersPath = 1247 std::string(userObjBasePath) + "/" + userName; 1248 1249 auto usrObj = managedObjs.find(usersPath); 1250 if (usrObj != managedObjs.end()) 1251 { 1252 // User exist. Lets check and update other fileds 1253 getUserObjProperties(usrObj->second, usrGrps, usrPriv, 1254 usrEnabled); 1255 if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) == 1256 usrGrps.end()) 1257 { 1258 // Group "ipmi" is removed so lets remove user in IPMI 1259 deleteUserIndex(usrIdx); 1260 } 1261 else 1262 { 1263 // Group "ipmi" is present so lets update other properties 1264 // in IPMI 1265 uint8_t priv = 1266 UserAccess::convertToIPMIPrivilege(usrPriv) & privMask; 1267 // Update all channels priv, only if it is not equivalent to 1268 // getUsrMgmtSyncIndex() 1269 if (userData->user[usrIdx] 1270 .userPrivAccess[getUsrMgmtSyncIndex()] 1271 .privilege != priv) 1272 { 1273 for (size_t chIndex = 0; chIndex < ipmiMaxChannels; 1274 ++chIndex) 1275 { 1276 userData->user[usrIdx] 1277 .userPrivAccess[chIndex] 1278 .privilege = priv; 1279 } 1280 } 1281 if (userData->user[usrIdx].userEnabled != usrEnabled) 1282 { 1283 userData->user[usrIdx].userEnabled = usrEnabled; 1284 } 1285 } 1286 1287 // We are done with this obj. lets delete from MAP 1288 managedObjs.erase(usrObj); 1289 } 1290 else 1291 { 1292 deleteUserIndex(usrIdx); 1293 } 1294 } 1295 } 1296 1297 // Walk through remnaining managedObj users list 1298 // Add them to ipmi data base 1299 for (const auto& usrObj : managedObjs) 1300 { 1301 std::vector<std::string> usrGrps; 1302 std::string usrPriv, userName; 1303 bool usrEnabled; 1304 std::string usrObjPath = std::string(usrObj.first); 1305 if (getUserNameFromPath(usrObj.first.str, userName) != 0) 1306 { 1307 log<level::ERR>("Error in user object path"); 1308 continue; 1309 } 1310 getUserObjProperties(usrObj.second, usrGrps, usrPriv, usrEnabled); 1311 // Add 'ipmi' group users 1312 if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) != 1313 usrGrps.end()) 1314 { 1315 // CREATE NEW USER 1316 if (true != addUserEntry(userName, usrPriv, usrEnabled)) 1317 { 1318 break; 1319 } 1320 } 1321 } 1322 1323 // All userData slots update done. Lets write the data 1324 writeUserData(); 1325 1326 return; 1327 } 1328 } // namespace ipmi 1329