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 
16 #include "permission_definition_cache.h"
17 
18 #include "access_token.h"
19 #include "access_token_error.h"
20 #include "accesstoken_log.h"
21 #include "generic_values.h"
22 #include "token_field_const.h"
23 
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 static const int32_t EXTENSION_PERMISSION_ID = 0;
29 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
30     LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "PermissionDefinitionCache"
31 };
32 std::recursive_mutex g_instanceMutex;
33 }
34 
GetInstance()35 PermissionDefinitionCache& PermissionDefinitionCache::GetInstance()
36 {
37     static PermissionDefinitionCache* instance = nullptr;
38     if (instance == nullptr) {
39         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
40         if (instance == nullptr) {
41             instance = new PermissionDefinitionCache();
42         }
43     }
44     return *instance;
45 }
46 
PermissionDefinitionCache()47 PermissionDefinitionCache::PermissionDefinitionCache()
48 {}
49 
~PermissionDefinitionCache()50 PermissionDefinitionCache::~PermissionDefinitionCache()
51 {}
52 
Insert(const PermissionDef & info,AccessTokenID tokenId)53 bool PermissionDefinitionCache::Insert(const PermissionDef& info, AccessTokenID tokenId)
54 {
55     Utils::UniqueWriteGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
56     auto it = permissionDefinitionMap_.find(info.permissionName);
57     if (it != permissionDefinitionMap_.end()) {
58         ACCESSTOKEN_LOG_DEBUG(LABEL, "Info for permission: %{public}s has been insert, please check!",
59             info.permissionName.c_str());
60         return false;
61     }
62     permissionDefinitionMap_[info.permissionName].permDef = info;
63     permissionDefinitionMap_[info.permissionName].tokenId = tokenId;
64     if (!hasHapPermissionDefinition_ && (tokenId != EXTENSION_PERMISSION_ID)) {
65         hasHapPermissionDefinition_ = true;
66     }
67     return true;
68 }
69 
Update(const PermissionDef & info,AccessTokenID tokenId)70 bool PermissionDefinitionCache::Update(const PermissionDef& info, AccessTokenID tokenId)
71 {
72     Utils::UniqueWriteGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
73     permissionDefinitionMap_[info.permissionName].permDef = info;
74     permissionDefinitionMap_[info.permissionName].tokenId = tokenId;
75     return true;
76 }
77 
DeleteByToken(AccessTokenID tokenId)78 void PermissionDefinitionCache::DeleteByToken(AccessTokenID tokenId)
79 {
80     Utils::UniqueWriteGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
81     auto it = permissionDefinitionMap_.begin();
82     while (it != permissionDefinitionMap_.end()) {
83         if (tokenId == it->second.tokenId) {
84             it = permissionDefinitionMap_.erase(it);
85         } else {
86             ++it;
87         }
88     }
89 }
90 
FindByPermissionName(const std::string & permissionName,PermissionDef & info)91 int PermissionDefinitionCache::FindByPermissionName(const std::string& permissionName, PermissionDef& info)
92 {
93     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
94     auto it = permissionDefinitionMap_.find(permissionName);
95     if (it == permissionDefinitionMap_.end()) {
96         ACCESSTOKEN_LOG_ERROR(LABEL, "Can not find definition info for permission: %{public}s",
97             permissionName.c_str());
98         return AccessTokenError::ERR_PERMISSION_NOT_EXIST;
99     }
100     info = it->second.permDef;
101     return RET_SUCCESS;
102 }
103 
IsSystemGrantedPermission(const std::string & permissionName)104 bool PermissionDefinitionCache::IsSystemGrantedPermission(const std::string& permissionName)
105 {
106     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
107     return IsGrantedModeEqualInner(permissionName, SYSTEM_GRANT);
108 }
109 
IsUserGrantedPermission(const std::string & permissionName)110 bool PermissionDefinitionCache::IsUserGrantedPermission(const std::string& permissionName)
111 {
112     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
113     return IsGrantedModeEqualInner(permissionName, USER_GRANT);
114 }
115 
IsGrantedModeEqualInner(const std::string & permissionName,int grantMode) const116 bool PermissionDefinitionCache::IsGrantedModeEqualInner(const std::string& permissionName, int grantMode) const
117 {
118     auto it = permissionDefinitionMap_.find(permissionName);
119     if (it == permissionDefinitionMap_.end()) {
120         return false;
121     }
122     return it->second.permDef.grantMode == grantMode;
123 }
124 
HasDefinition(const std::string & permissionName)125 bool PermissionDefinitionCache::HasDefinition(const std::string& permissionName)
126 {
127     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
128     auto it = permissionDefinitionMap_.find(permissionName);
129     if (it != permissionDefinitionMap_.end()) {
130         return true;
131     }
132     return false;
133 }
134 
HasHapPermissionDefinitionForHap(const std::string & permissionName)135 bool PermissionDefinitionCache::HasHapPermissionDefinitionForHap(const std::string& permissionName)
136 {
137     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
138     auto it = permissionDefinitionMap_.find(permissionName);
139     if ((it != permissionDefinitionMap_.end()) && (it->second.tokenId != EXTENSION_PERMISSION_ID)) {
140         return true;
141     }
142     return false;
143 }
144 
IsHapPermissionDefEmpty()145 bool PermissionDefinitionCache::IsHapPermissionDefEmpty()
146 {
147     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
148     return !hasHapPermissionDefinition_;
149 }
150 
StorePermissionDef(std::vector<GenericValues> & valueList)151 void PermissionDefinitionCache::StorePermissionDef(std::vector<GenericValues>& valueList)
152 {
153     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
154     auto it = permissionDefinitionMap_.begin();
155     while (it != permissionDefinitionMap_.end()) {
156         GenericValues genericValues;
157         genericValues.Put(TokenFiledConst::FIELD_TOKEN_ID, static_cast<int32_t>(it->second.tokenId));
158         DataTranslator::TranslationIntoGenericValues(it->second.permDef, genericValues);
159         valueList.emplace_back(genericValues);
160         ++it;
161     }
162 }
163 
StorePermissionDef(AccessTokenID tokenID,std::vector<GenericValues> & valueList)164 void PermissionDefinitionCache::StorePermissionDef(AccessTokenID tokenID, std::vector<GenericValues>& valueList)
165 {
166     Utils::UniqueWriteGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
167     auto it = permissionDefinitionMap_.begin();
168     while (it != permissionDefinitionMap_.end()) {
169         if (tokenID == it->second.tokenId) {
170             GenericValues genericValues;
171             genericValues.Put(TokenFiledConst::FIELD_TOKEN_ID, static_cast<int32_t>(it->second.tokenId));
172             DataTranslator::TranslationIntoGenericValues(it->second.permDef, genericValues);
173             valueList.emplace_back(genericValues);
174         }
175         ++it;
176     }
177 }
178 
GetDefPermissionsByTokenId(std::vector<PermissionDef> & permList,AccessTokenID tokenId)179 void PermissionDefinitionCache::GetDefPermissionsByTokenId(std::vector<PermissionDef>& permList,
180     AccessTokenID tokenId)
181 {
182     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
183     auto it = permissionDefinitionMap_.begin();
184     while (it != permissionDefinitionMap_.end()) {
185         if (tokenId == it->second.tokenId) {
186             permList.emplace_back(it->second.permDef);
187         }
188         ++it;
189     }
190 }
191 
RestorePermDefInfo(std::vector<GenericValues> & permDefRes)192 int32_t PermissionDefinitionCache::RestorePermDefInfo(std::vector<GenericValues>& permDefRes)
193 {
194     for (const GenericValues& defValue : permDefRes) {
195         PermissionDef def;
196         AccessTokenID tokenId = (AccessTokenID)defValue.GetInt(TokenFiledConst::FIELD_TOKEN_ID);
197         int32_t ret = DataTranslator::TranslationIntoPermissionDef(defValue, def);
198         if (ret != RET_SUCCESS) {
199             ACCESSTOKEN_LOG_ERROR(LABEL, "TokenId 0x%{public}x permDef is wrong.", tokenId);
200             return ret;
201         }
202         Insert(def, tokenId);
203     }
204     return RET_SUCCESS;
205 }
206 
GetDefPermissionsSize()207 uint32_t PermissionDefinitionCache::GetDefPermissionsSize()
208 {
209     Utils::UniqueReadGuard<Utils::RWLock> cacheGuard(this->cacheLock_);
210     return static_cast<uint32_t>(permissionDefinitionMap_.size());
211 }
212 } // namespace AccessToken
213 } // namespace Security
214 } // namespace OHOS
215