1 /*
2  * Copyright (c) 2021-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 "permission_validator.h"
16 
17 #include <set>
18 
19 #include "access_token.h"
20 #include "accesstoken_log.h"
21 #include "data_validator.h"
22 #include "permission_definition_cache.h"
23 
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermissionValidator"};
29 }
30 
IsGrantModeValid(int grantMode)31 bool PermissionValidator::IsGrantModeValid(int grantMode)
32 {
33     return grantMode == GrantMode::SYSTEM_GRANT || grantMode == GrantMode::USER_GRANT;
34 }
35 
IsGrantStatusValid(int grantStatus)36 bool PermissionValidator::IsGrantStatusValid(int grantStatus)
37 {
38     return grantStatus == PermissionState::PERMISSION_GRANTED || grantStatus == PermissionState::PERMISSION_DENIED;
39 }
40 
IsPermissionFlagValid(uint32_t flag)41 bool PermissionValidator::IsPermissionFlagValid(uint32_t flag)
42 {
43     return DataValidator::IsPermissionFlagValid(flag);
44 }
45 
IsPermissionNameValid(const std::string & permissionName)46 bool PermissionValidator::IsPermissionNameValid(const std::string& permissionName)
47 {
48     return DataValidator::IsPermissionNameValid(permissionName);
49 }
50 
IsUserIdValid(const int32_t userID)51 bool PermissionValidator::IsUserIdValid(const int32_t userID)
52 {
53     return DataValidator::IsUserIdValid(userID);
54 }
55 
IsToggleStatusValid(const uint32_t status)56 bool PermissionValidator::IsToggleStatusValid(const uint32_t status)
57 {
58     return DataValidator::IsToggleStatusValid(status);
59 }
60 
IsPermissionDefValid(const PermissionDef & permDef)61 bool PermissionValidator::IsPermissionDefValid(const PermissionDef& permDef)
62 {
63     if (!DataValidator::IsLabelValid(permDef.label)) {
64         ACCESSTOKEN_LOG_ERROR(LABEL, "Label invalid.");
65         return false;
66     }
67     if (!DataValidator::IsDescValid(permDef.description)) {
68         ACCESSTOKEN_LOG_ERROR(LABEL, "Desc invalid.");
69         return false;
70     }
71     if (!DataValidator::IsBundleNameValid(permDef.bundleName)) {
72         ACCESSTOKEN_LOG_ERROR(LABEL, "BundleName invalid.");
73         return false;
74     }
75     if (!DataValidator::IsPermissionNameValid(permDef.permissionName)) {
76         ACCESSTOKEN_LOG_ERROR(LABEL, "PermissionName invalid.");
77         return false;
78     }
79     if (!IsGrantModeValid(permDef.grantMode)) {
80         ACCESSTOKEN_LOG_ERROR(LABEL, "GrantMode invalid.");
81         return false;
82     }
83     if (!DataValidator::IsAvailableTypeValid(permDef.availableType)) {
84         ACCESSTOKEN_LOG_ERROR(LABEL, "AvailableType invalid.");
85         return false;
86     }
87     if (!DataValidator::IsAplNumValid(permDef.availableLevel)) {
88         ACCESSTOKEN_LOG_ERROR(LABEL, "AvailableLevel invalid.");
89         return false;
90     }
91     return true;
92 }
93 
IsPermissionAvailable(ATokenTypeEnum tokenType,const std::string & permissionName)94 bool PermissionValidator::IsPermissionAvailable(ATokenTypeEnum tokenType, const std::string& permissionName)
95 {
96     ACCESSTOKEN_LOG_DEBUG(LABEL, "TokenType is %{public}d.", tokenType);
97     if (tokenType == TOKEN_HAP) {
98         if (!PermissionDefinitionCache::GetInstance().HasHapPermissionDefinitionForHap(permissionName)) {
99             ACCESSTOKEN_LOG_ERROR(LABEL, "%{public}s is not defined for hap.", permissionName.c_str());
100             return false;
101         }
102     }
103     // permission request for TOKEN_NATIVE process is going to be check when the permission request way is normalized.
104     return true;
105 }
106 
IsPermissionStateValid(const PermissionStateFull & permState)107 bool PermissionValidator::IsPermissionStateValid(const PermissionStateFull& permState)
108 {
109     if (!DataValidator::IsPermissionNameValid(permState.permissionName)) {
110         return false;
111     }
112     size_t resDevIdSize = permState.resDeviceID.size();
113     size_t grantStatSize = permState.grantStatus.size();
114     size_t grantFlagSize = permState.grantFlags.size();
115     if ((grantStatSize != resDevIdSize) || (grantFlagSize != resDevIdSize)) {
116         ACCESSTOKEN_LOG_ERROR(LABEL,
117             "list size is invalid, grantStatSize %{public}zu, grantFlagSize %{public}zu, resDevIdSize %{public}zu.",
118             grantStatSize, grantFlagSize, resDevIdSize);
119         return false;
120     }
121     for (uint32_t i = 0; i < resDevIdSize; i++) {
122         if (!IsGrantStatusValid(permState.grantStatus[i]) ||
123             !IsPermissionFlagValid(permState.grantFlags[i])) {
124             ACCESSTOKEN_LOG_ERROR(LABEL, "GrantStatus or grantFlags is invalid");
125             return false;
126         }
127     }
128     return true;
129 }
130 
FilterInvalidPermissionDef(const std::vector<PermissionDef> & permList,std::vector<PermissionDef> & result)131 void PermissionValidator::FilterInvalidPermissionDef(
132     const std::vector<PermissionDef>& permList, std::vector<PermissionDef>& result)
133 {
134     std::set<std::string> permDefSet;
135     for (auto it = permList.begin(); it != permList.end(); ++it) {
136         std::string permName = it->permissionName;
137         if (!IsPermissionDefValid(*it) || permDefSet.count(permName) != 0) {
138             continue;
139         }
140         permDefSet.insert(permName);
141         result.emplace_back(*it);
142     }
143 }
144 
DeduplicateResDevID(const PermissionStateFull & permState,PermissionStateFull & result)145 void PermissionValidator::DeduplicateResDevID(const PermissionStateFull& permState, PermissionStateFull& result)
146 {
147     std::set<std::string> resDevId;
148     auto stateIter = permState.grantStatus.begin();
149     auto flagIter = permState.grantFlags.begin();
150     for (auto it = permState.resDeviceID.begin(); it != permState.resDeviceID.end(); ++it, ++stateIter, ++flagIter) {
151         if (resDevId.count(*it) != 0) {
152             continue;
153         }
154         resDevId.insert(*it);
155         result.resDeviceID.emplace_back(*it);
156         result.grantStatus.emplace_back(*stateIter);
157         result.grantFlags.emplace_back(*flagIter);
158     }
159     result.permissionName = permState.permissionName;
160     result.isGeneral = permState.isGeneral;
161 }
162 
FilterInvalidPermissionState(ATokenTypeEnum tokenType,bool doPermAvailableCheck,const std::vector<PermissionStateFull> & permList,std::vector<PermissionStateFull> & result)163 void PermissionValidator::FilterInvalidPermissionState(ATokenTypeEnum tokenType, bool doPermAvailableCheck,
164     const std::vector<PermissionStateFull>& permList, std::vector<PermissionStateFull>& result)
165 {
166     std::set<std::string> permStateSet;
167     for (auto it = permList.begin(); it != permList.end(); ++it) {
168         std::string permName = it->permissionName;
169         PermissionStateFull res;
170         if (!IsPermissionStateValid(*it) || permStateSet.count(permName) != 0) {
171             continue;
172         }
173         if (doPermAvailableCheck && !IsPermissionAvailable(tokenType, permName)) {
174             continue;
175         }
176         DeduplicateResDevID(*it, res);
177         permStateSet.insert(permName);
178         result.emplace_back(res);
179     }
180 }
181 } // namespace AccessToken
182 } // namespace Security
183 } // namespace OHOS
184