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