diff --git a/user_channel/user_mgmt.cpp b/user_channel/user_mgmt.cpp
new file mode 100644
index 0000000..e320e3f
--- /dev/null
+++ b/user_channel/user_mgmt.cpp
@@ -0,0 +1,1304 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#include "user_mgmt.hpp"
+
+#include "apphandler.hpp"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <boost/interprocess/sync/named_recursive_mutex.hpp>
+#include <boost/interprocess/sync/scoped_lock.hpp>
+#include <cerrno>
+#include <fstream>
+#include <host-ipmid/ipmid-host-cmd.hpp>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <regex>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/User/Common/error.hpp>
+
+namespace ipmi
+{
+
+// TODO: Move D-Bus & Object Manager related stuff, to common files
+// D-Bus property related
+static constexpr const char* dBusPropertiesInterface =
+    "org.freedesktop.DBus.Properties";
+static constexpr const char* getAllPropertiesMethod = "GetAll";
+static constexpr const char* propertiesChangedSignal = "PropertiesChanged";
+static constexpr const char* setPropertiesMethod = "Set";
+
+// Object Manager related
+static constexpr const char* dBusObjManager =
+    "org.freedesktop.DBus.ObjectManager";
+static constexpr const char* getManagedObjectsMethod = "GetManagedObjects";
+// Object Manager signals
+static constexpr const char* intfAddedSignal = "InterfacesAdded";
+static constexpr const char* intfRemovedSignal = "InterfacesRemoved";
+
+// Object Mapper related
+static constexpr const char* objMapperService =
+    "xyz.openbmc_project.ObjectMapper";
+static constexpr const char* objMapperPath =
+    "/xyz/openbmc_project/object_mapper";
+static constexpr const char* objMapperInterface =
+    "xyz.openbmc_project.ObjectMapper";
+static constexpr const char* getSubTreeMethod = "GetSubTree";
+static constexpr const char* getObjectMethod = "GetObject";
+
+static constexpr const char* ipmiUserMutex = "ipmi_usr_mutex";
+static constexpr const char* ipmiMutexCleanupLockFile =
+    "/var/lib/ipmi/ipmi_usr_mutex_cleanup";
+static constexpr const char* ipmiUserDataFile = "/var/lib/ipmi/ipmi_user.json";
+static constexpr const char* ipmiGrpName = "ipmi";
+static constexpr size_t privNoAccess = 0xF;
+static constexpr size_t privMask = 0xF;
+
+// User manager related
+static constexpr const char* userMgrObjBasePath = "/xyz/openbmc_project/user";
+static constexpr const char* userObjBasePath = "/xyz/openbmc_project/user";
+static constexpr const char* userMgrInterface =
+    "xyz.openbmc_project.User.Manager";
+static constexpr const char* usersInterface =
+    "xyz.openbmc_project.User.Attributes";
+static constexpr const char* deleteUserInterface =
+    "xyz.openbmc_project.Object.Delete";
+
+static constexpr const char* createUserMethod = "CreateUser";
+static constexpr const char* deleteUserMethod = "Delete";
+static constexpr const char* renameUserMethod = "RenameUser";
+// User manager signal memebers
+static constexpr const char* userRenamedSignal = "UserRenamed";
+// Mgr interface properties
+static constexpr const char* allPrivProperty = "AllPrivileges";
+static constexpr const char* allGrpProperty = "AllGroups";
+// User interface properties
+static constexpr const char* userPrivProperty = "UserPrivilege";
+static constexpr const char* userGrpProperty = "UserGroups";
+static constexpr const char* userEnabledProperty = "UserEnabled";
+
+static std::array<std::string, (PRIVILEGE_OEM + 1)> ipmiPrivIndex = {
+    "priv-reserved", // PRIVILEGE_RESERVED - 0
+    "priv-callback", // PRIVILEGE_CALLBACK - 1
+    "priv-user",     // PRIVILEGE_USER - 2
+    "priv-operator", // PRIVILEGE_OPERATOR - 3
+    "priv-admin",    // PRIVILEGE_ADMIN - 4
+    "priv-custom"    // PRIVILEGE_OEM - 5
+};
+
+using namespace phosphor::logging;
+using Json = nlohmann::json;
+
+using PrivAndGroupType =
+    sdbusplus::message::variant<std::string, std::vector<std::string>>;
+
+using NoResource =
+    sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource;
+
+using InternalFailure =
+    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+std::unique_ptr<sdbusplus::bus::match_t> userUpdatedSignal(nullptr);
+std::unique_ptr<sdbusplus::bus::match_t> userMgrRenamedSignal(nullptr);
+std::unique_ptr<sdbusplus::bus::match_t> userPropertiesSignal(nullptr);
+
+// TODO:  Below code can be removed once it is moved to common layer libmiscutil
+std::string getUserService(sdbusplus::bus::bus& bus, const std::string& intf,
+                           const std::string& path)
+{
+    auto mapperCall = bus.new_method_call(objMapperService, objMapperPath,
+                                          objMapperInterface, getObjectMethod);
+
+    mapperCall.append(path);
+    mapperCall.append(std::vector<std::string>({intf}));
+
+    auto mapperResponseMsg = bus.call(mapperCall);
+
+    std::map<std::string, std::vector<std::string>> mapperResponse;
+    mapperResponseMsg.read(mapperResponse);
+
+    if (mapperResponse.begin() == mapperResponse.end())
+    {
+        throw sdbusplus::exception::SdBusError(
+            -EIO, "ERROR in reading the mapper response");
+    }
+
+    return mapperResponse.begin()->first;
+}
+
+void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
+                     const std::string& objPath, const std::string& interface,
+                     const std::string& property,
+                     const DbusUserPropVariant& value)
+{
+    try
+    {
+        auto method =
+            bus.new_method_call(service.c_str(), objPath.c_str(),
+                                dBusPropertiesInterface, setPropertiesMethod);
+        method.append(interface, property, value);
+        bus.call(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::ERR>("Failed to set property",
+                        entry("PROPERTY=%s", property.c_str()),
+                        entry("PATH=%s", objPath.c_str()),
+                        entry("INTERFACE=%s", interface.c_str()));
+        throw;
+    }
+}
+
+static std::string getUserServiceName()
+{
+    static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+    static std::string userMgmtService;
+    if (userMgmtService.empty())
+    {
+        try
+        {
+            userMgmtService =
+                ipmi::getUserService(bus, userMgrInterface, userMgrObjBasePath);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            userMgmtService.clear();
+        }
+    }
+    return userMgmtService;
+}
+
+UserAccess& getUserAccessObject()
+{
+    static UserAccess userAccess;
+    return userAccess;
+}
+
+int getUserNameFromPath(const std::string& path, std::string& userName)
+{
+    static size_t pos = strlen(userObjBasePath) + 1;
+    if (path.find(userObjBasePath) == std::string::npos)
+    {
+        return -EINVAL;
+    }
+    userName.assign(path, pos, path.size());
+    return 0;
+}
+
+void userUpdateHelper(UserAccess& usrAccess, const UserUpdateEvent& userEvent,
+                      const std::string& userName, const std::string& priv,
+                      const bool& enabled, const std::string& newUserName)
+{
+    UsersTbl* userData = usrAccess.getUsersTblPtr();
+    if (userEvent == UserUpdateEvent::userCreated)
+    {
+        if (usrAccess.addUserEntry(userName, priv, enabled) == false)
+        {
+            return;
+        }
+    }
+    else
+    {
+        // user index 0 is reserved, starts with 1
+        size_t usrIndex = 1;
+        for (; usrIndex <= ipmiMaxUsers; ++usrIndex)
+        {
+            std::string curName(
+                reinterpret_cast<char*>(userData->user[usrIndex].userName), 0,
+                ipmiMaxUserName);
+            if (userName == curName)
+            {
+                break; // found the entry
+            }
+        }
+        if (usrIndex > ipmiMaxUsers)
+        {
+            log<level::DEBUG>("User not found for signal",
+                              entry("USER_NAME=%s", userName.c_str()),
+                              entry("USER_EVENT=%d", userEvent));
+            return;
+        }
+        switch (userEvent)
+        {
+            case UserUpdateEvent::userDeleted:
+            {
+                usrAccess.deleteUserIndex(usrIndex);
+                break;
+            }
+            case UserUpdateEvent::userPrivUpdated:
+            {
+                uint8_t userPriv =
+                    static_cast<uint8_t>(
+                        UserAccess::convertToIPMIPrivilege(priv)) &
+                    privMask;
+                // Update all channels privileges, only if it is not equivalent
+                // to getUsrMgmtSyncIndex()
+                if (userData->user[usrIndex]
+                        .userPrivAccess[UserAccess::getUsrMgmtSyncIndex()]
+                        .privilege != userPriv)
+                {
+                    for (size_t chIndex = 0; chIndex < ipmiMaxChannels;
+                         ++chIndex)
+                    {
+                        userData->user[usrIndex]
+                            .userPrivAccess[chIndex]
+                            .privilege = userPriv;
+                    }
+                }
+                break;
+            }
+            case UserUpdateEvent::userRenamed:
+            {
+                std::fill(
+                    static_cast<uint8_t*>(userData->user[usrIndex].userName),
+                    static_cast<uint8_t*>(userData->user[usrIndex].userName) +
+                        sizeof(userData->user[usrIndex].userName),
+                    0);
+                std::strncpy(
+                    reinterpret_cast<char*>(userData->user[usrIndex].userName),
+                    newUserName.c_str(), ipmiMaxUserName);
+                ipmiRenameUserEntryPassword(userName, newUserName);
+                break;
+            }
+            case UserUpdateEvent::userStateUpdated:
+            {
+                userData->user[usrIndex].userEnabled = enabled;
+                break;
+            }
+            default:
+            {
+                log<level::ERR>("Unhandled user event",
+                                entry("USER_EVENT=%d", userEvent));
+                return;
+            }
+        }
+    }
+    usrAccess.writeUserData();
+    log<level::DEBUG>("User event handled successfully",
+                      entry("USER_NAME=%s", userName.c_str()),
+                      entry("USER_EVENT=%d", userEvent));
+
+    return;
+}
+
+void userUpdatedSignalHandler(UserAccess& usrAccess,
+                              sdbusplus::message::message& msg)
+{
+    static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
+    std::string signal = msg.get_member();
+    std::string userName, update, priv, newUserName;
+    std::vector<std::string> groups;
+    bool enabled = false;
+    UserUpdateEvent userEvent = UserUpdateEvent::reservedEvent;
+    if (signal == intfAddedSignal)
+    {
+        DbusUserObjPath objPath;
+        DbusUserObjValue objValue;
+        msg.read(objPath, objValue);
+        getUserNameFromPath(objPath.str, userName);
+        if (usrAccess.getUserObjProperties(objValue, groups, priv, enabled) !=
+            0)
+        {
+            return;
+        }
+        if (std::find(groups.begin(), groups.end(), ipmiGrpName) ==
+            groups.end())
+        {
+            return;
+        }
+        userEvent = UserUpdateEvent::userCreated;
+    }
+    else if (signal == intfRemovedSignal)
+    {
+        DbusUserObjPath objPath;
+        std::vector<std::string> interfaces;
+        msg.read(objPath, interfaces);
+        getUserNameFromPath(objPath.str, userName);
+        userEvent = UserUpdateEvent::userDeleted;
+    }
+    else if (signal == userRenamedSignal)
+    {
+        msg.read(userName, newUserName);
+        userEvent = UserUpdateEvent::userRenamed;
+    }
+    else if (signal == propertiesChangedSignal)
+    {
+        getUserNameFromPath(msg.get_path(), userName);
+    }
+    else
+    {
+        log<level::ERR>("Unknown user update signal",
+                        entry("SIGNAL=%s", signal.c_str()));
+        return;
+    }
+
+    if (signal.empty() || userName.empty() ||
+        (signal == userRenamedSignal && newUserName.empty()))
+    {
+        log<level::ERR>("Invalid inputs received");
+        return;
+    }
+
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*(usrAccess.userMutex)};
+    usrAccess.checkAndReloadUserData();
+
+    if (signal == propertiesChangedSignal)
+    {
+        std::string intfName;
+        DbusUserObjProperties chProperties;
+        msg.read(intfName, chProperties); // skip reading 3rd argument.
+        for (const auto& prop : chProperties)
+        {
+            userEvent = UserUpdateEvent::reservedEvent;
+            std::string member = prop.first;
+            if (member == userPrivProperty)
+            {
+                priv = prop.second.get<std::string>();
+                userEvent = UserUpdateEvent::userPrivUpdated;
+            }
+            else if (member == userGrpProperty)
+            {
+                groups = prop.second.get<std::vector<std::string>>();
+                userEvent = UserUpdateEvent::userGrpUpdated;
+            }
+            else if (member == userEnabledProperty)
+            {
+                enabled = prop.second.get<bool>();
+                userEvent = UserUpdateEvent::userStateUpdated;
+            }
+            // Process based on event type.
+            if (userEvent == UserUpdateEvent::userGrpUpdated)
+            {
+                if (std::find(groups.begin(), groups.end(), ipmiGrpName) ==
+                    groups.end())
+                {
+                    // remove user from ipmi user list.
+                    userUpdateHelper(usrAccess, UserUpdateEvent::userDeleted,
+                                     userName, priv, enabled, newUserName);
+                }
+                else
+                {
+                    DbusUserObjProperties properties;
+                    try
+                    {
+                        auto method = bus.new_method_call(
+                            getUserServiceName().c_str(), msg.get_path(),
+                            dBusPropertiesInterface, getAllPropertiesMethod);
+                        method.append(usersInterface);
+                        auto reply = bus.call(method);
+                        reply.read(properties);
+                    }
+                    catch (const sdbusplus::exception::SdBusError& e)
+                    {
+                        log<level::DEBUG>(
+                            "Failed to excute method",
+                            entry("METHOD=%s", getAllPropertiesMethod),
+                            entry("PATH=%s", msg.get_path()));
+                        return;
+                    }
+                    usrAccess.getUserProperties(properties, groups, priv,
+                                                enabled);
+                    // add user to ipmi user list.
+                    userUpdateHelper(usrAccess, UserUpdateEvent::userCreated,
+                                     userName, priv, enabled, newUserName);
+                }
+            }
+            else if (userEvent != UserUpdateEvent::reservedEvent)
+            {
+                userUpdateHelper(usrAccess, userEvent, userName, priv, enabled,
+                                 newUserName);
+            }
+        }
+    }
+    else if (userEvent != UserUpdateEvent::reservedEvent)
+    {
+        userUpdateHelper(usrAccess, userEvent, userName, priv, enabled,
+                         newUserName);
+    }
+    return;
+}
+
+UserAccess::~UserAccess()
+{
+    if (signalHndlrObject)
+    {
+        userUpdatedSignal.reset();
+        userMgrRenamedSignal.reset();
+        userPropertiesSignal.reset();
+        sigHndlrLock.unlock();
+    }
+}
+
+UserAccess::UserAccess() : bus(ipmid_get_sd_bus_connection())
+{
+    std::ofstream mutexCleanUpFile;
+    mutexCleanUpFile.open(ipmiMutexCleanupLockFile,
+                          std::ofstream::out | std::ofstream::app);
+    if (!mutexCleanUpFile.good())
+    {
+        log<level::DEBUG>("Unable to open mutex cleanup file");
+        return;
+    }
+    mutexCleanUpFile.close();
+    mutexCleanupLock = boost::interprocess::file_lock(ipmiMutexCleanupLockFile);
+    if (mutexCleanupLock.try_lock())
+    {
+        boost::interprocess::named_recursive_mutex::remove(ipmiUserMutex);
+    }
+    mutexCleanupLock.lock_sharable();
+    userMutex = std::make_unique<boost::interprocess::named_recursive_mutex>(
+        boost::interprocess::open_or_create, ipmiUserMutex);
+
+    initUserDataFile();
+    getSystemPrivAndGroups();
+    sigHndlrLock = boost::interprocess::file_lock(ipmiUserDataFile);
+    // Register it for single object and single process either netipimd /
+    // host-ipmid
+    if (userUpdatedSignal == nullptr && sigHndlrLock.try_lock())
+    {
+        log<level::DEBUG>("Registering signal handler");
+        userUpdatedSignal = std::make_unique<sdbusplus::bus::match_t>(
+            bus,
+            sdbusplus::bus::match::rules::type::signal() +
+                sdbusplus::bus::match::rules::interface(dBusObjManager) +
+                sdbusplus::bus::match::rules::path(userMgrObjBasePath),
+            [&](sdbusplus::message::message& msg) {
+                userUpdatedSignalHandler(*this, msg);
+            });
+        userMgrRenamedSignal = std::make_unique<sdbusplus::bus::match_t>(
+            bus,
+            sdbusplus::bus::match::rules::type::signal() +
+                sdbusplus::bus::match::rules::interface(userMgrInterface) +
+                sdbusplus::bus::match::rules::path(userMgrObjBasePath),
+            [&](sdbusplus::message::message& msg) {
+                userUpdatedSignalHandler(*this, msg);
+            });
+        userPropertiesSignal = std::make_unique<sdbusplus::bus::match_t>(
+            bus,
+            sdbusplus::bus::match::rules::type::signal() +
+                sdbusplus::bus::match::rules::path_namespace(userObjBasePath) +
+                sdbusplus::bus::match::rules::interface(
+                    dBusPropertiesInterface) +
+                sdbusplus::bus::match::rules::member(propertiesChangedSignal) +
+                sdbusplus::bus::match::rules::argN(0, usersInterface),
+            [&](sdbusplus::message::message& msg) {
+                userUpdatedSignalHandler(*this, msg);
+            });
+        signalHndlrObject = true;
+    }
+}
+
+UserInfo* UserAccess::getUserInfo(const uint8_t& userId)
+{
+    checkAndReloadUserData();
+    return &usersTbl.user[userId];
+}
+
+void UserAccess::setUserInfo(const uint8_t& userId, UserInfo* userInfo)
+{
+    checkAndReloadUserData();
+    std::copy(reinterpret_cast<uint8_t*>(userInfo),
+              reinterpret_cast<uint8_t*>(userInfo) + sizeof(*userInfo),
+              reinterpret_cast<uint8_t*>(&usersTbl.user[userId]));
+    writeUserData();
+}
+
+bool UserAccess::isValidChannel(const uint8_t& chNum)
+{
+    return (chNum < ipmiMaxChannels);
+}
+
+bool UserAccess::isValidUserId(const uint8_t& userId)
+{
+    return ((userId <= ipmiMaxUsers) && (userId != reservedUserId));
+}
+
+bool UserAccess::isValidPrivilege(const uint8_t& priv)
+{
+    return ((priv >= PRIVILEGE_CALLBACK && priv <= PRIVILEGE_OEM) ||
+            priv == privNoAccess);
+}
+
+uint8_t UserAccess::getUsrMgmtSyncIndex()
+{
+    // TODO: Need to get LAN1 channel number dynamically,
+    // which has to be in sync with system user privilege
+    // level(Phosphor-user-manager). Note: For time being chanLan1 is marked as
+    // sync index to the user-manager privilege..
+    return static_cast<uint8_t>(EChannelID::chanLan1);
+}
+
+CommandPrivilege UserAccess::convertToIPMIPrivilege(const std::string& value)
+{
+    auto iter = std::find(ipmiPrivIndex.begin(), ipmiPrivIndex.end(), value);
+    if (iter == ipmiPrivIndex.end())
+    {
+        if (value == "")
+        {
+            return static_cast<CommandPrivilege>(privNoAccess);
+        }
+        log<level::ERR>("Error in converting to IPMI privilege",
+                        entry("PRIV=%s", value.c_str()));
+        throw std::out_of_range("Out of range - convertToIPMIPrivilege");
+    }
+    else
+    {
+        return static_cast<CommandPrivilege>(
+            std::distance(ipmiPrivIndex.begin(), iter));
+    }
+}
+
+std::string UserAccess::convertToSystemPrivilege(const CommandPrivilege& value)
+{
+    if (value == static_cast<CommandPrivilege>(privNoAccess))
+    {
+        return "";
+    }
+    try
+    {
+        return ipmiPrivIndex.at(value);
+    }
+    catch (const std::out_of_range& e)
+    {
+        log<level::ERR>("Error in converting to system privilege",
+                        entry("PRIV=%d", static_cast<uint8_t>(value)));
+        throw std::out_of_range("Out of range - convertToSystemPrivilege");
+    }
+}
+
+bool UserAccess::isValidUserName(const char* userNameInChar)
+{
+    if (!userNameInChar)
+    {
+        log<level::ERR>("null ptr");
+        return false;
+    }
+    std::string userName(userNameInChar, 0, ipmiMaxUserName);
+    if (!std::regex_match(userName.c_str(),
+                          std::regex("[a-zA-z_][a-zA-Z_0-9]*")))
+    {
+        log<level::ERR>("Unsupported characters in user name");
+        return false;
+    }
+    if (userName == "root")
+    {
+        log<level::ERR>("Invalid user name - root");
+        return false;
+    }
+    std::map<DbusUserObjPath, DbusUserObjValue> properties;
+    try
+    {
+        auto method = bus.new_method_call(getUserServiceName().c_str(),
+                                          userMgrObjBasePath, dBusObjManager,
+                                          getManagedObjectsMethod);
+        auto reply = bus.call(method);
+        reply.read(properties);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::ERR>("Failed to excute method",
+                        entry("METHOD=%s", getSubTreeMethod),
+                        entry("PATH=%s", userMgrObjBasePath));
+        return false;
+    }
+
+    std::string usersPath = std::string(userObjBasePath) + "/" + userName;
+    if (properties.find(usersPath) != properties.end())
+    {
+        log<level::DEBUG>("User name already exists",
+                          entry("USER_NAME=%s", userName.c_str()));
+        return false;
+    }
+
+    return true;
+}
+
+ipmi_ret_t UserAccess::setUserPrivilegeAccess(const uint8_t& userId,
+                                              const uint8_t& chNum,
+                                              const UserPrivAccess& privAccess,
+                                              const bool& otherPrivUpdates)
+{
+    if (!isValidChannel(chNum))
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+    if (!isValidUserId(userId))
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+    UserInfo* userInfo = getUserInfo(userId);
+    std::string userName;
+    userName.assign(reinterpret_cast<char*>(userInfo->userName), 0,
+                    ipmiMaxUserName);
+    if (userName.empty())
+    {
+        log<level::DEBUG>("User name not set / invalid");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    std::string priv = convertToSystemPrivilege(
+        static_cast<CommandPrivilege>(privAccess.privilege));
+    if (priv.empty())
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    uint8_t syncIndex = getUsrMgmtSyncIndex();
+    if (chNum == syncIndex &&
+        privAccess.privilege != userInfo->userPrivAccess[syncIndex].privilege)
+    {
+        std::string userPath = std::string(userObjBasePath) + "/" + userName;
+        setDbusProperty(bus, getUserServiceName().c_str(), userPath.c_str(),
+                        usersInterface, userPrivProperty, priv);
+    }
+    userInfo->userPrivAccess[chNum].privilege = privAccess.privilege;
+
+    if (otherPrivUpdates)
+    {
+        userInfo->userPrivAccess[chNum].ipmiEnabled = privAccess.ipmiEnabled;
+        userInfo->userPrivAccess[chNum].linkAuthEnabled =
+            privAccess.linkAuthEnabled;
+        userInfo->userPrivAccess[chNum].accessCallback =
+            privAccess.accessCallback;
+    }
+    try
+    {
+        writeUserData();
+    }
+    catch (const std::exception& e)
+    {
+        log<level::DEBUG>("Write user data failed");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    return IPMI_CC_OK;
+}
+
+uint8_t UserAccess::getUserId(const std::string& userName)
+{
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+    checkAndReloadUserData();
+    // user index 0 is reserved, starts with 1
+    size_t usrIndex = 1;
+    for (; usrIndex <= ipmiMaxUsers; ++usrIndex)
+    {
+        std::string curName(
+            reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0,
+            ipmiMaxUserName);
+        if (userName == curName)
+        {
+            break; // found the entry
+        }
+    }
+    if (usrIndex > ipmiMaxUsers)
+    {
+        log<level::DEBUG>("User not found",
+                          entry("USER_NAME=%s", userName.c_str()));
+        return invalidUserId;
+    }
+
+    return usrIndex;
+}
+
+ipmi_ret_t UserAccess::getUserName(const uint8_t& userId, std::string& userName)
+{
+    if (!isValidUserId(userId))
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+    UserInfo* userInfo = getUserInfo(userId);
+    userName.assign(reinterpret_cast<char*>(userInfo->userName), 0,
+                    ipmiMaxUserName);
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t UserAccess::setUserName(const uint8_t& userId,
+                                   const char* userNameInChar)
+{
+    if (!isValidUserId(userId))
+    {
+        return IPMI_CC_PARM_OUT_OF_RANGE;
+    }
+
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+    bool validUser = isValidUserName(userNameInChar);
+    std::string oldUser;
+    getUserName(userId, oldUser);
+    UserInfo* userInfo = getUserInfo(userId);
+
+    std::string newUser(userNameInChar, 0, ipmiMaxUserName);
+    if (newUser.empty() && !oldUser.empty())
+    {
+        // Delete existing user
+        std::string userPath = std::string(userObjBasePath) + "/" + oldUser;
+        try
+        {
+            auto method = bus.new_method_call(
+                getUserServiceName().c_str(), userPath.c_str(),
+                deleteUserInterface, deleteUserMethod);
+            auto reply = bus.call(method);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            log<level::DEBUG>("Failed to excute method",
+                              entry("METHOD=%s", deleteUserMethod),
+                              entry("PATH=%s", userPath.c_str()));
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        std::fill(userInfo->userName,
+                  userInfo->userName + sizeof(userInfo->userName), 0);
+        ipmiClearUserEntryPassword(oldUser);
+        userInfo->userInSystem = false;
+    }
+    else if (oldUser.empty() && !newUser.empty() && validUser)
+    {
+        try
+        {
+            // Create new user
+            auto method = bus.new_method_call(
+                getUserServiceName().c_str(), userMgrObjBasePath,
+                userMgrInterface, createUserMethod);
+            // TODO: Fetch proper privilege & enable state once set User access
+            // is implemented if LAN Channel specified, then create user for all
+            // groups follow channel privilege for user creation.
+            method.append(newUser.c_str(), availableGroups, "priv-admin", true);
+            auto reply = bus.call(method);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            log<level::DEBUG>("Failed to excute method",
+                              entry("METHOD=%s", createUserMethod),
+                              entry("PATH=%s", userMgrObjBasePath));
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        std::strncpy(reinterpret_cast<char*>(userInfo->userName),
+                     userNameInChar, ipmiMaxUserName);
+        userInfo->userInSystem = true;
+    }
+    else if (oldUser != newUser && validUser)
+    {
+        try
+        {
+            // User rename
+            auto method = bus.new_method_call(
+                getUserServiceName().c_str(), userMgrObjBasePath,
+                userMgrInterface, renameUserMethod);
+            method.append(oldUser.c_str(), newUser.c_str());
+            auto reply = bus.call(method);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            log<level::DEBUG>("Failed to excute method",
+                              entry("METHOD=%s", renameUserMethod),
+                              entry("PATH=%s", userMgrObjBasePath));
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        std::fill(static_cast<uint8_t*>(userInfo->userName),
+                  static_cast<uint8_t*>(userInfo->userName) +
+                      sizeof(userInfo->userName),
+                  0);
+        std::strncpy(reinterpret_cast<char*>(userInfo->userName),
+                     userNameInChar, ipmiMaxUserName);
+        ipmiRenameUserEntryPassword(oldUser, newUser);
+        userInfo->userInSystem = true;
+    }
+    else if (!validUser)
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+    try
+    {
+        writeUserData();
+    }
+    catch (const std::exception& e)
+    {
+        log<level::DEBUG>("Write user data failed");
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+    return IPMI_CC_OK;
+}
+
+static constexpr const char* jsonUserName = "user_name";
+static constexpr const char* jsonPriv = "privilege";
+static constexpr const char* jsonIpmiEnabled = "ipmi_enabled";
+static constexpr const char* jsonLinkAuthEnabled = "link_auth_enabled";
+static constexpr const char* jsonAccCallbk = "access_callback";
+static constexpr const char* jsonUserEnabled = "user_enabled";
+static constexpr const char* jsonUserInSys = "user_in_system";
+static constexpr const char* jsonFixedUser = "fixed_user_name";
+
+void UserAccess::readUserData()
+{
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+
+    std::ifstream iUsrData(ipmiUserDataFile, std::ios::in | std::ios::binary);
+    if (!iUsrData.good())
+    {
+        log<level::ERR>("Error in reading IPMI user data file");
+        throw std::ios_base::failure("Error opening IPMI user data file");
+    }
+
+    Json jsonUsersTbl = Json::array();
+    jsonUsersTbl = Json::parse(iUsrData, nullptr, false);
+
+    if (jsonUsersTbl.size() != ipmiMaxUsers)
+    {
+        log<level::ERR>(
+            "Error in reading IPMI user data file - User count issues");
+        throw std::runtime_error(
+            "Corrupted IPMI user data file - invalid user count");
+    }
+    // user index 0 is reserved, starts with 1
+    for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
+    {
+        Json userInfo = jsonUsersTbl[usrIndex - 1]; // json array starts with 0.
+        if (userInfo.is_null())
+        {
+            log<level::ERR>("Error in reading IPMI user data file - "
+                            "user info corrupted");
+            throw std::runtime_error(
+                "Corrupted IPMI user data file - invalid user info");
+        }
+        std::string userName = userInfo[jsonUserName].get<std::string>();
+        std::strncpy(reinterpret_cast<char*>(usersTbl.user[usrIndex].userName),
+                     userName.c_str(), ipmiMaxUserName);
+
+        std::vector<std::string> privilege =
+            userInfo[jsonPriv].get<std::vector<std::string>>();
+        std::vector<bool> ipmiEnabled =
+            userInfo[jsonIpmiEnabled].get<std::vector<bool>>();
+        std::vector<bool> linkAuthEnabled =
+            userInfo[jsonLinkAuthEnabled].get<std::vector<bool>>();
+        std::vector<bool> accessCallback =
+            userInfo[jsonAccCallbk].get<std::vector<bool>>();
+        if (privilege.size() != ipmiMaxChannels ||
+            ipmiEnabled.size() != ipmiMaxChannels ||
+            linkAuthEnabled.size() != ipmiMaxChannels ||
+            accessCallback.size() != ipmiMaxChannels)
+        {
+            log<level::ERR>("Error in reading IPMI user data file - "
+                            "properties corrupted");
+            throw std::runtime_error(
+                "Corrupted IPMI user data file - properties");
+        }
+        for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
+        {
+            usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege =
+                static_cast<uint8_t>(
+                    convertToIPMIPrivilege(privilege[chIndex]));
+            usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled =
+                ipmiEnabled[chIndex];
+            usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled =
+                linkAuthEnabled[chIndex];
+            usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback =
+                accessCallback[chIndex];
+        }
+        usersTbl.user[usrIndex].userEnabled =
+            userInfo[jsonUserEnabled].get<bool>();
+        usersTbl.user[usrIndex].userInSystem =
+            userInfo[jsonUserInSys].get<bool>();
+        usersTbl.user[usrIndex].fixedUserName =
+            userInfo[jsonFixedUser].get<bool>();
+    }
+
+    log<level::DEBUG>("User data read from IPMI data file");
+    iUsrData.close();
+    // Update the timestamp
+    fileLastUpdatedTime = getUpdatedFileTime();
+    return;
+}
+
+void UserAccess::writeUserData()
+{
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+
+    static std::string tmpFile{std::string(ipmiUserDataFile) + "_tmp"};
+    std::ofstream oUsrData(tmpFile, std::ios::out | std::ios::binary);
+    if (!oUsrData.good())
+    {
+        log<level::ERR>("Error in creating temporary IPMI user data file");
+        throw std::ios_base::failure(
+            "Error in creating temporary IPMI user data file");
+    }
+
+    Json jsonUsersTbl = Json::array();
+    // user index 0 is reserved, starts with 1
+    for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
+    {
+        Json jsonUserInfo;
+        jsonUserInfo[jsonUserName] = std::string(
+            reinterpret_cast<char*>(usersTbl.user[usrIndex].userName), 0,
+            ipmiMaxUserName);
+        std::vector<std::string> privilege(ipmiMaxChannels);
+        std::vector<bool> ipmiEnabled(ipmiMaxChannels);
+        std::vector<bool> linkAuthEnabled(ipmiMaxChannels);
+        std::vector<bool> accessCallback(ipmiMaxChannels);
+        for (size_t chIndex = 0; chIndex < ipmiMaxChannels; chIndex++)
+        {
+            privilege[chIndex] =
+                convertToSystemPrivilege(static_cast<CommandPrivilege>(
+                    usersTbl.user[usrIndex].userPrivAccess[chIndex].privilege));
+            ipmiEnabled[chIndex] =
+                usersTbl.user[usrIndex].userPrivAccess[chIndex].ipmiEnabled;
+            linkAuthEnabled[chIndex] =
+                usersTbl.user[usrIndex].userPrivAccess[chIndex].linkAuthEnabled;
+            accessCallback[chIndex] =
+                usersTbl.user[usrIndex].userPrivAccess[chIndex].accessCallback;
+        }
+        jsonUserInfo[jsonPriv] = privilege;
+        jsonUserInfo[jsonIpmiEnabled] = ipmiEnabled;
+        jsonUserInfo[jsonLinkAuthEnabled] = linkAuthEnabled;
+        jsonUserInfo[jsonAccCallbk] = accessCallback;
+        jsonUserInfo[jsonUserEnabled] = usersTbl.user[usrIndex].userEnabled;
+        jsonUserInfo[jsonUserInSys] = usersTbl.user[usrIndex].userInSystem;
+        jsonUserInfo[jsonFixedUser] = usersTbl.user[usrIndex].fixedUserName;
+        jsonUsersTbl.push_back(jsonUserInfo);
+    }
+
+    oUsrData << jsonUsersTbl;
+    oUsrData.flush();
+    oUsrData.close();
+
+    if (std::rename(tmpFile.c_str(), ipmiUserDataFile) != 0)
+    {
+        log<level::ERR>("Error in renaming temporary IPMI user data file");
+        throw std::runtime_error("Error in renaming IPMI user data file");
+    }
+    // Update the timestamp
+    fileLastUpdatedTime = getUpdatedFileTime();
+    return;
+}
+
+bool UserAccess::addUserEntry(const std::string& userName,
+                              const std::string& sysPriv, const bool& enabled)
+{
+    UsersTbl* userData = getUsersTblPtr();
+    size_t freeIndex = 0xFF;
+    // user index 0 is reserved, starts with 1
+    for (size_t usrIndex = 1; usrIndex <= ipmiMaxUsers; ++usrIndex)
+    {
+        std::string curName(
+            reinterpret_cast<char*>(userData->user[usrIndex].userName), 0,
+            ipmiMaxUserName);
+        if (userName == curName)
+        {
+            log<level::DEBUG>("User name exists",
+                              entry("USER_NAME=%s", userName.c_str()));
+            return false; // user name exists.
+        }
+
+        if ((!userData->user[usrIndex].userInSystem) &&
+            (userData->user[usrIndex].userName[0] == '\0') &&
+            (freeIndex == 0xFF))
+        {
+            freeIndex = usrIndex;
+        }
+    }
+    if (freeIndex == 0xFF)
+    {
+        log<level::ERR>("No empty slots found");
+        return false;
+    }
+    std::strncpy(reinterpret_cast<char*>(userData->user[freeIndex].userName),
+                 userName.c_str(), ipmiMaxUserName);
+    uint8_t priv =
+        static_cast<uint8_t>(UserAccess::convertToIPMIPrivilege(sysPriv)) &
+        privMask;
+    for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
+    {
+        userData->user[freeIndex].userPrivAccess[chIndex].privilege = priv;
+        userData->user[freeIndex].userPrivAccess[chIndex].ipmiEnabled = true;
+        userData->user[freeIndex].userPrivAccess[chIndex].linkAuthEnabled =
+            true;
+        userData->user[freeIndex].userPrivAccess[chIndex].accessCallback = true;
+    }
+    userData->user[freeIndex].userInSystem = true;
+    userData->user[freeIndex].userEnabled = enabled;
+
+    return true;
+}
+
+void UserAccess::deleteUserIndex(const size_t& usrIdx)
+{
+    UsersTbl* userData = getUsersTblPtr();
+
+    std::string userName(
+        reinterpret_cast<char*>(userData->user[usrIdx].userName), 0,
+        ipmiMaxUserName);
+    ipmiClearUserEntryPassword(userName);
+    std::fill(static_cast<uint8_t*>(userData->user[usrIdx].userName),
+              static_cast<uint8_t*>(userData->user[usrIdx].userName) +
+                  sizeof(userData->user[usrIdx].userName),
+              0);
+    for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
+    {
+        userData->user[usrIdx].userPrivAccess[chIndex].privilege = privNoAccess;
+        userData->user[usrIdx].userPrivAccess[chIndex].ipmiEnabled = false;
+        userData->user[usrIdx].userPrivAccess[chIndex].linkAuthEnabled = false;
+        userData->user[usrIdx].userPrivAccess[chIndex].accessCallback = false;
+    }
+    userData->user[usrIdx].userInSystem = false;
+    userData->user[usrIdx].userEnabled = false;
+    return;
+}
+
+void UserAccess::checkAndReloadUserData()
+{
+    std::time_t updateTime = getUpdatedFileTime();
+    if (updateTime != fileLastUpdatedTime || updateTime == -EIO)
+    {
+        std::fill(reinterpret_cast<uint8_t*>(&usersTbl),
+                  reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0);
+        readUserData();
+    }
+    return;
+}
+
+UsersTbl* UserAccess::getUsersTblPtr()
+{
+    // reload data before using it.
+    checkAndReloadUserData();
+    return &usersTbl;
+}
+
+void UserAccess::getSystemPrivAndGroups()
+{
+    std::map<std::string, PrivAndGroupType> properties;
+    try
+    {
+        auto method = bus.new_method_call(
+            getUserServiceName().c_str(), userMgrObjBasePath,
+            dBusPropertiesInterface, getAllPropertiesMethod);
+        method.append(userMgrInterface);
+
+        auto reply = bus.call(method);
+        reply.read(properties);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::DEBUG>("Failed to excute method",
+                          entry("METHOD=%s", getAllPropertiesMethod),
+                          entry("PATH=%s", userMgrObjBasePath));
+        return;
+    }
+    for (const auto& t : properties)
+    {
+        auto key = t.first;
+        if (key == allPrivProperty)
+        {
+            availablePrivileges = t.second.get<std::vector<std::string>>();
+        }
+        else if (key == allGrpProperty)
+        {
+            availableGroups = t.second.get<std::vector<std::string>>();
+        }
+    }
+    // TODO: Implement Supported Privilege & Groups verification logic
+    return;
+}
+
+std::time_t UserAccess::getUpdatedFileTime()
+{
+    struct stat fileStat;
+    if (stat(ipmiUserDataFile, &fileStat) != 0)
+    {
+        log<level::DEBUG>("Error in getting last updated time stamp");
+        return -EIO;
+    }
+    return fileStat.st_mtime;
+}
+
+void UserAccess::getUserProperties(const DbusUserObjProperties& properties,
+                                   std::vector<std::string>& usrGrps,
+                                   std::string& usrPriv, bool& usrEnabled)
+{
+    for (const auto& t : properties)
+    {
+        std::string key = t.first;
+        if (key == userPrivProperty)
+        {
+            usrPriv = t.second.get<std::string>();
+        }
+        else if (key == userGrpProperty)
+        {
+            usrGrps = t.second.get<std::vector<std::string>>();
+        }
+        else if (key == userEnabledProperty)
+        {
+            usrEnabled = t.second.get<bool>();
+        }
+    }
+    return;
+}
+
+int UserAccess::getUserObjProperties(const DbusUserObjValue& userObjs,
+                                     std::vector<std::string>& usrGrps,
+                                     std::string& usrPriv, bool& usrEnabled)
+{
+    auto usrObj = userObjs.find(usersInterface);
+    if (usrObj != userObjs.end())
+    {
+        getUserProperties(usrObj->second, usrGrps, usrPriv, usrEnabled);
+        return 0;
+    }
+    return -EIO;
+}
+
+void UserAccess::initUserDataFile()
+{
+    boost::interprocess::scoped_lock<boost::interprocess::named_recursive_mutex>
+        userLock{*userMutex};
+    try
+    {
+        readUserData();
+    }
+    catch (const std::ios_base::failure& e)
+    { // File is empty, create it for the first time
+        std::fill(reinterpret_cast<uint8_t*>(&usersTbl),
+                  reinterpret_cast<uint8_t*>(&usersTbl) + sizeof(usersTbl), 0);
+        // user index 0 is reserved, starts with 1
+        for (size_t userIndex = 1; userIndex <= ipmiMaxUsers; ++userIndex)
+        {
+            for (size_t chIndex = 0; chIndex < ipmiMaxChannels; ++chIndex)
+            {
+                usersTbl.user[userIndex].userPrivAccess[chIndex].privilege =
+                    privNoAccess;
+            }
+        }
+        writeUserData();
+    }
+    std::map<DbusUserObjPath, DbusUserObjValue> managedObjs;
+    try
+    {
+        auto method = bus.new_method_call(getUserServiceName().c_str(),
+                                          userMgrObjBasePath, dBusObjManager,
+                                          getManagedObjectsMethod);
+        auto reply = bus.call(method);
+        reply.read(managedObjs);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::DEBUG>("Failed to excute method",
+                          entry("METHOD=%s", getSubTreeMethod),
+                          entry("PATH=%s", userMgrObjBasePath));
+        return;
+    }
+
+    UsersTbl* userData = &usersTbl;
+    // user index 0 is reserved, starts with 1
+    for (size_t usrIdx = 1; usrIdx <= ipmiMaxUsers; ++usrIdx)
+    {
+        if ((userData->user[usrIdx].userInSystem) &&
+            (userData->user[usrIdx].userName[0] != '\0'))
+        {
+            std::vector<std::string> usrGrps;
+            std::string usrPriv;
+            bool usrEnabled;
+
+            std::string userName(
+                reinterpret_cast<char*>(userData->user[usrIdx].userName), 0,
+                ipmiMaxUserName);
+            std::string usersPath =
+                std::string(userObjBasePath) + "/" + userName;
+
+            auto usrObj = managedObjs.find(usersPath);
+            if (usrObj != managedObjs.end())
+            {
+                // User exist. Lets check and update other fileds
+                getUserObjProperties(usrObj->second, usrGrps, usrPriv,
+                                     usrEnabled);
+                if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) ==
+                    usrGrps.end())
+                {
+                    // Group "ipmi" is removed so lets remove user in IPMI
+                    deleteUserIndex(usrIdx);
+                }
+                else
+                {
+                    // Group "ipmi" is present so lets update other properties
+                    // in IPMI
+                    uint8_t priv =
+                        UserAccess::convertToIPMIPrivilege(usrPriv) & privMask;
+                    // Update all channels priv, only if it is not equivalent to
+                    // getUsrMgmtSyncIndex()
+                    if (userData->user[usrIdx]
+                            .userPrivAccess[getUsrMgmtSyncIndex()]
+                            .privilege != priv)
+                    {
+                        for (size_t chIndex = 0; chIndex < ipmiMaxChannels;
+                             ++chIndex)
+                        {
+                            userData->user[usrIdx]
+                                .userPrivAccess[chIndex]
+                                .privilege = priv;
+                        }
+                    }
+                    if (userData->user[usrIdx].userEnabled != usrEnabled)
+                    {
+                        userData->user[usrIdx].userEnabled = usrEnabled;
+                    }
+                }
+
+                // We are done with this obj. lets delete from MAP
+                managedObjs.erase(usrObj);
+            }
+            else
+            {
+                deleteUserIndex(usrIdx);
+            }
+        }
+    }
+
+    // Walk through remnaining managedObj users list
+    // Add them to ipmi data base
+    for (const auto& usrObj : managedObjs)
+    {
+        std::vector<std::string> usrGrps;
+        std::string usrPriv, userName;
+        bool usrEnabled;
+        std::string usrObjPath = std::string(usrObj.first);
+        if (getUserNameFromPath(usrObj.first.str, userName) != 0)
+        {
+            log<level::ERR>("Error in user object path");
+            continue;
+        }
+        getUserObjProperties(usrObj.second, usrGrps, usrPriv, usrEnabled);
+        // Add 'ipmi' group users
+        if (std::find(usrGrps.begin(), usrGrps.end(), ipmiGrpName) !=
+            usrGrps.end())
+        {
+            // CREATE NEW USER
+            if (true != addUserEntry(userName, usrPriv, usrEnabled))
+            {
+                break;
+            }
+        }
+    }
+
+    // All userData slots update done. Lets write the data
+    writeUserData();
+
+    return;
+}
+} // namespace ipmi
