1 /*
2 * Copyright (c) 2022-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
16 #include "token_modify_notifier.h"
17
18 #include "accesstoken_callback_proxys.h"
19 #include "accesstoken_id_manager.h"
20 #include "accesstoken_info_manager.h"
21 #include "accesstoken_common_log.h"
22 #include "access_token_error.h"
23 #include "hap_token_info.h"
24 #include "hap_token_info_inner.h"
25 #include "libraryloader.h"
26 #include "token_sync_kit_loader.h"
27
28 namespace OHOS {
29 namespace Security {
30 namespace AccessToken {
31 namespace {
32 std::recursive_mutex g_instanceMutex;
33 }
34
TokenModifyNotifier()35 TokenModifyNotifier::TokenModifyNotifier() : hasInited_(false), notifyTokenWorker_("TokenModify") {}
36
~TokenModifyNotifier()37 TokenModifyNotifier::~TokenModifyNotifier()
38 {
39 if (!hasInited_) {
40 return;
41 }
42 this->notifyTokenWorker_.Stop();
43 this->hasInited_ = false;
44 }
45
AddHapTokenObservation(AccessTokenID tokenID)46 void TokenModifyNotifier::AddHapTokenObservation(AccessTokenID tokenID)
47 {
48 if (AccessTokenIDManager::GetInstance().GetTokenIdType(tokenID) != TOKEN_HAP) {
49 LOGI(ATM_DOMAIN, ATM_TAG, "Observation token is not hap token");
50 return;
51 }
52 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->listLock_);
53 if (observationSet_.count(tokenID) <= 0) {
54 observationSet_.insert(tokenID);
55 }
56 }
57
NotifyTokenDelete(AccessTokenID tokenID)58 void TokenModifyNotifier::NotifyTokenDelete(AccessTokenID tokenID)
59 {
60 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->listLock_);
61 if (observationSet_.count(tokenID) <= 0) {
62 LOGD(ATM_DOMAIN, ATM_TAG, "Hap token is not observed");
63 return;
64 }
65 observationSet_.erase(tokenID);
66 deleteTokenList_.emplace_back(tokenID);
67 NotifyTokenChangedIfNeed();
68 }
69
NotifyTokenModify(AccessTokenID tokenID)70 void TokenModifyNotifier::NotifyTokenModify(AccessTokenID tokenID)
71 {
72 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->listLock_);
73 if (observationSet_.count(tokenID) <= 0) {
74 LOGD(ATM_DOMAIN, ATM_TAG, "Hap token is not observed");
75 return;
76 }
77 modifiedTokenList_.emplace_back(tokenID);
78 NotifyTokenChangedIfNeed();
79 }
80
GetInstance()81 TokenModifyNotifier& TokenModifyNotifier::GetInstance()
82 {
83 static TokenModifyNotifier* instance = nullptr;
84 if (instance == nullptr) {
85 std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
86 if (instance == nullptr) {
87 TokenModifyNotifier* tmp = new (std::nothrow) TokenModifyNotifier();
88 instance = std::move(tmp);
89 }
90 }
91
92 if (!instance->hasInited_) {
93 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(instance->initLock_);
94 if (!instance->hasInited_) {
95 instance->notifyTokenWorker_.Start(1);
96 instance->hasInited_ = true;
97 }
98 }
99
100 return *instance;
101 }
102
NotifyTokenSyncTask()103 void TokenModifyNotifier::NotifyTokenSyncTask()
104 {
105 LOGI(ATM_DOMAIN, ATM_TAG, "Called!");
106
107 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->notifyLock_);
108 LOGI(ATM_DOMAIN, ATM_TAG, "Start execution!");
109 LibraryLoader loader(TOKEN_SYNC_LIBPATH);
110 TokenSyncKitInterface* tokenSyncKit = loader.GetObject<TokenSyncKitInterface>();
111 if (tokenSyncKit == nullptr) {
112 LOGE(ATM_DOMAIN, ATM_TAG, "Dlopen libtokensync_sdk failed.");
113 return;
114 }
115
116 std::vector<AccessTokenID> deleteList;
117 std::vector<AccessTokenID> modifiedList;
118 {
119 Utils::UniqueWriteGuard<Utils::RWLock> listGuard(this->listLock_);
120 deleteList = deleteTokenList_;
121 modifiedList = modifiedTokenList_;
122 deleteTokenList_.clear();
123 modifiedTokenList_.clear();
124 }
125
126 for (AccessTokenID deleteToken : deleteList) {
127 int ret = TOKEN_SYNC_SUCCESS;
128 if (tokenSyncCallbackObject_ != nullptr) {
129 ret = tokenSyncCallbackObject_->DeleteRemoteHapTokenInfo(deleteToken);
130 }
131 ret = tokenSyncKit->DeleteRemoteHapTokenInfo(deleteToken);
132 if (ret != TOKEN_SYNC_SUCCESS) {
133 LOGE(ATM_DOMAIN, ATM_TAG, "Fail to delete remote haptoken info, ret is %{public}d", ret);
134 }
135 }
136
137 for (AccessTokenID modifyToken : modifiedList) {
138 HapTokenInfoForSync hapSync;
139 int ret = AccessTokenInfoManager::GetInstance().GetHapTokenSync(modifyToken, hapSync);
140 if (ret != RET_SUCCESS) {
141 LOGE(ATM_DOMAIN, ATM_TAG, "The hap token 0x%{public}x need to sync is not found!", modifyToken);
142 continue;
143 }
144 if (tokenSyncCallbackObject_ != nullptr) {
145 ret = tokenSyncCallbackObject_->UpdateRemoteHapTokenInfo(hapSync);
146 }
147 ret = tokenSyncKit->UpdateRemoteHapTokenInfo(hapSync);
148 if (ret != TOKEN_SYNC_SUCCESS) {
149 LOGE(ATM_DOMAIN, ATM_TAG, "Fail to update remote haptoken info, ret is %{public}d", ret);
150 }
151 }
152
153 LOGI(ATM_DOMAIN, ATM_TAG, "Over!");
154 }
155
GetRemoteHapTokenInfo(const std::string & deviceID,AccessTokenID tokenID)156 int32_t TokenModifyNotifier::GetRemoteHapTokenInfo(const std::string& deviceID, AccessTokenID tokenID)
157 {
158 if (tokenSyncCallbackObject_ != nullptr) {
159 Utils::UniqueReadGuard<Utils::RWLock> infoGuard(this->notifyLock_);
160 int32_t ret = tokenSyncCallbackObject_->GetRemoteHapTokenInfo(deviceID, tokenID);
161 if (ret != TOKEN_SYNC_OPENSOURCE_DEVICE) {
162 return ret;
163 }
164 }
165
166 LibraryLoader loader(TOKEN_SYNC_LIBPATH);
167 TokenSyncKitInterface* tokenSyncKit = loader.GetObject<TokenSyncKitInterface>();
168 if (tokenSyncKit == nullptr) {
169 LOGE(ATM_DOMAIN, ATM_TAG, "Dlopen libtokensync_sdk failed.");
170 return ERR_LOAD_SO_FAILED;
171 }
172 return tokenSyncKit->GetRemoteHapTokenInfo(deviceID, tokenID);
173 }
174
RegisterTokenSyncCallback(const sptr<IRemoteObject> & callback)175 int32_t TokenModifyNotifier::RegisterTokenSyncCallback(const sptr<IRemoteObject>& callback)
176 {
177 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->notifyLock_);
178 tokenSyncCallbackObject_ = new (std::nothrow) TokenSyncCallbackProxy(callback);
179 tokenSyncCallbackDeathRecipient_ = sptr<TokenSyncCallbackDeathRecipient>::MakeSptr();
180 if (tokenSyncCallbackDeathRecipient_ == nullptr) {
181 return RET_FAILED;
182 }
183 callback->AddDeathRecipient(tokenSyncCallbackDeathRecipient_);
184 LOGI(ATM_DOMAIN, ATM_TAG, "Register token sync callback successful.");
185 return ERR_OK;
186 }
187
UnRegisterTokenSyncCallback()188 void TokenModifyNotifier::UnRegisterTokenSyncCallback()
189 {
190 Utils::UniqueWriteGuard<Utils::RWLock> infoGuard(this->notifyLock_);
191 if (tokenSyncCallbackObject_ != nullptr && tokenSyncCallbackDeathRecipient_ != nullptr) {
192 tokenSyncCallbackObject_->AsObject()->RemoveDeathRecipient(tokenSyncCallbackDeathRecipient_);
193 }
194 tokenSyncCallbackObject_ = nullptr;
195 tokenSyncCallbackDeathRecipient_ = nullptr;
196 LOGI(ATM_DOMAIN, ATM_TAG, "Unregister token sync callback successful.");
197 }
198
NotifyTokenChangedIfNeed()199 void TokenModifyNotifier::NotifyTokenChangedIfNeed()
200 {
201 if (notifyTokenWorker_.GetCurTaskNum() > 1) {
202 LOGI(ATM_DOMAIN, ATM_TAG, " has notify task! taskNum is %{public}zu.", notifyTokenWorker_.GetCurTaskNum());
203 return;
204 }
205
206 notifyTokenWorker_.AddTask([]() {
207 TokenModifyNotifier::GetInstance().NotifyTokenSyncTask();
208 });
209 }
210 } // namespace AccessToken
211 } // namespace Security
212 } // namespace OHOS
213