1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define LOG_TAG "PermitDelegate"
17 #include "permit_delegate.h"
18 #include "accesstoken_kit.h"
19 #include "device_manager_adapter.h"
20 #include "log_print.h"
21 #include "metadata/appid_meta_data.h"
22 #include "metadata/meta_data_manager.h"
23 #include "metadata/strategy_meta_data.h"
24 #include "permission/permission_validator.h"
25 #include "runtime_config.h"
26 #include "store_types.h"
27 #include "user_delegate.h"
28 #include "utils/anonymous.h"
29 
30 namespace OHOS::DistributedData {
31 using DBStatus = DistributedDB::DBStatus;
32 using DBConfig = DistributedDB::RuntimeConfig;
33 using DBFlag = DistributedDB::PermissionCheckFlag;
34 using PermissionValidator = OHOS::DistributedKv::PermissionValidator;
35 
PermitDelegate()36 PermitDelegate::PermitDelegate()
37 {}
38 
~PermitDelegate()39 PermitDelegate::~PermitDelegate()
40 {}
41 
GetInstance()42 PermitDelegate &PermitDelegate::GetInstance()
43 {
44     static PermitDelegate permit;
45     return permit;
46 }
47 
Init()48 void PermitDelegate::Init()
49 {
50     auto activeCall = [this](const ActiveParam &param) -> bool {
51         return SyncActivate(param);
52     };
53     DBStatus status = DBConfig::SetSyncActivationCheckCallback(activeCall);
54     ZLOGI("set active callback status:%d.", status);
55 
56     auto permitCall = [this](const CheckParam &Param, uint8_t flag) -> bool {
57         return VerifyPermission(Param, flag);
58     };
59     status = DBConfig::SetPermissionCheckCallback(permitCall);
60     ZLOGI("set permission callback status:%d.", status);
61 
62     auto extraCall = [this](const CondParam &param) -> std::map<std::string, std::string> {
63         return GetExtraCondition(param);
64     };
65     status = DBConfig::SetPermissionConditionCallback(extraCall);
66     ZLOGI("set extra condition call status:%d.", status);
67 }
68 
SyncActivate(const ActiveParam & param)69 bool PermitDelegate::SyncActivate(const ActiveParam &param)
70 {
71     ZLOGD("user:%{public}s, app:%{public}s, store:%{public}s, instanceId:%{public}d",
72         param.userId.c_str(), param.appId.c_str(), Anonymous::Change(param.storeId).c_str(), param.instanceId);
73     if (param.instanceId != 0) {
74         return false;
75     }
76     std::set<std::string> activeUsers = UserDelegate::GetInstance().GetLocalUsers();
77     return activeUsers.count(param.userId);
78 }
79 
VerifyPermission(const CheckParam & param,uint8_t flag)80 bool PermitDelegate::VerifyPermission(const CheckParam &param, uint8_t flag)
81 {
82     ZLOGI("user:%{public}s, appId:%{public}s, storeId:%{public}s, remote devId:%{public}s, instanceId:%{public}d,"
83           "flag:%{public}u", param.userId.c_str(), param.appId.c_str(), Anonymous::Change(param.storeId).c_str(),
84           Anonymous::Change(param.deviceId).c_str(), param.instanceId, flag);
85 
86     auto devId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid;
87     StoreMetaData data;
88     data.user = param.userId == "default" ? DEFAULT_USER : param.userId;
89     data.storeId = param.storeId;
90     data.deviceId = devId;
91     data.instanceId = param.instanceId;
92     appId2BundleNameMap_.Compute(param.appId, [&data, &param](const auto &key, std::string &value) {
93         if (!value.empty()) {
94             data.bundleName = value;
95             return true;
96         }
97         AppIDMetaData appIDMeta;
98         MetaDataManager::GetInstance().LoadMeta(key, appIDMeta, true);
99         if (appIDMeta.appId == param.appId) {
100             data.bundleName = appIDMeta.bundleName;
101             value = appIDMeta.bundleName;
102         }
103         return !value.empty();
104     });
105     auto key = data.GetKey();
106     if (!metaDataBucket_.Get(key, data)) {
107         if (!MetaDataManager::GetInstance().LoadMeta(key, data)) {
108             ZLOGE("load meta failed.");
109             return false;
110         }
111         metaDataBucket_.Set(data.GetKey(), data);
112     }
113     if (data.appType.compare("default") == 0) {
114         ZLOGD("default, sync permission success.");
115         return true;
116     }
117     auto status = VerifyStrategy(data, param.deviceId);
118     if (status != Status::SUCCESS) {
119         ZLOGE("verify strategy failed.");
120         return false;
121     }
122     return PermissionValidator::GetInstance().CheckSyncPermission(data.tokenId);
123 }
124 
VerifyExtraCondition(const std::map<std::string,std::string> & cond) const125 bool PermitDelegate::VerifyExtraCondition(const std::map<std::string, std::string> &cond) const
126 {
127     (void)cond;
128     return true;
129 }
130 
GetExtraCondition(const CondParam & param)131 std::map<std::string, std::string> PermitDelegate::GetExtraCondition(const CondParam &param)
132 {
133     (void)param;
134     return {};
135 }
136 
VerifyStrategy(const StoreMetaData & data,const std::string & rmdevId) const137 Status PermitDelegate::VerifyStrategy(const StoreMetaData &data, const std::string &rmdevId) const
138 {
139     StrategyMeta local(data.deviceId, data.user, data.bundleName, data.storeId);
140     MetaDataManager::GetInstance().LoadMeta(local.GetKey(), local);
141     StrategyMeta remote(rmdevId, data.user, data.bundleName, data.storeId);
142     MetaDataManager::GetInstance().LoadMeta(remote.GetKey(), remote);
143     if (!local.IsEffect() || !remote.IsEffect()) {
144         ZLOGD("no range, sync permission success.");
145         return Status::SUCCESS;
146     }
147     auto lremotes = local.capabilityRange.remoteLabel;
148     auto rlocals = remote.capabilityRange.localLabel;
149     for (const auto &lrmote : lremotes) {
150         if (std::find(rlocals.begin(), rlocals.end(), lrmote) != rlocals.end()) {
151             ZLOGD("find range, sync permission success.");
152             return Status::SUCCESS;
153         }
154     }
155     return Status::ERROR;
156 }
157 
DelCache(const std::string & key)158 void PermitDelegate::DelCache(const std::string &key)
159 {
160     metaDataBucket_.Delete(key);
161 }
162 
VerifyPermission(const std::string & permission,uint32_t callerTokenId)163 bool PermitDelegate::VerifyPermission(const std::string &permission,
164     uint32_t callerTokenId)
165 {
166     if (!permission.empty()) {
167         int status =
168             Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerTokenId, permission);
169         if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
170             return false;
171         }
172     }
173     return true;
174 }
175 } // namespace OHOS::DistributedData
176