• 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 #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