• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_sched_utils.h"
17 
18 #include <algorithm>
19 #include <cstdlib>
20 #include <filesystem>
21 #include <fstream>
22 #include <iostream>
23 #include <vector>
24 
25 #include "ability_manager_client.h"
26 #include "config_policy_utils.h"
27 #include "securec.h"
28 
29 #include "dms_constant.h"
30 #include "dtbschedmgr_log.h"
31 
32 namespace OHOS {
33 namespace DistributedSchedule {
34 using namespace OHOS::DistributedSchedule::Constants;
35 
36 const std::string TAG = "DistributedSchedUtils";
37 const std::string CONTINUE_CONFIG_RELATIVE_PATH = "etc/distributedhardware/dms/continue_config.json";
38 const std::string ALLOW_APP_LIST_KEY = "allow_applist";
39 constexpr int32_t MAX_CONFIG_PATH_LEN = 1024;
40 constexpr size_t INT32_SHORT_ID_LEN = 20;
41 constexpr size_t INT32_MIN_ID_LEN = 6;
42 constexpr size_t INT32_PLAINTEXT_LEN = 4;
43 
44 constexpr uint32_t OFFSET2 = 2;
45 constexpr uint32_t OFFSET4 = 4;
46 constexpr uint32_t OFFSET6 = 6;
47 constexpr uint8_t PARAM_FC = 0xfc;
48 constexpr uint8_t PARAM_03 = 0x03;
49 constexpr uint8_t PARAM_F0 = 0xf0;
50 constexpr uint8_t PARAM_0F = 0x0f;
51 constexpr uint8_t PARAM_C0 = 0xc0;
52 constexpr uint8_t PARAM_3F = 0x3f;
53 constexpr uint32_t INDEX_FIRST = 0;
54 constexpr uint32_t INDEX_SECOND = 1;
55 constexpr uint32_t INDEX_THIRD = 2;
56 constexpr uint32_t INDEX_FORTH = 3;
57 
58 static std::atomic<bool> g_isMissContinueCfg = false;
59 static std::string g_continueCfgFullPath = "";
60 static std::vector<std::string> g_allowAppList;
61 std::mutex g_allowAppListMtx;
62 
63 using JsonTypeCheckFunc = bool (*)(const cJSON *paramValue);
64 std::map<std::string, JsonTypeCheckFunc> jsonTypeCheckMap = {
65     std::map<std::string, JsonTypeCheckFunc>::value_type(PARAM_KEY_OS_TYPE, &DistributedSchedule::IsInt32),
66     std::map<std::string, JsonTypeCheckFunc>::value_type(PARAM_KEY_OS_VERSION, &DistributedSchedule::IsString),
67 };
68 
IsValidPath(const std::string & inFilePath,std::string & realFilePath)69 bool IsValidPath(const std::string &inFilePath, std::string &realFilePath)
70 {
71     char path[PATH_MAX + 1] = { 0 };
72     if (inFilePath.empty() || inFilePath.length() > PATH_MAX || inFilePath.length() + 1 > MAX_CONFIG_PATH_LEN ||
73         realpath(inFilePath.c_str(), path) == nullptr) {
74         HILOGE("Get continue config file real path fail, inFilePath %{public}s.", GetAnonymStr(inFilePath).c_str());
75         return false;
76     }
77 
78     realFilePath = std::string(path);
79     if (realFilePath.empty()) {
80         HILOGE("Real file path is empty.");
81         return false;
82     }
83     if (!std::filesystem::exists(realFilePath)) {
84         HILOGE("The real file path %{public}s does not exist in the file system.", GetAnonymStr(realFilePath).c_str());
85         realFilePath = "";
86         return false;
87     }
88     HILOGI("The real file path %{public}s exist in the file system.", GetAnonymStr(realFilePath).c_str());
89     return true;
90 }
91 
UpdateAllowAppList(const std::string & cfgJsonStr)92 bool UpdateAllowAppList(const std::string &cfgJsonStr)
93 {
94     cJSON *inJson = nullptr;
95     cJSON *allowList = nullptr;
96     bool isSuccess = false;
97     do {
98         inJson = cJSON_Parse(cfgJsonStr.c_str());
99         if (inJson == nullptr) {
100             HILOGE("parse continue config json file stream to json fail.");
101             break;
102         }
103 
104         allowList = cJSON_GetObjectItem(inJson, ALLOW_APP_LIST_KEY.c_str());
105         if (allowList == nullptr || !cJSON_IsArray(allowList)) {
106             HILOGE("allow app list array is not in continue config json file.");
107             break;
108         }
109 
110         std::lock_guard<std::mutex> lock(g_allowAppListMtx);
111         for (int32_t i = 0; i < cJSON_GetArraySize(allowList); i++) {
112             cJSON *iAllowAppJson = cJSON_GetArrayItem(allowList, i);
113             if (!cJSON_IsString(iAllowAppJson)) {
114                 HILOGE("allow app list [%{public}d] is not string.", i);
115                 continue;
116             }
117 
118             std::string iAllowAppStr = std::string(cJSON_GetStringValue(iAllowAppJson));
119             HILOGI("allow app list show [%{public}d] : [%{public}s].", i, iAllowAppStr.c_str());
120             g_allowAppList.push_back(iAllowAppStr);
121         }
122         isSuccess = true;
123     } while (false);
124 
125     if (inJson != nullptr) {
126         cJSON_Delete(inJson);
127         inJson = nullptr;
128     }
129     return isSuccess;
130 }
131 
LoadContinueConfig()132 int32_t LoadContinueConfig()
133 {
134     HILOGI("Load continue config, isMissContinueCfg %{public}d, ContinueCfgFullPath %{public}s.",
135         g_isMissContinueCfg.load(), GetAnonymStr(g_continueCfgFullPath).c_str());
136     std::string tempPath = g_continueCfgFullPath;
137     if (!g_isMissContinueCfg.load() &&
138         (g_continueCfgFullPath.empty() || !IsValidPath(tempPath, g_continueCfgFullPath))) {
139         char cfgPathBuf[MAX_CONFIG_PATH_LEN] = { 0 };
140         char *filePath  = GetOneCfgFile(CONTINUE_CONFIG_RELATIVE_PATH.c_str(), cfgPathBuf, MAX_CONFIG_PATH_LEN);
141         if (filePath == nullptr || filePath != cfgPathBuf) {
142             HILOGI("Not find continue config file, relative path %{public}s.",
143                 GetAnonymStr(CONTINUE_CONFIG_RELATIVE_PATH).c_str());
144             g_isMissContinueCfg.store(true);
145             g_continueCfgFullPath = "";
146             return ERR_OK;
147         }
148         g_isMissContinueCfg.store(false);
149         g_continueCfgFullPath = std::string(filePath);
150         HILOGI("Get Continue config file full path success, cfgFullPath %{public}s.",
151             GetAnonymStr(g_continueCfgFullPath).c_str());
152     }
153     if (g_isMissContinueCfg.load()) {
154         HILOGI("Current device does not carry continue config file.");
155         return ERR_OK;
156     }
157     tempPath = g_continueCfgFullPath;
158     std::string anonymPath = GetAnonymStr(g_continueCfgFullPath);
159     if (!IsValidPath(tempPath, g_continueCfgFullPath)) {
160         HILOGE("Continue config full path is invalid, cfgFullPath %{public}s.", anonymPath.c_str());
161         return DMS_PERMISSION_DENIED;
162     }
163     std::ifstream in;
164     in.open(g_continueCfgFullPath.c_str(), std::ios::binary | std::ios::in);
165     if (!in.is_open()) {
166         HILOGE("Open continue config json file fail, cfgFullPath %{public}s.", anonymPath.c_str());
167         return DMS_PERMISSION_DENIED;
168     }
169 
170     std::string cfgFileContent;
171     in.seekg(0, std::ios::end);
172     cfgFileContent.resize(in.tellg());
173     in.seekg(0, std::ios::beg);
174     in.rdbuf()->sgetn(&cfgFileContent[0], cfgFileContent.size());
175     in.close();
176 
177     if (!UpdateAllowAppList(cfgFileContent)) {
178         HILOGE("Update allow app list fail, cfgFullPath %{public}s.", anonymPath.c_str());
179         return DMS_PERMISSION_DENIED;
180     }
181     HILOGI("Load continue config success, isMissContinueCfg %{public}d, cfgFullPath %{public}s.",
182         g_isMissContinueCfg.load(), anonymPath.c_str());
183     return ERR_OK;
184 }
185 
CheckBundleContinueConfig(const std::string & bundleName)186 bool CheckBundleContinueConfig(const std::string &bundleName)
187 {
188     if (g_isMissContinueCfg.load()) {
189         HILOGI("Current device does not carry continue config file.");
190         return true;
191     }
192 
193     std::lock_guard<std::mutex> lock(g_allowAppListMtx);
194     auto it = std::find(g_allowAppList.begin(), g_allowAppList.end(), bundleName);
195     if (it == g_allowAppList.end()) {
196         HILOGE("Current app is not allow to continue in config file, bundleName %{public}s, cfgPath %{public}s.",
197             bundleName.c_str(), GetAnonymStr(g_continueCfgFullPath).c_str());
198         return false;
199     }
200 
201     HILOGI("Current app is allow to continue in config file, bundleName %{public}s, cfgPath %{public}s.",
202         bundleName.c_str(), GetAnonymStr(g_continueCfgFullPath).c_str());
203     return true;
204 }
205 
GetCurrentMissionId()206 int32_t GetCurrentMissionId()
207 {
208     HILOGI("GetCurrentMission begin");
209     sptr<IRemoteObject> token;
210     int ret = AAFwk::AbilityManagerClient::GetInstance()->GetTopAbility(token);
211     if (ret != ERR_OK || token == nullptr) {
212         HILOGE("GetTopAbility failed, ret: %{public}d", ret);
213         return INVALID_MISSION_ID;
214     }
215     int32_t missionId = INVALID_MISSION_ID;
216     if (AAFwk::AbilityManagerClient::GetInstance()->GetMissionIdByToken(token, missionId) != ERR_OK) {
217         HILOGE("GetMissionIdByToken failed");
218         return INVALID_MISSION_ID;
219     }
220     return missionId;
221 }
222 
ParcelToBase64Str(const Parcel & parcel)223 std::string ParcelToBase64Str(const Parcel& parcel)
224 {
225     auto parcelSize = parcel.GetDataSize();
226     return Base64Encode(reinterpret_cast<const unsigned char *>(parcel.GetData()), parcelSize);
227 }
228 
Base64StrToParcel(const std::string & rawStr,Parcel & parcel)229 int32_t Base64StrToParcel(const std::string& rawStr, Parcel& parcel)
230 {
231     std::string str = Base64Decode(rawStr);
232     auto parcelSize = str.size();
233     if (!parcel.SetDataCapacity(parcelSize)) {
234         HILOGE("Base64 string parcel set data capacity %{public}zu fail.", parcelSize);
235         return INVALID_PARAMETERS_ERR;
236     }
237     auto ret = memcpy_s((void *)parcel.GetData(), parcel.GetMaxCapacity(), &str[0], parcelSize);
238     if (ret != ERR_OK || !parcel.SetDataSize(parcelSize)) {
239         HILOGE("Base64 string parcel memcpy raw string data fail.");
240         return INVALID_PARAMETERS_ERR;
241     }
242     return ERR_OK;
243 }
244 
Base64Encode(const unsigned char * toEncode,unsigned int len)245 std::string Base64Encode(const unsigned char *toEncode, unsigned int len)
246 {
247     std::string ret = "";
248     if (len == 0 || toEncode == nullptr) {
249         HILOGE("toEncode is null or len is zero.");
250         return ret;
251     }
252     uint32_t length = len;
253     uint32_t i = 0;
254     unsigned char charArray3[3];
255     unsigned char charArray4[4];
256 
257     while (length > 0) {
258         charArray3[i++] = *(toEncode++);
259         if (i == sizeof(charArray3)) {
260             charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2;
261             charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) +
262                 ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4);
263             charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) +
264                 ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6);
265             charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F;
266             for (i = 0; i < sizeof(charArray4); i++) {
267                 ret += BASE_64_CHARS[charArray4[i]];
268             }
269             i = 0;
270         }
271         length--;
272     }
273 
274     if (i > 0) {
275         uint32_t j = 0;
276         for (j = i; j < sizeof(charArray3); j++) {
277             charArray3[j] = '\0';
278         }
279         charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2;
280         charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) +
281             ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4);
282         charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) +
283             ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6);
284         charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F;
285         for (j = 0; j < i + 1; j++) {
286             ret += BASE_64_CHARS[charArray4[j]];
287         }
288         while (i++ < sizeof(charArray3)) {
289             ret += '=';
290         }
291     }
292     return ret;
293 }
294 
Base64Decode(const std::string & basicString)295 std::string Base64Decode(const std::string& basicString)
296 {
297     std::string ret = "";
298     if (basicString.empty()) {
299         HILOGE("basicString is empty.");
300         return ret;
301     }
302     uint32_t i = 0;
303     int index = 0;
304     int len = static_cast<int>(basicString.size());
305     unsigned char charArray3[3];
306     unsigned char charArray4[4];
307 
308     while (len-- && (basicString[index] != '=') && IsBase64(basicString[index])) {
309         charArray4[i++] = basicString[index];
310         index++;
311         if (i == sizeof(charArray4)) {
312             for (i = 0; i < sizeof(charArray4); i++) {
313                 charArray4[i] = BASE_64_CHARS.find(charArray4[i]);
314             }
315             charArray3[INDEX_FIRST] = (charArray4[INDEX_FIRST] << OFFSET2) +
316                 ((charArray4[INDEX_SECOND] & 0x30) >> OFFSET4);
317             charArray3[INDEX_SECOND] = ((charArray4[INDEX_SECOND] & 0xf) << OFFSET4) +
318                 ((charArray4[INDEX_THIRD] & 0x3c) >> OFFSET2);
319             charArray3[INDEX_THIRD] = ((charArray4[INDEX_THIRD] & 0x3) << OFFSET6) + charArray4[INDEX_FORTH];
320             for (i = 0; i < sizeof(charArray3); i++) {
321                 ret += charArray3[i];
322             }
323             i = 0;
324         }
325     }
326 
327     if (i > 0) {
328         uint32_t j = 0;
329         for (j = i; j < sizeof(charArray4); j++) {
330             charArray4[j] = 0;
331         }
332         for (j = 0; j < sizeof(charArray4); j++) {
333             charArray4[j] = BASE_64_CHARS.find(charArray4[j]);
334         }
335         charArray3[INDEX_FIRST] = (charArray4[INDEX_FIRST] << OFFSET2) +
336             ((charArray4[INDEX_SECOND] & 0x30) >> OFFSET4);
337         charArray3[INDEX_SECOND] = ((charArray4[INDEX_SECOND] & 0xf) << OFFSET4) +
338             ((charArray4[INDEX_THIRD] & 0x3c) >> OFFSET2);
339         charArray3[INDEX_THIRD] = ((charArray4[INDEX_THIRD] & 0x3) << OFFSET6) + charArray4[INDEX_FORTH];
340         for (j = 0; j < i - 1; j++) {
341             ret += charArray3[j];
342         }
343     }
344     return ret;
345 }
346 
IsBase64(unsigned char c)347 bool IsBase64(unsigned char c)
348 {
349     return (isalnum(c) || (c == '+') || (c == '/'));
350 }
351 
GetAnonymStr(const std::string & value)352 std::string GetAnonymStr(const std::string &value)
353 {
354     std::string res;
355     std::string tmpStr("******");
356     size_t strLen = value.length();
357     if (strLen < INT32_MIN_ID_LEN) {
358         return tmpStr;
359     }
360 
361     if (strLen <= INT32_SHORT_ID_LEN) {
362         res += value[0];
363         res += tmpStr;
364         res += value[strLen - 1];
365     } else {
366         res.append(value, 0, INT32_PLAINTEXT_LEN);
367         res += tmpStr;
368         res.append(value, strLen - INT32_PLAINTEXT_LEN, INT32_PLAINTEXT_LEN);
369     }
370 
371     return res;
372 }
373 
GetAnonymInt32(const int32_t value)374 std::string GetAnonymInt32(const int32_t value)
375 {
376     std::string tmpStr = std::to_string(value);
377     return GetAnonymStr(tmpStr);
378 }
379 
IsInt32(const cJSON * paramValue)380 bool IsInt32(const cJSON *paramValue)
381 {
382     if (paramValue == nullptr) {
383         HILOGE("JSON parameter is invalid.");
384         return false;
385     }
386 
387     if (!cJSON_IsNumber(paramValue)) {
388         HILOGE("JSON parameter is not number.");
389         return false;
390     }
391 
392     int32_t value = paramValue->valueint;
393     if (!(INT32_MIN <= value && value <= INT32_MAX)) {
394         HILOGE("JSON parameter number is outside the int32_t range.");
395         return false;
396     }
397     return true;
398 }
399 
IsString(const cJSON * paramValue)400 bool IsString(const cJSON *paramValue)
401 {
402     if (paramValue == nullptr) {
403         HILOGE("JSON parameter is invalid.");
404         return false;
405     }
406 
407     if (!cJSON_IsString(paramValue)) {
408         HILOGE("JSON parameter is not string.");
409         return false;
410     }
411     return true;
412 }
413 
CJsonParamCheck(const cJSON * jsonObj,const std::initializer_list<std::string> & keys)414 bool CJsonParamCheck(const cJSON *jsonObj, const std::initializer_list<std::string> &keys)
415 {
416     if (jsonObj == nullptr || !cJSON_IsObject(jsonObj)) {
417         HILOGE("JSON parameter is invalid.");
418         return false;
419     }
420 
421     for (auto it = keys.begin(); it != keys.end(); it++) {
422         cJSON *paramValue = cJSON_GetObjectItemCaseSensitive(jsonObj, (*it).c_str());
423         if (paramValue == nullptr) {
424             HILOGE("JSON parameter does not contain key: %{public}s", (*it).c_str());
425             return false;
426         }
427         auto iter = jsonTypeCheckMap.find(*it);
428         if (iter == jsonTypeCheckMap.end()) {
429             HILOGE("Check is not supported yet, key %{public}s.", (*it).c_str());
430             return false;
431         }
432         if (iter->second == nullptr) {
433             HILOGE("JsonTypeCheckFunc for key %{public}s is nullptr.", (*it).c_str());
434             return false;
435         }
436         JsonTypeCheckFunc &func = iter->second;
437         bool res = (*func)(paramValue);
438         if (!res) {
439             HILOGE("The key %{public}s value format in JSON is illegal.", (*it).c_str());
440             return false;
441         }
442     }
443     return true;
444 }
445 
GetOsInfoFromDM(const std::string & dmInfoEx,int32_t & osType,std::string & osVersion)446 bool GetOsInfoFromDM(const std::string &dmInfoEx, int32_t &osType, std::string &osVersion)
447 {
448     cJSON *dataJson = nullptr;
449     bool isSuccess = false;
450     do {
451         dataJson = cJSON_Parse(dmInfoEx.c_str());
452         if (dataJson == nullptr) {
453             HILOGE("Parse device info extra data to json fail.");
454             break;
455         }
456 
457         if (!CJsonParamCheck(dataJson, {PARAM_KEY_OS_TYPE, PARAM_KEY_OS_VERSION})) {
458             HILOGE("Check OS type and version from device extra data json fail.");
459             break;
460         }
461 
462         osType = cJSON_GetObjectItemCaseSensitive(dataJson, PARAM_KEY_OS_TYPE)->valueint;
463         osVersion = std::string(cJSON_GetObjectItemCaseSensitive(dataJson, PARAM_KEY_OS_VERSION)->valuestring);
464         isSuccess = true;
465     } while (false);
466 
467     if (dataJson != nullptr) {
468         cJSON_Delete(dataJson);
469         dataJson = nullptr;
470     }
471     return isSuccess;
472 }
473 } // namespace DistributedSchedule
474 } // namespace OHOS
475