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
16 #include "form_module_checker.h"
17
18 #include <functional>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 #include <fstream>
23 #include <filesystem>
24
25 #include "fms_log_wrapper.h"
26 #include "nlohmann/json.hpp"
27 #include "config_policy_utils.h"
28
29 namespace {
30 const std::string FORM_MODULE_WHITE_LIST_PATH = "/etc/form_fwk_module_white_list.json";
31 const std::string KEY_MODULE_ALLOW = "moduleAllowList";
32 const std::vector<std::string> MODULE_ALLOW_LIST = {
33 "mediaquery",
34 "display",
35 "effectKit",
36 "arkui.shape",
37 "hilog",
38 "url",
39 "util",
40 "util.ArrayList",
41 "util.HashMap",
42 "util.List",
43 "util.json",
44 "animator",
45 "measure",
46 "intl",
47 "systemDateTime",
48 "batteryInfo",
49 "commonEventManager"
50 };
51 const std::vector<std::string> MODULE_ALLOW_WITH_API_LIST = {
52 "i18n",
53 "font",
54 "multimedia.image",
55 "deviceInfo",
56 "window",
57 "process"
58 };
59 const std::vector<std::string> API_ALLOW_LIST = {
60 "i18n.System.getSystemLanguage",
61 "i18n.System.is24HourClock",
62 "i18n.System.getSystemLocale",
63 "i18n.System.getSystemRegion",
64 "i18n.isRTL",
65 "i18n.getTimeZone",
66 "i18n.getCalendar"
67 "i18n.Calendar.*",
68 "i18n.TimeZone.*",
69 "i18n.Unicode.*",
70 "font.registerFont",
71 "multimedia.image.PixelMapFormat.*",
72 "multimedia.image.Size.*",
73 "multimedia.image.AlphaType.*",
74 "multimedia.image.ScaleMode.*",
75 "multimedia.image.Region.*",
76 "multimedia.image.PositionArea.*",
77 "multimedia.image.ImageInfo.*",
78 "multimedia.image.DecodingOptions.*",
79 "multimedia.image.InitializationOptions.*",
80 "multimedia.image.SourceOptions.*",
81 "multimedia.image.createImageSource",
82 "multimedia.image.PixelMap.*",
83 "multimedia.image.ImageSource.*",
84 "deviceInfo.deviceType",
85 "deviceInfo.productModel",
86 "window.WindowType.*",
87 "window.AvoidAreaType.*",
88 "window.WindowMode.*",
89 "window.ColorSpace.*",
90 "window.WindowStageEventType.*",
91 "window.WindowEventType.*",
92 "window.WindowLayoutMode.*",
93 "window.Orientation.*",
94 "window.BlurStyle.*",
95 "window.WmErrorCode.*",
96 "window.WMError.*",
97 "window.WindowStatusType.*",
98 "window.RectChangeReason.*",
99 "window.MaximizePresentation.*",
100 "window.ExtensionWindowAttribute.*",
101 "window.ModalityType.*",
102 "window._napiwrapper.*",
103 "window.getTopWindow.*",
104 "window.getLastWindow.*",
105 "process.pid",
106 "process.tid"
107 };
108 } // namespace
109
110 std::vector<std::string> FormModuleChecker::modulesFromCfg_ = FormModuleChecker::GetModuleAllowList();
111
CheckApiAllowList(const std::string & apiPath)112 bool FormModuleChecker::CheckApiAllowList(const std::string& apiPath)
113 {
114 for (const auto& item : API_ALLOW_LIST) {
115 if (CheckApiWithSuffix(apiPath, item)) {
116 return true;
117 }
118 }
119
120 HILOG_ERROR("api not allowed, apiPath: '%{public}s'", apiPath.c_str());
121 return false;
122 }
123
CheckApiWithSuffix(const std::string & apiPath,const std::string & item)124 bool FormModuleChecker::CheckApiWithSuffix(const std::string& apiPath, const std::string& item)
125 {
126 HILOG_DEBUG("apiPath: '%{public}s', item: '%{public}s'", apiPath.c_str(), item.c_str());
127 if (item.compare(0, apiPath.size(), apiPath) == 0) {
128 return true;
129 }
130 const int32_t kSuffixLength = 2;
131 if (item.size() >= kSuffixLength && item.substr(item.size() - kSuffixLength) == ".*") {
132 const std::string path = item.substr(0, item.rfind('.'));
133 if (apiPath.compare(0, path.size(), path) == 0) {
134 return true;
135 }
136 }
137
138 return false;
139 }
140
CheckModuleLoadable(const char * moduleName,std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,bool isAppModule)141 bool FormModuleChecker::CheckModuleLoadable(const char *moduleName,
142 std::unique_ptr<ApiAllowListChecker> &apiAllowListChecker, bool isAppModule)
143 {
144 if (isAppModule) {
145 HILOG_ERROR("module is not system, moduleName= %{public}s", moduleName);
146 return false;
147 }
148
149 // only check module
150 for (const auto& item : modulesFromCfg_) {
151 if (item == moduleName) {
152 HILOG_DEBUG("load moduleName= %{public}s", moduleName);
153 return true;
154 }
155 }
156 for (const auto& item : MODULE_ALLOW_LIST) {
157 if (item == moduleName) {
158 HILOG_DEBUG("load moduleName= %{public}s", moduleName);
159 return true;
160 }
161 }
162
163 // check mnodule and api
164 if (IsModuelAllowToLoad(moduleName)) {
165 HILOG_DEBUG("module has been allowed by the allowlist in form, module name = %{public}s", moduleName);
166 if (apiAllowListChecker == nullptr) {
167 apiAllowListChecker = std::make_unique<ApiAllowListChecker>([](const std::string& apiPath) {
168 return CheckApiAllowList(apiPath);
169 });
170 }
171 return true;
172 }
173 HILOG_ERROR("module can't load in form,moduleName= %{public}s", moduleName);
174 return false;
175 }
176
IsModuelAllowToLoad(const std::string & moduleName)177 bool FormModuleChecker::IsModuelAllowToLoad(const std::string& moduleName)
178 {
179 for (const auto& item : MODULE_ALLOW_WITH_API_LIST) {
180 if (item == moduleName) {
181 return true;
182 }
183 }
184
185 return false;
186 }
187
GetModuleAllowList()188 std::vector<std::string> FormModuleChecker::GetModuleAllowList()
189 {
190 HILOG_INFO("read moduleAllowList from config file");
191 std::vector<std::string> result;
192 char buf[MAX_PATH_LEN];
193 char* path = GetOneCfgFile(FORM_MODULE_WHITE_LIST_PATH.c_str(), buf, MAX_PATH_LEN);
194 if (path == nullptr || *path == '\0') {
195 HILOG_ERROR("config file not found");
196 return result;
197 }
198 std::ifstream file(path);
199 if (!file.is_open()) {
200 HILOG_ERROR("failed to open config file");
201 return result;
202 }
203 HILOG_INFO("success to open config file");
204 nlohmann::json jsonData;
205 file >> jsonData;
206 if (jsonData.contains(KEY_MODULE_ALLOW) && jsonData[KEY_MODULE_ALLOW].is_array()) {
207 for (const auto& module : jsonData[KEY_MODULE_ALLOW]) {
208 HILOG_INFO("read moduleAllowList module: %{public}s", std::string(module).c_str());
209 result.push_back(module);
210 }
211 }
212 file.close();
213 return result;
214 }
215
DiskCheckOnly()216 bool FormModuleChecker::DiskCheckOnly()
217 {
218 return false;
219 }
220