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 #include "json_parse_loader.h"
16
17 #include <fcntl.h>
18 #include <memory>
19 #include <set>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "access_token_error.h"
25 #include "accesstoken_common_log.h"
26 #include "cjson_utils.h"
27 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
28 #include "config_policy_utils.h"
29 #endif
30 #include "data_validator.h"
31
32 namespace OHOS {
33 namespace Security {
34 namespace AccessToken {
35 namespace {
36 constexpr int32_t MAX_NATIVE_CONFIG_FILE_SIZE = 5 * 1024 * 1024; // 5M
37 constexpr size_t BUFFER_SIZE = 1024;
38
39 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
40 static constexpr const char* ACCESSTOKEN_CONFIG_FILE = "/etc/access_token/accesstoken_config.json";
41 static constexpr const char* PERMISSION_MANAGER_BUNDLE_NAME_KEY = "permission_manager_bundle_name";
42 static constexpr const char* GRANT_ABILITY_NAME_KEY = "grant_ability_name";
43 static constexpr const char* GRANT_SERVICE_ABILITY_NAME_KEY = "grant_service_ability_name";
44 static constexpr const char* PERMISSION_STATE_SHEET_ABILITY_NAME_KEY = "permission_state_sheet_ability_name";
45 static constexpr const char* GLOBAL_SWITCH_SHEET_ABILITY_NAME_KEY = "global_switch_sheet_ability_name";
46 static constexpr const char* TEMP_PERM_CANCLE_TIME_KEY = "temp_perm_cencle_time";
47 static constexpr const char* APPLICATION_SETTING_ABILITY_NAME_KEY = "application_setting_ability_name";
48
49 static constexpr const char* RECORD_SIZE_MAXIMUM_KEY = "permission_used_record_size_maximum";
50 static constexpr const char* RECORD_AGING_TIME_KEY = "permission_used_record_aging_time";
51 static constexpr const char* GLOBAL_DIALOG_BUNDLE_NAME_KEY = "global_dialog_bundle_name";
52 static constexpr const char* GLOBAL_DIALOG_ABILITY_NAME_KEY = "global_dialog_ability_name";
53
54 static constexpr const char* SEND_REQUEST_REPEAT_TIMES_KEY = "send_request_repeat_times";
55 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
56
57 // native_token.json
58 static const char* NATIVE_TOKEN_CONFIG_FILE = "/data/service/el0/access_token/nativetoken.json";
59 static const char* JSON_PROCESS_NAME = "processName";
60 static const char* JSON_APL = "APL";
61 static const char* JSON_VERSION = "version";
62 static const char* JSON_TOKEN_ID = "tokenId";
63 static const char* JSON_TOKEN_ATTR = "tokenAttr";
64 static const char* JSON_DCAPS = "dcaps";
65 static const char* JSON_PERMS = "permissions";
66 static const char* JSON_ACLS = "nativeAcls";
67 static const int32_t MAX_DCAPS_NUM = 10 * 1024;
68 static const int32_t MAX_REQ_PERM_NUM = 10 * 1024;
69
70 // dlp json
71 static const char* CLONE_PERMISSION_CONFIG_FILE = "/system/etc/dlp_permission/clone_app_permission.json";
72 }
73
ReadCfgFile(const std::string & file,std::string & rawData)74 int32_t ConfigPolicLoader::ReadCfgFile(const std::string& file, std::string& rawData)
75 {
76 char filePath[PATH_MAX] = {0};
77 if (realpath(file.c_str(), filePath) == nullptr) {
78 return ERR_FILE_OPERATE_FAILED;
79 }
80 int32_t fd = open(filePath, O_RDONLY);
81 if (fd < 0) {
82 LOGE(ATM_DOMAIN, ATM_TAG, "Open failed errno %{public}d.", errno);
83 return ERR_FILE_OPERATE_FAILED;
84 }
85 struct stat statBuffer;
86
87 if (fstat(fd, &statBuffer) != 0) {
88 LOGE(ATM_DOMAIN, ATM_TAG, "Fstat failed.");
89 close(fd);
90 return ERR_FILE_OPERATE_FAILED;
91 }
92
93 if (statBuffer.st_size == 0) {
94 LOGE(ATM_DOMAIN, ATM_TAG, "Config file size is invalid.");
95 close(fd);
96 return ERR_PARAM_INVALID;
97 }
98 if (statBuffer.st_size > MAX_NATIVE_CONFIG_FILE_SIZE) {
99 LOGE(ATM_DOMAIN, ATM_TAG, "Config file size is too large.");
100 close(fd);
101 return ERR_OVERSIZE;
102 }
103 rawData.reserve(statBuffer.st_size);
104
105 char buff[BUFFER_SIZE] = { 0 };
106 ssize_t readLen = 0;
107 while ((readLen = read(fd, buff, BUFFER_SIZE)) > 0) {
108 rawData.append(buff, readLen);
109 }
110 close(fd);
111 if (readLen == 0) {
112 return RET_SUCCESS;
113 }
114 return ERR_FILE_OPERATE_FAILED;
115 }
116
IsDirExsit(const std::string & file)117 bool ConfigPolicLoader::IsDirExsit(const std::string& file)
118 {
119 if (file.empty()) {
120 LOGE(ATM_DOMAIN, ATM_TAG, "File path is empty");
121 return false;
122 }
123
124 struct stat buf;
125 if (stat(file.c_str(), &buf) != 0) {
126 LOGE(ATM_DOMAIN, ATM_TAG, "Get file attributes failed, errno %{public}d.", errno);
127 return false;
128 }
129
130 if (!S_ISDIR(buf.st_mode)) {
131 LOGE(ATM_DOMAIN, ATM_TAG, "File mode is not directory.");
132 return false;
133 }
134
135 return true;
136 }
137
138 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
GetConfigFilePathList(std::vector<std::string> & pathList)139 void ConfigPolicLoader::GetConfigFilePathList(std::vector<std::string>& pathList)
140 {
141 CfgDir *dirs = GetCfgDirList(); // malloc a CfgDir point, need to free later
142 if (dirs == nullptr) {
143 LOGE(ATM_DOMAIN, ATM_TAG, "Can't get cfg file path.");
144 return;
145 }
146
147 for (const auto& path : dirs->paths) {
148 if ((path == nullptr) || (!IsDirExsit(path))) {
149 continue;
150 }
151
152 LOGI(ATM_DOMAIN, ATM_TAG, "Accesstoken cfg dir: %{public}s.", path);
153 pathList.emplace_back(path);
154 }
155
156 FreeCfgDirList(dirs); // free
157 }
158
GetAtCfgFromJson(const CJson * j,AccessTokenServiceConfig & a)159 bool GetAtCfgFromJson(const CJson* j, AccessTokenServiceConfig& a)
160 {
161 if (!GetStringFromJson(j, PERMISSION_MANAGER_BUNDLE_NAME_KEY, a.grantBundleName)) {
162 return false;
163 }
164
165 if (!GetStringFromJson(j, GRANT_ABILITY_NAME_KEY, a.grantAbilityName)) {
166 return false;
167 }
168
169 if (!GetStringFromJson(j, GRANT_SERVICE_ABILITY_NAME_KEY, a.grantAbilityName)) {
170 return false;
171 }
172
173 if (!GetStringFromJson(j, PERMISSION_STATE_SHEET_ABILITY_NAME_KEY, a.permStateAbilityName)) {
174 return false;
175 }
176
177 if (!GetStringFromJson(j, GLOBAL_SWITCH_SHEET_ABILITY_NAME_KEY, a.globalSwitchAbilityName)) {
178 return false;
179 }
180
181 if (!GetIntFromJson(j, TEMP_PERM_CANCLE_TIME_KEY, a.cancleTime)) {
182 return false;
183 }
184
185 GetStringFromJson(j, APPLICATION_SETTING_ABILITY_NAME_KEY, a.applicationSettingAbilityName);
186 return true;
187 }
188
GetPrivacyCfgFromJson(const CJson * j,PrivacyServiceConfig & p)189 bool GetPrivacyCfgFromJson(const CJson* j, PrivacyServiceConfig& p)
190 {
191 if (!GetIntFromJson(j, RECORD_SIZE_MAXIMUM_KEY, p.sizeMaxImum)) {
192 return false;
193 }
194
195 if (!GetIntFromJson(j, RECORD_AGING_TIME_KEY, p.agingTime)) {
196 return false;
197 }
198
199 if (!GetStringFromJson(j, GLOBAL_DIALOG_BUNDLE_NAME_KEY, p.globalDialogBundleName)) {
200 return false;
201 }
202
203 if (!GetStringFromJson(j, GLOBAL_DIALOG_ABILITY_NAME_KEY, p.globalDialogAbilityName)) {
204 return false;
205 }
206 return true;
207 }
208
GetTokenSyncCfgFromJson(const CJson * j,TokenSyncServiceConfig & t)209 bool GetTokenSyncCfgFromJson(const CJson* j, TokenSyncServiceConfig& t)
210 {
211 if (!GetIntFromJson(j, SEND_REQUEST_REPEAT_TIMES_KEY, t.sendRequestRepeatTimes)) {
212 return false;
213 }
214 return true;
215 }
216
GetConfigValueFromFile(const ServiceType & type,const std::string & fileContent,AccessTokenConfigValue & config)217 bool ConfigPolicLoader::GetConfigValueFromFile(const ServiceType& type, const std::string& fileContent,
218 AccessTokenConfigValue& config)
219 {
220 CJsonUnique jsonRes = CreateJsonFromString(fileContent);
221 if (jsonRes == nullptr) {
222 LOGE(ATM_DOMAIN, ATM_TAG, "JsonRes is invalid.");
223 return false;
224 }
225
226 if (type == ServiceType::ACCESSTOKEN_SERVICE) {
227 CJson *atJson = GetObjFromJson(jsonRes, "accesstoken");
228 return GetAtCfgFromJson(atJson, config.atConfig);
229 } else if (type == ServiceType::PRIVACY_SERVICE) {
230 CJson *prJson = GetObjFromJson(jsonRes, "privacy");
231 return GetPrivacyCfgFromJson(prJson, config.pConfig);
232 }
233 CJson *toSyncJson = GetObjFromJson(jsonRes, "tokensync");
234 return GetTokenSyncCfgFromJson(toSyncJson, config.tsConfig);
235 }
236 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
237
GetConfigValue(const ServiceType & type,AccessTokenConfigValue & config)238 bool ConfigPolicLoader::GetConfigValue(const ServiceType& type, AccessTokenConfigValue& config)
239 {
240 bool successFlag = false;
241 #ifdef CUSTOMIZATION_CONFIG_POLICY_ENABLE
242 std::vector<std::string> pathList;
243 GetConfigFilePathList(pathList);
244
245 for (const auto& path : pathList) {
246 std::string filePath = path + ACCESSTOKEN_CONFIG_FILE;
247 std::string fileContent;
248 int32_t res = ReadCfgFile(filePath, fileContent);
249 if (res != 0) {
250 continue;
251 }
252
253 if (GetConfigValueFromFile(type, fileContent, config)) {
254 LOGI(ATM_DOMAIN, ATM_TAG, "Get valid config value from file [%{public}s]!", filePath.c_str());
255 successFlag = true;
256 break; // once get the config value, break the loop
257 }
258 }
259 #endif // CUSTOMIZATION_CONFIG_POLICY_ENABLE
260 return successFlag;
261 }
262
NativeReqPermsGet(const CJson * j,std::vector<PermissionStatus> & permStateList)263 static int32_t NativeReqPermsGet(const CJson* j, std::vector<PermissionStatus>& permStateList)
264 {
265 CJson *permJson = GetArrayFromJson(j, JSON_PERMS);
266 if (permJson == nullptr) {
267 LOGE(ATM_DOMAIN, ATM_TAG, "JSON_PERMS is invalid.");
268 return ERR_PARAM_INVALID;
269 }
270 int32_t len = cJSON_GetArraySize(permJson);
271 if (len > MAX_REQ_PERM_NUM) {
272 LOGE(ATM_DOMAIN, ATM_TAG, "Permission num oversize.");
273 return ERR_OVERSIZE;
274 }
275 std::set<std::string> permRes;
276 for (int32_t i = 0; i < len; i++) {
277 std::string permReq = cJSON_GetStringValue(cJSON_GetArrayItem(permJson, i));
278 PermissionStatus permState;
279 if (permRes.count(permReq) != 0) {
280 continue;
281 }
282 permState.permissionName = permReq;
283 permState.grantStatus = PERMISSION_GRANTED;
284 permState.grantFlag = PERMISSION_SYSTEM_FIXED;
285 permStateList.push_back(permState);
286 permRes.insert(permReq);
287 }
288 return RET_SUCCESS;
289 }
290
GetTokenIdTypeEnum(AccessTokenID id)291 static ATokenTypeEnum GetTokenIdTypeEnum(AccessTokenID id)
292 {
293 AccessTokenIDInner *idInner = reinterpret_cast<AccessTokenIDInner *>(&id);
294 return static_cast<ATokenTypeEnum>(idInner->type);
295 }
296
GetSingleNativeTokenFromJson(const CJson * j,NativeTokenInfoBase & native)297 static void GetSingleNativeTokenFromJson(const CJson* j, NativeTokenInfoBase& native)
298 {
299 NativeTokenInfoBase info;
300 int32_t aplNum = 0;
301 if (!GetIntFromJson(j, JSON_APL, aplNum) || !DataValidator::IsAplNumValid(aplNum)) {
302 return;
303 }
304 info.apl = static_cast<ATokenAplEnum>(aplNum);
305 int32_t ver;
306 GetIntFromJson(j, JSON_VERSION, ver);
307 info.ver = (uint8_t)ver;
308 GetUnsignedIntFromJson(j, JSON_TOKEN_ID, info.tokenID);
309 if ((info.ver != DEFAULT_TOKEN_VERSION) || (info.tokenID == 0)) {
310 return;
311 }
312 ATokenTypeEnum type = GetTokenIdTypeEnum(info.tokenID);
313 if ((type != TOKEN_NATIVE) && (type != TOKEN_SHELL)) {
314 return;
315 }
316 if (!GetUnsignedIntFromJson(j, JSON_TOKEN_ATTR, info.tokenAttr)) {
317 return;
318 }
319 CJson *dcapsJson = GetArrayFromJson(j, JSON_DCAPS);
320 CJson *aclsJson = GetArrayFromJson(j, JSON_ACLS);
321 if ((dcapsJson == nullptr) || (aclsJson == nullptr)) {
322 return;
323 }
324 int32_t dcapLen = cJSON_GetArraySize(dcapsJson);
325 int32_t aclLen = cJSON_GetArraySize(aclsJson);
326 if ((dcapLen > MAX_DCAPS_NUM) || (aclLen > MAX_REQ_PERM_NUM)) {
327 LOGE(ATM_DOMAIN, ATM_TAG, "Native dcap oversize.");
328 return;
329 }
330 for (int32_t i = 0; i < dcapLen; i++) {
331 std::string item = cJSON_GetStringValue(cJSON_GetArrayItem(dcapsJson, i));
332 info.dcap.push_back(item);
333 }
334 for (int i = 0; i < aclLen; i++) {
335 std::string item = cJSON_GetStringValue(cJSON_GetArrayItem(aclsJson, i));
336 info.nativeAcls.push_back(item);
337 }
338
339 if (NativeReqPermsGet(j, info.permStateList) != RET_SUCCESS) {
340 return;
341 }
342
343 if (!GetStringFromJson(j, JSON_PROCESS_NAME, info.processName) ||
344 !DataValidator::IsProcessNameValid(info.processName)) {
345 return;
346 }
347 native = info;
348 }
349
ParserNativeRawData(const std::string & nativeRawData,std::vector<NativeTokenInfoBase> & tokenInfos)350 bool ConfigPolicLoader::ParserNativeRawData(
351 const std::string& nativeRawData, std::vector<NativeTokenInfoBase>& tokenInfos)
352 {
353 CJsonUnique jsonRes = CreateJsonFromString(nativeRawData);
354 if (jsonRes == nullptr) {
355 LOGE(ATM_DOMAIN, ATM_TAG, "JsonRes is invalid.");
356 return false;
357 }
358 int32_t len = cJSON_GetArraySize(jsonRes.get());
359 for (int32_t i = 0; i < len; i++) {
360 cJSON *item = cJSON_GetArrayItem(jsonRes.get(), i);
361 NativeTokenInfoBase token;
362 GetSingleNativeTokenFromJson(item, token);
363 if (!token.processName.empty()) {
364 tokenInfos.emplace_back(token);
365 }
366 }
367 return true;
368 }
369
GetAllNativeTokenInfo(std::vector<NativeTokenInfoBase> & tokenInfos)370 int32_t ConfigPolicLoader::GetAllNativeTokenInfo(std::vector<NativeTokenInfoBase>& tokenInfos)
371 {
372 std::string nativeRawData;
373 int32_t ret = ReadCfgFile(NATIVE_TOKEN_CONFIG_FILE, nativeRawData);
374 if (ret != RET_SUCCESS) {
375 LOGE(ATM_DOMAIN, ATM_TAG,
376 "Read native token json file failed, err = %{public}d.", ret);
377 return ret;
378 }
379 if (!ParserNativeRawData(nativeRawData, tokenInfos)) {
380 LOGE(ATM_DOMAIN, ATM_TAG, "ParserNativeRawData failed.");
381 return ERR_PRASE_RAW_DATA_FAILED;
382 }
383 return RET_SUCCESS;
384 }
385
JsonFromPermissionDlpMode(const CJson * j,PermissionDlpMode & p)386 static void JsonFromPermissionDlpMode(const CJson *j, PermissionDlpMode& p)
387 {
388 if (!GetStringFromJson(j, "name", p.permissionName)) {
389 return;
390 }
391 if (!DataValidator::IsProcessNameValid(p.permissionName)) {
392 return;
393 }
394
395 std::string dlpModeStr;
396 if (!GetStringFromJson(j, "dlpGrantRange", dlpModeStr)) {
397 return;
398 }
399 if (dlpModeStr == "all") {
400 p.dlpMode = DLP_PERM_ALL;
401 return;
402 }
403 if (dlpModeStr == "full_control") {
404 p.dlpMode = DLP_PERM_FULL_CONTROL;
405 return;
406 }
407 p.dlpMode = DLP_PERM_NONE;
408 return;
409 }
410
ParserDlpPermsRawData(const std::string & dlpPermsRawData,std::vector<PermissionDlpMode> & dlpPerms)411 bool ConfigPolicLoader::ParserDlpPermsRawData(
412 const std::string& dlpPermsRawData, std::vector<PermissionDlpMode>& dlpPerms)
413 {
414 CJsonUnique jsonRes = CreateJsonFromString(dlpPermsRawData);
415 if (jsonRes == nullptr) {
416 LOGE(ATM_DOMAIN, ATM_TAG, "JsonRes is invalid.");
417 return false;
418 }
419
420 cJSON *dlpPermTokenJson = GetArrayFromJson(jsonRes.get(), "dlpPermissions");
421 if ((dlpPermTokenJson != nullptr)) {
422 CJson *j = nullptr;
423 std::vector<PermissionDlpMode> dlpPermissions;
424 cJSON_ArrayForEach(j, dlpPermTokenJson) {
425 PermissionDlpMode p;
426 JsonFromPermissionDlpMode(j, p);
427 dlpPerms.emplace_back(p);
428 }
429 }
430 return true;
431 }
432
GetDlpPermissions(std::vector<PermissionDlpMode> & dlpPerms)433 int32_t ConfigPolicLoader::GetDlpPermissions(std::vector<PermissionDlpMode>& dlpPerms)
434 {
435 std::string dlpPermsRawData;
436 int32_t ret = ReadCfgFile(CLONE_PERMISSION_CONFIG_FILE, dlpPermsRawData);
437 if (ret != RET_SUCCESS) {
438 LOGE(ATM_DOMAIN, ATM_TAG,
439 "Read(%{public}s) failed, err = %{public}d.", CLONE_PERMISSION_CONFIG_FILE, ret);
440 return ret;
441 }
442 if (!ParserDlpPermsRawData(dlpPermsRawData, dlpPerms)) {
443 LOGE(ATM_DOMAIN, ATM_TAG, "ParserDlpPermsRawData failed.");
444 return ERR_PRASE_RAW_DATA_FAILED;
445 }
446 return RET_SUCCESS;
447 }
448
449 extern "C" {
Create()450 void* Create()
451 {
452 return reinterpret_cast<void*>(new ConfigPolicLoader);
453 }
454
Destroy(void * loaderPtr)455 void Destroy(void* loaderPtr)
456 {
457 ConfigPolicyLoaderInterface* loader = reinterpret_cast<ConfigPolicyLoaderInterface*>(loaderPtr);
458 if (loader != nullptr) {
459 delete loader;
460 }
461 }
462 }
463 } // namespace AccessToken
464 } // namespace Security
465 } // namespace OHOS
466