1 /*
2 * Copyright (c) 2021-2022 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 <fcntl.h>
16 #include <memory>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include "access_token_error.h"
22 #include "accesstoken_id_manager.h"
23 #include "accesstoken_info_manager.h"
24 #include "accesstoken_log.h"
25 #include "data_validator.h"
26 #include "json_parser.h"
27 #include "native_token_receptor.h"
28 #include "securec.h"
29
30 namespace OHOS {
31 namespace Security {
32 namespace AccessToken {
33 namespace {
34 std::recursive_mutex g_instanceMutex;
35 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "NativeTokenReceptor"};
36 static const std::string DEFAULT_DEVICEID = "0";
37 static const std::string JSON_PROCESS_NAME = "processName";
38 static const std::string JSON_APL = "APL";
39 static const std::string JSON_VERSION = "version";
40 static const std::string JSON_TOKEN_ID = "tokenId";
41 static const std::string JSON_TOKEN_ATTR = "tokenAttr";
42 static const std::string JSON_DCAPS = "dcaps";
43 static const std::string JSON_PERMS = "permissions";
44 static const std::string JSON_ACLS = "nativeAcls";
45 }
46
NativeReqPermsGet(const nlohmann::json & j,std::vector<PermissionStateFull> & permStateList)47 int32_t NativeReqPermsGet(
48 const nlohmann::json& j, std::vector<PermissionStateFull>& permStateList)
49 {
50 std::vector<std::string> permReqList;
51 if (j.find(JSON_PERMS) == j.end() || (!j.at(JSON_PERMS).is_array())) {
52 ACCESSTOKEN_LOG_ERROR(LABEL, "JSON_PERMS is invalid.");
53 return ERR_PARAM_INVALID;
54 }
55 permReqList = j.at(JSON_PERMS).get<std::vector<std::string>>();
56 if (permReqList.size() > MAX_REQ_PERM_NUM) {
57 ACCESSTOKEN_LOG_ERROR(LABEL, "Permission num oversize.");
58 return ERR_OVERSIZE;
59 }
60 std::set<std::string> permRes;
61 for (const auto& permReq : permReqList) {
62 PermissionStateFull permState;
63 if (permRes.count(permReq) != 0) {
64 continue;
65 }
66 permState.permissionName = permReq;
67 permState.isGeneral = true;
68 permState.resDeviceID.push_back(DEFAULT_DEVICEID);
69 permState.grantStatus.push_back(PERMISSION_GRANTED);
70 permState.grantFlags.push_back(PERMISSION_SYSTEM_FIXED);
71 permStateList.push_back(permState);
72 permRes.insert(permReq);
73 }
74 return RET_SUCCESS;
75 }
76
77 // nlohmann json need the function named from_json to parse NativeTokenInfo
from_json(const nlohmann::json & j,std::shared_ptr<NativeTokenInfoInner> & p)78 void from_json(const nlohmann::json& j, std::shared_ptr<NativeTokenInfoInner>& p)
79 {
80 NativeTokenInfo native;
81
82 if (!JsonParser::GetStringFromJson(j, JSON_PROCESS_NAME, native.processName) ||
83 !DataValidator::IsProcessNameValid(native.processName)) {
84 return;
85 }
86
87 int aplNum = 0;
88 if (!JsonParser::GetIntFromJson(j, JSON_APL, aplNum) || !DataValidator::IsAplNumValid(aplNum)) {
89 return;
90 }
91
92 native.apl = static_cast<ATokenAplEnum>(aplNum);
93
94 if (j.find(JSON_VERSION) == j.end() || (!j.at(JSON_VERSION).is_number())) {
95 return;
96 }
97 native.ver = (uint8_t)j.at(JSON_VERSION).get<int>();
98 if (native.ver != DEFAULT_TOKEN_VERSION) {
99 return;
100 }
101
102 if (!JsonParser::GetUnsignedIntFromJson(j, JSON_TOKEN_ID, native.tokenID) || (native.tokenID == 0)) {
103 return;
104 }
105
106 ATokenTypeEnum type = AccessTokenIDManager::GetTokenIdTypeEnum(native.tokenID);
107 if ((type != TOKEN_NATIVE) && (type != TOKEN_SHELL)) {
108 return;
109 }
110
111 if (!JsonParser::GetUnsignedIntFromJson(j, JSON_TOKEN_ATTR, native.tokenAttr)) {
112 return;
113 }
114
115 if (j.find(JSON_DCAPS) == j.end() || (!j.at(JSON_DCAPS).is_array())) {
116 return;
117 }
118 native.dcap = j.at(JSON_DCAPS).get<std::vector<std::string>>();
119 if (native.dcap.size() > MAX_DCAPS_NUM) {
120 ACCESSTOKEN_LOG_ERROR(LABEL, "Native dcap oversize.");
121 return;
122 }
123
124 if (j.find(JSON_ACLS) == j.end() || (!j.at(JSON_DCAPS).is_array())) {
125 return;
126 }
127 native.nativeAcls = j.at(JSON_ACLS).get<std::vector<std::string>>();
128 if (native.nativeAcls.size() > MAX_REQ_PERM_NUM) {
129 ACCESSTOKEN_LOG_ERROR(LABEL, "Permission num oversize.");
130 return;
131 }
132
133 std::vector<PermissionStateFull> permStateList;
134 if (NativeReqPermsGet(j, permStateList) != RET_SUCCESS) {
135 return;
136 }
137
138 p = std::make_shared<NativeTokenInfoInner>(native, permStateList);
139 }
140
ParserNativeRawData(const std::string & nativeRawData,std::vector<std::shared_ptr<NativeTokenInfoInner>> & tokenInfos)141 int32_t NativeTokenReceptor::ParserNativeRawData(const std::string& nativeRawData,
142 std::vector<std::shared_ptr<NativeTokenInfoInner>>& tokenInfos)
143 {
144 nlohmann::json jsonRes = nlohmann::json::parse(nativeRawData, nullptr, false);
145 if (jsonRes.is_discarded()) {
146 ACCESSTOKEN_LOG_ERROR(LABEL, "JsonRes is invalid.");
147 return ERR_PARAM_INVALID;
148 }
149 for (auto it = jsonRes.begin(); it != jsonRes.end(); it++) {
150 auto token = it->get<std::shared_ptr<NativeTokenInfoInner>>();
151 if (token != nullptr) {
152 tokenInfos.emplace_back(token);
153 } else {
154 ACCESSTOKEN_LOG_ERROR(LABEL, "Token is invalid.");
155 }
156 }
157 return RET_SUCCESS;
158 }
159
Init()160 int NativeTokenReceptor::Init()
161 {
162 std::string nativeRawData;
163 int ret = JsonParser::ReadCfgFile(NATIVE_TOKEN_CONFIG_FILE, nativeRawData);
164 if (ret != RET_SUCCESS) {
165 ACCESSTOKEN_LOG_ERROR(LABEL, "ReadCfgFile failed.");
166 return ret;
167 }
168 std::vector<std::shared_ptr<NativeTokenInfoInner>> tokenInfos;
169 ret = ParserNativeRawData(nativeRawData, tokenInfos);
170 if (ret != RET_SUCCESS) {
171 ACCESSTOKEN_LOG_ERROR(LABEL, "ParserNativeRawData failed.");
172 return ret;
173 }
174 AccessTokenInfoManager::GetInstance().ProcessNativeTokenInfos(tokenInfos);
175
176 ACCESSTOKEN_LOG_INFO(LABEL, "Init ok.");
177 return RET_SUCCESS;
178 }
179
GetInstance()180 NativeTokenReceptor& NativeTokenReceptor::GetInstance()
181 {
182 static NativeTokenReceptor* instance = nullptr;
183 if (instance == nullptr) {
184 std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
185 if (instance == nullptr) {
186 instance = new NativeTokenReceptor();
187 }
188 }
189 return *instance;
190 }
191 } // namespace AccessToken
192 } // namespace Security
193 } // namespace OHOS
194