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 "accesstoken_id_manager.h"
22 #include "accesstoken_info_manager.h"
23 #include "accesstoken_log.h"
24 #include "data_validator.h"
25 #include "native_token_receptor.h"
26 #include "securec.h"
27
28 namespace OHOS {
29 namespace Security {
30 namespace AccessToken {
31 namespace {
32 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "NativeTokenReceptor"};
33 static const std::string DEFAULT_DEVICEID = "0";
34 static const std::string JSON_PROCESS_NAME = "processName";
35 static const std::string JSON_APL = "APL";
36 static const std::string JSON_VERSION = "version";
37 static const std::string JSON_TOKEN_ID = "tokenId";
38 static const std::string JSON_TOKEN_ATTR = "tokenAttr";
39 static const std::string JSON_DCAPS = "dcaps";
40 static const std::string JSON_PERMS = "permissions";
41 static const std::string JSON_ACLS = "nativeAcls";
42 }
43
NativeReqPermsGet(const nlohmann::json & j,std::vector<PermissionStateFull> & permStateList)44 int32_t NativeReqPermsGet(
45 const nlohmann::json& j, std::vector<PermissionStateFull>& permStateList)
46 {
47 std::vector<std::string> permReqList;
48 if (j.find(JSON_PERMS) == j.end()) {
49 return RET_FAILED;
50 }
51 permReqList = j.at(JSON_PERMS).get<std::vector<std::string>>();
52 if (permReqList.size() > MAX_REQ_PERM_NUM) {
53 return RET_FAILED;
54 }
55 std::set<std::string> permRes;
56 for (const auto& permReq : permReqList) {
57 PermissionStateFull permState;
58 if (permRes.count(permReq) != 0) {
59 continue;
60 }
61 permState.permissionName = permReq;
62 permState.isGeneral = true;
63 permState.resDeviceID.push_back(DEFAULT_DEVICEID);
64 permState.grantStatus.push_back(PERMISSION_GRANTED);
65 permState.grantFlags.push_back(PERMISSION_SYSTEM_FIXED);
66 permStateList.push_back(permState);
67 permRes.insert(permReq);
68 }
69 return RET_SUCCESS;
70 }
71
72 // nlohmann json need the function named from_json to parse NativeTokenInfo
from_json(const nlohmann::json & j,std::shared_ptr<NativeTokenInfoInner> & p)73 void from_json(const nlohmann::json& j, std::shared_ptr<NativeTokenInfoInner>& p)
74 {
75 NativeTokenInfo native;
76 if (j.find(JSON_PROCESS_NAME) != j.end()) {
77 native.processName = j.at(JSON_PROCESS_NAME).get<std::string>();
78 if (!DataValidator::IsProcessNameValid(native.processName)) {
79 return;
80 }
81 } else {
82 return;
83 }
84
85 if (j.find(JSON_APL) != j.end()) {
86 int aplNum = j.at(JSON_APL).get<int>();
87 if (DataValidator::IsAplNumValid(aplNum)) {
88 native.apl = static_cast<ATokenAplEnum>(aplNum);
89 } else {
90 return;
91 }
92 } else {
93 return;
94 }
95
96 if (j.find(JSON_VERSION) != j.end()) {
97 native.ver = (uint8_t)j.at(JSON_VERSION).get<int>();
98 if (native.ver != DEFAULT_TOKEN_VERSION) {
99 return;
100 }
101 } else {
102 return;
103 }
104
105 if (j.find(JSON_TOKEN_ID) != j.end()) {
106 native.tokenID = j.at(JSON_TOKEN_ID).get<unsigned int>();
107 if (native.tokenID == 0) {
108 return;
109 }
110 ATokenTypeEnum type = AccessTokenIDManager::GetTokenIdTypeEnum(native.tokenID);
111 if ((type != TOKEN_NATIVE) && (type != TOKEN_SHELL)) {
112 return;
113 }
114 } else {
115 return;
116 }
117
118 if (j.find(JSON_TOKEN_ATTR) != j.end()) {
119 native.tokenAttr = j.at(JSON_TOKEN_ATTR).get<unsigned int>();
120 } else {
121 return;
122 }
123
124 if (j.find(JSON_DCAPS) != j.end()) {
125 native.dcap = j.at(JSON_DCAPS).get<std::vector<std::string>>();
126 if (native.dcap.size() > MAX_DCAPS_NUM) {
127 return;
128 }
129 } else {
130 return;
131 }
132
133 if (j.find(JSON_ACLS) != j.end()) {
134 native.nativeAcls = j.at(JSON_ACLS).get<std::vector<std::string>>();
135 if (native.nativeAcls.size() > MAX_REQ_PERM_NUM) {
136 return;
137 }
138 } else {
139 return;
140 }
141
142 std::vector<PermissionStateFull> permStateList;
143 if (NativeReqPermsGet(j, permStateList) != RET_SUCCESS) {
144 return;
145 }
146
147 p = std::make_shared<NativeTokenInfoInner>(native, permStateList);
148 }
149
ParserNativeRawData(const std::string & nativeRawData,std::vector<std::shared_ptr<NativeTokenInfoInner>> & tokenInfos)150 int32_t NativeTokenReceptor::ParserNativeRawData(const std::string& nativeRawData,
151 std::vector<std::shared_ptr<NativeTokenInfoInner>>& tokenInfos)
152 {
153 nlohmann::json jsonRes = nlohmann::json::parse(nativeRawData, nullptr, false);
154 if (jsonRes.is_discarded()) {
155 ACCESSTOKEN_LOG_ERROR(LABEL, "jsonRes is invalid.");
156 return RET_FAILED;
157 }
158 for (auto it = jsonRes.begin(); it != jsonRes.end(); it++) {
159 auto token = it->get<std::shared_ptr<NativeTokenInfoInner>>();
160 if (token != nullptr) {
161 tokenInfos.emplace_back(token);
162 }
163 }
164 return RET_SUCCESS;
165 }
166
ReadCfgFile(std::string & nativeRawData)167 int NativeTokenReceptor::ReadCfgFile(std::string& nativeRawData)
168 {
169 int32_t fd = open(NATIVE_TOKEN_CONFIG_FILE.c_str(), O_RDONLY);
170 if (fd < 0) {
171 ACCESSTOKEN_LOG_ERROR(LABEL, "open failed errno %{public}d.", errno);
172 return RET_FAILED;
173 }
174 struct stat statBuffer;
175
176 if (fstat(fd, &statBuffer) != 0) {
177 ACCESSTOKEN_LOG_ERROR(LABEL, "fstat failed.");
178 close(fd);
179 return RET_FAILED;
180 }
181
182 if (statBuffer.st_size == 0) {
183 ACCESSTOKEN_LOG_ERROR(LABEL, "config file size is invalid.");
184 close(fd);
185 return RET_FAILED;
186 }
187 if (statBuffer.st_size > MAX_NATIVE_CONFIG_FILE_SIZE) {
188 ACCESSTOKEN_LOG_ERROR(LABEL, "config file size is too large.");
189 close(fd);
190 return RET_FAILED;
191 }
192 nativeRawData.reserve(statBuffer.st_size);
193
194 char buff[BUFFER_SIZE] = { 0 };
195 ssize_t readLen = 0;
196 while ((readLen = read(fd, buff, BUFFER_SIZE)) > 0) {
197 nativeRawData.append(buff, readLen);
198 }
199 close(fd);
200
201 if (readLen == 0) {
202 return RET_SUCCESS;
203 }
204 return RET_FAILED;
205 }
206
Init()207 int NativeTokenReceptor::Init()
208 {
209 std::string nativeRawData;
210 int ret = ReadCfgFile(nativeRawData);
211 if (ret != RET_SUCCESS) {
212 ACCESSTOKEN_LOG_ERROR(LABEL, "readCfgFile failed.");
213 return RET_FAILED;
214 }
215 std::vector<std::shared_ptr<NativeTokenInfoInner>> tokenInfos;
216 ret = ParserNativeRawData(nativeRawData, tokenInfos);
217 if (ret != RET_SUCCESS) {
218 ACCESSTOKEN_LOG_ERROR(LABEL, "ParserNativeRawData failed.");
219 return RET_FAILED;
220 }
221 AccessTokenInfoManager::GetInstance().ProcessNativeTokenInfos(tokenInfos);
222
223 ACCESSTOKEN_LOG_INFO(LABEL, "init ok.");
224 return RET_SUCCESS;
225 }
226
GetInstance()227 NativeTokenReceptor& NativeTokenReceptor::GetInstance()
228 {
229 static NativeTokenReceptor instance;
230 return instance;
231 }
232 } // namespace AccessToken
233 } // namespace Security
234 } // namespace OHOS
235