/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    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.
 */

// Included for the default AccessControlDelegate logging enables/disables.
// See `chip_access_control_policy_logging_verbosity` in `src/app/BUILD.gn` for
// the levels available.
#include <app/AppConfig.h>

#include "AccessControl.h"

namespace chip {
namespace Access {

using chip::CATValues;
using chip::FabricIndex;
using chip::NodeId;
using namespace chip::Access;

namespace {

AccessControl defaultAccessControl;
AccessControl * globalAccessControl = &defaultAccessControl;

static_assert(((unsigned(Privilege::kAdminister) & unsigned(Privilege::kManage)) == 0) &&
                  ((unsigned(Privilege::kAdminister) & unsigned(Privilege::kOperate)) == 0) &&
                  ((unsigned(Privilege::kAdminister) & unsigned(Privilege::kView)) == 0) &&
                  ((unsigned(Privilege::kAdminister) & unsigned(Privilege::kProxyView)) == 0) &&
                  ((unsigned(Privilege::kManage) & unsigned(Privilege::kOperate)) == 0) &&
                  ((unsigned(Privilege::kManage) & unsigned(Privilege::kView)) == 0) &&
                  ((unsigned(Privilege::kManage) & unsigned(Privilege::kProxyView)) == 0) &&
                  ((unsigned(Privilege::kOperate) & unsigned(Privilege::kView)) == 0) &&
                  ((unsigned(Privilege::kOperate) & unsigned(Privilege::kProxyView)) == 0) &&
                  ((unsigned(Privilege::kView) & unsigned(Privilege::kProxyView)) == 0),
              "Privilege bits must be unique");

bool CheckRequestPrivilegeAgainstEntryPrivilege(Privilege requestPrivilege, Privilege entryPrivilege)
{
    switch (entryPrivilege)
    {
    case Privilege::kView:
        return requestPrivilege == Privilege::kView;
    case Privilege::kProxyView:
        return requestPrivilege == Privilege::kProxyView || requestPrivilege == Privilege::kView;
    case Privilege::kOperate:
        return requestPrivilege == Privilege::kOperate || requestPrivilege == Privilege::kView;
    case Privilege::kManage:
        return requestPrivilege == Privilege::kManage || requestPrivilege == Privilege::kOperate ||
            requestPrivilege == Privilege::kView;
    case Privilege::kAdminister:
        return requestPrivilege == Privilege::kAdminister || requestPrivilege == Privilege::kManage ||
            requestPrivilege == Privilege::kOperate || requestPrivilege == Privilege::kView ||
            requestPrivilege == Privilege::kProxyView;
    }
    return false;
}

constexpr bool IsValidCaseNodeId(NodeId aNodeId)
{
    if (IsOperationalNodeId(aNodeId))
    {
        return true;
    }

    if (IsCASEAuthTag(aNodeId) && (GetCASEAuthTagVersion(CASEAuthTagFromNodeId(aNodeId)) != 0))
    {
        return true;
    }

    return false;
}

constexpr bool IsValidGroupNodeId(NodeId aNodeId)
{
    return IsGroupId(aNodeId) && IsValidGroupId(GroupIdFromNodeId(aNodeId));
}

#if CHIP_PROGRESS_LOGGING && CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1

char GetAuthModeStringForLogging(AuthMode authMode)
{
    switch (authMode)
    {
    case AuthMode::kNone:
        return 'n';
    case AuthMode::kPase:
        return 'p';
    case AuthMode::kCase:
        return 'c';
    case AuthMode::kGroup:
        return 'g';
    }
    return 'u';
}

constexpr int kCharsPerCatForLogging = 11; // including final null terminator

char * GetCatStringForLogging(char * buf, size_t size, const CATValues & cats)
{
    if (size == 0)
    {
        return nullptr;
    }
    char * p         = buf;
    char * const end = buf + size;
    *p               = '\0';
    // Format string chars needed:
    //   1 for comma (optional)
    //   2 for 0x prefix
    //   8 for 32-bit hex value
    //   1 for null terminator (at end)
    constexpr char fmtWithoutComma[] = "0x%08" PRIX32;
    constexpr char fmtWithComma[]    = ",0x%08" PRIX32;
    constexpr int countWithoutComma  = 10;
    constexpr int countWithComma     = countWithoutComma + 1;
    bool withComma                   = false;
    for (auto cat : cats.values)
    {
        if (cat == chip::kUndefinedCAT)
        {
            break;
        }
        snprintf(p, static_cast<size_t>(end - p), withComma ? fmtWithComma : fmtWithoutComma, cat);
        p += withComma ? countWithComma : countWithoutComma;
        if (p >= end)
        {
            // Output was truncated.
            p = end - ((size < 4) ? size : 4);
            while (*p)
            {
                // Indicate truncation if possible.
                *p++ = '.';
            }
            break;
        }
        withComma = true;
    }
    return buf;
}

char GetPrivilegeStringForLogging(Privilege privilege)
{
    switch (privilege)
    {
    case Privilege::kView:
        return 'v';
    case Privilege::kProxyView:
        return 'p';
    case Privilege::kOperate:
        return 'o';
    case Privilege::kManage:
        return 'm';
    case Privilege::kAdminister:
        return 'a';
    }
    return 'u';
}

#endif // CHIP_PROGRESS_LOGGING && CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1

} // namespace

AccessControl::Entry::Delegate AccessControl::Entry::mDefaultDelegate;
AccessControl::EntryIterator::Delegate AccessControl::EntryIterator::mDefaultDelegate;

CHIP_ERROR AccessControl::Init(AccessControl::Delegate * delegate, DeviceTypeResolver & deviceTypeResolver)
{
    VerifyOrReturnError(!IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    ChipLogProgress(DataManagement, "AccessControl: initializing");

    VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    CHIP_ERROR retval = delegate->Init();
    if (retval == CHIP_NO_ERROR)
    {
        mDelegate           = delegate;
        mDeviceTypeResolver = &deviceTypeResolver;
    }

    return retval;
}

void AccessControl::Finish()
{
    VerifyOrReturn(IsInitialized());
    ChipLogProgress(DataManagement, "AccessControl: finishing");
    mDelegate->Finish();
    mDelegate = nullptr;
}

CHIP_ERROR AccessControl::CreateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t * index,
                                      const Entry & entry)
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    size_t count    = 0;
    size_t maxCount = 0;
    ReturnErrorOnFailure(mDelegate->GetEntryCount(fabric, count));
    ReturnErrorOnFailure(mDelegate->GetMaxEntriesPerFabric(maxCount));

    VerifyOrReturnError((count + 1) <= maxCount, CHIP_ERROR_BUFFER_TOO_SMALL);

    ReturnErrorCodeIf(!IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);

    size_t i = 0;
    ReturnErrorOnFailure(mDelegate->CreateEntry(&i, entry, &fabric));

    if (index)
    {
        *index = i;
    }

    NotifyEntryChanged(subjectDescriptor, fabric, i, &entry, EntryListener::ChangeType::kAdded);
    return CHIP_NO_ERROR;
}

CHIP_ERROR AccessControl::UpdateEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index,
                                      const Entry & entry)
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(!IsValid(entry), CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorOnFailure(mDelegate->UpdateEntry(index, entry, &fabric));
    NotifyEntryChanged(subjectDescriptor, fabric, index, &entry, EntryListener::ChangeType::kUpdated);
    return CHIP_NO_ERROR;
}

CHIP_ERROR AccessControl::DeleteEntry(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index)
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
    Entry entry;
    Entry * p = nullptr;
    if (mEntryListener != nullptr && ReadEntry(fabric, index, entry) == CHIP_NO_ERROR)
    {
        p = &entry;
    }
    ReturnErrorOnFailure(mDelegate->DeleteEntry(index, &fabric));
    if (p && p->HasDefaultDelegate())
    {
        // The entry was read prior to deletion so its latest value could be provided
        // to the listener after deletion. If it's been reset to its default delegate,
        // that best effort attempt to retain the latest value failed. This is
        // regrettable but OK.
        p = nullptr;
    }
    NotifyEntryChanged(subjectDescriptor, fabric, index, p, EntryListener::ChangeType::kRemoved);
    return CHIP_NO_ERROR;
}

void AccessControl::AddEntryListener(EntryListener & listener)
{
    if (mEntryListener == nullptr)
    {
        mEntryListener = &listener;
        listener.mNext = nullptr;
        return;
    }

    for (EntryListener * l = mEntryListener; /**/; l = l->mNext)
    {
        if (l == &listener)
        {
            return;
        }

        if (l->mNext == nullptr)
        {
            l->mNext       = &listener;
            listener.mNext = nullptr;
            return;
        }
    }
}

void AccessControl::RemoveEntryListener(EntryListener & listener)
{
    if (mEntryListener == &listener)
    {
        mEntryListener = listener.mNext;
        listener.mNext = nullptr;
        return;
    }

    for (EntryListener * l = mEntryListener; l != nullptr; l = l->mNext)
    {
        if (l->mNext == &listener)
        {
            l->mNext       = listener.mNext;
            listener.mNext = nullptr;
            return;
        }
    }
}

CHIP_ERROR AccessControl::Check(const SubjectDescriptor & subjectDescriptor, const RequestPath & requestPath,
                                Privilege requestPrivilege)
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

#if CHIP_PROGRESS_LOGGING && CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
    {
        constexpr size_t kMaxCatsToLog = 6;
        char catLogBuf[kMaxCatsToLog * kCharsPerCatForLogging];
        ChipLogProgress(DataManagement,
                        "AccessControl: checking f=%u a=%c s=0x" ChipLogFormatX64 " t=%s c=" ChipLogFormatMEI " e=%u p=%c",
                        subjectDescriptor.fabricIndex, GetAuthModeStringForLogging(subjectDescriptor.authMode),
                        ChipLogValueX64(subjectDescriptor.subject),
                        GetCatStringForLogging(catLogBuf, sizeof(catLogBuf), subjectDescriptor.cats),
                        ChipLogValueMEI(requestPath.cluster), requestPath.endpoint, GetPrivilegeStringForLogging(requestPrivilege));
    }
#endif // CHIP_PROGRESS_LOGGING && CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1

    {
        CHIP_ERROR result = mDelegate->Check(subjectDescriptor, requestPath, requestPrivilege);
        if (result != CHIP_ERROR_NOT_IMPLEMENTED)
        {
#if CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 0
            ChipLogProgress(DataManagement, "AccessControl: %s (delegate)",
                            (result == CHIP_NO_ERROR) ? "allowed" : (result == CHIP_ERROR_ACCESS_DENIED) ? "denied" : "error");
#else
            if (result != CHIP_NO_ERROR)
            {
                ChipLogProgress(DataManagement, "AccessControl: %s (delegate)",
                                (result == CHIP_ERROR_ACCESS_DENIED) ? "denied" : "error");
            }
#endif // CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 0
            return result;
        }
    }

    // Operational PASE not supported for v1.0, so PASE implies commissioning, which has highest privilege.
    // Currently, subject descriptor is only PASE if this node is the responder (aka commissionee);
    // if this node is the initiator (aka commissioner) then the subject descriptor remains blank.
    if (subjectDescriptor.authMode == AuthMode::kPase)
    {
#if CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
        ChipLogProgress(DataManagement, "AccessControl: implicit admin (PASE)");
#endif // CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
        return CHIP_NO_ERROR;
    }

    EntryIterator iterator;
    ReturnErrorOnFailure(Entries(iterator, &subjectDescriptor.fabricIndex));

    Entry entry;
    while (iterator.Next(entry) == CHIP_NO_ERROR)
    {
        AuthMode authMode = AuthMode::kNone;
        ReturnErrorOnFailure(entry.GetAuthMode(authMode));
        // Operational PASE not supported for v1.0.
        VerifyOrReturnError(authMode == AuthMode::kCase || authMode == AuthMode::kGroup, CHIP_ERROR_INCORRECT_STATE);
        if (authMode != subjectDescriptor.authMode)
        {
            continue;
        }

        Privilege privilege = Privilege::kView;
        ReturnErrorOnFailure(entry.GetPrivilege(privilege));
        if (!CheckRequestPrivilegeAgainstEntryPrivilege(requestPrivilege, privilege))
        {
            continue;
        }

        size_t subjectCount = 0;
        ReturnErrorOnFailure(entry.GetSubjectCount(subjectCount));
        if (subjectCount > 0)
        {
            bool subjectMatched = false;
            for (size_t i = 0; i < subjectCount; ++i)
            {
                NodeId subject = kUndefinedNodeId;
                ReturnErrorOnFailure(entry.GetSubject(i, subject));
                if (IsOperationalNodeId(subject))
                {
                    VerifyOrReturnError(authMode == AuthMode::kCase, CHIP_ERROR_INCORRECT_STATE);
                    if (subject == subjectDescriptor.subject)
                    {
                        subjectMatched = true;
                        break;
                    }
                }
                else if (IsCASEAuthTag(subject))
                {
                    VerifyOrReturnError(authMode == AuthMode::kCase, CHIP_ERROR_INCORRECT_STATE);
                    if (subjectDescriptor.cats.CheckSubjectAgainstCATs(subject))
                    {
                        subjectMatched = true;
                        break;
                    }
                }
                else if (IsGroupId(subject))
                {
                    VerifyOrReturnError(authMode == AuthMode::kGroup, CHIP_ERROR_INCORRECT_STATE);
                    if (subject == subjectDescriptor.subject)
                    {
                        subjectMatched = true;
                        break;
                    }
                }
                else
                {
                    // Operational PASE not supported for v1.0.
                    return CHIP_ERROR_INCORRECT_STATE;
                }
            }
            if (!subjectMatched)
            {
                continue;
            }
        }

        size_t targetCount = 0;
        ReturnErrorOnFailure(entry.GetTargetCount(targetCount));
        if (targetCount > 0)
        {
            bool targetMatched = false;
            for (size_t i = 0; i < targetCount; ++i)
            {
                Entry::Target target;
                ReturnErrorOnFailure(entry.GetTarget(i, target));
                if ((target.flags & Entry::Target::kCluster) && target.cluster != requestPath.cluster)
                {
                    continue;
                }
                if ((target.flags & Entry::Target::kEndpoint) && target.endpoint != requestPath.endpoint)
                {
                    continue;
                }
                if (target.flags & Entry::Target::kDeviceType &&
                    !mDeviceTypeResolver->IsDeviceTypeOnEndpoint(target.deviceType, requestPath.endpoint))
                {
                    continue;
                }
                targetMatched = true;
                break;
            }
            if (!targetMatched)
            {
                continue;
            }
        }
        // Entry passed all checks: access is allowed.

#if CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 0
        ChipLogProgress(DataManagement, "AccessControl: allowed");
#endif // CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 0

        return CHIP_NO_ERROR;
    }

    // No entry was found which passed all checks: access is denied.
    ChipLogProgress(DataManagement, "AccessControl: denied");
    return CHIP_ERROR_ACCESS_DENIED;
}

#if CHIP_ACCESS_CONTROL_DUMP_ENABLED
CHIP_ERROR AccessControl::Dump(const Entry & entry)
{
    CHIP_ERROR err;

    ChipLogDetail(DataManagement, "----- BEGIN ENTRY -----");

    {
        FabricIndex fabricIndex;
        SuccessOrExit(err = entry.GetFabricIndex(fabricIndex));
        ChipLogDetail(DataManagement, "fabricIndex: %u", fabricIndex);
    }

    {
        Privilege privilege;
        SuccessOrExit(err = entry.GetPrivilege(privilege));
        ChipLogDetail(DataManagement, "privilege: %d", to_underlying(privilege));
    }

    {
        AuthMode authMode;
        SuccessOrExit(err = entry.GetAuthMode(authMode));
        ChipLogDetail(DataManagement, "authMode: %d", to_underlying(authMode));
    }

    {
        size_t count;
        SuccessOrExit(err = entry.GetSubjectCount(count));
        if (count)
        {
            ChipLogDetail(DataManagement, "subjects: %u", static_cast<unsigned>(count));
            for (size_t i = 0; i < count; ++i)
            {
                NodeId subject;
                SuccessOrExit(err = entry.GetSubject(i, subject));
                ChipLogDetail(DataManagement, "  %u: 0x" ChipLogFormatX64, static_cast<unsigned>(i), ChipLogValueX64(subject));
            }
        }
    }

    {
        size_t count;
        SuccessOrExit(err = entry.GetTargetCount(count));
        if (count)
        {
            ChipLogDetail(DataManagement, "targets: %u", static_cast<unsigned>(count));
            for (size_t i = 0; i < count; ++i)
            {
                Entry::Target target;
                SuccessOrExit(err = entry.GetTarget(i, target));
                if (target.flags & Entry::Target::kCluster)
                {
                    ChipLogDetail(DataManagement, "  %u: cluster: 0x" ChipLogFormatMEI, static_cast<unsigned>(i),
                                  ChipLogValueMEI(target.cluster));
                }
                if (target.flags & Entry::Target::kEndpoint)
                {
                    ChipLogDetail(DataManagement, "  %u: endpoint: %u", static_cast<unsigned>(i), target.endpoint);
                }
                if (target.flags & Entry::Target::kDeviceType)
                {
                    ChipLogDetail(DataManagement, "  %u: deviceType: 0x" ChipLogFormatMEI, static_cast<unsigned>(i),
                                  ChipLogValueMEI(target.deviceType));
                }
            }
        }
    }

    ChipLogDetail(DataManagement, "----- END ENTRY -----");

    return CHIP_NO_ERROR;

exit:
    ChipLogError(DataManagement, "AccessControl: dump failed %" CHIP_ERROR_FORMAT, err.Format());
    return err;
}
#endif

bool AccessControl::IsValid(const Entry & entry)
{
    const char * log = "unexpected error";
    IgnoreUnusedVariable(log); // logging may be disabled

    AuthMode authMode       = AuthMode::kNone;
    FabricIndex fabricIndex = kUndefinedFabricIndex;
    Privilege privilege     = static_cast<Privilege>(0);
    size_t subjectCount     = 0;
    size_t targetCount      = 0;

    SuccessOrExit(entry.GetAuthMode(authMode));
    SuccessOrExit(entry.GetFabricIndex(fabricIndex));
    SuccessOrExit(entry.GetPrivilege(privilege));
    SuccessOrExit(entry.GetSubjectCount(subjectCount));
    SuccessOrExit(entry.GetTargetCount(targetCount));

#if CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
    ChipLogProgress(DataManagement, "AccessControl: validating f=%u p=%c a=%c s=%d t=%d", fabricIndex,
                    GetPrivilegeStringForLogging(privilege), GetAuthModeStringForLogging(authMode), static_cast<int>(subjectCount),
                    static_cast<int>(targetCount));
#endif // CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1

    // Fabric index must be defined.
    VerifyOrExit(fabricIndex != kUndefinedFabricIndex, log = "invalid fabric index");

    if (authMode != AuthMode::kCase)
    {
        // Operational PASE not supported for v1.0 (so must be group).
        VerifyOrExit(authMode == AuthMode::kGroup, log = "invalid auth mode");

        // Privilege must not be administer.
        VerifyOrExit(privilege != Privilege::kAdminister, log = "invalid privilege");
    }

    for (size_t i = 0; i < subjectCount; ++i)
    {
        NodeId subject;
        SuccessOrExit(entry.GetSubject(i, subject));
        const bool kIsCase  = authMode == AuthMode::kCase;
        const bool kIsGroup = authMode == AuthMode::kGroup;
#if CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
        ChipLogProgress(DataManagement, "  validating subject 0x" ChipLogFormatX64, ChipLogValueX64(subject));
#endif // CHIP_CONFIG_ACCESS_CONTROL_POLICY_LOGGING_VERBOSITY > 1
        VerifyOrExit((kIsCase && IsValidCaseNodeId(subject)) || (kIsGroup && IsValidGroupNodeId(subject)), log = "invalid subject");
    }

    for (size_t i = 0; i < targetCount; ++i)
    {
        Entry::Target target;
        SuccessOrExit(entry.GetTarget(i, target));
        const bool kHasCluster    = target.flags & Entry::Target::kCluster;
        const bool kHasEndpoint   = target.flags & Entry::Target::kEndpoint;
        const bool kHasDeviceType = target.flags & Entry::Target::kDeviceType;
        VerifyOrExit((kHasCluster || kHasEndpoint || kHasDeviceType) && !(kHasEndpoint && kHasDeviceType) &&
                         (!kHasCluster || IsValidClusterId(target.cluster)) &&
                         (!kHasEndpoint || IsValidEndpointId(target.endpoint)) &&
                         (!kHasDeviceType || IsValidDeviceTypeId(target.deviceType)),
                     log = "invalid target");
    }

    return true;

exit:
    ChipLogError(DataManagement, "AccessControl: %s", log);
    return false;
}

void AccessControl::NotifyEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index,
                                       const Entry * entry, EntryListener::ChangeType changeType)
{
    for (EntryListener * listener = mEntryListener; listener != nullptr; listener = listener->mNext)
    {
        listener->OnEntryChanged(subjectDescriptor, fabric, index, entry, changeType);
    }
}

AccessControl & GetAccessControl()
{
    return *globalAccessControl;
}

void SetAccessControl(AccessControl & accessControl)
{
    ChipLogProgress(DataManagement, "AccessControl: setting");
    globalAccessControl = &accessControl;
}

void ResetAccessControlToDefault()
{
    globalAccessControl = &defaultAccessControl;
}

} // namespace Access
} // namespace chip
