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