Matter SDK Coverage Report
Current view: top level - app/server - DefaultAclStorage.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 17.0 % 53 9
Test Date: 2025-01-17 19:00:11 Functions: 66.7 % 3 2

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2022 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #include <app/server/DefaultAclStorage.h>
      19              : 
      20              : #include <lib/support/DefaultStorageKeyAllocator.h>
      21              : 
      22              : using namespace chip;
      23              : using namespace chip::app;
      24              : using namespace chip::Access;
      25              : 
      26              : using EncodableEntry   = AclStorage::EncodableEntry;
      27              : using Entry            = AccessControl::Entry;
      28              : using EntryListener    = AccessControl::EntryListener;
      29              : using StagingAuthMode  = Clusters::AccessControl::AccessControlEntryAuthModeEnum;
      30              : using StagingPrivilege = Clusters::AccessControl::AccessControlEntryPrivilegeEnum;
      31              : using StagingTarget    = Clusters::AccessControl::Structs::AccessControlTargetStruct::Type;
      32              : using Target           = AccessControl::Entry::Target;
      33              : 
      34              : namespace {
      35              : 
      36              : /*
      37              : Size calculation for TLV encoded entry.
      38              : 
      39              : Because EncodeForWrite is used without an accessing fabric, the fabric index is
      40              : not encoded. However, let's assume it is. This yields 17 bytes total overhead,
      41              : but it's wise to add a few more for safety.
      42              : 
      43              : Each subject may require up to 9 bytes. Each target may require up to 14 bytes
      44              : (only one of endpoint or device type will be encoded).
      45              : 
      46              : DATA                                    C   T   L   V   NOTES
      47              : structure (anonymous)                   1               0x15
      48              :   field 1 privilege                     1   1       1
      49              :   field 2 authmode                      1   1       1
      50              :   field 3 subjects                      1   1
      51              :     uint64                              1           8   per subject
      52              :   end list                              1               0x18
      53              :   field 4 targets                       1   1
      54              :     structure (anonymous)               1               per target
      55              :       field 0 cluster                   1   1       4
      56              :       field 1 endpoint                  1   1       2   only field 1 or 2
      57              :       field 2 devicetype                1   1       4   only field 1 or 2
      58              :     end structure                       1
      59              :   end list                              1               0x18
      60              :   field 254 fabric index                1   1       1   not written
      61              : end structure                           1               0x18
      62              : */
      63              : 
      64              : // TODO(#14455): get actual values for max subjects/targets
      65              : constexpr int kEncodedEntryOverheadBytes = 17 + 8;
      66              : constexpr int kEncodedEntrySubjectBytes  = 9 * CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY;
      67              : constexpr int kEncodedEntryTargetBytes   = 14 * CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY;
      68              : constexpr int kEncodedEntryTotalBytes    = kEncodedEntryOverheadBytes + kEncodedEntrySubjectBytes + kEncodedEntryTargetBytes;
      69              : 
      70              : class : public EntryListener
      71              : {
      72              : public:
      73            0 :     void OnEntryChanged(const SubjectDescriptor * subjectDescriptor, FabricIndex fabric, size_t index, const Entry * entry,
      74              :                         ChangeType changeType) override
      75              :     {
      76              :         CHIP_ERROR err;
      77              : 
      78            0 :         uint8_t buffer[kEncodedEntryTotalBytes] = { 0 };
      79              : 
      80            0 :         VerifyOrExit(mPersistentStorage != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
      81              : 
      82            0 :         if (changeType == ChangeType::kRemoved)
      83              :         {
      84              :             // Shuffle down entries past index, then delete entry at last index.
      85              :             while (true)
      86              :             {
      87            0 :                 uint16_t size = static_cast<uint16_t>(sizeof(buffer));
      88            0 :                 err           = mPersistentStorage->SyncGetKeyValue(
      89            0 :                     DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index + 1).KeyName(), buffer, size);
      90            0 :                 if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
      91              :                 {
      92            0 :                     break;
      93              :                 }
      94            0 :                 SuccessOrExit(err);
      95            0 :                 SuccessOrExit(err = mPersistentStorage->SyncSetKeyValue(
      96              :                                   DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(), buffer, size));
      97            0 :                 index++;
      98            0 :             }
      99            0 :             SuccessOrExit(err = mPersistentStorage->SyncDeleteKeyValue(
     100              :                               DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName()));
     101              :         }
     102              :         else
     103              :         {
     104              :             // Write added/updated entry at index.
     105            0 :             VerifyOrExit(entry != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
     106            0 :             TLV::TLVWriter writer;
     107            0 :             writer.Init(buffer);
     108            0 :             EncodableEntry encodableEntry(*entry);
     109            0 :             SuccessOrExit(err = encodableEntry.EncodeForWrite(writer, TLV::AnonymousTag()));
     110            0 :             SuccessOrExit(err = mPersistentStorage->SyncSetKeyValue(
     111              :                               DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(), buffer,
     112              :                               static_cast<uint16_t>(writer.GetLengthWritten())));
     113              :         }
     114              : 
     115            0 :         return;
     116              : 
     117            0 :     exit:
     118            0 :         ChipLogError(DataManagement, "DefaultAclStorage: failed %" CHIP_ERROR_FORMAT, err.Format());
     119              :     }
     120              : 
     121              :     // Must initialize before use.
     122            1 :     void Init(PersistentStorageDelegate & persistentStorage) { mPersistentStorage = &persistentStorage; }
     123              : 
     124              : private:
     125              :     PersistentStorageDelegate * mPersistentStorage = nullptr;
     126              : 
     127              : } sEntryListener;
     128              : 
     129              : } // namespace
     130              : 
     131              : namespace chip {
     132              : namespace app {
     133              : 
     134            1 : CHIP_ERROR DefaultAclStorage::Init(PersistentStorageDelegate & persistentStorage, ConstFabricIterator first,
     135              :                                    ConstFabricIterator last)
     136              : {
     137            1 :     ChipLogProgress(DataManagement, "DefaultAclStorage: initializing");
     138              : 
     139              :     CHIP_ERROR err;
     140              : 
     141            1 :     [[maybe_unused]] size_t count = 0;
     142              : 
     143            1 :     for (auto it = first; it != last; ++it)
     144              :     {
     145            0 :         auto fabric = it->GetFabricIndex();
     146            0 :         for (size_t index = 0; /**/; ++index)
     147              :         {
     148            0 :             uint8_t buffer[kEncodedEntryTotalBytes] = { 0 };
     149            0 :             uint16_t size                           = static_cast<uint16_t>(sizeof(buffer));
     150            0 :             err = persistentStorage.SyncGetKeyValue(DefaultStorageKeyAllocator::AccessControlAclEntry(fabric, index).KeyName(),
     151              :                                                     buffer, size);
     152            0 :             if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     153              :             {
     154            0 :                 break;
     155              :             }
     156            0 :             SuccessOrExit(err);
     157              : 
     158            0 :             TLV::TLVReader reader;
     159            0 :             reader.Init(buffer, size);
     160            0 :             SuccessOrExit(err = reader.Next());
     161              : 
     162            0 :             DecodableEntry decodableEntry;
     163            0 :             SuccessOrExit(err = decodableEntry.Decode(reader));
     164              : 
     165            0 :             Entry & entry = decodableEntry.GetEntry();
     166            0 :             SuccessOrExit(err = entry.SetFabricIndex(fabric));
     167              : 
     168            0 :             SuccessOrExit(err = GetAccessControl().CreateEntry(nullptr, fabric, nullptr, entry));
     169            0 :             count++;
     170            0 :         }
     171              :     }
     172              : 
     173            1 :     ChipLogProgress(DataManagement, "DefaultAclStorage: %u entries loaded", (unsigned) count);
     174              : 
     175            1 :     sEntryListener.Init(persistentStorage);
     176            1 :     GetAccessControl().AddEntryListener(sEntryListener);
     177              : 
     178            1 :     return CHIP_NO_ERROR;
     179              : 
     180            0 : exit:
     181            0 :     ChipLogError(DataManagement, "DefaultAclStorage: failed %" CHIP_ERROR_FORMAT, err.Format());
     182            0 :     return err;
     183              : }
     184              : 
     185              : } // namespace app
     186              : } // namespace chip
        

Generated by: LCOV version 2.0-1