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 "permission_definition_parser.h"
16 
17 #include <fcntl.h>
18 #include <memory>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include "accesstoken_log.h"
24 #include "access_token.h"
25 #include "access_token_error.h"
26 #include "accesstoken_info_manager.h"
27 #include "data_validator.h"
28 #include "hisysevent_adapter.h"
29 #include "json_parser.h"
30 #include "permission_def.h"
31 #include "permission_definition_cache.h"
32 #include "securec.h"
33 
34 namespace OHOS {
35 namespace Security {
36 namespace AccessToken {
37 namespace {
38 std::recursive_mutex g_instanceMutex;
39 static const int32_t EXTENSION_PERMISSION_ID = 0;
40 static const std::string PERMISSION_NAME = "name";
41 static const std::string PERMISSION_GRANT_MODE = "grantMode";
42 static const std::string PERMISSION_AVAILABLE_LEVEL = "availableLevel";
43 static const std::string PERMISSION_AVAILABLE_TYPE = "availableType";
44 static const std::string PERMISSION_PROVISION_ENABLE = "provisionEnable";
45 static const std::string PERMISSION_DISTRIBUTED_SCENE_ENABLE = "distributedSceneEnable";
46 static const std::string PERMISSION_LABEL = "label";
47 static const std::string PERMISSION_DESCRIPTION = "description";
48 static const std::string AVAILABLE_TYPE_NORMAL_HAP = "NORMAL";
49 static const std::string AVAILABLE_TYPE_SYSTEM_HAP = "SYSTEM";
50 static const std::string AVAILABLE_TYPE_MDM = "MDM";
51 static const std::string AVAILABLE_TYPE_SYSTEM_AND_MDM = "SYSTEM_AND_MDM";
52 static const std::string AVAILABLE_TYPE_SERVICE = "SERVICE";
53 static const std::string AVAILABLE_LEVEL_NORMAL = "normal";
54 static const std::string AVAILABLE_LEVEL_SYSTEM_BASIC = "system_basic";
55 static const std::string AVAILABLE_LEVEL_SYSTEM_CORE = "system_core";
56 static const std::string PERMISSION_GRANT_MODE_SYSTEM_GRANT = "system_grant";
57 static const std::string PERMISSION_GRANT_MODE_USER_GRANT = "user_grant";
58 static const std::string SYSTEM_GRANT_DEFINE_PERMISSION = "systemGrantPermissions";
59 static const std::string USER_GRANT_DEFINE_PERMISSION = "userGrantPermissions";
60 static const std::string DEFINE_PERMISSION_FILE = "/system/etc/access_token/permission_definitions.json";
61 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE,
62     SECURITY_DOMAIN_ACCESSTOKEN, "PermissionDefinitionParser"};
63 }
64 
GetPermissionApl(const std::string & apl,AccessToken::ATokenAplEnum & aplNum)65 static bool GetPermissionApl(const std::string &apl, AccessToken::ATokenAplEnum& aplNum)
66 {
67     if (apl == AVAILABLE_LEVEL_SYSTEM_CORE) {
68         aplNum = AccessToken::ATokenAplEnum::APL_SYSTEM_CORE;
69         return true;
70     }
71     if (apl == AVAILABLE_LEVEL_SYSTEM_BASIC) {
72         aplNum = AccessToken::ATokenAplEnum::APL_SYSTEM_BASIC;
73         return true;
74     }
75     if (apl == AVAILABLE_LEVEL_NORMAL) {
76         aplNum = AccessToken::ATokenAplEnum::APL_NORMAL;
77         return true;
78     }
79     ACCESSTOKEN_LOG_ERROR(LABEL, "Apl: %{public}s is invalid.", apl.c_str());
80     return false;
81 }
82 
GetPermissionAvailableType(const std::string & availableType,AccessToken::ATokenAvailableTypeEnum & typeNum)83 static bool GetPermissionAvailableType(const std::string &availableType, AccessToken::ATokenAvailableTypeEnum& typeNum)
84 {
85     if (availableType == AVAILABLE_TYPE_NORMAL_HAP) {
86         typeNum = AccessToken::ATokenAvailableTypeEnum::NORMAL;
87         return true;
88     }
89     if (availableType == AVAILABLE_TYPE_SYSTEM_HAP) {
90         typeNum = AccessToken::ATokenAvailableTypeEnum::SYSTEM;
91         return true;
92     }
93     if (availableType == AVAILABLE_TYPE_MDM) {
94         typeNum = AccessToken::ATokenAvailableTypeEnum::MDM;
95         return true;
96     }
97     if (availableType == AVAILABLE_TYPE_SYSTEM_AND_MDM) {
98         typeNum = AccessToken::ATokenAvailableTypeEnum::SYSTEM_AND_MDM;
99         return true;
100     }
101     if (availableType == AVAILABLE_TYPE_SERVICE) {
102         typeNum = AccessToken::ATokenAvailableTypeEnum::SERVICE;
103         return true;
104     }
105     typeNum = AccessToken::ATokenAvailableTypeEnum::INVALID;
106     ACCESSTOKEN_LOG_ERROR(LABEL, "AvailableType: %{public}s is invalid.", availableType.c_str());
107     return false;
108 }
109 
GetPermissionGrantMode(const std::string & mode)110 static int32_t GetPermissionGrantMode(const std::string &mode)
111 {
112     if (mode == PERMISSION_GRANT_MODE_SYSTEM_GRANT) {
113         return AccessToken::GrantMode::SYSTEM_GRANT;
114     }
115     return AccessToken::GrantMode::USER_GRANT;
116 }
117 
from_json(const nlohmann::json & j,PermissionDefParseRet & result)118 void from_json(const nlohmann::json& j, PermissionDefParseRet& result)
119 {
120     result.isSuccessful = false;
121     PermissionDef permDef;
122     if (!JsonParser::GetStringFromJson(j, PERMISSION_NAME, permDef.permissionName) ||
123         !DataValidator::IsProcessNameValid(permDef.permissionName)) {
124         return;
125     }
126     std::string grantModeStr;
127     if (!JsonParser::GetStringFromJson(j, PERMISSION_GRANT_MODE, grantModeStr)) {
128         return;
129     }
130     permDef.grantMode = GetPermissionGrantMode(grantModeStr);
131 
132     std::string availableLevelStr;
133     if (!JsonParser::GetStringFromJson(j, PERMISSION_AVAILABLE_LEVEL, availableLevelStr)) {
134         return;
135     }
136     if (!GetPermissionApl(availableLevelStr, permDef.availableLevel)) {
137         return;
138     }
139 
140     std::string availableTypeStr;
141     if (!JsonParser::GetStringFromJson(j, PERMISSION_AVAILABLE_TYPE, availableTypeStr)) {
142         return;
143     }
144     if (!GetPermissionAvailableType(availableTypeStr, permDef.availableType)) {
145         return;
146     }
147 
148     if (!JsonParser::GetBoolFromJson(j, PERMISSION_PROVISION_ENABLE, permDef.provisionEnable)) {
149         return;
150     }
151     if (!JsonParser::GetBoolFromJson(j, PERMISSION_DISTRIBUTED_SCENE_ENABLE, permDef.distributedSceneEnable)) {
152         return;
153     }
154     permDef.bundleName = "system_ability";
155     if (permDef.grantMode == AccessToken::GrantMode::SYSTEM_GRANT) {
156         result.permDef = permDef;
157         result.isSuccessful = true;
158         return;
159     }
160     if (!JsonParser::GetStringFromJson(j, PERMISSION_LABEL, permDef.label)) {
161         return;
162     }
163     if (!JsonParser::GetStringFromJson(j, PERMISSION_DESCRIPTION, permDef.description)) {
164         return;
165     }
166     result.permDef = permDef;
167     result.isSuccessful = true;
168     return;
169 }
170 
CheckPermissionDefRules(const PermissionDef & permDef)171 static bool CheckPermissionDefRules(const PermissionDef& permDef)
172 {
173     // Extension permission support permission for service only.
174     if (permDef.availableType != AccessToken::ATokenAvailableTypeEnum::SERVICE) {
175         ACCESSTOKEN_LOG_DEBUG(LABEL, "%{public}s is for hap.", permDef.permissionName.c_str());
176         return false;
177     }
178     return true;
179 }
180 
GetPermissionDefList(const nlohmann::json & json,const std::string & permsRawData,const std::string & type,std::vector<PermissionDef> & permDefList)181 int32_t PermissionDefinitionParser::GetPermissionDefList(const nlohmann::json& json, const std::string& permsRawData,
182     const std::string& type, std::vector<PermissionDef>& permDefList)
183 {
184     if ((json.find(type) == json.end()) || (!json.at(type).is_array())) {
185         ACCESSTOKEN_LOG_ERROR(LABEL, "Json is not array.");
186         return ERR_PARAM_INVALID;
187     }
188 
189     nlohmann::json JsonData = json.at(type).get<nlohmann::json>();
190     for (auto it = JsonData.begin(); it != JsonData.end(); it++) {
191         auto result = it->get<PermissionDefParseRet>();
192         if (!result.isSuccessful) {
193             ACCESSTOKEN_LOG_ERROR(LABEL, "Get permission def failed.");
194             return ERR_PERM_REQUEST_CFG_FAILED;
195         }
196         if (!CheckPermissionDefRules(result.permDef)) {
197             continue;
198         }
199         ACCESSTOKEN_LOG_DEBUG(LABEL, "%{public}s insert.", result.permDef.permissionName.c_str());
200         permDefList.emplace_back(result.permDef);
201     }
202     return RET_SUCCESS;
203 }
204 
ParserPermsRawData(const std::string & permsRawData,std::vector<PermissionDef> & permDefList)205 int32_t PermissionDefinitionParser::ParserPermsRawData(const std::string& permsRawData,
206     std::vector<PermissionDef>& permDefList)
207 {
208     nlohmann::json jsonRes = nlohmann::json::parse(permsRawData, nullptr, false);
209     if (jsonRes.is_discarded()) {
210         ACCESSTOKEN_LOG_ERROR(LABEL, "JsonRes is invalid.");
211         return ERR_PARAM_INVALID;
212     }
213 
214     int32_t ret = GetPermissionDefList(jsonRes, permsRawData, SYSTEM_GRANT_DEFINE_PERMISSION, permDefList);
215     if (ret != RET_SUCCESS) {
216         ACCESSTOKEN_LOG_ERROR(LABEL, "Get system_grant permission def list failed.");
217         return ret;
218     }
219     ACCESSTOKEN_LOG_INFO(LABEL, "Get system_grant permission size=%{public}zu.", permDefList.size());
220     ret = GetPermissionDefList(jsonRes, permsRawData, USER_GRANT_DEFINE_PERMISSION, permDefList);
221     if (ret != RET_SUCCESS) {
222         ACCESSTOKEN_LOG_ERROR(LABEL, "Get user_grant permission def list failed.");
223         return ret;
224     }
225     ACCESSTOKEN_LOG_INFO(LABEL, "Get permission size=%{public}zu.", permDefList.size());
226     return RET_SUCCESS;
227 }
228 
Init()229 int32_t PermissionDefinitionParser::Init()
230 {
231     ACCESSTOKEN_LOG_INFO(LABEL, "System permission set begin.");
232     if (ready_) {
233         ACCESSTOKEN_LOG_ERROR(LABEL, " system permission has been set.");
234         return RET_SUCCESS;
235     }
236 
237     std::string permsRawData;
238     int32_t ret = JsonParser::ReadCfgFile(DEFINE_PERMISSION_FILE, permsRawData);
239     if (ret != RET_SUCCESS) {
240         ACCESSTOKEN_LOG_ERROR(LABEL, "ReadCfgFile failed.");
241         ReportSysEventServiceStartError(INIT_PERM_DEF_JSON_ERROR, "ReadCfgFile fail.", ret);
242         return ERR_FILE_OPERATE_FAILED;
243     }
244     std::vector<PermissionDef> permDefList;
245     ret = ParserPermsRawData(permsRawData, permDefList);
246     if (ret != RET_SUCCESS) {
247         ReportSysEventServiceStartError(INIT_PERM_DEF_JSON_ERROR, "ParserPermsRawData fail.", ret);
248         ACCESSTOKEN_LOG_ERROR(LABEL, "ParserPermsRawData failed.");
249         return ret;
250     }
251 
252     for (const auto& perm : permDefList) {
253         PermissionDefinitionCache::GetInstance().Insert(perm, EXTENSION_PERMISSION_ID);
254     }
255     ready_ = true;
256     ACCESSTOKEN_LOG_INFO(LABEL, "Init ok.");
257     return RET_SUCCESS;
258 }
259 
GetInstance()260 PermissionDefinitionParser& PermissionDefinitionParser::GetInstance()
261 {
262     static PermissionDefinitionParser* instance = nullptr;
263     if (instance == nullptr) {
264         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
265         if (instance == nullptr) {
266             instance = new PermissionDefinitionParser();
267         }
268     }
269     return *instance;
270 }
271 } // namespace AccessToken
272 } // namespace Security
273 } // namespace OHOS
274