• 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 "guard_options.h"
17 
18 #include <regex>
19 #include "utils/logger.h"
20 
21 #include "util/assert_util.h"
22 #include "util/file_util.h"
23 #include "util/json_util.h"
24 #include "util/string_util.h"
25 
26 namespace {
27 constexpr std::string_view TAG = "[Guard_Options]";
28 
29 constexpr std::string_view ABC_FILE_PATH = "abcFilePath";
30 constexpr std::string_view OBF_ABC_FILE_PATH = "obfAbcFilePath";
31 constexpr std::string_view OBF_PA_FILE_PATH = "obfPaFilePath";
32 constexpr std::string_view COMPILE_SDK_VERSION = "compileSdkVersion";
33 constexpr std::string_view TARGET_API_VERSION = "targetApiVersion";
34 constexpr std::string_view TARGET_API_SUB_VERSION = "targetApiSubVersion";
35 constexpr std::string_view FILES_INFO_PATH = "filesInfoPath";
36 constexpr std::string_view SOURCE_MAPS_PATH = "sourceMapsPath";
37 constexpr std::string_view ENTRY_PACKAGE_INFO = "entryPackageInfo";
38 constexpr std::string_view DEFAULT_NAME_CACHE_PATH = "defaultNameCachePath";
39 constexpr std::string_view SKIPPED_REMOTE_HAR_LIST = "skippedRemoteHarList";
40 constexpr std::string_view USE_NORMALIZED_OHM_URL = "useNormalizedOHMUrl";
41 constexpr std::string_view OBFUSCATION_RULES = "obfuscationRules";
42 constexpr std::string_view DISABLE_OBFUSCATION = "disableObfuscation";
43 constexpr std::string_view ENABLE_EXPORT_OBFUSCATION = "enableExportObfuscation";
44 constexpr std::string_view ENABLE_REMOVE_LOG = "enableRemoveLog";
45 constexpr std::string_view PRINT_NAME_CACHE = "printNameCache";
46 constexpr std::string_view APPLY_NAME_CACHE = "applyNameCache";
47 constexpr std::string_view RESERVED_NAMES = "reservedNames";
48 constexpr std::string_view ENABLE = "enable";
49 constexpr std::string_view PROPERTY_OBFUSCATION = "propertyObfuscation";
50 constexpr std::string_view RESERVED_PROPERTIES = "reservedProperties";
51 constexpr std::string_view UNIVERSAL_RESERVED_PROPERTIES = "universalReservedProperties";
52 constexpr std::string_view TOPLEVEL_OBFUSCATION = "toplevelObfuscation";
53 constexpr std::string_view RESERVED_TOPLEVEL_NAMES = "reservedToplevelNames";
54 constexpr std::string_view UNIVERSAL_RESERVED_TOPLEVEL_NAMES = "universalReservedToplevelNames";
55 constexpr std::string_view FILE_NAME_OBFUSCATION = "fileNameObfuscation";
56 constexpr std::string_view RESERVED_FILE_NAMES = "reservedFileNames";
57 constexpr std::string_view UNIVERSAL_RESERVED_FILE_NAMES = "universalReservedFileNames";
58 constexpr std::string_view KEEP_OPTIONS = "keepOptions";
59 constexpr std::string_view KEEP_PATHS = "keepPaths";
60 
61 constexpr std::string_view FILES_INFO_DELIMITER = ";";
62 constexpr size_t FILES_INFO_INDEX_1_RECORD_NAME = 1;
63 constexpr size_t FILES_INFO_INDEX_3_SOURCE_KEY = 3;
64 const std::string_view SOURCE_MAPS_SOURCES = "sources";
65 
ParseObfuscationOption(const panda::JsonObject * object,const std::string_view & objKey,const std::string_view & reservedKey,const std::string_view & universalKey,panda::guard::ObfuscationOption & option)66 void ParseObfuscationOption(const panda::JsonObject *object, const std::string_view &objKey,
67                             const std::string_view &reservedKey, const std::string_view &universalKey,
68                             panda::guard::ObfuscationOption &option)
69 {
70     auto innerObj = panda::guard::JsonUtil::GetJsonObject(object, objKey);
71     if (!innerObj) {
72         LOG(INFO, PANDAGUARD) << TAG << "fail to obtain object field :" << objKey << " from json object";
73         return;
74     }
75     option.enable = panda::guard::JsonUtil::GetBoolValue(innerObj, ENABLE);
76     option.reservedList = panda::guard::JsonUtil::GetArrayStringValue(innerObj, reservedKey);
77     option.universalReservedList = panda::guard::JsonUtil::GetArrayStringValue(innerObj, universalKey);
78     for (auto &str : option.universalReservedList) {
79         panda::guard::StringUtil::RemoveSlashFromBothEnds(str);
80     }
81 }
82 
ParsePropertyOption(const panda::JsonObject * obj,panda::guard::ObfuscationOption & option)83 void ParsePropertyOption(const panda::JsonObject *obj, panda::guard::ObfuscationOption &option)
84 {
85     ParseObfuscationOption(obj, PROPERTY_OBFUSCATION, RESERVED_PROPERTIES, UNIVERSAL_RESERVED_PROPERTIES, option);
86 }
87 
ParseToplevelOption(const panda::JsonObject * obj,panda::guard::ObfuscationOption & option)88 void ParseToplevelOption(const panda::JsonObject *obj, panda::guard::ObfuscationOption &option)
89 {
90     ParseObfuscationOption(obj, TOPLEVEL_OBFUSCATION, RESERVED_TOPLEVEL_NAMES, UNIVERSAL_RESERVED_TOPLEVEL_NAMES,
91                            option);
92 }
93 
ParseFileNameOption(const panda::JsonObject * obj,panda::guard::ObfuscationOption & option)94 void ParseFileNameOption(const panda::JsonObject *obj, panda::guard::ObfuscationOption &option)
95 {
96     ParseObfuscationOption(obj, FILE_NAME_OBFUSCATION, RESERVED_FILE_NAMES, UNIVERSAL_RESERVED_FILE_NAMES, option);
97 }
98 
ParseKeepOption(const panda::JsonObject * obj,panda::guard::KeepOption & option)99 void ParseKeepOption(const panda::JsonObject *obj, panda::guard::KeepOption &option)
100 {
101     auto innerObj = panda::guard::JsonUtil::GetJsonObject(obj, KEEP_OPTIONS);
102     if (!innerObj) {
103         LOG(INFO, PANDAGUARD) << TAG << "fail to obtain object field :" << KEEP_OPTIONS << " from json object";
104         return;
105     }
106     option.enable = panda::guard::JsonUtil::GetBoolValue(innerObj, ENABLE);
107     option.keepPaths = panda::guard::JsonUtil::GetArrayStringValue(innerObj, KEEP_PATHS);
108 }
109 
ParseObfuscationConfigFile(const std::string & content,panda::guard::ObfuscationConfig & obfConfig)110 void ParseObfuscationConfigFile(const std::string &content, panda::guard::ObfuscationConfig &obfConfig)
111 {
112     panda::JsonObject configObj(content);
113     PANDA_GUARD_ASSERT_PRINT(!configObj.IsValid(), TAG, panda::guard::ErrorCode::CONFIG_FILE_FORMAT_ERROR,
114                              "the config file is not a valid json");
115 
116     obfConfig.abcFilePath = panda::guard::JsonUtil::GetStringValue(&configObj, ABC_FILE_PATH, false);
117     obfConfig.obfAbcFilePath = panda::guard::JsonUtil::GetStringValue(&configObj, OBF_ABC_FILE_PATH, false);
118     obfConfig.obfPaFilePath = panda::guard::JsonUtil::GetStringValue(&configObj, OBF_PA_FILE_PATH);
119     obfConfig.compileSdkVersion = panda::guard::JsonUtil::GetStringValue(&configObj, COMPILE_SDK_VERSION, false);
120     obfConfig.targetApiVersion = (uint8_t)panda::guard::JsonUtil::GetDoubleValue(&configObj, TARGET_API_VERSION, false);
121     obfConfig.targetApiSubVersion = panda::guard::JsonUtil::GetStringValue(&configObj, TARGET_API_SUB_VERSION);
122     obfConfig.filesInfoPath = panda::guard::JsonUtil::GetStringValue(&configObj, FILES_INFO_PATH);
123     obfConfig.sourceMapsPath = panda::guard::JsonUtil::GetStringValue(&configObj, SOURCE_MAPS_PATH);
124     obfConfig.entryPackageInfo = panda::guard::JsonUtil::GetStringValue(&configObj, ENTRY_PACKAGE_INFO, false);
125     obfConfig.defaultNameCachePath = panda::guard::JsonUtil::GetStringValue(&configObj, DEFAULT_NAME_CACHE_PATH, false);
126     obfConfig.skippedRemoteHarList = panda::guard::JsonUtil::GetArrayStringValue(&configObj, SKIPPED_REMOTE_HAR_LIST);
127     obfConfig.useNormalizedOHMUrl = panda::guard::JsonUtil::GetBoolValue(&configObj, USE_NORMALIZED_OHM_URL);
128 
129     auto rulesObj = panda::guard::JsonUtil::GetJsonObject(&configObj, OBFUSCATION_RULES);
130     PANDA_GUARD_ASSERT_PRINT(!rulesObj, TAG, panda::guard::ErrorCode::NOT_CONFIGURED_OBFUSCATION_RULES,
131                              "there is no confusion rule configured in the config file");
132 
133     auto obfRule = &obfConfig.obfuscationRules;
134     obfRule->disableObfuscation = panda::guard::JsonUtil::GetBoolValue(rulesObj, DISABLE_OBFUSCATION);
135     obfRule->enableExportObfuscation = panda::guard::JsonUtil::GetBoolValue(rulesObj, ENABLE_EXPORT_OBFUSCATION);
136     obfRule->enableRemoveLog = panda::guard::JsonUtil::GetBoolValue(rulesObj, ENABLE_REMOVE_LOG);
137     obfRule->printNameCache = panda::guard::JsonUtil::GetStringValue(rulesObj, PRINT_NAME_CACHE);
138     obfRule->applyNameCache = panda::guard::JsonUtil::GetStringValue(rulesObj, APPLY_NAME_CACHE);
139     obfRule->reservedNames = panda::guard::JsonUtil::GetArrayStringValue(rulesObj, RESERVED_NAMES);
140     ParsePropertyOption(rulesObj, obfRule->propertyOption);
141     ParseToplevelOption(rulesObj, obfRule->toplevelOption);
142     ParseFileNameOption(rulesObj, obfRule->fileNameOption);
143     ParseKeepOption(rulesObj, obfRule->keepOption);
144 }
145 
NeedToBeReserved(const std::vector<std::string> & reservedNames,const std::vector<std::string> & universalReservedNames,const std::string & name)146 bool NeedToBeReserved(const std::vector<std::string> &reservedNames,
147                       const std::vector<std::string> &universalReservedNames, const std::string &name)
148 {
149     if (std::any_of(reservedNames.begin(), reservedNames.end(), [&](const auto &field) { return field == name; })) {
150         return true;
151     }
152 
153     return std::any_of(universalReservedNames.begin(), universalReservedNames.end(), [&](const auto &field) {
154         std::regex pattern(field);
155         return std::regex_search(name, pattern);
156     });
157 }
158 
ParseFilesInfo(const std::string & filesInfoPath,std::unordered_map<std::string,std::string> & filesInfoTable)159 void ParseFilesInfo(const std::string &filesInfoPath, std::unordered_map<std::string, std::string> &filesInfoTable)
160 {
161     if (filesInfoPath.empty()) {
162         LOG(INFO, PANDAGUARD) << TAG << "filesInfoPath is empty";
163         return;
164     }
165     auto lineDataList = panda::guard::FileUtil::GetLineDataFromFile(filesInfoPath);
166     if (lineDataList.empty()) {
167         LOG(WARNING, PANDAGUARD) << TAG << "fail to get line data from filesInfoPath";
168         return;
169     }
170     for (const auto &line : lineDataList) {
171         auto infoList = panda::guard::StringUtil::StrictSplit(line, FILES_INFO_DELIMITER.data());
172         if (infoList.size() < (FILES_INFO_INDEX_3_SOURCE_KEY + 1)) {
173             LOG(WARNING, PANDAGUARD) << TAG << "line info is not of normal size : " << line;
174             continue;
175         }
176         filesInfoTable.emplace(infoList[FILES_INFO_INDEX_1_RECORD_NAME], infoList[FILES_INFO_INDEX_3_SOURCE_KEY]);
177     }
178 }
179 
ParseSourceMaps(const std::string & sourceMapsPath,std::unordered_map<std::string,std::string> & sourceMapsTable)180 void ParseSourceMaps(const std::string &sourceMapsPath, std::unordered_map<std::string, std::string> &sourceMapsTable)
181 {
182     if (sourceMapsPath.empty()) {
183         LOG(INFO, PANDAGUARD) << TAG << "sourceMapsPath is empty";
184         return;
185     }
186     std::string content = panda::guard::FileUtil::GetFileContent(sourceMapsPath);
187     if (content.empty()) {
188         LOG(WARNING, PANDAGUARD) << TAG << "get sourceMaps file content failed";
189         return;
190     }
191     panda::JsonObject sourceMapsObj(content);
192     if (!sourceMapsObj.IsValid()) {
193         LOG(WARNING, PANDAGUARD) << TAG << "the sourceMaps file is not a valid json";
194         return;
195     }
196     for (size_t idx = 0; idx < sourceMapsObj.GetSize(); idx++) {
197         auto key = sourceMapsObj.GetKeyByIndex(idx);
198         auto sourceObj = panda::guard::JsonUtil::GetJsonObject(&sourceMapsObj, key);
199         if (!sourceObj) {
200             LOG(WARNING, PANDAGUARD) << TAG << "failed to obtain object field :" << key << " from sourceMaps file";
201             continue;
202         }
203         auto sources = panda::guard::JsonUtil::GetArrayStringValue(sourceObj, SOURCE_MAPS_SOURCES);
204         if (sources.empty()) {
205             LOG(WARNING, PANDAGUARD) << TAG << "the array field :" << key << " in the sourceMaps file is empty";
206             continue;
207         }
208         sourceMapsTable.emplace(key, sources[0]);
209     }
210 }
211 
ParseFilesInfoAndSourceMaps(const std::string & filesInfoPath,const std::string & sourceMapsPath,std::unordered_map<std::string,std::string> & sourceNameTable)212 void ParseFilesInfoAndSourceMaps(const std::string &filesInfoPath, const std::string &sourceMapsPath,
213                                  std::unordered_map<std::string, std::string> &sourceNameTable)
214 {
215     std::unordered_map<std::string, std::string> filesInfoTable;
216     ParseFilesInfo(filesInfoPath, filesInfoTable);
217     if (filesInfoTable.empty()) {
218         return;
219     }
220 
221     std::unordered_map<std::string, std::string> sourceMapsTable;
222     ParseSourceMaps(sourceMapsPath, sourceMapsTable);
223     if (sourceMapsTable.empty()) {
224         return;
225     }
226 
227     for (const auto &[recordName, sourceMapsKey] : filesInfoTable) {
228         auto item = sourceMapsTable.find(sourceMapsKey);
229         if (item == sourceMapsTable.end()) {
230             LOG(WARNING, PANDAGUARD) << TAG << sourceMapsKey << " in filesInfo, but not in sourceMaps";
231             continue;
232         }
233         sourceNameTable.emplace(recordName, item->second);
234     }
235 }
236 }  // namespace
237 
Load(const std::string & configFilePath)238 void panda::guard::GuardOptions::Load(const std::string &configFilePath)
239 {
240     std::string fileContent = FileUtil::GetFileContent(configFilePath);
241     PANDA_GUARD_ASSERT_PRINT(fileContent.empty(), TAG, ErrorCode::CONFIG_FILE_CONTENT_EMPTY, "config file is empty");
242 
243     ParseObfuscationConfigFile(fileContent, this->obfConfig_);
244     PANDA_GUARD_ASSERT_PRINT(obfConfig_.abcFilePath.empty(), TAG, ErrorCode::NOT_CONFIGURED_ABC_FILE_PATH,
245                              "the value of field abcFilePath in the configuration file is invalid");
246     PANDA_GUARD_ASSERT_PRINT(obfConfig_.obfAbcFilePath.empty(), TAG, ErrorCode::NOT_CONFIGURED_OBF_ABC_FILE_PATH,
247                              "the value of field obfAbcFilePath in the configuration file is invalid");
248     PANDA_GUARD_ASSERT_PRINT((obfConfig_.targetApiVersion == 0), TAG, ErrorCode::NOT_CONFIGURED_TARGET_API_VERSION,
249                              "the value of field targetApiVersion in the configuration file is invalid");
250 
251     LOG(INFO, PANDAGUARD) << TAG << "disableObfuscation_:" << obfConfig_.obfuscationRules.disableObfuscation;
252     LOG(INFO, PANDAGUARD) << TAG << "export obfuscation:" << obfConfig_.obfuscationRules.enableExportObfuscation;
253     LOG(INFO, PANDAGUARD) << TAG << "removeLog obfuscation:" << obfConfig_.obfuscationRules.enableRemoveLog;
254     LOG(INFO, PANDAGUARD) << TAG << "property obfuscation:" << obfConfig_.obfuscationRules.propertyOption.enable;
255     LOG(INFO, PANDAGUARD) << TAG << "topLevel obfuscation:" << obfConfig_.obfuscationRules.toplevelOption.enable;
256     LOG(INFO, PANDAGUARD) << TAG << "fileName obfuscation:" << obfConfig_.obfuscationRules.fileNameOption.enable;
257 
258     ParseFilesInfoAndSourceMaps(obfConfig_.filesInfoPath, obfConfig_.sourceMapsPath, this->sourceNameTable_);
259 }
260 
GetAbcFilePath() const261 const std::string &panda::guard::GuardOptions::GetAbcFilePath() const
262 {
263     return obfConfig_.abcFilePath;
264 }
265 
GetObfAbcFilePath() const266 const std::string &panda::guard::GuardOptions::GetObfAbcFilePath() const
267 {
268     return obfConfig_.obfAbcFilePath;
269 }
270 
GetObfPaFilePath() const271 const std::string &panda::guard::GuardOptions::GetObfPaFilePath() const
272 {
273     return obfConfig_.obfPaFilePath;
274 }
275 
GetCompileSdkVersion() const276 const std::string &panda::guard::GuardOptions::GetCompileSdkVersion() const
277 {
278     return obfConfig_.compileSdkVersion;
279 }
280 
GetTargetApiVersion() const281 uint8_t panda::guard::GuardOptions::GetTargetApiVersion() const
282 {
283     return obfConfig_.targetApiVersion;
284 }
285 
GetTargetApiSubVersion() const286 const std::string &panda::guard::GuardOptions::GetTargetApiSubVersion() const
287 {
288     return obfConfig_.targetApiSubVersion;
289 }
290 
GetEntryPackageInfo() const291 const std::string &panda::guard::GuardOptions::GetEntryPackageInfo() const
292 {
293     return obfConfig_.entryPackageInfo;
294 }
295 
GetDefaultNameCachePath() const296 const std::string &panda::guard::GuardOptions::GetDefaultNameCachePath() const
297 {
298     return obfConfig_.defaultNameCachePath;
299 }
300 
DisableObfuscation() const301 bool panda::guard::GuardOptions::DisableObfuscation() const
302 {
303     return obfConfig_.obfuscationRules.disableObfuscation;
304 }
305 
IsExportObfEnabled() const306 bool panda::guard::GuardOptions::IsExportObfEnabled() const
307 {
308     return obfConfig_.obfuscationRules.enableExportObfuscation;
309 }
310 
IsRemoveLogObfEnabled() const311 bool panda::guard::GuardOptions::IsRemoveLogObfEnabled() const
312 {
313     return obfConfig_.obfuscationRules.enableRemoveLog;
314 }
315 
GetPrintNameCache() const316 const std::string &panda::guard::GuardOptions::GetPrintNameCache() const
317 {
318     return obfConfig_.obfuscationRules.printNameCache;
319 }
320 
GetApplyNameCache() const321 const std::string &panda::guard::GuardOptions::GetApplyNameCache() const
322 {
323     return obfConfig_.obfuscationRules.applyNameCache;
324 }
325 
IsPropertyObfEnabled() const326 bool panda::guard::GuardOptions::IsPropertyObfEnabled() const
327 {
328     return obfConfig_.obfuscationRules.propertyOption.enable;
329 }
330 
IsToplevelObfEnabled() const331 bool panda::guard::GuardOptions::IsToplevelObfEnabled() const
332 {
333     return obfConfig_.obfuscationRules.toplevelOption.enable;
334 }
335 
IsFileNameObfEnabled() const336 bool panda::guard::GuardOptions::IsFileNameObfEnabled() const
337 {
338     return obfConfig_.obfuscationRules.fileNameOption.enable;
339 }
340 
IsKeepPath(const std::string & path) const341 bool panda::guard::GuardOptions::IsKeepPath(const std::string &path) const
342 {
343     const auto keepOption = &obfConfig_.obfuscationRules.keepOption;
344     if (!keepOption->enable || path.empty()) {
345         return false;
346     }
347 
348     std::vector<std::string> universalKeepPaths;  // keep paths not have universal
349     return NeedToBeReserved(keepOption->keepPaths, universalKeepPaths, path);
350 }
351 
IsReservedNames(const std::string & name) const352 bool panda::guard::GuardOptions::IsReservedNames(const std::string &name) const
353 {
354     std::vector<std::string> universalReservedNames;  // names not have universal
355     return NeedToBeReserved(obfConfig_.obfuscationRules.reservedNames, universalReservedNames, name);
356 }
357 
IsReservedProperties(const std::string & name) const358 bool panda::guard::GuardOptions::IsReservedProperties(const std::string &name) const
359 {
360     return NeedToBeReserved(obfConfig_.obfuscationRules.propertyOption.reservedList,
361                             obfConfig_.obfuscationRules.propertyOption.universalReservedList, name);
362 }
363 
IsReservedToplevelNames(const std::string & name) const364 bool panda::guard::GuardOptions::IsReservedToplevelNames(const std::string &name) const
365 {
366     return NeedToBeReserved(obfConfig_.obfuscationRules.toplevelOption.reservedList,
367                             obfConfig_.obfuscationRules.toplevelOption.universalReservedList, name);
368 }
369 
IsReservedFileNames(const std::string & name) const370 bool panda::guard::GuardOptions::IsReservedFileNames(const std::string &name) const
371 {
372     return NeedToBeReserved(obfConfig_.obfuscationRules.fileNameOption.reservedList,
373                             obfConfig_.obfuscationRules.fileNameOption.universalReservedList, name);
374 }
375 
GetSourceName(const std::string & name) const376 const std::string &panda::guard::GuardOptions::GetSourceName(const std::string &name) const
377 {
378     auto item = this->sourceNameTable_.find(name);
379     if (item == this->sourceNameTable_.end()) {
380         return name;
381     }
382     return item->second;
383 }
384 
IsSkippedRemoteHar(const std::string & pkgName) const385 bool panda::guard::GuardOptions::IsSkippedRemoteHar(const std::string &pkgName) const
386 {
387     return std::any_of(
388         obfConfig_.skippedRemoteHarList.begin(), obfConfig_.skippedRemoteHarList.end(),
389         [pkgName](const std::string &remoteHar) { return StringUtil::IsSuffixMatched(remoteHar, pkgName); });
390 }
391 
IsUseNormalizedOhmUrl() const392 bool panda::guard::GuardOptions::IsUseNormalizedOhmUrl() const
393 {
394     return obfConfig_.useNormalizedOHMUrl;
395 }
396