1 /*
2  * Copyright (c) 2022-2023 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 #include "distributed_bms.h"
17 
18 #include <fstream>
19 #include <vector>
20 
21 #include "accesstoken_kit.h"
22 #include "account_manager_helper.h"
23 #include "app_log_wrapper.h"
24 #include "appexecfwk_errors.h"
25 #include "bundle_mgr_interface.h"
26 #include "bundle_mgr_proxy.h"
27 #include "distributed_bms_proxy.h"
28 #include "distributed_data_storage.h"
29 #include "event_report.h"
30 #include "iservice_registry.h"
31 #include "if_system_ability_manager.h"
32 #include "locale_config.h"
33 #include "locale_info.h"
34 #include "image_compress.h"
35 #ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
36 #include "image_packer.h"
37 #include "image_source.h"
38 #endif
39 #include "ipc_skeleton.h"
40 #include "system_ability_definition.h"
41 #include "tokenid_kit.h"
42 #ifdef HICOLLIE_ENABLE
43 #include "xcollie/xcollie.h"
44 #include "xcollie/xcollie_define.h"
45 #endif
46 
47 namespace OHOS {
48 namespace AppExecFwk {
49 namespace {
50 #ifdef HICOLLIE_ENABLE
51     const unsigned int LOCAL_TIME_OUT_SECONDS = 5;
52     const unsigned int REMOTE_TIME_OUT_SECONDS = 10;
53 #endif
54     const uint8_t DECODE_VALUE_ONE = 1;
55     const uint8_t DECODE_VALUE_TWO = 2;
56     const uint8_t DECODE_VALUE_THREE = 3;
57     const unsigned char DECODE_VALUE_CHAR_THREE = 3;
58     const uint8_t DECODE_VALUE_FOUR = 4;
59     const uint8_t DECODE_VALUE_SIX = 6;
60     const uint32_t DBMS_UID = 6000;
61     const unsigned char DECODE_VALUE_CHAR_FIFTEEN = 15;
62     const unsigned char DECODE_VALUE_CHAR_SIXTY_THREE = 63;
63     const std::vector<char> DECODE_TABLE = {
64         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
65         'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
66         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
67         'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
68         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
69     };
70     const std::string POSTFIX = "_Compress.";
71 #ifdef HISYSEVENT_ENABLE
GetEventInfo(const std::vector<ElementName> & elements,const std::string & localeInfo,int32_t resultCode)72     DBMSEventInfo GetEventInfo(
73         const std::vector<ElementName> &elements, const std::string &localeInfo, int32_t resultCode)
74     {
75         DBMSEventInfo eventInfo;
76         if (elements.empty()) {
77             return eventInfo;
78         }
79 
80         eventInfo.deviceID = elements[0].GetDeviceID();
81         eventInfo.localeInfo = localeInfo;
82         for (auto element : elements) {
83             if (eventInfo.bundleName.empty()) {
84                 eventInfo.bundleName.append(element.GetBundleName());
85             } else {
86                 eventInfo.bundleName.append(";").append(element.GetBundleName());
87             }
88 
89             if (eventInfo.abilityName.empty()) {
90                 eventInfo.abilityName.append(element.GetAbilityName());
91             } else {
92                 eventInfo.abilityName.append(";").append(element.GetAbilityName());
93             }
94         }
95 
96         eventInfo.resultCode = resultCode;
97         return eventInfo;
98     }
99 
GetEventInfo(const ElementName & element,const std::string & localeInfo,int32_t resultCode)100     DBMSEventInfo GetEventInfo(
101         const ElementName &element, const std::string &localeInfo, int32_t resultCode)
102     {
103         DBMSEventInfo eventInfo;
104         eventInfo.bundleName = element.GetBundleName();
105         eventInfo.abilityName = element.GetAbilityName();
106         eventInfo.deviceID = element.GetDeviceID();
107         eventInfo.localeInfo = localeInfo;
108         eventInfo.resultCode = resultCode;
109         return eventInfo;
110     }
111 #endif
112 }
113 const bool REGISTER_RESULT =
114     SystemAbility::MakeAndRegisterAbility(DelayedSingleton<DistributedBms>::GetInstance().get());
115 
DistributedBms()116 DistributedBms::DistributedBms() : SystemAbility(DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, true)
117 {
118     APP_LOGI("DistributedBms :%{public}s call", __func__);
119 }
120 
~DistributedBms()121 DistributedBms::~DistributedBms()
122 {
123     APP_LOGI("DistributedBms: DBundleMgrService");
124 }
125 
OnStart()126 void DistributedBms::OnStart()
127 {
128     APP_LOGI("DistributedBms: OnStart");
129     Init();
130     bool res = Publish(this);
131     if (!res) {
132         APP_LOGE("DistributedBms: OnStart failed");
133     }
134     APP_LOGI("DistributedBms: OnStart end");
135 }
136 
OnStop()137 void DistributedBms::OnStop()
138 {
139     APP_LOGI("DistributedBms: OnStop");
140     if (distributedSub_ != nullptr) {
141         EventFwk::CommonEventManager::UnSubscribeCommonEvent(distributedSub_);
142     }
143 }
144 
Init()145 void DistributedBms::Init()
146 {
147     APP_LOGI("DistributedBms: Init");
148     InitDeviceManager();
149     DistributedDataStorage::GetInstance();
150     if (distributedSub_ == nullptr) {
151         EventFwk::MatchingSkills matchingSkills;
152         matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
153         matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED);
154         matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED);
155         matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
156         EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
157         distributedSub_ = std::make_shared<DistributedMonitor>(subscribeInfo);
158         EventFwk::CommonEventManager::SubscribeCommonEvent(distributedSub_);
159     }
160     int32_t userId = AccountManagerHelper::GetCurrentActiveUserId();
161     if (userId == Constants::INVALID_USERID) {
162         APP_LOGW("get user id failed");
163         return;
164     }
165     DistributedDataStorage::GetInstance()->UpdateDistributedData(userId);
166 }
167 
InitDeviceManager()168 void DistributedBms::InitDeviceManager()
169 {
170     if (dbmsDeviceManager_ == nullptr) {
171         std::lock_guard<std::mutex> lock(dbmsDeviceManagerMutex_);
172         if (dbmsDeviceManager_ == nullptr) {
173             APP_LOGI("Create device manager");
174             dbmsDeviceManager_ = std::make_shared<DbmsDeviceManager>();
175         }
176     }
177 }
178 
GetBundleMgr()179 OHOS::sptr<OHOS::AppExecFwk::IBundleMgr> DistributedBms::GetBundleMgr()
180 {
181     if (bundleMgr_ == nullptr) {
182         std::lock_guard<std::mutex> lock(bundleMgrMutex_);
183         if (bundleMgr_ == nullptr) {
184             auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
185             if (systemAbilityManager == nullptr) {
186                 APP_LOGE("GetBundleMgr GetSystemAbilityManager is null");
187                 return nullptr;
188             }
189             auto bundleMgrSa = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
190             if (bundleMgrSa == nullptr) {
191                 APP_LOGE("GetBundleMgr GetSystemAbility is null");
192                 return nullptr;
193             }
194             bundleMgr_ = OHOS::iface_cast<IBundleMgr>(bundleMgrSa);
195         }
196     }
197     return bundleMgr_;
198 }
199 
GetUdidByNetworkId(const std::string & networkId,std::string & udid)200 int32_t DistributedBms::GetUdidByNetworkId(const std::string &networkId, std::string &udid)
201 {
202     if (dbmsDeviceManager_ == nullptr) {
203         APP_LOGI("deviceManager_ is nullptr");
204         InitDeviceManager();
205     }
206     return dbmsDeviceManager_->GetUdidByNetworkId(networkId, udid);
207 }
208 
GetUuidByNetworkId(const std::string & networkId,std::string & uuid)209 int32_t DistributedBms::GetUuidByNetworkId(const std::string &networkId, std::string &uuid)
210 {
211     if (dbmsDeviceManager_ == nullptr) {
212         APP_LOGI("deviceManager_ is nullptr");
213         InitDeviceManager();
214     }
215     return dbmsDeviceManager_->GetUuidByNetworkId(networkId, uuid);
216 }
217 
GetDistributedBundleMgr(const std::string & deviceId)218 static OHOS::sptr<OHOS::AppExecFwk::IDistributedBms> GetDistributedBundleMgr(const std::string &deviceId)
219 {
220     auto samgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
221     if (samgr == nullptr) {
222         APP_LOGE("GetSystemAbilityManager failed");
223         return nullptr;
224     }
225     OHOS::sptr<OHOS::IRemoteObject> remoteObject;
226     if (deviceId.empty()) {
227         APP_LOGW("GetDistributedBundleMgr deviceId is empty");
228         return nullptr;
229     } else {
230         APP_LOGI("GetDistributedBundleMgr get remote d-bms");
231         remoteObject = samgr->CheckSystemAbility(OHOS::DISTRIBUTED_BUNDLE_MGR_SERVICE_SYS_ABILITY_ID, deviceId);
232     }
233     return OHOS::iface_cast<IDistributedBms>(remoteObject);
234 }
235 
GetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,RemoteAbilityInfo & remoteAbilityInfo)236 int32_t DistributedBms::GetRemoteAbilityInfo(
237     const OHOS::AppExecFwk::ElementName &elementName, RemoteAbilityInfo &remoteAbilityInfo)
238 {
239     return GetRemoteAbilityInfo(elementName, "", remoteAbilityInfo);
240 }
241 
GetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,const std::string & localeInfo,RemoteAbilityInfo & remoteAbilityInfo)242 int32_t DistributedBms::GetRemoteAbilityInfo(const OHOS::AppExecFwk::ElementName &elementName,
243     const std::string &localeInfo, RemoteAbilityInfo &remoteAbilityInfo)
244 {
245     if (!VerifySystemApp()) {
246         APP_LOGE("verify system app failed");
247         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
248     }
249     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
250         APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
251         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
252     }
253     auto iDistBundleMgr = GetDistributedBundleMgr(elementName.GetDeviceID());
254     int32_t resultCode = 0;
255     if (!iDistBundleMgr) {
256         APP_LOGE("GetDistributedBundle object failed");
257         resultCode = ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
258     } else {
259 #ifdef HICOLLIE_ENABLE
260         int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetRemoteAbilityInfo", REMOTE_TIME_OUT_SECONDS,
261             nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
262         HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
263 #endif
264         APP_LOGD("GetDistributedBundleMgr get remote d-bms");
265         resultCode = iDistBundleMgr->GetAbilityInfo(elementName, localeInfo, remoteAbilityInfo);
266     }
267 
268 #ifdef HISYSEVENT_ENABLE
269     EventReport::SendSystemEvent(
270         DBMSEventType::GET_REMOTE_ABILITY_INFO, GetEventInfo(elementName, localeInfo, resultCode));
271 #endif
272     return resultCode;
273 }
274 
GetRemoteAbilityInfos(const std::vector<ElementName> & elementNames,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)275 int32_t DistributedBms::GetRemoteAbilityInfos(
276     const std::vector<ElementName> &elementNames, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
277 {
278     return GetRemoteAbilityInfos(elementNames, "", remoteAbilityInfos);
279 }
280 
GetRemoteAbilityInfos(const std::vector<ElementName> & elementNames,const std::string & localeInfo,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)281 int32_t DistributedBms::GetRemoteAbilityInfos(const std::vector<ElementName> &elementNames,
282     const std::string &localeInfo, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
283 {
284     if (!VerifySystemApp()) {
285         APP_LOGE("verify system app failed");
286         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
287     }
288     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
289         APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
290         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
291     }
292     if (elementNames.empty()) {
293         APP_LOGE("GetDistributedBundle failed due to elementNames empty");
294         return ERR_BUNDLE_MANAGER_PARAM_ERROR;
295     }
296     auto iDistBundleMgr = GetDistributedBundleMgr(elementNames[0].GetDeviceID());
297     int32_t resultCode = 0;
298     if (!iDistBundleMgr) {
299         APP_LOGE("GetDistributedBundle object failed");
300         resultCode = ERR_BUNDLE_MANAGER_DEVICE_ID_NOT_EXIST;
301     } else {
302 #ifdef HICOLLIE_ENABLE
303         int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetRemoteAbilityInfos", REMOTE_TIME_OUT_SECONDS,
304             nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
305         HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
306 #endif
307         APP_LOGD("GetDistributedBundleMgr get remote d-bms");
308         resultCode = iDistBundleMgr->GetAbilityInfos(elementNames, localeInfo, remoteAbilityInfos);
309     }
310 #ifdef HISYSEVENT_ENABLE
311     EventReport::SendSystemEvent(
312         DBMSEventType::GET_REMOTE_ABILITY_INFOS, GetEventInfo(elementNames, localeInfo, resultCode));
313 #endif
314     return resultCode;
315 }
316 
GetAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,RemoteAbilityInfo & remoteAbilityInfo)317 int32_t DistributedBms::GetAbilityInfo(
318     const OHOS::AppExecFwk::ElementName &elementName, RemoteAbilityInfo &remoteAbilityInfo)
319 {
320     return GetAbilityInfo(elementName, "", remoteAbilityInfo);
321 }
322 
GetAbilityInfo(const OHOS::AppExecFwk::ElementName & elementName,const std::string & localeInfo,RemoteAbilityInfo & remoteAbilityInfo)323 int32_t DistributedBms::GetAbilityInfo(const OHOS::AppExecFwk::ElementName &elementName,
324     const std::string &localeInfo, RemoteAbilityInfo &remoteAbilityInfo)
325 {
326     APP_LOGI("DistributedBms GetAbilityInfo bundleName:%{public}s , abilityName:%{public}s, localeInfo:%{public}s",
327         elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str(), localeInfo.c_str());
328     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
329         APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
330         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
331     }
332     auto iBundleMgr = GetBundleMgr();
333     if (!iBundleMgr) {
334         APP_LOGE("DistributedBms GetBundleMgr failed");
335         return ERR_APPEXECFWK_FAILED_SERVICE_DIED;
336     }
337     int userId = AccountManagerHelper::GetCurrentActiveUserId();
338     if (userId == Constants::INVALID_USERID) {
339         APP_LOGE("GetCurrentUserId failed");
340         return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
341     }
342     std::vector<AbilityInfo> abilityInfos;
343     OHOS::AAFwk::Want want;
344     want.SetElement(elementName);
345     ErrCode ret = iBundleMgr->QueryAbilityInfosV9(want, static_cast<int32_t>(
346         GetAbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION), userId, abilityInfos);
347     if (ret != ERR_OK) {
348         APP_LOGE("DistributedBms QueryAbilityInfo failed");
349         return ret;
350     }
351     if (abilityInfos.empty()) {
352         APP_LOGE("DistributedBms QueryAbilityInfo abilityInfos empty");
353         return ERR_APPEXECFWK_FAILED_GET_ABILITY_INFO;
354     }
355     std::string label = iBundleMgr->GetStringById(
356         abilityInfos[0].bundleName, abilityInfos[0].moduleName, abilityInfos[0].labelId, userId, localeInfo);
357     if (label.empty()) {
358         APP_LOGE("DistributedBms QueryAbilityInfo label empty");
359         return ERR_APPEXECFWK_FAILED_GET_ABILITY_INFO;
360     }
361     remoteAbilityInfo.label = label;
362     remoteAbilityInfo.elementName = elementName;
363     return GetAbilityIconByContent(abilityInfos[0], userId, remoteAbilityInfo);
364 }
365 
GetAbilityIconByContent(const AbilityInfo & abilityInfo,int32_t userId,RemoteAbilityInfo & remoteAbilityInfo)366 int32_t DistributedBms::GetAbilityIconByContent(
367     const AbilityInfo &abilityInfo, int32_t userId, RemoteAbilityInfo &remoteAbilityInfo)
368 {
369     auto iBundleMgr = GetBundleMgr();
370     if (!iBundleMgr) {
371         APP_LOGE("DistributedBms GetBundleMgr failed");
372         return ERR_APPEXECFWK_FAILED_SERVICE_DIED;
373     }
374 #ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
375     std::unique_ptr<uint8_t[]> imageContent;
376     size_t imageContentSize = 0;
377     ErrCode ret = iBundleMgr->GetMediaData(abilityInfo.bundleName, abilityInfo.moduleName, abilityInfo.name,
378         imageContent, imageContentSize, userId);
379     if (ret != ERR_OK) {
380         APP_LOGE("DistributedBms GetMediaData failed");
381         return ret;
382     }
383     APP_LOGD("imageContentSize is %{public}d", static_cast<int32_t>(imageContentSize));
384     std::unique_ptr<ImageCompress> imageCompress = std::make_unique<ImageCompress>();
385     if (imageCompress->IsImageNeedCompressBySize(imageContentSize)) {
386         std::unique_ptr<uint8_t[]> compressData;
387         int64_t compressSize = 0;
388         std::string imageType;
389         if (!imageCompress->CompressImageByContent(imageContent, imageContentSize,
390             compressData, compressSize, imageType)) {
391             return Base64WithoutCompress(imageContent, imageContentSize, remoteAbilityInfo);
392         }
393         if (!GetMediaBase64(compressData, compressSize, imageType, remoteAbilityInfo.icon)) {
394             APP_LOGE("DistributedBms GetMediaBase64 failed");
395             return ERR_APPEXECFWK_ENCODE_BASE64_FILE_FAILED;
396         }
397     } else {
398         return Base64WithoutCompress(imageContent, imageContentSize, remoteAbilityInfo);
399     }
400 #endif
401     return OHOS::NO_ERROR;
402 }
403 
404 #ifdef DISTRIBUTED_BUNDLE_IMAGE_ENABLE
Base64WithoutCompress(std::unique_ptr<uint8_t[]> & imageContent,size_t imageContentSize,RemoteAbilityInfo & remoteAbilityInfo)405 int32_t DistributedBms::Base64WithoutCompress(std::unique_ptr<uint8_t[]> &imageContent, size_t imageContentSize,
406     RemoteAbilityInfo &remoteAbilityInfo)
407 {
408     std::string imageType;
409     std::unique_ptr<ImageCompress> imageCompress = std::make_unique<ImageCompress>();
410     if (!imageCompress->GetImageTypeString(imageContent, imageContentSize, imageType)) {
411         return ERR_APPEXECFWK_INPUT_WRONG_TYPE_FILE;
412     }
413     if (!GetMediaBase64(imageContent, static_cast<int64_t>(imageContentSize), imageType, remoteAbilityInfo.icon)) {
414         APP_LOGE("DistributedBms GetMediaBase64 failed");
415         return ERR_APPEXECFWK_ENCODE_BASE64_FILE_FAILED;
416     }
417     return OHOS::NO_ERROR;
418 }
419 #endif
420 
GetAbilityInfos(const std::vector<ElementName> & elementNames,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)421 int32_t DistributedBms::GetAbilityInfos(
422     const std::vector<ElementName> &elementNames, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
423 {
424     APP_LOGD("DistributedBms GetAbilityInfos");
425     return GetAbilityInfos(elementNames, "", remoteAbilityInfos);
426 }
427 
GetAbilityInfos(const std::vector<ElementName> & elementNames,const std::string & localeInfo,std::vector<RemoteAbilityInfo> & remoteAbilityInfos)428 int32_t DistributedBms::GetAbilityInfos(const std::vector<ElementName> &elementNames,
429     const std::string &localeInfo, std::vector<RemoteAbilityInfo> &remoteAbilityInfos)
430 {
431     APP_LOGD("DistributedBms GetAbilityInfos");
432     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
433         APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
434         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
435     }
436     for (auto elementName : elementNames) {
437         RemoteAbilityInfo remoteAbilityInfo;
438         int32_t result = GetAbilityInfo(elementName, localeInfo, remoteAbilityInfo);
439         if (result) {
440             APP_LOGE("get AbilityInfo:%{public}s, %{public}s, %{public}s failed", elementName.GetBundleName().c_str(),
441                 elementName.GetModuleName().c_str(), elementName.GetAbilityName().c_str());
442             return result;
443         }
444         remoteAbilityInfos.push_back(remoteAbilityInfo);
445     }
446     return OHOS::NO_ERROR;
447 }
448 
GetMediaBase64(std::unique_ptr<uint8_t[]> & data,int64_t fileLength,std::string & imageType,std::string & value)449 bool DistributedBms::GetMediaBase64(std::unique_ptr<uint8_t[]> &data, int64_t fileLength,
450     std::string &imageType, std::string &value)
451 {
452     std::unique_ptr<char[]> base64Data = EncodeBase64(data, fileLength);
453     value = "data:" + imageType + ";base64," + base64Data.get();
454     return true;
455 }
456 
GetDistributedBundleInfo(const std::string & networkId,const std::string & bundleName,DistributedBundleInfo & distributedBundleInfo)457 bool DistributedBms::GetDistributedBundleInfo(const std::string &networkId, const std::string &bundleName,
458     DistributedBundleInfo &distributedBundleInfo)
459 {
460     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
461         APP_LOGE("verify GET_BUNDLE_INFO_PRIVILEGED failed");
462         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
463     }
464 #ifdef HICOLLIE_ENABLE
465     int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetDistributedBundleInfo", LOCAL_TIME_OUT_SECONDS,
466         nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
467 #endif
468     bool ret = DistributedDataStorage::GetInstance()->GetStorageDistributeInfo(
469         networkId, bundleName, distributedBundleInfo);
470 #ifdef HICOLLIE_ENABLE
471     HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
472 #endif
473     return ret;
474 }
475 
GetDistributedBundleName(const std::string & networkId,uint32_t accessTokenId,std::string & bundleName)476 int32_t DistributedBms::GetDistributedBundleName(const std::string &networkId,  uint32_t accessTokenId,
477     std::string &bundleName)
478 {
479     if (!VerifyCallingPermission(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
480         APP_LOGE("verify calling permission failed");
481         return ERR_BUNDLE_MANAGER_PERMISSION_DENIED;
482     }
483 #ifdef HICOLLIE_ENABLE
484     int timerId = HiviewDFX::XCollie::GetInstance().SetTimer("GetDistributedBundleName", LOCAL_TIME_OUT_SECONDS,
485         nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_RECOVERY);
486 #endif
487     int32_t ret = DistributedDataStorage::GetInstance()->GetDistributedBundleName(
488         networkId, accessTokenId, bundleName);
489 #ifdef HICOLLIE_ENABLE
490     HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
491 #endif
492     return ret;
493 }
494 
EncodeBase64(std::unique_ptr<uint8_t[]> & data,int srcLen)495 std::unique_ptr<char[]> DistributedBms::EncodeBase64(std::unique_ptr<uint8_t[]> &data, int srcLen)
496 {
497     int len = (srcLen / DECODE_VALUE_THREE) * DECODE_VALUE_FOUR; // Split 3 bytes to 4 parts, each containing 6 bits.
498     int outLen = ((srcLen % DECODE_VALUE_THREE) != 0) ? (len + DECODE_VALUE_FOUR) : len;
499     const uint8_t *srcData = data.get();
500     std::unique_ptr<char[]>  result = std::make_unique<char[]>(outLen + DECODE_VALUE_ONE);
501     char *dstData = result.get();
502     int j = 0;
503     int i = 0;
504     for (; i < srcLen - DECODE_VALUE_THREE; i += DECODE_VALUE_THREE) {
505         unsigned char byte1 = srcData[i];
506         unsigned char byte2 = srcData[i + DECODE_VALUE_ONE];
507         unsigned char byte3 = srcData[i + DECODE_VALUE_TWO];
508         dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
509         dstData[j++] =
510             DECODE_TABLE[(static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR)
511              | (byte2 >> DECODE_VALUE_FOUR)];
512         dstData[j++] =
513             DECODE_TABLE[(static_cast<uint8_t>(byte2 & DECODE_VALUE_CHAR_FIFTEEN)
514                 << DECODE_VALUE_TWO) | (byte3 >> DECODE_VALUE_SIX)];
515         dstData[j++] = DECODE_TABLE[byte3 & DECODE_VALUE_CHAR_SIXTY_THREE];
516     }
517     if (srcLen % DECODE_VALUE_THREE == DECODE_VALUE_ONE) {
518         unsigned char byte1 = srcData[i];
519         dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
520         dstData[j++] = DECODE_TABLE[static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR];
521         dstData[j++] = '=';
522         dstData[j++] = '=';
523     } else {
524         unsigned char byte1 = srcData[i];
525         unsigned char byte2 = srcData[i + DECODE_VALUE_ONE];
526         dstData[j++] = DECODE_TABLE[byte1 >> DECODE_VALUE_TWO];
527         dstData[j++] =
528             DECODE_TABLE[(static_cast<uint8_t>(byte1 & DECODE_VALUE_CHAR_THREE) << DECODE_VALUE_FOUR)
529              | (byte2 >> DECODE_VALUE_FOUR)];
530         dstData[j++] = DECODE_TABLE[static_cast<uint8_t>(byte2 & DECODE_VALUE_CHAR_FIFTEEN)
531                                     << DECODE_VALUE_TWO];
532         dstData[j++] = '=';
533     }
534     dstData[outLen] = '\0';
535 
536     return result;
537 }
538 
VerifySystemApp()539 bool DistributedBms::VerifySystemApp()
540 {
541     APP_LOGI("verifying systemApp");
542     int32_t callingUid = IPCSkeleton::GetCallingUid();
543     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
544     if (VerifyTokenNative(callerToken) || VerifyTokenShell(callerToken)
545         || callingUid == Constants::ROOT_UID) {
546         APP_LOGI("caller tokenType is native or shell, verify success");
547         return true;
548     }
549     uint64_t accessTokenIdEx = IPCSkeleton::GetCallingFullTokenID();
550     if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenIdEx)) {
551         APP_LOGE("non-system app calling system api");
552         return false;
553     }
554     return true;
555 }
556 
VerifyTokenNative(Security::AccessToken::AccessTokenID callerToken)557 bool DistributedBms::VerifyTokenNative(Security::AccessToken::AccessTokenID callerToken)
558 {
559     APP_LOGD("verifying system app for native token");
560     Security::AccessToken::ATokenTypeEnum tokenType =
561         Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
562     APP_LOGD("token type is %{public}d", static_cast<int32_t>(tokenType));
563     if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
564         APP_LOGI("caller tokenType is native, verify success");
565         return true;
566     }
567     APP_LOGE("caller tokenType not native, verify failed");
568     return false;
569 }
570 
VerifyTokenShell(Security::AccessToken::AccessTokenID callerToken)571 bool DistributedBms::VerifyTokenShell(Security::AccessToken::AccessTokenID callerToken)
572 {
573     APP_LOGD("verifying system app for shell token");
574     Security::AccessToken::ATokenTypeEnum tokenType =
575         Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
576     APP_LOGD("token type is %{public}d", static_cast<int32_t>(tokenType));
577     if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
578         APP_LOGI("caller tokenType is shell, verify success");
579         return true;
580     }
581     APP_LOGE("caller tokenType not shell, verify failed");
582     return false;
583 }
584 
VerifyCallingPermission(const std::string & permissionName)585 bool DistributedBms::VerifyCallingPermission(const std::string &permissionName)
586 {
587     APP_LOGD("VerifyCallingPermission permission %{public}s", permissionName.c_str());
588     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
589     auto uid = IPCSkeleton::GetCallingUid();
590     APP_LOGD("VerifyCallingPermission callingUid %{public}d", uid);
591     int32_t ret = OHOS::Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
592     if ((ret == OHOS::Security::AccessToken::PermissionState::PERMISSION_GRANTED) || (uid == DBMS_UID)) {
593         APP_LOGD("verify permission success");
594         return true;
595     }
596     APP_LOGE("permission %{public}s: PERMISSION_DENIED", permissionName.c_str());
597     return false;
598 }
599 }
600 }