1 /*
2 * Copyright (c) 2023-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 "extension_config.h"
17
18 #include <fstream>
19
20 #include "config_policy_utils.h"
21 #include "hilog_tag_wrapper.h"
22
23 namespace OHOS {
24 namespace AAFwk {
25 namespace {
26 constexpr const char* EXTENSION_CONFIG_DEFAULT_PATH = "/system/etc/ams_extension_config.json";
27 constexpr const char* EXTENSION_CONFIG_FILE_PATH = "/etc/ams_extension_config.json";
28
29 constexpr const char* EXTENSION_CONFIG_NAME = "ams_extension_config";
30 constexpr const char* EXTENSION_TYPE_NAME = "extension_type_name";
31 constexpr const char* EXTENSION_AUTO_DISCONNECT_TIME = "auto_disconnect_time";
32
33 constexpr const char* EXTENSION_THIRD_PARTY_APP_BLOCKED_FLAG_NAME = "third_party_app_blocked_flag";
34 constexpr const char* EXTENSION_SERVICE_BLOCKED_LIST_NAME = "service_blocked_list";
35 constexpr const char* EXTENSION_SERVICE_STARTUP_ENABLE_FLAG = "service_startup_enable_flag";
36 constexpr const char* EXTENSION_NETWORK_ENABLE_FLAG = "network_access_enable_flag";
37 constexpr const char* EXTENSION_SA_ENABLE_FLAG = "sa_access_enable_flag";
38 }
39
GetExtensionConfigPath() const40 std::string ExtensionConfig::GetExtensionConfigPath() const
41 {
42 char buf[MAX_PATH_LEN] = { 0 };
43 char *configPath = GetOneCfgFile(EXTENSION_CONFIG_FILE_PATH, buf, MAX_PATH_LEN);
44 if (configPath == nullptr || configPath[0] == '\0' || strlen(configPath) > MAX_PATH_LEN) {
45 return EXTENSION_CONFIG_DEFAULT_PATH;
46 }
47 return configPath;
48 }
49
LoadExtensionConfiguration()50 void ExtensionConfig::LoadExtensionConfiguration()
51 {
52 TAG_LOGD(AAFwkTag::ABILITYMGR, "call");
53 nlohmann::json jsonBuf;
54 if (!ReadFileInfoJson(GetExtensionConfigPath().c_str(), jsonBuf)) {
55 TAG_LOGE(AAFwkTag::ABILITYMGR, "parse file failed");
56 return;
57 }
58
59 LoadExtensionConfig(jsonBuf);
60 }
61
GetExtensionAutoDisconnectTime(const std::string & extensionTypeName)62 int32_t ExtensionConfig::GetExtensionAutoDisconnectTime(const std::string &extensionTypeName)
63 {
64 std::lock_guard lock(configMapMutex_);
65 if (configMap_.find(extensionTypeName) != configMap_.end()) {
66 return configMap_[extensionTypeName].extensionAutoDisconnectTime;
67 }
68 return DEFAULT_EXTENSION_AUTO_DISCONNECT_TIME;
69 }
70
IsExtensionStartThirdPartyAppEnable(const std::string & extensionTypeName)71 bool ExtensionConfig::IsExtensionStartThirdPartyAppEnable(const std::string &extensionTypeName)
72 {
73 std::lock_guard lock(configMapMutex_);
74 if (configMap_.find(extensionTypeName) != configMap_.end()) {
75 return configMap_[extensionTypeName].thirdPartyAppEnableFlag;
76 }
77 return EXTENSION_THIRD_PARTY_APP_ENABLE_FLAG_DEFAULT;
78 }
79
IsExtensionStartServiceEnable(const std::string & extensionTypeName,const std::string & targetUri)80 bool ExtensionConfig::IsExtensionStartServiceEnable(const std::string &extensionTypeName, const std::string &targetUri)
81 {
82 AppExecFwk::ElementName targetElementName;
83 std::lock_guard lock(configMapMutex_);
84 if (configMap_.find(extensionTypeName) != configMap_.end() &&
85 !configMap_[extensionTypeName].serviceEnableFlag) {
86 return false;
87 }
88 if (!targetElementName.ParseURI(targetUri) ||
89 configMap_.find(extensionTypeName) == configMap_.end()) {
90 return EXTENSION_START_SERVICE_ENABLE_FLAG_DEFAULT;
91 }
92 for (const auto& iter : configMap_[extensionTypeName].serviceBlockedList) {
93 AppExecFwk::ElementName iterElementName;
94 if (iterElementName.ParseURI(iter) &&
95 iterElementName.GetBundleName() == targetElementName.GetBundleName() &&
96 iterElementName.GetAbilityName() == targetElementName.GetAbilityName()) {
97 return false;
98 }
99 }
100 return EXTENSION_START_SERVICE_ENABLE_FLAG_DEFAULT;
101 }
102
LoadExtensionConfig(const nlohmann::json & object)103 void ExtensionConfig::LoadExtensionConfig(const nlohmann::json &object)
104 {
105 if (!object.contains(EXTENSION_CONFIG_NAME) || !object.at(EXTENSION_CONFIG_NAME).is_array()) {
106 TAG_LOGE(AAFwkTag::ABILITYMGR, "extension config null");
107 return;
108 }
109
110 for (auto &item : object.at(EXTENSION_CONFIG_NAME).items()) {
111 const nlohmann::json& jsonObject = item.value();
112 if (!jsonObject.contains(EXTENSION_TYPE_NAME) || !jsonObject.at(EXTENSION_TYPE_NAME).is_string()) {
113 continue;
114 }
115 std::lock_guard lock(configMapMutex_);
116 std::string extensionTypeName = jsonObject.at(EXTENSION_TYPE_NAME).get<std::string>();
117 LoadExtensionAutoDisconnectTime(jsonObject, extensionTypeName);
118 LoadExtensionThirdPartyAppBlockedList(jsonObject, extensionTypeName);
119 LoadExtensionServiceBlockedList(jsonObject, extensionTypeName);
120 LoadExtensionNetworkEnable(jsonObject, extensionTypeName);
121 LoadExtensionSAEnable(jsonObject, extensionTypeName);
122 }
123 }
124
LoadExtensionAutoDisconnectTime(const nlohmann::json & object,std::string extensionTypeName)125 void ExtensionConfig::LoadExtensionAutoDisconnectTime(const nlohmann::json &object, std::string extensionTypeName)
126 {
127 if (!object.contains(EXTENSION_AUTO_DISCONNECT_TIME) ||
128 !object.at(EXTENSION_AUTO_DISCONNECT_TIME).is_number()) {
129 TAG_LOGE(AAFwkTag::ABILITYMGR, "auto disconnect time config null");
130 return;
131 }
132 int32_t extensionAutoDisconnectTime = object.at(EXTENSION_AUTO_DISCONNECT_TIME).get<int32_t>();
133 configMap_[extensionTypeName].extensionAutoDisconnectTime = extensionAutoDisconnectTime;
134 }
135
LoadExtensionThirdPartyAppBlockedList(const nlohmann::json & object,std::string extensionTypeName)136 void ExtensionConfig::LoadExtensionThirdPartyAppBlockedList(const nlohmann::json &object,
137 std::string extensionTypeName)
138 {
139 TAG_LOGD(AAFwkTag::ABILITYMGR, "call.");
140 if (!object.contains(EXTENSION_THIRD_PARTY_APP_BLOCKED_FLAG_NAME) ||
141 !object.at(EXTENSION_THIRD_PARTY_APP_BLOCKED_FLAG_NAME).is_boolean()) {
142 TAG_LOGE(AAFwkTag::ABILITYMGR, "third Party config null");
143 return;
144 }
145 bool flag = object.at(EXTENSION_THIRD_PARTY_APP_BLOCKED_FLAG_NAME).get<bool>();
146 configMap_[extensionTypeName].thirdPartyAppEnableFlag = flag;
147 TAG_LOGD(AAFwkTag::ABILITYMGR, "The %{public}s extension's third party app blocked flag is %{public}d",
148 extensionTypeName.c_str(), flag);
149 }
150
LoadExtensionServiceBlockedList(const nlohmann::json & object,std::string extensionTypeName)151 void ExtensionConfig::LoadExtensionServiceBlockedList(const nlohmann::json &object, std::string extensionTypeName)
152 {
153 TAG_LOGD(AAFwkTag::ABILITYMGR, "call.");
154 if (!object.contains(EXTENSION_SERVICE_STARTUP_ENABLE_FLAG) ||
155 !object.at(EXTENSION_SERVICE_STARTUP_ENABLE_FLAG).is_boolean()) {
156 TAG_LOGE(AAFwkTag::ABILITYMGR, "service enable config null");
157 return;
158 }
159 bool serviceEnableFlag = object.at(EXTENSION_SERVICE_STARTUP_ENABLE_FLAG).get<bool>();
160 if (!serviceEnableFlag) {
161 configMap_[extensionTypeName].serviceEnableFlag = serviceEnableFlag;
162 TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s Service startup is blocked.", extensionTypeName.c_str());
163 return;
164 }
165 if (!object.contains(EXTENSION_SERVICE_BLOCKED_LIST_NAME) ||
166 !object.at(EXTENSION_SERVICE_BLOCKED_LIST_NAME).is_array()) {
167 TAG_LOGE(AAFwkTag::ABILITYMGR, "service config null");
168 return;
169 }
170 std::unordered_set<std::string> serviceBlockedList;
171 for (auto &item : object.at(EXTENSION_SERVICE_BLOCKED_LIST_NAME).items()) {
172 const nlohmann::json& jsonObject = item.value();
173 if (!jsonObject.is_string()) {
174 continue;
175 }
176 std::string serviceUri = jsonObject.get<std::string>();
177 if (CheckServiceExtensionUriValid(serviceUri)) {
178 serviceBlockedList.emplace(serviceUri);
179 }
180 }
181 configMap_[extensionTypeName].serviceBlockedList = serviceBlockedList;
182 TAG_LOGD(AAFwkTag::ABILITYMGR, "The size of %{public}s extension's service blocked list is %{public}zu",
183 extensionTypeName.c_str(), serviceBlockedList.size());
184 }
185
LoadExtensionNetworkEnable(const nlohmann::json & object,const std::string & extensionTypeName)186 void ExtensionConfig::LoadExtensionNetworkEnable(const nlohmann::json &object,
187 const std::string &extensionTypeName)
188 {
189 TAG_LOGD(AAFwkTag::ABILITYMGR, "LoadExtensionNetworkEnable call");
190 if (!object.contains(EXTENSION_NETWORK_ENABLE_FLAG) || !object.at(EXTENSION_NETWORK_ENABLE_FLAG).is_boolean()) {
191 TAG_LOGW(AAFwkTag::ABILITYMGR, "network enable flag null");
192 return;
193 }
194 bool flag = object.at(EXTENSION_NETWORK_ENABLE_FLAG).get<bool>();
195 configMap_[extensionTypeName].networkEnableFlag = flag;
196 TAG_LOGD(AAFwkTag::ABILITYMGR, "The %{public}s extension's network enable flag is %{public}d",
197 extensionTypeName.c_str(), flag);
198 }
199
LoadExtensionSAEnable(const nlohmann::json & object,const std::string & extensionTypeName)200 void ExtensionConfig::LoadExtensionSAEnable(const nlohmann::json &object,
201 const std::string &extensionTypeName)
202 {
203 TAG_LOGD(AAFwkTag::ABILITYMGR, "LoadExtensionSAEnable call");
204 if (!object.contains(EXTENSION_SA_ENABLE_FLAG) || !object.at(EXTENSION_SA_ENABLE_FLAG).is_boolean()) {
205 TAG_LOGW(AAFwkTag::ABILITYMGR, "sa enable flag null");
206 return;
207 }
208 bool flag = object.at(EXTENSION_SA_ENABLE_FLAG).get<bool>();
209 configMap_[extensionTypeName].saEnableFlag = flag;
210 TAG_LOGD(AAFwkTag::ABILITYMGR, "The %{public}s extension's sa enable flag is %{public}d",
211 extensionTypeName.c_str(), flag);
212 }
213
IsExtensionNetworkEnable(const std::string & extensionTypeName)214 bool ExtensionConfig::IsExtensionNetworkEnable(const std::string &extensionTypeName)
215 {
216 std::lock_guard lock(configMapMutex_);
217 if (configMap_.find(extensionTypeName) != configMap_.end()) {
218 return configMap_[extensionTypeName].networkEnableFlag;
219 }
220 return EXTENSION_NETWORK_ENABLE_FLAG_DEFAULT;
221 }
222
IsExtensionSAEnable(const std::string & extensionTypeName)223 bool ExtensionConfig::IsExtensionSAEnable(const std::string &extensionTypeName)
224 {
225 std::lock_guard lock(configMapMutex_);
226 if (configMap_.find(extensionTypeName) != configMap_.end()) {
227 return configMap_[extensionTypeName].saEnableFlag;
228 }
229 return EXTENSION_SA_ENABLE_FLAG_DEFAULT;
230 }
231
ReadFileInfoJson(const std::string & filePath,nlohmann::json & jsonBuf)232 bool ExtensionConfig::ReadFileInfoJson(const std::string &filePath, nlohmann::json &jsonBuf)
233 {
234 if (access(filePath.c_str(), F_OK) != 0) {
235 TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s, not existed", filePath.c_str());
236 return false;
237 }
238
239 std::fstream in;
240 char errBuf[256];
241 errBuf[0] = '\0';
242 in.open(filePath, std::ios_base::in);
243 if (!in.is_open()) {
244 strerror_r(errno, errBuf, sizeof(errBuf));
245 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed due to %{public}s", errBuf);
246 return false;
247 }
248
249 in.seekg(0, std::ios::end);
250 int64_t size = in.tellg();
251 if (size <= 0) {
252 TAG_LOGE(AAFwkTag::ABILITYMGR, "empty file");
253 in.close();
254 return false;
255 }
256
257 in.seekg(0, std::ios::beg);
258 jsonBuf = nlohmann::json::parse(in, nullptr, false);
259 in.close();
260 if (jsonBuf.is_discarded()) {
261 TAG_LOGE(AAFwkTag::ABILITYMGR, "bad profile file");
262 return false;
263 }
264
265 return true;
266 }
267
CheckServiceExtensionUriValid(const std::string & uri)268 bool ExtensionConfig::CheckServiceExtensionUriValid(const std::string &uri)
269 {
270 const size_t memberNum = 4;
271 if (std::count(uri.begin(), uri.end(), '/') != memberNum - 1) {
272 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid uri: %{public}s", uri.c_str());
273 return false;
274 }
275 // correct uri: "/bundleName/moduleName/abilityName"
276 std::string::size_type pos1 = 0;
277 std::string::size_type pos2 = uri.find('/', pos1 + 1);
278 std::string::size_type pos3 = uri.find('/', pos2 + 1);
279 std::string::size_type pos4 = uri.find('/', pos3 + 1);
280 if ((pos3 == pos2 + 1) || (pos4 == pos3 + 1) || (pos4 == uri.size() - 1)) {
281 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid uri: %{public}s", uri.c_str());
282 return false;
283 }
284 return true;
285 }
286 }
287 }