LCOV - code coverage report
Current view: top level - app/server - DefaultAclStorage.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 9 53 17.0 %
Date: 2024-02-15 08:20:41 Functions: 2 3 66.7 %

          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           0 :         }
     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 :     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             :             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 1.14