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