1 /*
2 * Copyright (c) 2025 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 "appspawn_utils.h"
17 #include "cJSON.h"
18 #include "config_policy_utils.h"
19 #include "dec_api.h"
20 #include "hilog/log.h"
21 #include "json_utils.h"
22
InitDecConfig(void)23 static std::vector<cJSON *> InitDecConfig(void)
24 {
25 std::vector<cJSON *> sandboxConfig = {};
26 CfgFiles *files = GetCfgFiles("etc/sandbox");
27 for (int i = 0; (files != nullptr) && (i < MAX_CFG_POLICY_DIRS_CNT); ++i) {
28 if (files->paths[i] == nullptr) {
29 continue;
30 }
31 std::string path = files->paths[i];
32 std::string appPath = path + "/appdata-sandbox.json";
33 APPSPAWN_LOGV("Init sandbox dec config %{public}s", appPath.c_str());
34 cJSON *config = GetJsonObjFromFile(appPath.c_str());
35 APPSPAWN_CHECK((config != nullptr && cJSON_IsObject(config)), continue,
36 "Failed to init sandbox dec config %{public}s", appPath.c_str());
37 sandboxConfig.push_back(config);
38 }
39 FreeCfgFiles(files);
40 return sandboxConfig;
41 }
42
DestroyDecConfig(std::vector<cJSON * > & sandboxConfig)43 static void DestroyDecConfig(std::vector<cJSON *> &sandboxConfig)
44 {
45 for (auto& config : sandboxConfig) {
46 APPSPAWN_CHECK_ONLY_EXPER(config != nullptr, continue);
47 cJSON_Delete(config);
48 config = nullptr;
49 }
50 sandboxConfig.clear();
51 }
52
ConvertDecPath(std::string path)53 static std::string ConvertDecPath(std::string path)
54 {
55 std::vector<std::pair<std::string, std::string>> replacements = {
56 {"<currentUserId>", "currentUser"},
57 {"<PackageName>", "com.ohos.dlpmanager"}
58 };
59
60 for (const auto& [from, to] : replacements) {
61 size_t pos = 0;
62 while ((pos = path.find(from, pos)) != std::string::npos) {
63 path.replace(pos, from.length(), to);
64 pos += to.length();
65 }
66 }
67 return path;
68 }
69
AddDecPathsByPermission(std::map<std::string,std::vector<std::string>> & decMap,const std::string permission,const cJSON * permItem)70 static void AddDecPathsByPermission(std::map<std::string, std::vector<std::string>> &decMap,
71 const std::string permission, const cJSON *permItem)
72 {
73 cJSON *mountPoints = cJSON_GetObjectItemCaseSensitive(permItem, "mount-paths");
74 APPSPAWN_CHECK(mountPoints != nullptr && cJSON_IsArray(mountPoints), return,
75 "Don't get mountPoints json from permission");
76
77 std::vector<std::string> decPaths = {};
78 int arraySize = cJSON_GetArraySize(mountPoints);
79 for (int i = 0; i < arraySize; ++i) {
80 cJSON *mntPoint = cJSON_GetArrayItem(mountPoints, i);
81 APPSPAWN_CHECK(mntPoint != nullptr && cJSON_IsObject(mntPoint), continue,
82 "Don't get mntPoint json from mountPoints");
83
84 cJSON *decPathJson = cJSON_GetObjectItemCaseSensitive(mntPoint, "dec-paths");
85 if (decPathJson == nullptr || !cJSON_IsArray(decPathJson)) {
86 APPSPAWN_LOGV("Don't get decPath json from mntPoint");
87 continue;
88 }
89
90 int count = cJSON_GetArraySize(decPathJson);
91 for (int j = 0; j < count; ++j) {
92 cJSON *item = cJSON_GetArrayItem(decPathJson, j);
93 APPSPAWN_CHECK(item != nullptr && cJSON_IsString(item), continue, "Don't get decPath item");
94 const char *strValue = cJSON_GetStringValue(item);
95 APPSPAWN_CHECK_ONLY_EXPER(strValue != nullptr, continue);
96
97 std::string decPath = ConvertDecPath(strValue);
98 APPSPAWN_LOGI("Get decPath %{public}s from %{public}s", decPath.c_str(), permission.c_str());
99 decPaths.push_back(decPath);
100 }
101 }
102
103 if (!decPaths.empty()) {
104 auto it = decMap.find(permission);
105 if (it == decMap.end()) {
106 decMap[permission] = decPaths;
107 } else {
108 for (const auto& path : decPaths) {
109 it->second.push_back(path);
110 }
111 }
112 }
113 }
114
ProcessConfig(const cJSON * config,std::map<std::string,std::vector<std::string>> & decMap)115 static void ProcessConfig(const cJSON *config, std::map<std::string, std::vector<std::string>> &decMap)
116 {
117 cJSON *permission = cJSON_GetObjectItemCaseSensitive(config, "permission");
118 APPSPAWN_CHECK(permission != nullptr && cJSON_IsArray(permission), return,
119 "Don't get permission json from config");
120
121 int arraySize = cJSON_GetArraySize(permission);
122 for (int i = 0; i < arraySize; ++i) {
123 cJSON *item = cJSON_GetArrayItem(permission, i);
124 cJSON *permissionChild = item->child;
125 while (permissionChild != nullptr && cJSON_IsArray(permissionChild)) {
126 cJSON *permItem = cJSON_GetArrayItem(permissionChild, 0);
127 APPSPAWN_CHECK(permItem != nullptr && cJSON_IsObject(permItem), permissionChild = permissionChild->next;
128 continue, "Don't get permission item");
129 APPSPAWN_LOGV("AddDecPathsByPermission %{public}s", permissionChild->string);
130 AddDecPathsByPermission(decMap, permissionChild->string, permItem);
131 permissionChild = permissionChild->next;
132 }
133 }
134 }
135
GetDecPathMap(void)136 std::map<std::string, std::vector<std::string>> GetDecPathMap(void)
137 {
138 std::vector<cJSON *> sandboxConfig = InitDecConfig();
139 APPSPAWN_CHECK(!sandboxConfig.empty(), return {}, "Sandbox dec config is empty");
140
141 std::map<std::string, std::vector<std::string>> decMap = {};
142 for (auto& config : sandboxConfig) {
143 ProcessConfig(config, decMap);
144 }
145
146 DestroyDecConfig(sandboxConfig);
147 return decMap;
148 }
149