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