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 <variant>
35 #include <xyz/openbmc_project/Common/error.hpp>
36 #include <xyz/openbmc_project/User/Common/error.hpp>
37 
38 namespace ipmi
39 {
40 
41 // TODO: Move D-Bus & Object Manager related stuff, to common files
42 // D-Bus property related
43 static constexpr const char* dBusPropertiesInterface =
44     "org.freedesktop.DBus.Properties";
45 static constexpr const char* getAllPropertiesMethod = "GetAll";
46 static constexpr const char* propertiesChangedSignal = "PropertiesChanged";
47 static constexpr const char* setPropertiesMethod = "Set";
48 
49 // Object Manager related
50 static constexpr const char* dBusObjManager =
51     "org.freedesktop.DBus.ObjectManager";
52 static constexpr const char* getManagedObjectsMethod = "GetManagedObjects";
53 // Object Manager signals
54 static constexpr const char* intfAddedSignal = "InterfacesAdded";
55 static constexpr const char* intfRemovedSignal = "InterfacesRemoved";
56 
57 // Object Mapper related
58 static constexpr const char* objMapperService =
59     "xyz.openbmc_project.ObjectMapper";
60 static constexpr const char* objMapperPath =
61     "/xyz/openbmc_project/object_mapper";
62 static constexpr const char* objMapperInterface =
63     "xyz.openbmc_project.ObjectMapper";
64 static constexpr const char* getSubTreeMethod = "GetSubTree";
65 static constexpr const char* getObjectMethod = "GetObject";
66 
67 static constexpr const char* ipmiUserMutex = "ipmi_usr_mutex";
68 static constexpr const char* ipmiMutexCleanupLockFile =
69     "/var/lib/ipmi/ipmi_usr_mutex_cleanup";
70 static constexpr const char* ipmiUserDataFile = "/var/lib/ipmi/ipmi_user.json";
71 static constexpr const char* ipmiGrpName = "ipmi";
72 static constexpr size_t privNoAccess = 0xF;
73 static constexpr size_t privMask = 0xF;
74 
75 // User manager related
76 static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
77 static constexpr const char* userObjBasePath = "/xyz/openbmc_project/user";
78 static constexpr const char* userMgrInterface =
79     "xyz.openbmc_project.User.Manager";
80 static constexpr const char* usersInterface =
81     "xyz.openbmc_project.User.Attributes";
82 static constexpr const char* deleteUserInterface =
83     "xyz.openbmc_project.Object.Delete";
84 
85 static constexpr const char* createUserMethod = "CreateUser";
86 static constexpr const char* deleteUserMethod = "Delete";
87 static constexpr const char* renameUserMethod = "RenameUser";
88 // User manager signal memebers
89 static constexpr const char* userRenamedSignal = "UserRenamed";
90 // Mgr interface properties
91 static constexpr const char* allPrivProperty = "AllPrivileges";
92 static constexpr const char* allGrpProperty = "AllGroups";
93 // User interface properties
94 static constexpr const char* userPrivProperty = "UserPrivilege";
95 static constexpr const char* userGrpProperty = "UserGroups";
96 static constexpr const char* userEnabledProperty = "UserEnabled";
97 
98 static std::array<std::string, (PRIVILEGE_OEM + 1)> ipmiPrivIndex = {
99     "priv-reserved", // PRIVILEGE_RESERVED - 0
100     "priv-callback", // PRIVILEGE_CALLBACK - 1
101     "priv-user",     // PRIVILEGE_USER - 2
102     "priv-operator", // PRIVILEGE_OPERATOR - 3
103     "priv-admin",    // PRIVILEGE_ADMIN - 4
104     "priv-custom"    // PRIVILEGE_OEM - 5
105 };
106 
107 using namespace phosphor::logging;
108 using Json = nlohmann::json;
109 
110 using PrivAndGroupType = std::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 bool pamUserCheckAuthenticate(std::string_view username,
719                               std::string_view password)
720 {
721     const struct pam_conv localConversation = {
722         pamFunctionConversation, const_cast<char*>(password.data())};
723 
724     pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
725 
726     if (pam_start("dropbear", username.data(), &localConversation,
727                   &localAuthHandle) != PAM_SUCCESS)
728     {
729         log<level::ERR>("User Authentication Failure");
730         return false;
731     }
732 
733     int retval = pam_authenticate(localAuthHandle,
734                                   PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
735 
736     if (retval != PAM_SUCCESS)
737     {
738         log<level::DEBUG>("pam_authenticate returned failure",
739                           entry("ERROR=%d", retval));
740 
741         pam_end(localAuthHandle, retval);
742         return false;
743     }
744 
745     if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
746         PAM_SUCCESS)
747     {
748         pam_end(localAuthHandle, PAM_SUCCESS);
749         return false;
750     }
751 
752     if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
753     {
754         return false;
755     }
756     return true;
757 }
758 
759 ipmi_ret_t UserAccess::setSpecialUserPassword(const std::string& userName,
760                                               const std::string& userPassword)
761 {
762     if (!pamUpdatePasswd(userName.c_str(), userPassword.c_str()))
763     {
764         log<level::DEBUG>("Failed to update password");
765         return IPMI_CC_UNSPECIFIED_ERROR;
766     }
767     return IPMI_CC_OK;
768 }
769 
770 ipmi_ret_t UserAccess::setUserPassword(const uint8_t userId,
771                                        const char* userPassword)
772 {
773     std::string userName;
774     if (ipmiUserGetUserName(userId, userName) != IPMI_CC_OK)
775     {
776         log<level::DEBUG>("User Name not found",
777                           entry("USER-ID:%d", (uint8_t)userId));
778         return IPMI_CC_PARM_OUT_OF_RANGE;
779     }
780     std::string passwd;
781     passwd.assign(reinterpret_cast<const char*>(userPassword), 0,
782                   maxIpmi20PasswordSize);
783     if (!std::regex_match(passwd.c_str(),
784                           std::regex("[a-zA-z_0-9][a-zA-Z_0-9,?:`!\"]*")))
785     {
786         log<level::DEBUG>("Invalid password fields",
787                           entry("USER-ID:%d", (uint8_t)userId));
788         return IPMI_CC_INVALID_FIELD_REQUEST;
789     }
790     if (!pamUpdatePasswd(userName.c_str(), passwd.c_str()))
791     {
792         log<level::DEBUG>("Failed to update password",
793                           entry("USER-ID:%d", (uint8_t)userId));
794         return IPMI_CC_UNSPECIFIED_ERROR;
795     }
796     return IPMI_CC_OK;
797 }
798 
799 ipmi_ret_t UserAccess::setUserEnabledState(const uint8_t userId,
800                                            const bool& enabledState)
801 {
802     if (!isValidUserId(userId))
803     {
804         return IPMI_CC_PARM_OUT_OF_RANGE;
805     }
806     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
807         userLock{*userMutex};
808     UserInfo* userInfo = getUserInfo(userId);
809     std::string userName;
810     userName.assign(reinterpret_cast<char*>(userInfo->userName), 0,
811                     ipmiMaxUserName);
812     if (userName.empty())
813     {
814         log<level::DEBUG>("User name not set / invalid");
815         return IPMI_CC_UNSPECIFIED_ERROR;
816     }
817     if (userInfo->userEnabled != enabledState)
818     {
819         std::string userPath = std::string(userObjBasePath) + "/" + userName;
820         setDbusProperty(bus, getUserServiceName(), userPath, usersInterface,
821                         userEnabledProperty, enabledState);
822         userInfo->userEnabled = enabledState;
823         try
824         {
825             writeUserData();
826         }
827         catch (const std::exception& e)
828         {
829             log<level::DEBUG>("Write user data failed");
830             return IPMI_CC_UNSPECIFIED_ERROR;
831         }
832     }
833     return IPMI_CC_OK;
834 }
835 
836 ipmi_ret_t UserAccess::setUserPrivilegeAccess(const uint8_t userId,
837                                               const uint8_t chNum,
838                                               const UserPrivAccess& privAccess,
839                                               const bool& otherPrivUpdates)
840 {
841     if (!isValidChannel(chNum))
842     {
843         return IPMI_CC_INVALID_FIELD_REQUEST;
844     }
845     if (!isValidUserId(userId))
846     {
847         return IPMI_CC_PARM_OUT_OF_RANGE;
848     }
849     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
850         userLock{*userMutex};
851     UserInfo* userInfo = getUserInfo(userId);
852     std::string userName;
853     userName.assign(reinterpret_cast<char*>(userInfo->userName), 0,
854                     ipmiMaxUserName);
855     if (userName.empty())
856     {
857         log<level::DEBUG>("User name not set / invalid");
858         return IPMI_CC_UNSPECIFIED_ERROR;
859     }
860     std::string priv = convertToSystemPrivilege(
861         static_cast<CommandPrivilege>(privAccess.privilege));
862     uint8_t syncIndex = getUsrMgmtSyncIndex();
863     if (chNum == syncIndex &&
864         privAccess.privilege != userInfo->userPrivAccess[syncIndex].privilege)
865     {
866         std::string userPath = std::string(userObjBasePath) + "/" + userName;
867         setDbusProperty(bus, getUserServiceName(), userPath, usersInterface,
868                         userPrivProperty, priv);
869     }
870     userInfo->userPrivAccess[chNum].privilege = privAccess.privilege;
871 
872     if (otherPrivUpdates)
873     {
874         userInfo->userPrivAccess[chNum].ipmiEnabled = privAccess.ipmiEnabled;
875         userInfo->userPrivAccess[chNum].linkAuthEnabled =
876             privAccess.linkAuthEnabled;
877         userInfo->userPrivAccess[chNum].accessCallback =
878             privAccess.accessCallback;
879     }
880     try
881     {
882         writeUserData();
883     }
884     catch (const std::exception& e)
885     {
886         log<level::DEBUG>("Write user data failed");
887         return IPMI_CC_UNSPECIFIED_ERROR;
888     }
889     return IPMI_CC_OK;
890 }
891 
892 uint8_t UserAccess::getUserId(const std::string& userName)
893 {
894     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
895         userLock{*userMutex};
896     checkAndReloadUserData();
897     // user index 0 is reserved, starts with 1
898     size_t usrIndex = 1;
899     for (; usrIndex <= ipmiMaxUsers; ++usrIndex)
900     {
901         std::string curName(
902             reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0,
903             ipmiMaxUserName);
904         if (userName == curName)
905         {
906             break; // found the entry
907         }
908     }
909     if (usrIndex > ipmiMaxUsers)
910     {
911         log<level::DEBUG>("User not found",
912                           entry("USER_NAME=%s", userName.c_str()));
913         return invalidUserId;
914     }
915 
916     return usrIndex;
917 }
918 
919 ipmi_ret_t UserAccess::getUserName(const uint8_t userId, std::string& userName)
920 {
921     if (!isValidUserId(userId))
922     {
923         return IPMI_CC_PARM_OUT_OF_RANGE;
924     }
925     UserInfo* userInfo = getUserInfo(userId);
926     userName.assign(reinterpret_cast<char*>(userInfo->userName), 0,
927                     ipmiMaxUserName);
928     return IPMI_CC_OK;
929 }
930 
931 ipmi_ret_t UserAccess::setUserName(const uint8_t userId,
932                                    const char* userNameInChar)
933 {
934     if (!isValidUserId(userId))
935     {
936         return IPMI_CC_PARM_OUT_OF_RANGE;
937     }
938 
939     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
940         userLock{*userMutex};
941     std::string oldUser;
942     getUserName(userId, oldUser);
943 
944     std::string newUser(userNameInChar, 0, ipmiMaxUserName);
945     if (oldUser == newUser)
946     {
947         // requesting to set the same user name, return success.
948         return IPMI_CC_OK;
949     }
950     bool validUser = isValidUserName(userNameInChar);
951     UserInfo* userInfo = getUserInfo(userId);
952     if (newUser.empty() && !oldUser.empty())
953     {
954         // Delete existing user
955         std::string userPath = std::string(userObjBasePath) + "/" + oldUser;
956         try
957         {
958             auto method = bus.new_method_call(
959                 getUserServiceName().c_str(), userPath.c_str(),
960                 deleteUserInterface, deleteUserMethod);
961             auto reply = bus.call(method);
962         }
963         catch (const sdbusplus::exception::SdBusError& e)
964         {
965             log<level::DEBUG>("Failed to excute method",
966                               entry("METHOD=%s", deleteUserMethod),
967                               entry("PATH=%s", userPath.c_str()));
968             return IPMI_CC_UNSPECIFIED_ERROR;
969         }
970         deleteUserIndex(userId);
971     }
972     else if (oldUser.empty() && !newUser.empty() && validUser)
973     {
974         try
975         {
976             // Create new user
977             auto method = bus.new_method_call(
978                 getUserServiceName().c_str(), userMgrObjBasePath,
979                 userMgrInterface, createUserMethod);
980             method.append(newUser.c_str(), availableGroups, "", false);
981             auto reply = bus.call(method);
982         }
983         catch (const sdbusplus::exception::SdBusError& e)
984         {
985             log<level::DEBUG>("Failed to excute method",
986                               entry("METHOD=%s", createUserMethod),
987                               entry("PATH=%s", userMgrObjBasePath));
988             return IPMI_CC_UNSPECIFIED_ERROR;
989         }
990         std::memcpy(userInfo->userName, userNameInChar, ipmiMaxUserName);
991         userInfo->userInSystem = true;
992     }
993     else if (oldUser != newUser && validUser)
994     {
995         try
996         {
997             // User rename
998             auto method = bus.new_method_call(
999                 getUserServiceName().c_str(), userMgrObjBasePath,
1000                 userMgrInterface, renameUserMethod);
1001             method.append(oldUser.c_str(), newUser.c_str());
1002             auto reply = bus.call(method);
1003         }
1004         catch (const sdbusplus::exception::SdBusError& e)
1005         {
1006             log<level::DEBUG>("Failed to excute method",
1007                               entry("METHOD=%s", renameUserMethod),
1008                               entry("PATH=%s", userMgrObjBasePath));
1009             return IPMI_CC_UNSPECIFIED_ERROR;
1010         }
1011         std::fill(static_cast<uint8_t*>(userInfo->userName),
1012                   static_cast<uint8_t*>(userInfo->userName) +
1013                       sizeof(userInfo->userName),
1014                   0);
1015         std::memcpy(userInfo->userName, userNameInChar, ipmiMaxUserName);
1016         ipmiRenameUserEntryPassword(oldUser, newUser);
1017         userInfo->userInSystem = true;
1018     }
1019     else if (!validUser)
1020     {
1021         return IPMI_CC_INVALID_FIELD_REQUEST;
1022     }
1023     try
1024     {
1025         writeUserData();
1026     }
1027     catch (const std::exception& e)
1028     {
1029         log<level::DEBUG>("Write user data failed");
1030         return IPMI_CC_UNSPECIFIED_ERROR;
1031     }
1032     return IPMI_CC_OK;
1033 }
1034 
1035 static constexpr const char* jsonUserName = "user_name";
1036 static constexpr const char* jsonPriv = "privilege";
1037 static constexpr const char* jsonIpmiEnabled = "ipmi_enabled";
1038 static constexpr const char* jsonLinkAuthEnabled = "link_auth_enabled";
1039 static constexpr const char* jsonAccCallbk = "access_callback";
1040 static constexpr const char* jsonUserEnabled = "user_enabled";
1041 static constexpr const char* jsonUserInSys = "user_in_system";
1042 static constexpr const char* jsonFixedUser = "fixed_user_name";
1043 
1044 void UserAccess::readUserData()
1045 {
1046     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1047         userLock{*userMutex};
1048 
1049     std::ifstream iUsrData(ipmiUserDataFile, std::ios::in | std::ios::binary);
1050     if (!iUsrData.good())
1051     {
1052         log<level::ERR>("Error in reading IPMI user data file");
1053         throw std::ios_base::failure("Error opening IPMI user data file");
1054     }
1055 
1056     Json jsonUsersTbl = Json::array();
1057     jsonUsersTbl = Json::parse(iUsrData, nullptr, false);
1058 
1059     if (jsonUsersTbl.size() != ipmiMaxUsers)
1060     {
1061         log<level::ERR>(
1062             "Error in reading IPMI user data file - User count issues");
1063         throw std::runtime_error(
1064             "Corrupted IPMI user data file - invalid user count");
1065     }
1066     // user index 0 is reserved, starts with 1
1067     for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
1068     {
1069         Json userInfo = jsonUsersTbl[usrIndex - 1]; // json array starts with 0.
1070         if (userInfo.is_null())
1071         {
1072             log<level::ERR>("Error in reading IPMI user data file - "
1073                             "user info corrupted");
1074             throw std::runtime_error(
1075                 "Corrupted IPMI user data file - invalid user info");
1076         }
1077         std::string userName = userInfo[jsonUserName].get<std::string>();
1078         std::strncpy(reinterpret_cast<char*>(usersTbl.user[usrIndex].userName),
1079                      userName.c_str(), ipmiMaxUserName);
1080 
1081         std::vector<std::string> privilege =
1082             userInfo[jsonPriv].get<std::vector<std::string>>();
1083         std::vector<bool> ipmiEnabled =
1084             userInfo[jsonIpmiEnabled].get<std::vector<bool>>();
1085         std::vector<bool> linkAuthEnabled =
1086             userInfo[jsonLinkAuthEnabled].get<std::vector<bool>>();
1087         std::vector<bool> accessCallback =
1088             userInfo[jsonAccCallbk].get<std::vector<bool>>();
1089         if (privilege.size() != ipmiMaxChannels ||
1090             ipmiEnabled.size() != ipmiMaxChannels ||
1091             linkAuthEnabled.size() != ipmiMaxChannels ||
1092             accessCallback.size() != ipmiMaxChannels)
1093         {
1094             log<level::ERR>("Error in reading IPMI user data file - "
1095                             "properties corrupted");
1096             throw std::runtime_error(
1097                 "Corrupted IPMI user data file - properties");
1098         }
1099         for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
1100         {
1101             usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege =
1102                 static_cast<uint8_t>(
1103                     convertToIPMIPrivilege(privilege[chIndex]));
1104             usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled =
1105                 ipmiEnabled[chIndex];
1106             usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled =
1107                 linkAuthEnabled[chIndex];
1108             usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback =
1109                 accessCallback[chIndex];
1110         }
1111         usersTbl.user[usrIndex].userEnabled =
1112             userInfo[jsonUserEnabled].get<bool>();
1113         usersTbl.user[usrIndex].userInSystem =
1114             userInfo[jsonUserInSys].get<bool>();
1115         usersTbl.user[usrIndex].fixedUserName =
1116             userInfo[jsonFixedUser].get<bool>();
1117     }
1118 
1119     log<level::DEBUG>("User data read from IPMI data file");
1120     iUsrData.close();
1121     // Update the timestamp
1122     fileLastUpdatedTime = getUpdatedFileTime();
1123     return;
1124 }
1125 
1126 void UserAccess::writeUserData()
1127 {
1128     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1129         userLock{*userMutex};
1130 
1131     Json jsonUsersTbl = Json::array();
1132     // user index 0 is reserved, starts with 1
1133     for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
1134     {
1135         Json jsonUserInfo;
1136         jsonUserInfo[jsonUserName] = std::string(
1137             reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0,
1138             ipmiMaxUserName);
1139         std::vector<std::string> privilege(ipmiMaxChannels);
1140         std::vector<bool> ipmiEnabled(ipmiMaxChannels);
1141         std::vector<bool> linkAuthEnabled(ipmiMaxChannels);
1142         std::vector<bool> accessCallback(ipmiMaxChannels);
1143         for (size_t chIndex = 0; chIndex < ipmiMaxChannels; chIndex++)
1144         {
1145             privilege[chIndex] =
1146                 convertToSystemPrivilege(static_cast<CommandPrivilege>(
1147                     usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege));
1148             ipmiEnabled[chIndex] =
1149                 usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled;
1150             linkAuthEnabled[chIndex] =
1151                 usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled;
1152             accessCallback[chIndex] =
1153                 usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback;
1154         }
1155         jsonUserInfo[jsonPriv] = privilege;
1156         jsonUserInfo[jsonIpmiEnabled] = ipmiEnabled;
1157         jsonUserInfo[jsonLinkAuthEnabled] = linkAuthEnabled;
1158         jsonUserInfo[jsonAccCallbk] = accessCallback;
1159         jsonUserInfo[jsonUserEnabled] = usersTbl.user[usrIndex].userEnabled;
1160         jsonUserInfo[jsonUserInSys] = usersTbl.user[usrIndex].userInSystem;
1161         jsonUserInfo[jsonFixedUser] = usersTbl.user[usrIndex].fixedUserName;
1162         jsonUsersTbl.push_back(jsonUserInfo);
1163     }
1164 
1165     static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"};
1166     int fd = open(tmpFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_SYNC,
1167                   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1168     if (fd < 0)
1169     {
1170         log<level::ERR>("Error in creating temporary IPMI user data file");
1171         throw std::ios_base::failure(
1172             "Error in creating temporary IPMI user data file");
1173     }
1174     const auto& writeStr = jsonUsersTbl.dump();
1175     if (write(fd, writeStr.c_str(), writeStr.size()) !=
1176         static_cast<ssize_t>(writeStr.size()))
1177     {
1178         close(fd);
1179         log<level::ERR>("Error in writing temporary IPMI user data file");
1180         throw std::ios_base::failure(
1181             "Error in writing temporary IPMI user data file");
1182     }
1183     close(fd);
1184 
1185     if (std::rename(tmpFile.c_str(), ipmiUserDataFile) != 0)
1186     {
1187         log<level::ERR>("Error in renaming temporary IPMI user data file");
1188         throw std::runtime_error("Error in renaming IPMI user data file");
1189     }
1190     // Update the timestamp
1191     fileLastUpdatedTime = getUpdatedFileTime();
1192     return;
1193 }
1194 
1195 bool UserAccess::addUserEntry(const std::string& userName,
1196                               const std::string& sysPriv, const bool& enabled)
1197 {
1198     UsersTbl* userData = getUsersTblPtr();
1199     size_t freeIndex = 0xFF;
1200     // user index 0 is reserved, starts with 1
1201     for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
1202     {
1203         std::string curName(
1204             reinterpret_cast<char*>(userData->user[usrIndex].userName), 0,
1205             ipmiMaxUserName);
1206         if (userName == curName)
1207         {
1208             log<level::DEBUG>("User name exists",
1209                               entry("USER_NAME=%s", userName.c_str()));
1210             return false; // user name exists.
1211         }
1212 
1213         if ((!userData->user[usrIndex].userInSystem) &&
1214             (userData->user[usrIndex].userName[0] == '\0') &&
1215             (freeIndex == 0xFF))
1216         {
1217             freeIndex = usrIndex;
1218         }
1219     }
1220     if (freeIndex == 0xFF)
1221     {
1222         log<level::ERR>("No empty slots found");
1223         return false;
1224     }
1225     std::strncpy(reinterpret_cast<char*>(userData->user[freeIndex].userName),
1226                  userName.c_str(), ipmiMaxUserName);
1227     uint8_t priv =
1228         static_cast<uint8_t>(UserAccess::convertToIPMIPrivilege(sysPriv)) &
1229         privMask;
1230     for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
1231     {
1232         userData->user[freeIndex].userPrivAccess[chIndex].privilege = priv;
1233         userData->user[freeIndex].userPrivAccess[chIndex].ipmiEnabled = true;
1234         userData->user[freeIndex].userPrivAccess[chIndex].linkAuthEnabled =
1235             true;
1236         userData->user[freeIndex].userPrivAccess[chIndex].accessCallback = true;
1237     }
1238     userData->user[freeIndex].userInSystem = true;
1239     userData->user[freeIndex].userEnabled = enabled;
1240 
1241     return true;
1242 }
1243 
1244 void UserAccess::deleteUserIndex(const size_t& usrIdx)
1245 {
1246     UsersTbl* userData = getUsersTblPtr();
1247 
1248     std::string userName(
1249         reinterpret_cast<char*>(userData->user[usrIdx].userName), 0,
1250         ipmiMaxUserName);
1251     ipmiClearUserEntryPassword(userName);
1252     std::fill(static_cast<uint8_t*>(userData->user[usrIdx].userName),
1253               static_cast<uint8_t*>(userData->user[usrIdx].userName) +
1254                   sizeof(userData->user[usrIdx].userName),
1255               0);
1256     for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
1257     {
1258         userData->user[usrIdx].userPrivAccess[chIndex].privilege = privNoAccess;
1259         userData->user[usrIdx].userPrivAccess[chIndex].ipmiEnabled = false;
1260         userData->user[usrIdx].userPrivAccess[chIndex].linkAuthEnabled = false;
1261         userData->user[usrIdx].userPrivAccess[chIndex].accessCallback = false;
1262     }
1263     userData->user[usrIdx].userInSystem = false;
1264     userData->user[usrIdx].userEnabled = false;
1265     return;
1266 }
1267 
1268 void UserAccess::checkAndReloadUserData()
1269 {
1270     std::time_t updateTime = getUpdatedFileTime();
1271     if (updateTime != fileLastUpdatedTime || updateTime == -EIO)
1272     {
1273         std::fill(reinterpret_cast<uint8_t*>(&usersTbl),
1274                   reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0);
1275         readUserData();
1276     }
1277     return;
1278 }
1279 
1280 UsersTbl* UserAccess::getUsersTblPtr()
1281 {
1282     // reload data before using it.
1283     checkAndReloadUserData();
1284     return &usersTbl;
1285 }
1286 
1287 void UserAccess::getSystemPrivAndGroups()
1288 {
1289     std::map<std::string, PrivAndGroupType> properties;
1290     try
1291     {
1292         auto method = bus.new_method_call(
1293             getUserServiceName().c_str(), userMgrObjBasePath,
1294             dBusPropertiesInterface, getAllPropertiesMethod);
1295         method.append(userMgrInterface);
1296 
1297         auto reply = bus.call(method);
1298         reply.read(properties);
1299     }
1300     catch (const sdbusplus::exception::SdBusError& e)
1301     {
1302         log<level::DEBUG>("Failed to excute method",
1303                           entry("METHOD=%s", getAllPropertiesMethod),
1304                           entry("PATH=%s", userMgrObjBasePath));
1305         return;
1306     }
1307     for (const auto& t : properties)
1308     {
1309         auto key = t.first;
1310         if (key == allPrivProperty)
1311         {
1312             availablePrivileges = std::get<std::vector<std::string>>(t.second);
1313         }
1314         else if (key == allGrpProperty)
1315         {
1316             availableGroups = std::get<std::vector<std::string>>(t.second);
1317         }
1318     }
1319     // TODO: Implement Supported Privilege & Groups verification logic
1320     return;
1321 }
1322 
1323 std::time_t UserAccess::getUpdatedFileTime()
1324 {
1325     struct stat fileStat;
1326     if (stat(ipmiUserDataFile, &fileStat) != 0)
1327     {
1328         log<level::DEBUG>("Error in getting last updated time stamp");
1329         return -EIO;
1330     }
1331     return fileStat.st_mtime;
1332 }
1333 
1334 void UserAccess::getUserProperties(const DbusUserObjProperties& properties,
1335                                    std::vector<std::string>& usrGrps,
1336                                    std::string& usrPriv, bool& usrEnabled)
1337 {
1338     for (const auto& t : properties)
1339     {
1340         std::string key = t.first;
1341         if (key == userPrivProperty)
1342         {
1343             usrPriv = std::get<std::string>(t.second);
1344         }
1345         else if (key == userGrpProperty)
1346         {
1347             usrGrps = std::get<std::vector<std::string>>(t.second);
1348         }
1349         else if (key == userEnabledProperty)
1350         {
1351             usrEnabled = std::get<bool>(t.second);
1352         }
1353     }
1354     return;
1355 }
1356 
1357 int UserAccess::getUserObjProperties(const DbusUserObjValue& userObjs,
1358                                      std::vector<std::string>& usrGrps,
1359                                      std::string& usrPriv, bool& usrEnabled)
1360 {
1361     auto usrObj = userObjs.find(usersInterface);
1362     if (usrObj != userObjs.end())
1363     {
1364         getUserProperties(usrObj->second, usrGrps, usrPriv, usrEnabled);
1365         return 0;
1366     }
1367     return -EIO;
1368 }
1369 
1370 void UserAccess::initUserDataFile()
1371 {
1372     boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
1373         userLock{*userMutex};
1374     try
1375     {
1376         readUserData();
1377     }
1378     catch (const std::ios_base::failure& e)
1379     { // File is empty, create it for the first time
1380         std::fill(reinterpret_cast<uint8_t*>(&usersTbl),
1381                   reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0);
1382         // user index 0 is reserved, starts with 1
1383         for (size_t userIndex = 1; userIndex <= ipmiMaxUsers; ++userIndex)
1384         {
1385             for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
1386             {
1387                 usersTbl.user[userIndex].userPrivAccess[chIndex].privilege =
1388                     privNoAccess;
1389             }
1390         }
1391         writeUserData();
1392     }
1393     std::map<DbusUserObjPath, DbusUserObjValue> managedObjs;
1394     try
1395     {
1396         auto method = bus.new_method_call(getUserServiceName().c_str(),
1397                                           userMgrObjBasePath, dBusObjManager,
1398                                           getManagedObjectsMethod);
1399         auto reply = bus.call(method);
1400         reply.read(managedObjs);
1401     }
1402     catch (const sdbusplus::exception::SdBusError& e)
1403     {
1404         log<level::DEBUG>("Failed to excute method",
1405                           entry("METHOD=%s", getSubTreeMethod),
1406                           entry("PATH=%s", userMgrObjBasePath));
1407         return;
1408     }
1409     bool updateRequired = false;
1410     UsersTbl* userData = &usersTbl;
1411     // user index 0 is reserved, starts with 1
1412     for (size_t usrIdx = 1; usrIdx <= ipmiMaxUsers; ++usrIdx)
1413     {
1414         if ((userData->user[usrIdx].userInSystem) &&
1415             (userData->user[usrIdx].userName[0] != '\0'))
1416         {
1417             std::vector<std::string> usrGrps;
1418             std::string usrPriv;
1419             bool usrEnabled;
1420 
1421             std::string userName(
1422                 reinterpret_cast<char*>(userData->user[usrIdx].userName), 0,
1423                 ipmiMaxUserName);
1424             std::string usersPath =
1425                 std::string(userObjBasePath) + "/" + userName;
1426 
1427             auto usrObj = managedObjs.find(usersPath);
1428             if (usrObj != managedObjs.end())
1429             {
1430                 // User exist. Lets check and update other fileds
1431                 getUserObjProperties(usrObj->second, usrGrps, usrPriv,
1432                                      usrEnabled);
1433                 if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) ==
1434                     usrGrps.end())
1435                 {
1436                     updateRequired = true;
1437                     // Group "ipmi" is removed so lets remove user in IPMI
1438                     deleteUserIndex(usrIdx);
1439                 }
1440                 else
1441                 {
1442                     // Group "ipmi" is present so lets update other properties
1443                     // in IPMI
1444                     uint8_t priv =
1445                         UserAccess::convertToIPMIPrivilege(usrPriv) & privMask;
1446                     // Update all channels priv, only if it is not equivalent to
1447                     // getUsrMgmtSyncIndex()
1448                     if (userData->user[usrIdx]
1449                             .userPrivAccess[getUsrMgmtSyncIndex()]
1450                             .privilege != priv)
1451                     {
1452                         updateRequired = true;
1453                         for (size_t chIndex = 0; chIndex < ipmiMaxChannels;
1454                              ++chIndex)
1455                         {
1456                             userData->user[usrIdx]
1457                                 .userPrivAccess[chIndex]
1458                                 .privilege = priv;
1459                         }
1460                     }
1461                     if (userData->user[usrIdx].userEnabled != usrEnabled)
1462                     {
1463                         updateRequired = true;
1464                         userData->user[usrIdx].userEnabled = usrEnabled;
1465                     }
1466                 }
1467 
1468                 // We are done with this obj. lets delete from MAP
1469                 managedObjs.erase(usrObj);
1470             }
1471             else
1472             {
1473                 updateRequired = true;
1474                 deleteUserIndex(usrIdx);
1475             }
1476         }
1477     }
1478 
1479     // Walk through remnaining managedObj users list
1480     // Add them to ipmi data base
1481     for (const auto& usrObj : managedObjs)
1482     {
1483         std::vector<std::string> usrGrps;
1484         std::string usrPriv, userName;
1485         bool usrEnabled;
1486         std::string usrObjPath = std::string(usrObj.first);
1487         if (getUserNameFromPath(usrObj.first.str, userName) != 0)
1488         {
1489             log<level::ERR>("Error in user object path");
1490             continue;
1491         }
1492         getUserObjProperties(usrObj.second, usrGrps, usrPriv, usrEnabled);
1493         // Add 'ipmi' group users
1494         if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) !=
1495             usrGrps.end())
1496         {
1497             updateRequired = true;
1498             // CREATE NEW USER
1499             if (true != addUserEntry(userName, usrPriv, usrEnabled))
1500             {
1501                 break;
1502             }
1503         }
1504     }
1505 
1506     if (updateRequired)
1507     {
1508         // All userData slots update done. Lets write the data
1509         writeUserData();
1510     }
1511 
1512     return;
1513 }
1514 } // namespace ipmi
1515