/*
// 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 "usercommands.hpp"

#include "channel_layer.hpp"
#include "user_layer.hpp"

#include <security/pam_appl.h>

#include <ipmid/api.hpp>
#include <phosphor-logging/lg2.hpp>

#include <regex>

namespace ipmi
{

static constexpr uint8_t enableOperation = 0x00;
static constexpr uint8_t disableOperation = 0x01;

/** @brief implements the set user access command
 *  @param ctx - IPMI context pointer (for channel)
 *  @param channel - channel number
 *  @param ipmiEnabled - indicates ipmi messaging state
 *  @param linkAuthEnabled - indicates link authentication state
 *  @param accessCallback - indicates callback state
 *  @param bitsUpdate - indicates update request
 *  @param userId - user id
 *  @param reserved1 - skip 2 bits
 *  @param privilege - user privilege
 *  @param reserved2 - skip 4 bits
 *  @param sessionLimit - optional - unused for now
 *
 *  @returns ipmi completion code
 */
ipmi::RspType<> ipmiSetUserAccess(
    ipmi::Context::ptr ctx, uint4_t channel, uint1_t ipmiEnabled,
    uint1_t linkAuthEnabled, uint1_t accessCallback, uint1_t bitsUpdate,

    uint6_t userId, uint2_t reserved1,

    uint4_t privilege, uint4_t reserved2,

    std::optional<uint8_t> sessionLimit)
{
    uint8_t sessLimit = sessionLimit.value_or(0);
    if (reserved1 || reserved2 || sessLimit ||
        !ipmiUserIsValidPrivilege(static_cast<uint8_t>(privilege)))
    {
        lg2::debug("Set user access - Invalid field in request");
        return ipmi::responseInvalidFieldRequest();
    }

    uint8_t chNum =
        convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
    if (!isValidChannel(chNum))
    {
        lg2::debug("Set user access - Invalid channel request: {CHANNEL}",
                   "CHANNEL", chNum);
        return ipmi::response(invalidChannel);
    }
    if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
    {
        lg2::debug("Set user access - No support on channel");
        return ipmi::response(ccActionNotSupportedForChannel);
    }
    if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
    {
        lg2::debug("Set user access - Parameter out of range");
        return ipmi::responseParmOutOfRange();
    }

    PrivAccess privAccess = {};
    if (bitsUpdate)
    {
        privAccess.ipmiEnabled = static_cast<uint8_t>(ipmiEnabled);
        privAccess.linkAuthEnabled = static_cast<uint8_t>(linkAuthEnabled);
        privAccess.accessCallback = static_cast<uint8_t>(accessCallback);
    }
    privAccess.privilege = static_cast<uint8_t>(privilege);
    return ipmi::response(
        ipmiUserSetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
                                   privAccess, static_cast<bool>(bitsUpdate)));
}

/** @brief implements the set user access command
 *  @param ctx - IPMI context pointer (for channel)
 *  @param channel - channel number
 *  @param reserved1 - skip 4 bits
 *  @param userId - user id
 *  @param reserved2 - skip 2 bits
 *
 *  @returns ipmi completion code plus response data
 *   - maxChUsers - max channel users
 *   - reserved1 - skip 2 bits
 *   - enabledUsers - enabled users count
 *   - enabledStatus - enabled status
 *   - fixedUsers - fixed users count
 *   - reserved2 - skip 2 bits
 *   - privilege - user privilege
 *   - ipmiEnabled - ipmi messaging state
 *   - linkAuthEnabled - link authenticatin state
 *   - accessCallback - callback state
 *   - reserved - skip 1 bit
 */
ipmi::RspType<uint6_t, // max channel users
              uint2_t, // reserved1

              uint6_t, // enabled users count
              uint2_t, // enabled status

              uint6_t, // fixed users count
              uint2_t, // reserved2

              uint4_t, // privilege
              uint1_t, // ipmi messaging state
              uint1_t, // link authentication state
              uint1_t, // access callback state
              uint1_t  // reserved3
              >
    ipmiGetUserAccess(ipmi::Context::ptr ctx, uint4_t channel,
                      uint4_t reserved1,

                      uint6_t userId, uint2_t reserved2)
{
    uint8_t chNum =
        convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);

    if (reserved1 || reserved2 || !isValidChannel(chNum))
    {
        lg2::debug("Get user access - Invalid field in request");
        return ipmi::responseInvalidFieldRequest();
    }

    if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
    {
        lg2::debug("Get user access - No support on channel");
        return ipmi::response(ccActionNotSupportedForChannel);
    }
    if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
    {
        lg2::debug("Get user access - Parameter out of range");
        return ipmi::responseParmOutOfRange();
    }

    uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
    ipmi::Cc retStatus;
    retStatus = ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
    if (retStatus != ccSuccess)
    {
        return ipmi::response(retStatus);
    }

    bool enabledState = false;
    retStatus =
        ipmiUserCheckEnabled(static_cast<uint8_t>(userId), enabledState);
    if (retStatus != ccSuccess)
    {
        return ipmi::response(retStatus);
    }

    uint2_t enabledStatus = enabledState ? userIdEnabledViaSetPassword
                                         : userIdDisabledViaSetPassword;
    PrivAccess privAccess{};
    retStatus = ipmiUserGetPrivilegeAccess(static_cast<uint8_t>(userId), chNum,
                                           privAccess);
    if (retStatus != ccSuccess)
    {
        return ipmi::response(retStatus);
    }
    constexpr uint2_t res2Bits = 0;
    return ipmi::responseSuccess(
        static_cast<uint6_t>(maxChUsers), res2Bits,

        static_cast<uint6_t>(enabledUsers), enabledStatus,

        static_cast<uint6_t>(fixedUsers), res2Bits,

        static_cast<uint4_t>(privAccess.privilege),
        static_cast<uint1_t>(privAccess.ipmiEnabled),
        static_cast<uint1_t>(privAccess.linkAuthEnabled),
        static_cast<uint1_t>(privAccess.accessCallback),
        static_cast<uint1_t>(privAccess.reserved));
}

/** @brief implementes the get user name command
 *  @param[in] ctx - ipmi command context
 *  @param[in] userId - 6-bit user ID
 *  @param[in] reserved - 2-bits reserved
 *  @param[in] name - 16-byte array for username

 *  @returns ipmi response
 */
ipmi::RspType<> ipmiSetUserName(
    [[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id, uint2_t reserved,
    const std::array<uint8_t, ipmi::ipmiMaxUserName>& name)
{
    if (reserved)
    {
        return ipmi::responseInvalidFieldRequest();
    }
    uint8_t userId = static_cast<uint8_t>(id);
    if (!ipmiUserIsValidUserId(userId))
    {
        lg2::debug("Set user name - Invalid user id");
        return ipmi::responseParmOutOfRange();
    }

    size_t nameLen = strnlen(reinterpret_cast<const char*>(name.data()),
                             ipmi::ipmiMaxUserName);
    const std::string strUserName(reinterpret_cast<const char*>(name.data()),
                                  nameLen);

    ipmi::Cc res = ipmiUserSetUserName(userId, strUserName);
    return ipmi::response(res);
}

/** @brief implementes the get user name command
 *  @param[in] ctx - ipmi command context
 *  @param[in] userId - 6-bit user ID
 *  @param[in] reserved - 2-bits reserved

 *  @returns ipmi response with 16-byte username
 */
ipmi::RspType<std::array<uint8_t, ipmi::ipmiMaxUserName>> // user name
    ipmiGetUserName([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
                    uint2_t reserved)
{
    if (reserved)
    {
        return ipmi::responseInvalidFieldRequest();
    }

    uint8_t userId = static_cast<uint8_t>(id);
    std::string userName;
    if (ipmiUserGetUserName(userId, userName) != ccSuccess)
    { // Invalid User ID
        lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
                   userId);
        return ipmi::responseParmOutOfRange();
    }
    // copy the std::string into a fixed array
    if (userName.size() > ipmi::ipmiMaxUserName)
    {
        return ipmi::responseUnspecifiedError();
    }
    std::array<uint8_t, ipmi::ipmiMaxUserName> userNameFixed;
    std::fill(userNameFixed.begin(), userNameFixed.end(), 0);
    std::copy(userName.begin(), userName.end(), userNameFixed.begin());
    return ipmi::responseSuccess(std::move(userNameFixed));
}

/** @brief implementes the get user name command
 *  @param[in] ctx - ipmi command context
 *  @param[in] userId - 6-bit user ID
 *  @param[in] reserved - 2-bits reserved

 *  @returns ipmi response with 16-byte username
 */
ipmi::RspType<> // user name
    ipmiSetUserPassword([[maybe_unused]] ipmi::Context::ptr ctx, uint6_t id,
                        bool reserved1, bool pwLen20, uint2_t operation,
                        uint6_t reserved2, SecureBuffer& userPassword)
{
    if (reserved1 || reserved2)
    {
        lg2::debug("Invalid data field in request");
        return ipmi::responseInvalidFieldRequest();
    }

    static constexpr uint2_t opDisableUser = 0x00;
    static constexpr uint2_t opEnableUser = 0x01;
    static constexpr uint2_t opSetPassword = 0x02;
    static constexpr uint2_t opTestPassword = 0x03;

    // If set / test password operation then password size has to be 16 or 20
    // bytes based on the password size bit
    if (((operation == opSetPassword) || (operation == opTestPassword)) &&
        ((pwLen20 && (userPassword.size() != maxIpmi20PasswordSize)) ||
         (!pwLen20 && (userPassword.size() != maxIpmi15PasswordSize))))
    {
        lg2::debug("Invalid Length");
        return ipmi::responseReqDataLenInvalid();
    }

    size_t passwordLength = userPassword.size();

    uint8_t userId = static_cast<uint8_t>(id);
    std::string userName;
    if (ipmiUserGetUserName(userId, userName) != ccSuccess)
    {
        lg2::debug("User Name not found, user Id: {USER_ID}", "USER_ID",
                   userId);
        return ipmi::responseParmOutOfRange();
    }

    if (operation == opSetPassword)
    {
        // turn the non-nul terminated SecureBuffer into a SecureString
        SecureString password(
            reinterpret_cast<const char*>(userPassword.data()), passwordLength);
        ipmi::Cc res = ipmiUserSetUserPassword(userId, password.data());
        return ipmi::response(res);
    }
    else if (operation == opEnableUser || operation == opDisableUser)
    {
        ipmi::Cc res =
            ipmiUserUpdateEnabledState(userId, static_cast<bool>(operation));
        return ipmi::response(res);
    }
    else if (operation == opTestPassword)
    {
        SecureString password = ipmiUserGetPassword(userName);
        // extend with zeros, if needed
        if (password.size() < passwordLength)
        {
            password.resize(passwordLength, '\0');
        }
        SecureString testPassword(
            reinterpret_cast<const char*>(userPassword.data()), passwordLength);
        // constant time string compare: always compare exactly as many bytes
        // as the length of the input, resizing the actual password to match,
        // maintaining a knowledge if the sizes differed originally
        static const std::array<char, maxIpmi20PasswordSize> empty = {'\0'};
        size_t cmpLen = testPassword.size();
        bool pwLenDiffers = password.size() != cmpLen;
        const char* cmpPassword = nullptr;
        if (pwLenDiffers)
        {
            cmpPassword = empty.data();
        }
        else
        {
            cmpPassword = password.data();
        }
        bool pwBad = CRYPTO_memcmp(cmpPassword, testPassword.data(), cmpLen);
        pwBad |= pwLenDiffers;
        if (pwBad)
        {
            lg2::debug("Test password failed, user Id: {USER_ID}", "USER_ID",
                       userId);
            return ipmi::response(ipmiCCPasswdFailMismatch);
        }
        return ipmi::responseSuccess();
    }
    return ipmi::responseInvalidFieldRequest();
}

/** @brief implements the get channel authentication command
 *  @param ctx - IPMI context pointer (for channel)
 *  @param extData - get IPMI 2.0 extended data
 *  @param reserved1 - skip 3 bits
 *  @param chNum - channel number to get info about
 *  @param reserved2 - skip 4 bits
 *  @param privLevel - requested privilege level

 *  @returns ipmi completion code plus response data
 *   - channel number
 *   - rmcpAuthTypes - RMCP auth types (IPMI 1.5)
 *   - reserved1
 *   - extDataSupport - true for IPMI 2.0 extensions
 *   - anonymousLogin - true for anonymous login enabled
 *   - nullUsers - true for null user names enabled
 *   - nonNullUsers - true for non-null usernames enabled
 *   - userAuth - false for user authentication enabled
 *   - perMessageAuth - false for per message authentication enabled
 *   - KGStatus - true for Kg required for authentication
 *   - reserved2
 *   - rmcp - RMCP (IPMI 1.5) connection support
 *   - rmcpp - RMCP+ (IPMI 2.0) connection support
 *   - reserved3
 *   - oemID - OEM IANA of any OEM auth support
 *   - oemAuxillary - OEM data for auth
 */
ipmi::RspType<uint8_t,  // channel number
              uint6_t,  // rmcpAuthTypes
              bool,     // reserved1
              bool,     // extDataSupport
              bool,     // anonymousLogin
              bool,     // nullUsers
              bool,     // nonNullUsers
              bool,     // userAuth
              bool,     // perMessageAuth
              bool,     // KGStatus
              uint2_t,  // reserved2
              bool,     // rmcp
              bool,     // rmcpp
              uint6_t,  // reserved3
              uint24_t, // oemID
              uint8_t   // oemAuxillary
              >
    ipmiGetChannelAuthenticationCapabilities(
        ipmi::Context::ptr ctx, uint4_t chNum, uint3_t reserved1,
        [[maybe_unused]] bool extData, uint4_t privLevel, uint4_t reserved2)
{
    uint8_t channel =
        convertCurrentChannelNum(static_cast<uint8_t>(chNum), ctx->channel);

    if (reserved1 || reserved2 || !isValidChannel(channel) ||
        !isValidPrivLimit(static_cast<uint8_t>(privLevel)))
    {
        lg2::debug("Get channel auth capabilities - Invalid field in request");
        return ipmi::responseInvalidFieldRequest();
    }

    if (getChannelSessionSupport(channel) == EChannelSessSupported::none)
    {
        lg2::debug("Get channel auth capabilities - No support on channel");
        return ipmi::response(ccActionNotSupportedForChannel);
    }

    constexpr bool extDataSupport = true; // true for IPMI 2.0 extensions
    constexpr bool reserved3 = false;
    constexpr uint6_t rmcpAuthTypes = 0;  // IPMI 1.5 auth types - not supported
    constexpr uint2_t reserved4 = 0;
    constexpr bool KGStatus = false;      // Not supporting now.
    constexpr bool perMessageAuth = false; // Per message auth - enabled
    constexpr bool userAuth = false;       // User authentication - enabled
    constexpr bool nullUsers = false;      // Null user names - not supported
    constexpr bool anonymousLogin = false; // Anonymous login - not supported
    constexpr uint6_t reserved5 = 0;
    constexpr bool rmcpp = true;           // IPMI 2.0 - supported
    constexpr bool rmcp = false;           // IPMI 1.5 - not supported
    constexpr uint24_t oemID = 0;
    constexpr uint8_t oemAuxillary = 0;

    bool nonNullUsers = 0;
    uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
    ipmi::ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers);
    nonNullUsers = enabledUsers > 0;

    return ipmi::responseSuccess(
        channel, rmcpAuthTypes, reserved3, extDataSupport, anonymousLogin,
        nullUsers, nonNullUsers, userAuth, perMessageAuth, KGStatus, reserved4,
        rmcp, rmcpp, reserved5, oemID, oemAuxillary);
}

/** @brief implements the set user payload access command.
 *  @param ctx - IPMI context pointer (for channel)
 *  @param channel - channel number (4 bits)
 *  @param reserved1 - skip 4 bits
 *  @param userId - user id (6 bits)
 *  @param operation - access ENABLE /DISABLE. (2 bits)
 *  @param stdPayload0 - IPMI - reserved. (1 bit)
 *  @param stdPayload1 - SOL.             (1 bit)
 *  @param stdPayload2 -                  (1 bit)
 *  @param stdPayload3 -                  (1 bit)
 *  @param stdPayload4 -                  (1 bit)
 *  @param stdPayload5 -                  (1 bit)
 *  @param stdPayload6 -                  (1 bit)
 *  @param stdPayload7 -                  (1 bit)
 *  @param stdPayloadEnables2Reserved -   (8 bits)
 *  @param oemPayload0 -                  (1 bit)
 *  @param oemPayload1 -                  (1 bit)
 *  @param oemPayload2 -                  (1 bit)
 *  @param oemPayload3 -                  (1 bit)
 *  @param oemPayload4 -                  (1 bit)
 *  @param oemPayload5 -                  (1 bit)
 *  @param oemPayload6 -                  (1 bit)
 *  @param oemPayload7 -                  (1 bit)
 *  @param oemPayloadEnables2Reserved -   (8 bits)
 *
 *  @returns IPMI completion code
 */
ipmi::RspType<> ipmiSetUserPayloadAccess(
    ipmi::Context::ptr ctx,

    uint4_t channel, uint4_t reserved,

    uint6_t userId, uint2_t operation,

    bool stdPayload0ipmiReserved, bool stdPayload1SOL, bool stdPayload2,
    bool stdPayload3, bool stdPayload4, bool stdPayload5, bool stdPayload6,
    bool stdPayload7,

    uint8_t stdPayloadEnables2Reserved,

    bool oemPayload0, bool oemPayload1, bool oemPayload2, bool oemPayload3,
    bool oemPayload4, bool oemPayload5, bool oemPayload6, bool oemPayload7,

    uint8_t oemPayloadEnables2Reserved)
{
    auto chNum =
        convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);
    // Validate the reserved args. Only SOL payload is supported as on date.
    if (reserved || stdPayload0ipmiReserved || stdPayload2 || stdPayload3 ||
        stdPayload4 || stdPayload5 || stdPayload6 || stdPayload7 ||
        oemPayload0 || oemPayload1 || oemPayload2 || oemPayload3 ||
        oemPayload4 || oemPayload5 || oemPayload6 || oemPayload7 ||
        stdPayloadEnables2Reserved || oemPayloadEnables2Reserved ||
        !isValidChannel(chNum))
    {
        return ipmi::responseInvalidFieldRequest();
    }

    if ((operation != enableOperation && operation != disableOperation))
    {
        return ipmi::responseInvalidFieldRequest();
    }
    if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
    {
        return ipmi::response(ccActionNotSupportedForChannel);
    }
    if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
    {
        return ipmi::responseParmOutOfRange();
    }

    PayloadAccess payloadAccess = {};
    payloadAccess.stdPayloadEnables1[1] = stdPayload1SOL;

    return ipmi::response(ipmiUserSetUserPayloadAccess(
        chNum, static_cast<uint8_t>(operation), static_cast<uint8_t>(userId),
        payloadAccess));
}

/** @brief implements the get user payload access command
 *  This command returns information about user payload enable settings
 *  that were set using the 'Set User Payload Access' Command.
 *
 *  @param ctx - IPMI context pointer (for channel)
 *  @param channel - channel number
 *  @param reserved1 - skip 4 bits
 *  @param userId - user id
 *  @param reserved2 - skip 2 bits
 *
 *  @returns IPMI completion code plus response data
 *   - stdPayload0ipmiReserved - IPMI payload (reserved).
 *   - stdPayload1SOL - SOL payload
 *   - stdPayload2
 *   - stdPayload3
 *   - stdPayload4
 *   - stdPayload5
 *   - stdPayload6
 *   - stdPayload7

 *   - stdPayloadEnables2Reserved - Reserved.

 *   - oemPayload0
 *   - oemPayload1
 *   - oemPayload2
 *   - oemPayload3
 *   - oemPayload4
 *   - oemPayload5
 *   - oemPayload6
 *   - oemPayload7

 *  - oemPayloadEnables2Reserved - Reserved
 */
ipmi::RspType<bool,    // stdPayload0ipmiReserved
              bool,    // stdPayload1SOL
              bool,    // stdPayload2
              bool,    // stdPayload3
              bool,    // stdPayload4
              bool,    // stdPayload5
              bool,    // stdPayload6
              bool,    // stdPayload7

              uint8_t, // stdPayloadEnables2Reserved

              bool,    // oemPayload0
              bool,    // oemPayload1
              bool,    // oemPayload2
              bool,    // oemPayload3
              bool,    // oemPayload4
              bool,    // oemPayload5
              bool,    // oemPayload6
              bool,    // oemPayload7

              uint8_t  // oemPayloadEnables2Reserved
              >
    ipmiGetUserPayloadAccess(ipmi::Context::ptr ctx,

                             uint4_t channel, uint4_t reserved1,

                             uint6_t userId, uint2_t reserved2)
{
    uint8_t chNum =
        convertCurrentChannelNum(static_cast<uint8_t>(channel), ctx->channel);

    if (reserved1 || reserved2 || !isValidChannel(chNum))
    {
        return ipmi::responseInvalidFieldRequest();
    }
    if (getChannelSessionSupport(chNum) == EChannelSessSupported::none)
    {
        return ipmi::response(ccActionNotSupportedForChannel);
    }
    if (!ipmiUserIsValidUserId(static_cast<uint8_t>(userId)))
    {
        return ipmi::responseParmOutOfRange();
    }

    ipmi::Cc retStatus;
    PayloadAccess payloadAccess = {};
    retStatus = ipmiUserGetUserPayloadAccess(
        chNum, static_cast<uint8_t>(userId), payloadAccess);
    if (retStatus != ccSuccess)
    {
        return ipmi::response(retStatus);
    }
    constexpr uint8_t res8bits = 0;
    return ipmi::responseSuccess(
        payloadAccess.stdPayloadEnables1.test(0),
        payloadAccess.stdPayloadEnables1.test(1),
        payloadAccess.stdPayloadEnables1.test(2),
        payloadAccess.stdPayloadEnables1.test(3),
        payloadAccess.stdPayloadEnables1.test(4),
        payloadAccess.stdPayloadEnables1.test(5),
        payloadAccess.stdPayloadEnables1.test(6),
        payloadAccess.stdPayloadEnables1.test(7),

        res8bits,

        payloadAccess.oemPayloadEnables1.test(0),
        payloadAccess.oemPayloadEnables1.test(1),
        payloadAccess.oemPayloadEnables1.test(2),
        payloadAccess.oemPayloadEnables1.test(3),
        payloadAccess.oemPayloadEnables1.test(4),
        payloadAccess.oemPayloadEnables1.test(5),
        payloadAccess.oemPayloadEnables1.test(6),
        payloadAccess.oemPayloadEnables1.test(7),

        res8bits);
}

void registerUserIpmiFunctions() __attribute__((constructor));
void registerUserIpmiFunctions()
{
    post_work([]() { ipmiUserInit(); });
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdSetUserAccessCommand,
                          ipmi::Privilege::Admin, ipmiSetUserAccess);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdGetUserAccessCommand,
                          ipmi::Privilege::Admin, ipmiGetUserAccess);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdGetUserNameCommand,
                          ipmi::Privilege::Admin, ipmiGetUserName);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdSetUserName, ipmi::Privilege::Admin,
                          ipmiSetUserName);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdSetUserPasswordCommand,
                          ipmi::Privilege::Admin, ipmiSetUserPassword);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdGetChannelAuthCapabilities,
                          ipmi::Privilege::Callback,
                          ipmiGetChannelAuthenticationCapabilities);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdSetUserPayloadAccess,
                          ipmi::Privilege::Admin, ipmiSetUserPayloadAccess);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp,
                          ipmi::app::cmdGetUserPayloadAccess,
                          ipmi::Privilege::Operator, ipmiGetUserPayloadAccess);

    return;
}
} // namespace ipmi
