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