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 ¶m) -> 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 ¶m) -> 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 ¶m)
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 ¶m, 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, ¶m](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 ¶m)
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