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 #define LOG_TAG "RdbServiceImpl"
16 #include "rdb_service_impl.h"
17 #include "accesstoken_kit.h"
18 #include "account/account_delegate.h"
19 #include "checker/checker_manager.h"
20 #include "communicator/communication_provider.h"
21 #include "crypto_manager.h"
22 #include "ipc_skeleton.h"
23 #include "log_print.h"
24 #include "metadata/meta_data_manager.h"
25 #include "metadata/store_meta_data.h"
26 #include "permission/permission_validator.h"
27 #include "types_export.h"
28 #include "utils/anonymous.h"
29 using OHOS::DistributedKv::AccountDelegate;
30 using OHOS::AppDistributedKv::CommunicationProvider;
31 using OHOS::DistributedData::CheckerManager;
32 using OHOS::DistributedData::MetaDataManager;
33 using OHOS::DistributedData::StoreMetaData;
34 using OHOS::DistributedData::Anonymous;
35 using namespace OHOS::DistributedData;
36 using DistributedDB::RelationalStoreManager;
37
38 constexpr uint32_t ITERATE_TIMES = 10000;
39 namespace OHOS::DistributedRdb {
40 __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_;
Factory()41 RdbServiceImpl::Factory::Factory()
42 {
43 FeatureSystem::GetInstance().RegisterCreator("relational_store",
44 []() { return std::make_shared<RdbServiceImpl>(); });
45 }
46
~Factory()47 RdbServiceImpl::Factory::~Factory()
48 {
49 }
50
DeathRecipientImpl(const DeathCallback & callback)51 RdbServiceImpl::DeathRecipientImpl::DeathRecipientImpl(const DeathCallback& callback)
52 : callback_(callback)
53 {
54 ZLOGI("construct");
55 }
56
~DeathRecipientImpl()57 RdbServiceImpl::DeathRecipientImpl::~DeathRecipientImpl()
58 {
59 ZLOGI("destroy");
60 }
61
OnRemoteDied(const wptr<IRemoteObject> & object)62 void RdbServiceImpl::DeathRecipientImpl::OnRemoteDied(const wptr<IRemoteObject> &object)
63 {
64 ZLOGI("enter");
65 if (callback_) {
66 callback_();
67 }
68 }
69
RdbServiceImpl()70 RdbServiceImpl::RdbServiceImpl()
71 : timer_("SyncerTimer", -1), autoLaunchObserver_(this)
72 {
73 ZLOGI("construct");
74 timer_.Setup();
75 DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback(
76 [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) {
77 return ResolveAutoLaunch(identifier, param);
78 });
79 }
80
ResolveAutoLaunch(const std::string & identifier,DistributedDB::AutoLaunchParam & param)81 int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m)
82 {
83 std::string identifierHex = TransferStringToHex(identifier);
84 ZLOGI("%{public}.6s", identifierHex.c_str());
85 std::vector<StoreMetaData> entries;
86 auto localId = CommunicationProvider::GetInstance().GetLocalDevice().uuid;
87 if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ localId }), entries)) {
88 ZLOGE("get meta failed");
89 return false;
90 }
91 ZLOGI("size=%{public}d", static_cast<int32_t>(entries.size()));
92 for (const auto& entry : entries) {
93 if (entry.storeType != RDB_DEVICE_COLLABORATION) {
94 continue;
95 }
96
97 auto aIdentifier = DistributedDB::RelationalStoreManager::GetRelationalStoreIdentifier(
98 entry.user, entry.appId, entry.storeId);
99 ZLOGI("%{public}s %{public}s %{public}s", entry.user.c_str(), entry.appId.c_str(), entry.storeId.c_str());
100 if (aIdentifier != identifier) {
101 continue;
102 }
103 ZLOGI("find identifier %{public}s", entry.storeId.c_str());
104 param.userId = entry.user;
105 param.appId = entry.appId;
106 param.storeId = entry.storeId;
107 param.path = entry.dataDir;
108 param.option.storeObserver = &autoLaunchObserver_;
109 param.option.isEncryptedDb = entry.isEncrypt;
110 if (entry.isEncrypt) {
111 param.option.iterateTimes = ITERATE_TIMES;
112 param.option.cipher = DistributedDB::CipherType::AES_256_GCM;
113 RdbSyncer::GetPassword(entry, param.option.passwd);
114 }
115 return true;
116 }
117
118 ZLOGE("not find identifier");
119 return false;
120 }
121
OnClientDied(pid_t pid)122 void RdbServiceImpl::OnClientDied(pid_t pid)
123 {
124 ZLOGI("client dead pid=%{public}d", pid);
125 syncers_.ComputeIfPresent(pid, [this](const auto& key, StoreSyncersType& syncers) {
126 syncerNum_ -= static_cast<int32_t>(syncers.size());
127 for (const auto& [name, syncer] : syncers) {
128 timer_.Unregister(syncer->GetTimerId());
129 }
130 return false;
131 });
132 notifiers_.Erase(pid);
133 identifiers_.EraseIf([pid](const auto& key, pid_t& value) {
134 return pid == value;
135 });
136 }
137
CheckAccess(const RdbSyncerParam & param)138 bool RdbServiceImpl::CheckAccess(const RdbSyncerParam ¶m)
139 {
140 CheckerManager::StoreInfo storeInfo;
141 storeInfo.uid = IPCSkeleton::GetCallingUid();
142 storeInfo.tokenId = IPCSkeleton::GetCallingTokenID();
143 storeInfo.bundleName = param.bundleName_;
144 storeInfo.storeId = RdbSyncer::RemoveSuffix(param.storeName_);
145 auto instanceId = RdbSyncer::GetInstIndex(storeInfo.tokenId, storeInfo.bundleName);
146 if (instanceId != 0) {
147 return false;
148 }
149 return !CheckerManager::GetInstance().GetAppId(storeInfo).empty();
150 }
151
ObtainDistributedTableName(const std::string & device,const std::string & table)152 std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table)
153 {
154 ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str());
155 auto uuid = AppDistributedKv::CommunicationProvider::GetInstance().GetUuidByNodeId(device);
156 if (uuid.empty()) {
157 ZLOGE("get uuid failed");
158 return "";
159 }
160 return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
161 }
162
InitNotifier(const RdbSyncerParam & param,const sptr<IRemoteObject> notifier)163 int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam& param, const sptr<IRemoteObject> notifier)
164 {
165 if (!CheckAccess(param)) {
166 ZLOGE("permission error");
167 return RDB_ERROR;
168 }
169
170 pid_t pid = IPCSkeleton::GetCallingPid();
171 auto recipient = new(std::nothrow) DeathRecipientImpl([this, pid] {
172 OnClientDied(pid);
173 });
174 if (recipient == nullptr) {
175 ZLOGE("malloc recipient failed");
176 return RDB_ERROR;
177 }
178
179 if (!notifier->AddDeathRecipient(recipient)) {
180 ZLOGE("link to death failed");
181 return RDB_ERROR;
182 }
183 notifiers_.Insert(pid, iface_cast<RdbNotifierProxy>(notifier));
184 ZLOGI("success pid=%{public}d", pid);
185
186 return RDB_OK;
187 }
188
OnDataChange(pid_t pid,const DistributedDB::StoreChangedData & data)189 void RdbServiceImpl::OnDataChange(pid_t pid, const DistributedDB::StoreChangedData &data)
190 {
191 DistributedDB::StoreProperty property;
192 data.GetStoreProperty(property);
193 ZLOGI("%{public}d %{public}s", pid, property.storeId.c_str());
194 if (pid == 0) {
195 auto identifier = RelationalStoreManager::GetRelationalStoreIdentifier(property.userId, property.appId,
196 property.storeId);
197 auto pair = identifiers_.Find(TransferStringToHex(identifier));
198 if (!pair.first) {
199 ZLOGI("client doesn't subscribe");
200 return;
201 }
202 pid = pair.second;
203 ZLOGI("fixed pid=%{public}d", pid);
204 }
205 notifiers_.ComputeIfPresent(pid, [&data, &property] (const auto& key, const sptr<RdbNotifierProxy>& value) {
206 std::string device = data.GetDataChangeDevice();
207 auto networkId = CommunicationProvider::GetInstance().ToNodeId(device);
208 value->OnChange(property.storeId, { networkId });
209 return true;
210 });
211 }
212
SyncerTimeout(std::shared_ptr<RdbSyncer> syncer)213 void RdbServiceImpl::SyncerTimeout(std::shared_ptr<RdbSyncer> syncer)
214 {
215 if (syncer == nullptr) {
216 return;
217 }
218 ZLOGI("%{public}s", syncer->GetStoreId().c_str());
219 syncers_.ComputeIfPresent(syncer->GetPid(), [this, &syncer](const auto& key, StoreSyncersType& syncers) {
220 syncers.erase(syncer->GetStoreId());
221 syncerNum_--;
222 return true;
223 });
224 }
225
GetRdbSyncer(const RdbSyncerParam & param)226 std::shared_ptr<RdbSyncer> RdbServiceImpl::GetRdbSyncer(const RdbSyncerParam ¶m)
227 {
228 pid_t pid = IPCSkeleton::GetCallingPid();
229 pid_t uid = IPCSkeleton::GetCallingUid();
230 uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
231 std::shared_ptr<RdbSyncer> syncer;
232 syncers_.Compute(pid, [this, ¶m, pid, uid, tokenId, &syncer] (const auto& key, StoreSyncersType& syncers) {
233 auto storeId = RdbSyncer::RemoveSuffix(param.storeName_);
234 auto it = syncers.find(storeId);
235 if (it != syncers.end()) {
236 syncer = it->second;
237 if (!param.isEncrypt_ || param.password_.empty()) {
238 timer_.Unregister(syncer->GetTimerId());
239 uint32_t timerId = timer_.Register([this, syncer]() { SyncerTimeout(syncer); }, SYNCER_TIMEOUT, true);
240 syncer->SetTimerId(timerId);
241 return true;
242 }
243 syncers.erase(storeId);
244 }
245 if (syncers.size() >= MAX_SYNCER_PER_PROCESS) {
246 ZLOGE("%{public}d exceed MAX_PROCESS_SYNCER_NUM", pid);
247 return !syncers.empty();
248 }
249 if (syncerNum_ >= MAX_SYNCER_NUM) {
250 ZLOGE("no available syncer");
251 return !syncers.empty();
252 }
253 auto syncer_ = std::make_shared<RdbSyncer>(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
254 if (syncer_->Init(pid, uid, tokenId) != 0) {
255 return !syncers.empty();
256 }
257 syncers[storeId] = syncer_;
258 syncer = syncer_;
259 syncerNum_++;
260 uint32_t timerId = timer_.Register([this, syncer]() { SyncerTimeout(syncer); }, SYNCER_TIMEOUT, true);
261 syncer->SetTimerId(timerId);
262 return !syncers.empty();
263 });
264
265 if (syncer != nullptr) {
266 identifiers_.Insert(syncer->GetIdentifier(), pid);
267 } else {
268 ZLOGE("syncer is nullptr");
269 }
270 return syncer;
271 }
272
SetDistributedTables(const RdbSyncerParam & param,const std::vector<std::string> & tables)273 int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector<std::string> &tables)
274 {
275 ZLOGI("enter");
276 if (!CheckAccess(param)) {
277 ZLOGE("permission error");
278 return RDB_ERROR;
279 }
280 auto syncer = GetRdbSyncer(param);
281 if (syncer == nullptr) {
282 return RDB_ERROR;
283 }
284 return syncer->SetDistributedTables(tables);
285 }
286
DoSync(const RdbSyncerParam & param,const SyncOption & option,const RdbPredicates & predicates,SyncResult & result)287 int32_t RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const SyncOption &option,
288 const RdbPredicates &predicates, SyncResult &result)
289 {
290 if (!CheckAccess(param)) {
291 ZLOGE("permission error");
292 return RDB_ERROR;
293 }
294 auto syncer = GetRdbSyncer(param);
295 if (syncer == nullptr) {
296 return RDB_ERROR;
297 }
298 return syncer->DoSync(option, predicates, result);
299 }
300
OnAsyncComplete(pid_t pid,uint32_t seqNum,const SyncResult & result)301 void RdbServiceImpl::OnAsyncComplete(pid_t pid, uint32_t seqNum, const SyncResult &result)
302 {
303 ZLOGI("pid=%{public}d seqnum=%{public}u", pid, seqNum);
304 notifiers_.ComputeIfPresent(pid, [seqNum, &result] (const auto& key, const sptr<RdbNotifierProxy>& value) {
305 value->OnComplete(seqNum, result);
306 return true;
307 });
308 }
309
DoAsync(const RdbSyncerParam & param,uint32_t seqNum,const SyncOption & option,const RdbPredicates & predicates)310 int32_t RdbServiceImpl::DoAsync(const RdbSyncerParam ¶m, uint32_t seqNum, const SyncOption &option,
311 const RdbPredicates &predicates)
312 {
313 if (!CheckAccess(param)) {
314 ZLOGE("permission error");
315 return RDB_ERROR;
316 }
317 pid_t pid = IPCSkeleton::GetCallingPid();
318 ZLOGI("seq num=%{public}u", seqNum);
319 auto syncer = GetRdbSyncer(param);
320 if (syncer == nullptr) {
321 return RDB_ERROR;
322 }
323 return syncer->DoAsync(option, predicates,
324 [this, pid, seqNum] (const SyncResult& result) {
325 OnAsyncComplete(pid, seqNum, result);
326 });
327 }
328
TransferStringToHex(const std::string & origStr)329 std::string RdbServiceImpl::TransferStringToHex(const std::string &origStr)
330 {
331 if (origStr.empty()) {
332 return "";
333 }
334 const char *hex = "0123456789abcdef";
335 std::string tmp;
336 for (auto item : origStr) {
337 auto currentByte = static_cast<uint8_t>(item);
338 tmp.push_back(hex[currentByte >> 4]); // high 4 bit to one hex.
339 tmp.push_back(hex[currentByte & 0x0F]); // low 4 bit to one hex.
340 }
341 return tmp;
342 }
343
GenIdentifier(const RdbSyncerParam & param)344 std::string RdbServiceImpl::GenIdentifier(const RdbSyncerParam ¶m)
345 {
346 pid_t uid = IPCSkeleton::GetCallingUid();
347 uint32_t token = IPCSkeleton::GetCallingTokenID();
348 auto storeId = RdbSyncer::RemoveSuffix(param.storeName_);
349 CheckerManager::StoreInfo storeInfo{ uid, token, param.bundleName_, storeId };
350 std::string userId = AccountDelegate::GetInstance()->GetDeviceAccountIdByUID(uid);
351 std::string appId = CheckerManager::GetInstance().GetAppId(storeInfo);
352 std::string identifier = RelationalStoreManager::GetRelationalStoreIdentifier(userId, appId, storeId);
353 return TransferStringToHex(identifier);
354 }
355
DoSubscribe(const RdbSyncerParam & param)356 int32_t RdbServiceImpl::DoSubscribe(const RdbSyncerParam& param)
357 {
358 pid_t pid = IPCSkeleton::GetCallingPid();
359 auto identifier = GenIdentifier(param);
360 ZLOGI("%{public}s %{public}.6s %{public}d", param.storeName_.c_str(), identifier.c_str(), pid);
361 identifiers_.Insert(identifier, pid);
362 return RDB_OK;
363 }
364
DoUnSubscribe(const RdbSyncerParam & param)365 int32_t RdbServiceImpl::DoUnSubscribe(const RdbSyncerParam& param)
366 {
367 auto identifier = GenIdentifier(param);
368 ZLOGI("%{public}s %{public}.6s", param.storeName_.c_str(), identifier.c_str());
369 identifiers_.Erase(identifier);
370 return RDB_OK;
371 }
372
RemoteQuery(const RdbSyncerParam & param,const std::string & device,const std::string & sql,const std::vector<std::string> & selectionArgs,sptr<IRemoteObject> & resultSet)373 int32_t RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql,
374 const std::vector<std::string>& selectionArgs, sptr<IRemoteObject>& resultSet)
375 {
376 if (!CheckAccess(param)) {
377 ZLOGE("permission error");
378 return RDB_ERROR;
379 }
380 auto syncer = GetRdbSyncer(param);
381 if (syncer == nullptr) {
382 ZLOGE("syncer is null");
383 return RDB_ERROR;
384 }
385 return syncer->RemoteQuery(device, sql, selectionArgs, resultSet);
386 }
387
CreateRDBTable(const RdbSyncerParam & param,const std::string & writePermission,const std::string & readPermission)388 int32_t RdbServiceImpl::CreateRDBTable(
389 const RdbSyncerParam ¶m, const std::string &writePermission, const std::string &readPermission)
390 {
391 if (!CheckAccess(param)) {
392 ZLOGE("permission error");
393 return RDB_ERROR;
394 }
395
396 pid_t pid = IPCSkeleton::GetCallingPid();
397 auto syncer = new (std::nothrow)RdbSyncer(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
398 if (syncer == nullptr) {
399 ZLOGE("new syncer error");
400 return RDB_ERROR;
401 }
402 auto uid = IPCSkeleton::GetCallingUid();
403 auto tokenId = IPCSkeleton::GetCallingTokenID();
404 if (syncer->Init(pid, uid, tokenId, writePermission, readPermission) != RDB_OK) {
405 ZLOGE("Init error");
406 delete syncer;
407 return RDB_ERROR;
408 }
409 delete syncer;
410 return RDB_OK;
411 }
412
DestroyRDBTable(const RdbSyncerParam & param)413 int32_t RdbServiceImpl::DestroyRDBTable(const RdbSyncerParam ¶m)
414 {
415 if (!CheckAccess(param)) {
416 ZLOGE("permission error");
417 return RDB_ERROR;
418 }
419 pid_t pid = IPCSkeleton::GetCallingPid();
420 auto syncer = new (std::nothrow)RdbSyncer(param, new (std::nothrow) RdbStoreObserverImpl(this, pid));
421 if (syncer == nullptr) {
422 ZLOGE("new syncer error");
423 return RDB_ERROR;
424 }
425
426 StoreMetaData meta;
427 if (syncer->DestroyMetaData(meta) != RDB_OK) {
428 ZLOGE("Init error");
429 delete syncer;
430 return RDB_ERROR;
431 }
432 delete syncer;
433 return RDB_OK;
434 }
435 } // namespace OHOS::DistributedRdb
436