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 "accesstoken_id_manager.h"
17 #include <mutex>
18 #include "accesstoken_log.h"
19 #include "access_token_error.h"
20 #include "data_validator.h"
21 #include "random.h"
22 
23 namespace OHOS {
24 namespace Security {
25 namespace AccessToken {
26 namespace {
27 std::recursive_mutex g_instanceMutex;
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AccessTokenIDManager"};
29 }
30 
GetTokenIdTypeEnum(AccessTokenID id)31 ATokenTypeEnum AccessTokenIDManager::GetTokenIdTypeEnum(AccessTokenID id)
32 {
33     AccessTokenIDInner *idInner = reinterpret_cast<AccessTokenIDInner *>(&id);
34     return static_cast<ATokenTypeEnum>(idInner->type);
35 }
36 
GetTokenIdDlpFlag(AccessTokenID id)37 int AccessTokenIDManager::GetTokenIdDlpFlag(AccessTokenID id)
38 {
39     AccessTokenIDInner *idInner = reinterpret_cast<AccessTokenIDInner *>(&id);
40     return idInner->dlpFlag;
41 }
42 
GetTokenIdCloneFlag(AccessTokenID id)43 int AccessTokenIDManager::GetTokenIdCloneFlag(AccessTokenID id)
44 {
45     AccessTokenIDInner *idInner = reinterpret_cast<AccessTokenIDInner *>(&id);
46     return idInner->cloneFlag;
47 }
48 
GetTokenIdType(AccessTokenID id)49 ATokenTypeEnum AccessTokenIDManager::GetTokenIdType(AccessTokenID id)
50 {
51     {
52         Utils::UniqueReadGuard<Utils::RWLock> idGuard(this->tokenIdLock_);
53         if (tokenIdSet_.count(id) == 0) {
54             return TOKEN_INVALID;
55         }
56     }
57     return GetTokenIdTypeEnum(id);
58 }
59 
RegisterTokenId(AccessTokenID id,ATokenTypeEnum type)60 int AccessTokenIDManager::RegisterTokenId(AccessTokenID id, ATokenTypeEnum type)
61 {
62     AccessTokenIDInner *idInner = reinterpret_cast<AccessTokenIDInner *>(&id);
63     if (idInner->version != DEFAULT_TOKEN_VERSION || idInner->type != type) {
64         return ERR_PARAM_INVALID;
65     }
66 
67     Utils::UniqueWriteGuard<Utils::RWLock> idGuard(this->tokenIdLock_);
68 
69     for (std::set<AccessTokenID>::iterator it = tokenIdSet_.begin(); it != tokenIdSet_.end(); ++it) {
70         AccessTokenID tokenId = *it;
71         AccessTokenIDInner *idInnerExist = reinterpret_cast<AccessTokenIDInner *>(&tokenId);
72         if ((type == idInnerExist->type) && (idInnerExist->tokenUniqueID == idInner->tokenUniqueID)) {
73             return ERR_TOKENID_HAS_EXISTED;
74         }
75     }
76     tokenIdSet_.insert(id);
77     return RET_SUCCESS;
78 }
79 
GetHapTokenIdList(std::vector<AccessTokenID> & idList)80 void AccessTokenIDManager::GetHapTokenIdList(std::vector<AccessTokenID>& idList)
81 {
82     Utils::UniqueReadGuard<Utils::RWLock> idGuard(this->tokenIdLock_);
83 
84     for (std::set<AccessTokenID>::iterator it = tokenIdSet_.begin(); it != tokenIdSet_.end(); ++it) {
85         AccessTokenID tokenId = *it;
86         if (TOKEN_HAP == GetTokenIdTypeEnum(tokenId)) {
87             idList.emplace_back(*it);
88         }
89     }
90 }
91 
CreateTokenId(ATokenTypeEnum type,int32_t dlpFlag,int32_t cloneFlag) const92 AccessTokenID AccessTokenIDManager::CreateTokenId(ATokenTypeEnum type, int32_t dlpFlag, int32_t cloneFlag) const
93 {
94     unsigned int rand = GetRandomUint32();
95     if (rand == 0) {
96         ACCESSTOKEN_LOG_ERROR(LABEL, "Get random failed");
97         return 0;
98     }
99 
100     AccessTokenIDInner innerId = {0};
101     innerId.version = DEFAULT_TOKEN_VERSION;
102     innerId.type = type;
103     innerId.res = 0;
104     innerId.cloneFlag = static_cast<uint32_t>(cloneFlag);
105     innerId.renderFlag = 0;
106     innerId.dlpFlag = static_cast<uint32_t>(dlpFlag);
107     innerId.tokenUniqueID = rand & TOKEN_RANDOM_MASK;
108     AccessTokenID tokenId = *reinterpret_cast<AccessTokenID *>(&innerId);
109     return tokenId;
110 }
111 
CreateAndRegisterTokenId(ATokenTypeEnum type,int32_t dlpFlag,int32_t cloneFlag)112 AccessTokenID AccessTokenIDManager::CreateAndRegisterTokenId(ATokenTypeEnum type, int32_t dlpFlag, int32_t cloneFlag)
113 {
114     AccessTokenID tokenId = 0;
115     // random maybe repeat, retry twice.
116     for (int i = 0; i < MAX_CREATE_TOKEN_ID_RETRY; i++) {
117         tokenId = CreateTokenId(type, dlpFlag, cloneFlag);
118         if (tokenId == INVALID_TOKENID) {
119             ACCESSTOKEN_LOG_ERROR(LABEL, "Create tokenId failed");
120             return INVALID_TOKENID;
121         }
122 
123         int ret = RegisterTokenId(tokenId, type);
124         if (ret == RET_SUCCESS) {
125             break;
126         } else if (i < MAX_CREATE_TOKEN_ID_RETRY - 1) {
127             ACCESSTOKEN_LOG_WARN(LABEL, "Reigster tokenId failed, maybe repeat, retry");
128         } else {
129             ACCESSTOKEN_LOG_ERROR(LABEL, "Reigster tokenId finally failed");
130             tokenId = INVALID_TOKENID;
131         }
132     }
133     return tokenId;
134 }
135 
ReleaseTokenId(AccessTokenID id)136 void AccessTokenIDManager::ReleaseTokenId(AccessTokenID id)
137 {
138     Utils::UniqueWriteGuard<Utils::RWLock> idGuard(this->tokenIdLock_);
139     if (tokenIdSet_.count(id) == 0) {
140         ACCESSTOKEN_LOG_INFO(LABEL, "Id %{public}x is not exist", id);
141         return;
142     }
143     tokenIdSet_.erase(id);
144 }
145 
GetInstance()146 AccessTokenIDManager& AccessTokenIDManager::GetInstance()
147 {
148     static AccessTokenIDManager* instance = nullptr;
149     if (instance == nullptr) {
150         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
151         if (instance == nullptr) {
152             instance = new AccessTokenIDManager();
153         }
154     }
155     return *instance;
156 }
157 } // namespace AccessToken
158 } // namespace Security
159 } // namespace OHOS
160