• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #define LOG_TAG "PreProcessUtils"
16 
17 #include "preprocess_utils.h"
18 
19 #include <sstream>
20 
21 #include "dds_trace.h"
22 #include "udmf_radar_reporter.h"
23 #include "accesstoken_kit.h"
24 #include "device_manager_adapter.h"
25 #include "log_print.h"
26 #include "udmf_radar_reporter.h"
27 #include "udmf_utils.h"
28 #include "remote_file_share.h"
29 #include "utils/crypto.h"
30 #include "uri_permission_manager_client.h"
31 namespace OHOS {
32 namespace UDMF {
33 static constexpr int ID_LEN = 32;
34 static constexpr int MINIMUM = 48;
35 static constexpr int MAXIMUM = 121;
36 constexpr char SPECIAL = '^';
37 constexpr const char *FILE_SCHEME = "file";
38 constexpr const char *TAG = "PreProcessUtils::";
39 constexpr const char *FILE_SCHEME_PREFIX = "file://";
40 constexpr const char *DOCS_LOCAL_TAG = "/docs/";
41 static constexpr uint32_t DOCS_LOCAL_PATH_SUBSTR_START_INDEX = 1;
42 static constexpr uint32_t VERIFY_URI_PERMISSION_MAX_SIZE = 500;
43 constexpr const char *TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag";
44 static constexpr size_t TEMP_UDATA_RECORD_SIZE = 1;
45 static constexpr uint32_t PREFIX_LEN = 24;
46 static constexpr uint32_t INDEX_LEN = 8;
47 static constexpr const char PLACE_HOLDER = '0';
48 using namespace OHOS::DistributedDataDfx;
49 using namespace Security::AccessToken;
50 using namespace OHOS::AppFileService::ModuleRemoteFileShare;
51 using namespace RadarReporter;
52 
RuntimeDataImputation(UnifiedData & data,CustomOption & option)53 int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option)
54 {
55     auto it = UD_INTENTION_MAP.find(option.intention);
56     if (it == UD_INTENTION_MAP.end()) {
57         return E_ERROR;
58     }
59     std::string bundleName;
60     GetHapBundleNameByToken(option.tokenId, bundleName);
61     std::string intention = it->second;
62     UnifiedKey key(intention, bundleName, GenerateId());
63     Privilege privilege;
64     privilege.tokenId = option.tokenId;
65     Runtime runtime;
66     runtime.key = key;
67     runtime.privileges.emplace_back(privilege);
68     runtime.createTime = GetTimestamp();
69     runtime.sourcePackage = bundleName;
70     runtime.createPackage = bundleName;
71     runtime.deviceId = GetLocalDeviceId();
72     runtime.recordTotalNum = static_cast<uint32_t>(data.GetRecords().size());
73     runtime.tokenId = option.tokenId;
74     runtime.sdkVersion = GetSdkVersionByToken(option.tokenId);
75     data.SetRuntime(runtime);
76     return E_OK;
77 }
78 
GenerateId()79 std::string PreProcessUtils::GenerateId()
80 {
81     std::vector<uint8_t> randomDevices = DistributedData::Crypto::Random(ID_LEN, MINIMUM, MAXIMUM);
82     std::stringstream idStr;
83     for (auto &randomDevice : randomDevices) {
84         auto asc = randomDevice;
85         asc = asc >= SPECIAL ? asc + 1 : asc;
86         idStr << static_cast<uint8_t>(asc);
87     }
88     return idStr.str();
89 }
90 
GetTimestamp()91 time_t PreProcessUtils::GetTimestamp()
92 {
93     std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp =
94         std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
95     time_t timestamp = tp.time_since_epoch().count();
96     return timestamp;
97 }
98 
GetHapUidByToken(uint32_t tokenId,int & userId)99 int32_t PreProcessUtils::GetHapUidByToken(uint32_t tokenId, int &userId)
100 {
101     Security::AccessToken::HapTokenInfo tokenInfo;
102     auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
103     if (result != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
104         ZLOGE("GetHapUidByToken failed, result = %{public}d.", result);
105         return E_ERROR;
106     }
107     userId = tokenInfo.userID;
108     return E_OK;
109 }
110 
GetHapBundleNameByToken(int tokenId,std::string & bundleName)111 bool PreProcessUtils::GetHapBundleNameByToken(int tokenId, std::string &bundleName)
112 {
113     Security::AccessToken::HapTokenInfo hapInfo;
114     if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo)
115         == Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
116         bundleName = hapInfo.bundleName;
117         return true;
118     }
119     if (UTILS::IsTokenNative()) {
120         ZLOGD("TypeATokenTypeEnum is TOKEN_HAP");
121         std::string processName;
122         if (GetNativeProcessNameByToken(tokenId, processName)) {
123             bundleName = processName;
124             return true;
125         }
126     }
127     ZLOGE("Get bundle name faild");
128     return false;
129 }
130 
GetNativeProcessNameByToken(int tokenId,std::string & processName)131 bool PreProcessUtils::GetNativeProcessNameByToken(int tokenId, std::string &processName)
132 {
133     Security::AccessToken::NativeTokenInfo nativeInfo;
134     if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, nativeInfo)
135         != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
136         return false;
137     }
138     processName = nativeInfo.processName;
139     return true;
140 }
141 
GetLocalDeviceId()142 std::string PreProcessUtils::GetLocalDeviceId()
143 {
144     auto info = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice();
145     std::string encryptedUuid = DistributedData::DeviceManagerAdapter::GetInstance().CalcClientUuid(" ", info.uuid);
146     return encryptedUuid;
147 }
148 
SetRemoteData(UnifiedData & data)149 void PreProcessUtils::SetRemoteData(UnifiedData &data)
150 {
151     if (data.IsEmpty()) {
152         ZLOGD("invalid data.");
153         return;
154     }
155     std::shared_ptr<Runtime> runtime = data.GetRuntime();
156     if (runtime->deviceId == GetLocalDeviceId()) {
157         ZLOGD("not remote data.");
158         return;
159     }
160     ZLOGD("is remote data.");
161     auto records = data.GetRecords();
162     ProcessFileType(records, [] (std::shared_ptr<Object> obj) {
163         std::shared_ptr<Object> detailObj;
164         obj->GetValue(DETAILS, detailObj);
165         if (detailObj == nullptr) {
166             ZLOGE("No details for object");
167             return false;
168         }
169         UDDetails details = ObjectUtils::ConvertToUDDetails(detailObj);
170         details.insert({ "isRemote", "true" });
171         obj->value_[DETAILS] = ObjectUtils::ConvertToObject(details);
172         return true;
173     });
174 }
175 
IsFileType(std::shared_ptr<UnifiedRecord> record)176 bool PreProcessUtils::IsFileType(std::shared_ptr<UnifiedRecord> record)
177 {
178     if (record == nullptr) {
179         return false;
180     }
181     if (!std::holds_alternative<std::shared_ptr<Object>>(record->GetOriginValue())) {
182         return false;
183     }
184     auto obj = std::get<std::shared_ptr<Object>>(record->GetOriginValue());
185     return obj->value_.find(ORI_URI) != obj->value_.end();
186 }
187 
SetRemoteUri(uint32_t tokenId,UnifiedData & data)188 int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data)
189 {
190     std::vector<std::string> uris;
191     ProcessFileType(data.GetRecords(), [&uris](std::shared_ptr<Object> obj) {
192         std::string oriUri;
193         obj->GetValue(ORI_URI, oriUri);
194         if (oriUri.empty()) {
195             ZLOGW("URI is empty, please check");
196             return false;
197         }
198         Uri uri(oriUri);
199         std::string scheme = uri.GetScheme();
200         std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
201         if (uri.GetAuthority().empty() || scheme != FILE_SCHEME) {
202             ZLOGW("Empty URI authority or scheme not file");
203             return false;
204         }
205         uris.push_back(oriUri);
206         return true;
207     });
208     GetHtmlFileUris(tokenId, data, true, uris);
209     if (!uris.empty()) {
210         ZLOGI("Read to check uri authorization");
211         if (!CheckUriAuthorization(uris, tokenId)) {
212             ZLOGE("UriAuth check failed:bundleName:%{public}s,tokenId:%{public}d,uris size:%{public}zu",
213                   data.GetRuntime()->createPackage.c_str(), tokenId, uris.size());
214             RadarReporterAdapter::ReportFail(std::string(__FUNCTION__),
215                 BizScene::SET_DATA, SetDataStage::VERIFY_SHARE_PERMISSIONS, StageRes::FAILED, E_NO_PERMISSION);
216             return E_NO_PERMISSION;
217         }
218         if (!IsNetworkingEnabled()) {
219             return E_OK;
220         }
221         int32_t userId;
222         if (GetHapUidByToken(tokenId, userId) == E_OK) {
223             GetDfsUrisFromLocal(uris, userId, data);
224         }
225     }
226     return E_OK;
227 }
228 
GetDfsUrisFromLocal(const std::vector<std::string> & uris,int32_t userId,UnifiedData & data)229 int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector<std::string> &uris, int32_t userId, UnifiedData &data)
230 {
231     DdsTrace trace(
232         std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON);
233     RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
234         BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE, BizState::DFX_BEGIN);
235     std::unordered_map<std::string, HmdfsUriInfo> dfsUris;
236     int ret = RemoteFileShare::GetDfsUrisFromLocal(uris, userId, dfsUris);
237     if (ret != 0 || dfsUris.empty()) {
238         RadarReporterAdapter::ReportFail(std::string(__FUNCTION__),
239             BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, E_FS_ERROR, BizState::DFX_END);
240         ZLOGE("Get remoteUri failed, ret = %{public}d, userId: %{public}d, uri size:%{public}zu.",
241               ret, userId, uris.size());
242         return E_FS_ERROR;
243     }
244     RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
245         BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS);
246     ProcessFileType(data.GetRecords(), [&dfsUris] (std::shared_ptr<Object> obj) {
247         std::string oriUri;
248         obj->GetValue(ORI_URI, oriUri);
249         auto iter = dfsUris.find(oriUri);
250         if (iter != dfsUris.end()) {
251             obj->value_[REMOTE_URI] = (iter->second).uriStr;
252         }
253         return true;
254     });
255     for (auto &record : data.GetRecords()) {
256         if (record == nullptr) {
257             continue;
258         }
259         record->ComputeUris([&dfsUris] (UriInfo &uriInfo) {
260             auto iter = dfsUris.find(uriInfo.authUri);
261             if (iter != dfsUris.end()) {
262                 uriInfo.dfsUri = (iter->second).uriStr;
263             }
264             return true;
265         });
266     }
267     RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
268         BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS, BizState::DFX_END);
269     return E_OK;
270 }
271 
CheckUriAuthorization(const std::vector<std::string> & uris,uint32_t tokenId)272 bool PreProcessUtils::CheckUriAuthorization(const std::vector<std::string>& uris, uint32_t tokenId)
273 {
274     for (size_t index = 0; index < uris.size(); index += VERIFY_URI_PERMISSION_MAX_SIZE) {
275         std::vector<std::string> urisToBeChecked(
276             uris.begin() + index, uris.begin() + std::min(index + VERIFY_URI_PERMISSION_MAX_SIZE, uris.size()));
277         auto checkResults = AAFwk::UriPermissionManagerClient::GetInstance().CheckUriAuthorization(
278             urisToBeChecked, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, tokenId);
279         auto iter = find(checkResults.begin(), checkResults.end(), false);
280         if (iter != checkResults.end()) {
281             return false;
282         }
283     }
284     return true;
285 }
286 
GetInstIndex(uint32_t tokenId,int32_t & instIndex)287 bool PreProcessUtils::GetInstIndex(uint32_t tokenId, int32_t &instIndex)
288 {
289     if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
290         instIndex = 0;
291         return true;
292     }
293     HapTokenInfo tokenInfo;
294     int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
295     if (errCode != RET_SUCCESS) {
296         ZLOGE("Get Hap TokenInfo error:%{public}d, tokenId:0x%{public}x", errCode, tokenId);
297         return false;
298     }
299     instIndex = tokenInfo.instIndex;
300     return true;
301 }
302 
IsNetworkingEnabled()303 bool PreProcessUtils::IsNetworkingEnabled()
304 {
305     std::vector<AppDistributedKv::DeviceInfo> devInfos =
306         DistributedData::DeviceManagerAdapter::GetInstance().GetRemoteDevices();
307     ZLOGI("Remote devices count:%{public}u", static_cast<uint32_t>(devInfos.size()));
308     if (devInfos.empty()) {
309         return false;
310     }
311     return true;
312 }
313 
ProcessFileType(std::vector<std::shared_ptr<UnifiedRecord>> records,std::function<bool (std::shared_ptr<Object>)> callback)314 void PreProcessUtils::ProcessFileType(std::vector<std::shared_ptr<UnifiedRecord>> records,
315     std::function<bool(std::shared_ptr<Object>)> callback)
316 {
317     for (auto record : records) {
318         if (record == nullptr) {
319             continue;
320         }
321         if (!PreProcessUtils::IsFileType(record)) {
322             continue;
323         }
324         auto obj = std::get<std::shared_ptr<Object>>(record->GetOriginValue());
325         if (obj == nullptr) {
326             ZLOGE("ValueType is not Object, Not convert to remote uri!");
327             continue;
328         }
329         if (!callback(obj)) {
330             continue;
331         }
332     }
333 }
334 
ProcessRecord(std::shared_ptr<UnifiedRecord> record,uint32_t tokenId,bool isLocal,std::vector<std::string> & uris)335 void PreProcessUtils::ProcessRecord(std::shared_ptr<UnifiedRecord> record, uint32_t tokenId,
336     bool isLocal, std::vector<std::string> &uris)
337 {
338     record->ComputeUris([&uris, &isLocal, &tokenId] (UriInfo &uriInfo) {
339         std::string newUriStr = "";
340         if (isLocal) {
341             Uri tmpUri(uriInfo.oriUri);
342             std::string path = tmpUri.GetPath();
343             std::string bundleName;
344             if (!GetHapBundleNameByToken(tokenId, bundleName)) {
345                 return true;
346             }
347             if (path.substr(0, strlen(DOCS_LOCAL_TAG)) == DOCS_LOCAL_TAG) {
348                 newUriStr = FILE_SCHEME_PREFIX;
349                 newUriStr += path.substr(DOCS_LOCAL_PATH_SUBSTR_START_INDEX);
350             } else {
351                 newUriStr = FILE_SCHEME_PREFIX;
352                 newUriStr += bundleName + path;
353             }
354             uriInfo.authUri = newUriStr;
355         } else {
356             newUriStr = uriInfo.dfsUri;
357         }
358         Uri uri(newUriStr);
359         if (uri.GetAuthority().empty()) {
360             return true;
361         }
362         std::string scheme = uri.GetScheme();
363         std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
364         if (scheme != FILE_SCHEME) {
365             return true;
366         }
367         auto iter = std::find(uris.begin(), uris.end(), newUriStr);
368         if (iter == uris.end()) {
369             uris.push_back(std::move(newUriStr));
370         }
371         return true;
372     });
373 }
374 
GetHtmlFileUris(uint32_t tokenId,UnifiedData & data,bool isLocal,std::vector<std::string> & uris)375 void PreProcessUtils::GetHtmlFileUris(uint32_t tokenId, UnifiedData &data,
376     bool isLocal, std::vector<std::string> &uris)
377 {
378     for (auto &record : data.GetRecords()) {
379         if (record == nullptr) {
380             continue;
381         }
382         PreProcessUtils::ProcessRecord(record, tokenId, isLocal, uris);
383     }
384 }
385 
ClearHtmlDfsUris(UnifiedData & data)386 void PreProcessUtils::ClearHtmlDfsUris(UnifiedData &data)
387 {
388     for (auto &record : data.GetRecords()) {
389         if (record == nullptr) {
390             continue;
391         }
392         record->ComputeUris([] (UriInfo &uriInfo) {
393             uriInfo.dfsUri = "";
394             return true;
395         });
396     }
397 }
398 
ProcessHtmlFileUris(uint32_t tokenId,UnifiedData & data,bool isLocal,std::vector<Uri> & uris)399 void PreProcessUtils::ProcessHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector<Uri> &uris)
400 {
401     std::vector<std::string> strUris;
402     PreProcessUtils::GetHtmlFileUris(tokenId, data, isLocal, strUris);
403     for (auto &uri : strUris) {
404         uris.emplace_back(Uri(uri));
405     }
406     if (isLocal) {
407         PreProcessUtils::ClearHtmlDfsUris(data);
408     }
409 }
410 
SetRecordUid(UnifiedData & data)411 void PreProcessUtils::SetRecordUid(UnifiedData &data)
412 {
413     uint32_t index = 0;
414     auto prefix = PreProcessUtils::GenerateId().substr(0, PREFIX_LEN);
415     for (const auto &record : data.GetRecords()) {
416         std::ostringstream oss;
417         oss << std::setw(INDEX_LEN) << std::setfill(PLACE_HOLDER) << index;
418         record->SetUid(prefix + oss.str());
419         index++;
420     }
421 }
422 
GetDetailsFromUData(const UnifiedData & data,UDDetails & details)423 bool PreProcessUtils::GetDetailsFromUData(const UnifiedData &data, UDDetails &details)
424 {
425     auto records = data.GetRecords();
426     if (records.size() != TEMP_UDATA_RECORD_SIZE) {
427         ZLOGI("Records size:%{public}zu", records.size());
428         return false;
429     }
430     if (records[0] == nullptr) {
431         ZLOGE("First record is null.");
432         return false;
433     }
434     if (records[0]->GetType() != UDType::FILE) {
435         ZLOGE("First record is not file.");
436         return false;
437     }
438     auto value = records[0]->GetOriginValue();
439     auto obj = std::get_if<std::shared_ptr<Object>>(&value);
440     if (obj == nullptr || *obj == nullptr) {
441         ZLOGE("ValueType is not Object!");
442         return false;
443     }
444     std::shared_ptr<Object> detailObj;
445     (*obj)->GetValue(DETAILS, detailObj);
446     if (detailObj == nullptr) {
447         ZLOGE("Not contain details for object!");
448         return false;
449     }
450     auto result = ObjectUtils::ConvertToUDDetails(detailObj);
451     if (result.find(TEMP_UNIFIED_DATA_FLAG) == result.end()) {
452         ZLOGE("Not find temp file.");
453         return false;
454     }
455     details = std::move(result);
456     return true;
457 }
458 
GetSummaryFromDetails(const UDDetails & details,Summary & summary)459 Status PreProcessUtils::GetSummaryFromDetails(const UDDetails &details, Summary &summary)
460 {
461     for (auto &item : details) {
462         if (item.first == TEMP_UNIFIED_DATA_FLAG) {
463             continue;
464         }
465         auto int64Value = std::get_if<int64_t>(&item.second);
466         if (int64Value != nullptr) {
467             summary.summary[item.first] = *int64Value;
468             summary.totalSize += *int64Value;
469         }
470     }
471     return E_OK;
472 }
473 
GetSdkVersionByToken(uint32_t tokenId)474 std::string PreProcessUtils::GetSdkVersionByToken(uint32_t tokenId)
475 {
476     if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) !=
477         Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
478         ZLOGE("Caller is not application, tokenid is %{public}u", tokenId);
479         return "";
480     }
481     Security::AccessToken::HapTokenInfo hapTokenInfo;
482     auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo);
483     if (ret != 0) {
484         ZLOGE("GetHapTokenInfo fail, tokenid is %{public}u, ret is %{public}d.", tokenId, ret);
485         return "";
486     }
487     return std::to_string(hapTokenInfo.apiVersion);
488 }
489 } // namespace UDMF
490 } // namespace OHOS