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 <random>
20 #include <sstream>
21
22 #include "dds_trace.h"
23 #include "udmf_radar_reporter.h"
24 #include "accesstoken_kit.h"
25 #include "bundlemgr/bundle_mgr_client_impl.h"
26 #include "device_manager_adapter.h"
27 #include "error_code.h"
28 #include "ipc_skeleton.h"
29 #include "log_print.h"
30 #include "udmf_radar_reporter.h"
31 #include "udmf_utils.h"
32 #include "remote_file_share.h"
33 #include "uri.h"
34 #include "utils/crypto.h"
35 #include "want.h"
36 #include "uri_permission_manager_client.h"
37 namespace OHOS {
38 namespace UDMF {
39 static constexpr int ID_LEN = 32;
40 static constexpr int MINIMUM = 48;
41 static constexpr int MAXIMUM = 121;
42 constexpr char SPECIAL = '^';
43 constexpr const char *FILE_SCHEME = "file";
44 constexpr const char *TAG = "PreProcessUtils::";
45 static constexpr uint32_t VERIFY_URI_PERMISSION_MAX_SIZE = 500;
46 using namespace OHOS::DistributedDataDfx;
47 using namespace Security::AccessToken;
48 using namespace OHOS::AppFileService::ModuleRemoteFileShare;
49 using namespace RadarReporter;
50
RuntimeDataImputation(UnifiedData & data,CustomOption & option)51 int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option)
52 {
53 auto it = UD_INTENTION_MAP.find(option.intention);
54 if (it == UD_INTENTION_MAP.end()) {
55 return E_ERROR;
56 }
57 std::string bundleName;
58 GetHapBundleNameByToken(option.tokenId, bundleName);
59 std::string intention = it->second;
60 UnifiedKey key(intention, bundleName, GenerateId());
61 Privilege privilege;
62 privilege.tokenId = option.tokenId;
63 Runtime runtime;
64 runtime.key = key;
65 runtime.privileges.emplace_back(privilege);
66 runtime.createTime = GetTimestamp();
67 runtime.sourcePackage = bundleName;
68 runtime.createPackage = bundleName;
69 runtime.deviceId = GetLocalDeviceId();
70 runtime.recordTotalNum = static_cast<uint32_t>(data.GetRecords().size());
71 runtime.tokenId = option.tokenId;
72 data.SetRuntime(runtime);
73 return E_OK;
74 }
75
GenerateId()76 std::string PreProcessUtils::GenerateId()
77 {
78 std::vector<uint8_t> randomDevices = DistributedData::Crypto::Random(ID_LEN, MINIMUM, MAXIMUM);
79 std::stringstream idStr;
80 for (auto &randomDevice : randomDevices) {
81 auto asc = randomDevice;
82 asc = asc >= SPECIAL ? asc + 1 : asc;
83 idStr << static_cast<uint8_t>(asc);
84 }
85 return idStr.str();
86 }
87
GetTimestamp()88 time_t PreProcessUtils::GetTimestamp()
89 {
90 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp =
91 std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
92 time_t timestamp = tp.time_since_epoch().count();
93 return timestamp;
94 }
95
GetHapUidByToken(uint32_t tokenId,int & userId)96 int32_t PreProcessUtils::GetHapUidByToken(uint32_t tokenId, int &userId)
97 {
98 Security::AccessToken::HapTokenInfo tokenInfo;
99 auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
100 if (result != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
101 ZLOGE("GetHapUidByToken failed, result = %{public}d.", result);
102 return E_ERROR;
103 }
104 userId = tokenInfo.userID;
105 return E_OK;
106 }
107
GetHapBundleNameByToken(int tokenId,std::string & bundleName)108 bool PreProcessUtils::GetHapBundleNameByToken(int tokenId, std::string &bundleName)
109 {
110 Security::AccessToken::HapTokenInfo hapInfo;
111 if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo)
112 == Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
113 bundleName = hapInfo.bundleName;
114 return true;
115 }
116 if (UTILS::IsTokenNative()) {
117 ZLOGD("TypeATokenTypeEnum is TOKEN_HAP");
118 std::string processName;
119 if (GetNativeProcessNameByToken(tokenId, processName)) {
120 bundleName = processName;
121 return true;
122 }
123 }
124 ZLOGE("GetHapBundleNameByToken faild");
125 return false;
126 }
127
GetNativeProcessNameByToken(int tokenId,std::string & processName)128 bool PreProcessUtils::GetNativeProcessNameByToken(int tokenId, std::string &processName)
129 {
130 Security::AccessToken::NativeTokenInfo nativeInfo;
131 if (Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(tokenId, nativeInfo)
132 != Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) {
133 return false;
134 }
135 processName = nativeInfo.processName;
136 return true;
137 }
138
GetLocalDeviceId()139 std::string PreProcessUtils::GetLocalDeviceId()
140 {
141 auto info = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice();
142 std::string encryptedUuid = DistributedData::DeviceManagerAdapter::GetInstance().CalcClientUuid(" ", info.uuid);
143 return encryptedUuid;
144 }
145
SetRemoteData(UnifiedData & data)146 void PreProcessUtils::SetRemoteData(UnifiedData &data)
147 {
148 if (data.IsEmpty()) {
149 ZLOGD("invalid data.");
150 return;
151 }
152 std::shared_ptr<Runtime> runtime = data.GetRuntime();
153 if (runtime->deviceId == GetLocalDeviceId()) {
154 ZLOGD("not remote data.");
155 return;
156 }
157 ZLOGD("is remote data.");
158 auto records = data.GetRecords();
159 ProcessFileType(records, [] (std::shared_ptr<Object> obj) {
160 std::shared_ptr<Object> detailObj;
161 obj->GetValue(DETAILS, detailObj);
162 if (detailObj == nullptr) {
163 ZLOGE("Not contain details for object!");
164 return false;
165 }
166 UDDetails details = ObjectUtils::ConvertToUDDetails(detailObj);
167 details.insert({ "isRemote", "true" });
168 obj->value_[DETAILS] = ObjectUtils::ConvertToObject(details);
169 return true;
170 });
171 }
172
IsFileType(std::shared_ptr<UnifiedRecord> record)173 bool PreProcessUtils::IsFileType(std::shared_ptr<UnifiedRecord> record)
174 {
175 if (record == nullptr) {
176 return false;
177 }
178 if (!std::holds_alternative<std::shared_ptr<Object>>(record->GetOriginValue())) {
179 return false;
180 }
181 auto obj = std::get<std::shared_ptr<Object>>(record->GetOriginValue());
182 return obj->value_.find(ORI_URI) != obj->value_.end();
183 }
184
SetRemoteUri(uint32_t tokenId,UnifiedData & data)185 int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data)
186 {
187 std::vector<std::string> uris;
188 ProcessFileType(data.GetRecords(), [&uris](std::shared_ptr<Object> obj) {
189 std::string oriUri;
190 obj->GetValue(ORI_URI, oriUri);
191 if (oriUri.empty()) {
192 ZLOGW("Get uri empty, plase check the uri.");
193 return false;
194 }
195 Uri uri(oriUri);
196 std::string scheme = uri.GetScheme();
197 std::transform(scheme.begin(), scheme.end(), scheme.begin(), ::tolower);
198 if (uri.GetAuthority().empty() || scheme != FILE_SCHEME) {
199 ZLOGW("Get uri authority empty or uri scheme not equals to file.");
200 return false;
201 }
202 uris.push_back(oriUri);
203 return true;
204 });
205 if (!uris.empty()) {
206 ZLOGI("Read to check uri authorization");
207 if (!CheckUriAuthorization(uris, tokenId)) {
208 ZLOGE("CheckUriAuthorization failed, bundleName:%{public}s, tokenId: %{public}d, uris size:%{public}zu.",
209 data.GetRuntime()->createPackage.c_str(), tokenId, uris.size());
210 RadarReporterAdapter::ReportFail(std::string(__FUNCTION__),
211 BizScene::SET_DATA, SetDataStage::VERIFY_SHARE_PERMISSIONS, StageRes::FAILED, E_NO_PERMISSION);
212 return E_NO_PERMISSION;
213 }
214 if (!IsNetworkingEnabled()) {
215 return E_OK;
216 }
217 int32_t userId;
218 if (GetHapUidByToken(tokenId, userId) == E_OK) {
219 GetDfsUrisFromLocal(uris, userId, data);
220 }
221 }
222 return E_OK;
223 }
224
GetDfsUrisFromLocal(const std::vector<std::string> & uris,int32_t userId,UnifiedData & data)225 int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector<std::string> &uris, int32_t userId, UnifiedData &data)
226 {
227 DdsTrace trace(
228 std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON);
229 RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
230 BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE, BizState::DFX_BEGIN);
231 std::unordered_map<std::string, HmdfsUriInfo> dfsUris;
232 int ret = RemoteFileShare::GetDfsUrisFromLocal(uris, userId, dfsUris);
233 if (ret != 0 || dfsUris.empty()) {
234 RadarReporterAdapter::ReportFail(std::string(__FUNCTION__),
235 BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, E_FS_ERROR, BizState::DFX_END);
236 ZLOGE("Get remoteUri failed, ret = %{public}d, userId: %{public}d, uri size:%{public}zu.",
237 ret, userId, uris.size());
238 return E_FS_ERROR;
239 }
240 RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
241 BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS);
242 ProcessFileType(data.GetRecords(), [&dfsUris] (std::shared_ptr<Object> obj) {
243 std::string oriUri;
244 obj->GetValue(ORI_URI, oriUri);
245 auto iter = dfsUris.find(oriUri);
246 if (iter != dfsUris.end()) {
247 obj->value_[REMOTE_URI] = (iter->second).uriStr;
248 }
249 return true;
250 });
251 RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__),
252 BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS, BizState::DFX_END);
253 return E_OK;
254 }
255
CheckUriAuthorization(const std::vector<std::string> & uris,uint32_t tokenId)256 bool PreProcessUtils::CheckUriAuthorization(const std::vector<std::string>& uris, uint32_t tokenId)
257 {
258 for (size_t index = 0; index < uris.size(); index += VERIFY_URI_PERMISSION_MAX_SIZE) {
259 std::vector<std::string> urisToBeChecked(
260 uris.begin() + index, uris.begin() + std::min(index + VERIFY_URI_PERMISSION_MAX_SIZE, uris.size()));
261 auto checkResults = AAFwk::UriPermissionManagerClient::GetInstance().CheckUriAuthorization(
262 urisToBeChecked, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, tokenId);
263 auto iter = find(checkResults.begin(), checkResults.end(), false);
264 if (iter != checkResults.end()) {
265 return false;
266 }
267 }
268 return true;
269 }
270
GetInstIndex(uint32_t tokenId,int32_t & instIndex)271 bool PreProcessUtils::GetInstIndex(uint32_t tokenId, int32_t &instIndex)
272 {
273 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
274 instIndex = 0;
275 return true;
276 }
277 HapTokenInfo tokenInfo;
278 int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
279 if (errCode != RET_SUCCESS) {
280 ZLOGE("Get Hap TokenInfo error:%{public}d, tokenId:0x%{public}x", errCode, tokenId);
281 return false;
282 }
283 instIndex = tokenInfo.instIndex;
284 return true;
285 }
286
IsNetworkingEnabled()287 bool PreProcessUtils::IsNetworkingEnabled()
288 {
289 std::vector<AppDistributedKv::DeviceInfo> devInfos =
290 DistributedData::DeviceManagerAdapter::GetInstance().GetRemoteDevices();
291 ZLOGI("DM remote devices count is %{public}u.", static_cast<uint32_t>(devInfos.size()));
292 if (devInfos.empty()) {
293 return false;
294 }
295 return true;
296 }
297
ProcessFileType(std::vector<std::shared_ptr<UnifiedRecord>> records,std::function<bool (std::shared_ptr<Object>)> callback)298 void PreProcessUtils::ProcessFileType(std::vector<std::shared_ptr<UnifiedRecord>> records,
299 std::function<bool(std::shared_ptr<Object>)> callback)
300 {
301 for (auto record : records) {
302 if (record == nullptr) {
303 continue;
304 }
305 if (!PreProcessUtils::IsFileType(record)) {
306 continue;
307 }
308 auto obj = std::get<std::shared_ptr<Object>>(record->GetOriginValue());
309 if (obj == nullptr) {
310 ZLOGE("ValueType is not Object, Not convert to remote uri!");
311 continue;
312 }
313 if (!callback(obj)) {
314 continue;
315 }
316 }
317 }
318 } // namespace UDMF
319 } // namespace OHOS