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