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 #include "local_app_config.h"
16 #include <unordered_set>
17 #include "app_info_rdb_helper.h"
18 #include "security_guard_log.h"
19 #include "security_guard_utils.h"
20 #include "security_guard_define.h"
21 #include "file_ex.h"
22 #include "json_cfg.h"
23 namespace OHOS::Security::SecurityGuard {
24 namespace {
25     const char* APPS = "apps";
26     const char* NAME = "name";
27     const char* FINGERPRINTER = "fingerprint";
28     const char* ATTRIBUTE = "attribute";
29     const char* ISUPDATE = "isUpdate";
30     constexpr uint32_t HASHLENGTH = 64;
31     constexpr uint32_t MAXAPPNAMELENGTH = 256;
32 }
Load(int mode)33 bool LocalAppConfig::Load(int mode)
34 {
35     std::string path;
36     if (mode == INIT_MODE) {
37         if (FileExists(CONFIG_CACHE_FILES[LOCAL_APP_CFG_INDEX])) {
38             path = CONFIG_CACHE_FILES[LOCAL_APP_CFG_INDEX];
39         } else {
40             return true;
41         }
42     }
43     if (mode == UPDATE_MODE) {
44         if (FileExists(CONFIG_CACHE_FILES[LOCAL_APP_CFG_INDEX])) {
45             path = CONFIG_CACHE_FILES[LOCAL_APP_CFG_INDEX];
46         }
47     }
48     SGLOGI("path=%{public}s", path.c_str());
49     if (path.empty()) {
50         SGLOGE("path is empty");
51         return false;
52     }
53     stream_ = std::ifstream(path, std::ios::in);
54     if (!stream_.is_open() || !stream_) {
55         SGLOGE("stream error, %{public}s", strerror(errno));
56         return false;
57     }
58     return true;
59 }
Parse()60 bool LocalAppConfig::Parse()
61 {
62     return true;
63 }
Update()64 bool LocalAppConfig::Update()
65 {
66     if (!stream_.is_open() || !stream_) {
67         SGLOGE("stream error");
68         return false;
69     }
70     nlohmann::json jsonObj = nlohmann::json::parse(stream_, nullptr, false);
71     stream_.close();
72     if (jsonObj.is_discarded()) {
73         SGLOGE("Parse LocalAppConfig json error");
74         return false;
75     }
76     std::vector<AppInfo> configs;
77     if (!ParseAppListConfig(configs, jsonObj)) {
78         SGLOGE("Parse LocalAppConfig error");
79         return false;
80     }
81     for (size_t i = 0; i < configs.size(); i++) {
82         for (size_t j = i + 1; j < configs.size(); j++) {
83             if (configs[i].appName == configs[j].appName) {
84                 SGLOGE("app%{public}s name repeate", configs[i].appName.c_str());
85                 return false;
86             }
87         }
88     }
89     if (!UpdateInfoToDb(configs)) {
90         SGLOGE("UpdateInfoToDb error");
91         return false;
92     }
93 
94     SecurityGuardUtils::CopyFile(CONFIG_CACHE_FILES[LOCAL_APP_CFG_INDEX], CONFIG_UPTATE_FILES[LOCAL_APP_CFG_INDEX]);
95     return true;
96 }
97 
ParseAppListConfig(std::vector<AppInfo> & configs,const nlohmann::json & json)98 bool LocalAppConfig::ParseAppListConfig(std::vector<AppInfo>& configs, const nlohmann::json& json)
99 {
100     if (json.find(APPS) == json.end() || !json.at(APPS).is_array()) {
101         SGLOGE("check %{public}s error", APPS);
102         return false;
103     }
104     for (auto it : json.at(APPS)) {
105         AppInfo config {};
106         if (!JsonCfg::Unmarshal(config.appHash, it, FINGERPRINTER) || config.appHash.size() != HASHLENGTH) {
107             SGLOGE("parse %{public}s error", FINGERPRINTER);
108             return false;
109         }
110         if (!JsonCfg::Unmarshal(config.appName, it, NAME) || config.appName.size() > MAXAPPNAMELENGTH ||
111             config.appName.empty()) {
112             SGLOGE("parse %{public}s error", NAME);
113             return false;
114         }
115         std::unordered_set<std::string> tmp = {"monitoring", "payment", "malicious"};
116         if (!JsonCfg::Unmarshal(config.attrs, it, ATTRIBUTE) || config.attrs.size() >= ATTRMAX) {
117             SGLOGE("parse %{public}s error", ATTRIBUTE);
118             return false;
119         }
120         for (auto iter : config.attrs) {
121             if (tmp.count(iter) == 0) {
122                 SGLOGE("check %{public}s error", ATTRIBUTE);
123                 return false;
124             }
125         }
126         if (!JsonCfg::Unmarshal(config.isUpdate, it, ISUPDATE) || (config.isUpdate != 0 && config.isUpdate != 1)) {
127             SGLOGE("parse %{public}s error", ISUPDATE);
128             return false;
129         }
130         configs.emplace_back(config);
131     }
132     return true;
133 }
134 
IsNeedUpdate(const AppInfo & config,const AppInfo & dbConfig,bool & isFind)135 bool LocalAppConfig::IsNeedUpdate(const AppInfo &config, const AppInfo &dbConfig, bool &isFind)
136 {
137     if (config.appName == dbConfig.appName) {
138         isFind = true;
139         if (config.isUpdate == 1) {
140             AppInfoRdbHelper::GetInstance().DeleteAppInfoByNameAndGlobbalFlag(config.appName, 0);
141             if (AppInfoRdbHelper::GetInstance().InsertAppInfo(config) != SUCCESS) {
142                 SGLOGE("InsertAppInfo error");
143                 return false;
144             }
145         }
146     }
147     return true;
148 }
149 
UpdateInfoToDb(const std::vector<AppInfo> & configs)150 bool LocalAppConfig::UpdateInfoToDb(const std::vector<AppInfo> &configs)
151 {
152     SGLOGI("UpdateInfoToDb ..................");
153     std::vector<AppInfo> dbConfigs;
154     if (AppInfoRdbHelper::GetInstance().QueryAllAppInfo(dbConfigs) != SUCCESS) {
155         SGLOGE("QueryAllAppInfo error");
156         return false;
157     }
158     for (auto iter : dbConfigs) {
159         bool isFind = false;
160         SGLOGI("appName %{public}s isGlobalApp %{public}d", iter.appName.c_str(), iter.isGlobalApp);
161         if (iter.isGlobalApp == 1) {
162             continue;
163         }
164         for (auto it : configs) {
165             if (!IsNeedUpdate(it, iter, isFind)) {
166                 return false;
167             }
168         }
169         if (!isFind) {
170             AppInfoRdbHelper::GetInstance().DeleteAppInfoByNameAndGlobbalFlag(iter.appName, 0);
171         }
172     }
173     for (auto iter : configs) {
174         bool isFind = false;
175         for (auto it : dbConfigs) {
176             if (it.appName == iter.appName && it.isGlobalApp == 0) {
177                 isFind = true;
178                 break;
179             }
180         }
181         if (!isFind && (iter.isUpdate == 1)) {
182             if (AppInfoRdbHelper::GetInstance().InsertAppInfo(iter) != SUCCESS) {
183                 SGLOGE("InsertAppInfo error");
184                 return false;
185             }
186         }
187     }
188     return true;
189 }
190 }