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