• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #define LOG_TAG "AccountDelegateNormalImpl"
16 
17 #include "account_delegate_normal_impl.h"
18 
19 #include <algorithm>
20 #include <endian.h>
21 #include <regex>
22 #include <thread>
23 #include <unistd.h>
24 
25 #include "accesstoken_kit.h"
26 #include "log_print.h"
27 #include "ohos_account_kits.h"
28 #include "os_account_manager.h"
29 #include "os_account_subscribe_info.h"
30 
31 namespace OHOS {
32 namespace DistributedData {
33 using namespace OHOS::AAFwk;
34 using namespace OHOS::DistributedData;
35 using namespace Security::AccessToken;
36 __attribute__((used)) static bool g_isInit = AccountDelegateNormalImpl::Init();
37 static constexpr int32_t STOPPING_TIMEOUT = 5;
38 static inline const std::map<int32_t, AccountStatus> STATUS = {
39     { AccountSA::REMOVED, AccountStatus::DEVICE_ACCOUNT_DELETE },
40     { AccountSA::SWITCHED, AccountStatus::DEVICE_ACCOUNT_SWITCHED },
41     { AccountSA::UNLOCKED, AccountStatus::DEVICE_ACCOUNT_UNLOCKED },
42     { AccountSA::STOPPING, AccountStatus::DEVICE_ACCOUNT_STOPPING },
43     { AccountSA::STOPPED, AccountStatus::DEVICE_ACCOUNT_STOPPED }
44 };
45 
AccountSubscriber(const OsAccountSubscribeInfo & info,std::shared_ptr<ExecutorPool> executors)46 AccountSubscriber::AccountSubscriber(const OsAccountSubscribeInfo &info, std::shared_ptr<ExecutorPool> executors)
47     : OsAccountSubscriber(info), executors_(executors)
48 {
49 }
50 
OnStateChanged(const OsAccountStateData & data)51 void AccountSubscriber::OnStateChanged(const OsAccountStateData &data)
52 {
53     ZLOGI("state change. state:%{public}d, from %{public}d to %{public}d", data.state, data.fromId, data.toId);
54 
55     auto it = STATUS.find(data.state);
56     if (it == STATUS.end()) {
57         return;
58     }
59     AccountEventInfo accountEventInfo;
60     accountEventInfo.userId = std::to_string(data.toId);
61     accountEventInfo.status = it->second;
62     int32_t timeout = accountEventInfo.status == AccountStatus::DEVICE_ACCOUNT_STOPPING ? STOPPING_TIMEOUT : 0;
63     eventCallback_(accountEventInfo, timeout);
64     if (data.callback == nullptr) {
65         return;
66     }
67     if (executors_ != nullptr) {
68         executors_->Execute([callback = data.callback]() {
69             callback->OnComplete();
70         });
71     } else {
72         data.callback->OnComplete();
73     }
74 }
75 
SetEventCallback(EventCallback callback)76 void AccountSubscriber::SetEventCallback(EventCallback callback)
77 {
78     eventCallback_ = callback;
79 }
80 
AccountDelegateNormalImpl()81 AccountDelegateNormalImpl::AccountDelegateNormalImpl()
82 {
83     userDeactivating_.InsertOrAssign(0, false);
84 }
85 
GetCurrentAccountId() const86 std::string AccountDelegateNormalImpl::GetCurrentAccountId() const
87 {
88     ZLOGD("start");
89     auto ohosAccountInfo = AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
90     if (!ohosAccountInfo.first) {
91         ZLOGE("get ohosAccountInfo from OhosAccountKits is null, return default");
92         return AccountSA::DEFAULT_OHOS_ACCOUNT_UID;
93     }
94     if (ohosAccountInfo.second.uid_.empty()) {
95         ZLOGE("get ohosAccountInfo from OhosAccountKits is null, return default");
96         return AccountSA::DEFAULT_OHOS_ACCOUNT_UID;
97     }
98 
99     return Sha256AccountId(ohosAccountInfo.second.uid_);
100 }
101 
GetUserByToken(uint32_t tokenId) const102 int32_t AccountDelegateNormalImpl::GetUserByToken(uint32_t tokenId) const
103 {
104     auto type = AccessTokenKit::GetTokenTypeFlag(tokenId);
105     if (type == TOKEN_NATIVE || type == TOKEN_SHELL) {
106         return 0;
107     }
108 
109     HapTokenInfo tokenInfo;
110     auto result = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo);
111     if (result != RET_SUCCESS) {
112         ZLOGE("token:0x%{public}x, result:%{public}d", tokenId, result);
113         return -1;
114     }
115     return tokenInfo.userID;
116 }
117 
QueryUsers(std::vector<int> & users)118 bool AccountDelegateNormalImpl::QueryUsers(std::vector<int> &users)
119 {
120     users = { 0 }; // default user
121     return AccountSA::OsAccountManager::QueryActiveOsAccountIds(users) == 0;
122 }
123 
QueryForegroundUsers(std::vector<int> & users)124 bool AccountDelegateNormalImpl::QueryForegroundUsers(std::vector<int> &users)
125 {
126     std::vector<AccountSA::ForegroundOsAccount> accounts;
127     if (AccountSA::OsAccountManager::GetForegroundOsAccounts(accounts) != 0) {
128         return false;
129     }
130     for (auto &account : accounts) {
131         users.push_back(account.localId);
132     }
133     return true;
134 }
135 
IsLoginAccount()136 bool AccountDelegateNormalImpl::IsLoginAccount()
137 {
138     return GetCurrentAccountId() != AccountSA::DEFAULT_OHOS_ACCOUNT_UID;
139 }
140 
IsVerified(int userId)141 bool AccountDelegateNormalImpl::IsVerified(int userId)
142 {
143     auto [success, res] = userStatus_.Find(userId);
144     if (success && res) {
145         return true;
146     }
147     auto status = AccountSA::OsAccountManager::IsOsAccountVerified(userId, res);
148     if (status == 0) {
149         userStatus_.InsertOrAssign(userId, res);
150     }
151     return status == 0 && res;
152 }
153 
SubscribeAccountEvent()154 void AccountDelegateNormalImpl::SubscribeAccountEvent()
155 {
156     ZLOGI("Subscribe account event listener start.");
157     if (accountSubscriber_ == nullptr) {
158         std::set<OsAccountState> states;
159         states.insert(AccountSA::REMOVED);
160         states.insert(AccountSA::SWITCHED);
161         states.insert(AccountSA::UNLOCKED);
162         states.insert(AccountSA::STOPPING);
163         states.insert(AccountSA::STOPPED);
164         OsAccountSubscribeInfo info(states, true);
165         accountSubscriber_ = std::make_shared<AccountSubscriber>(info, executors_);
166         accountSubscriber_->SetEventCallback([this](AccountEventInfo &account, int32_t timeout) {
167             UpdateUserStatus(account);
168             account.harmonyAccountId = GetCurrentAccountId();
169             NotifyAccountChanged(account, timeout);
170         });
171     }
172     executors_->Execute(GetTask(0));
173 }
174 
UpdateUserStatus(const AccountEventInfo & account)175 void AccountDelegateNormalImpl::UpdateUserStatus(const AccountEventInfo &account)
176 {
177     uint32_t status = static_cast<uint32_t>(account.status);
178     switch (status) {
179         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_STOPPING):
180         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_DELETE):
181             userStatus_.Erase(atoi(account.userId.c_str()));
182             userDeactivating_.Erase(atoi(account.userId.c_str()));
183             break;
184         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_UNLOCKED):
185             userStatus_.InsertOrAssign(atoi(account.userId.c_str()), true);
186             break;
187         case static_cast<uint32_t>(AccountStatus::DEVICE_ACCOUNT_STOPPED):
188             userStatus_.InsertOrAssign(atoi(account.userId.c_str()), false);
189             break;
190         default:
191             break;
192     }
193 }
194 
GetTask(uint32_t retry)195 ExecutorPool::Task AccountDelegateNormalImpl::GetTask(uint32_t retry)
196 {
197     return [this, retry] {
198         auto result = OsAccountManager::SubscribeOsAccount(accountSubscriber_);
199         if (result == ERR_OK) {
200             ZLOGI("success to register subscriber.");
201             return;
202         }
203         ZLOGD("fail to register subscriber, error:%{public}d, time:%{public}d", result, retry);
204 
205         if (retry + 1 > MAX_RETRY_TIME) {
206             ZLOGE("fail to register subscriber!");
207             return;
208         }
209         executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1));
210     };
211 }
212 
~AccountDelegateNormalImpl()213 AccountDelegateNormalImpl::~AccountDelegateNormalImpl()
214 {
215     ZLOGD("destruct");
216     auto res = OsAccountManager::UnsubscribeOsAccount(accountSubscriber_);
217     if (res != ERR_OK) {
218         ZLOGW("unregister account event fail res:%d", res);
219     }
220 }
221 
UnsubscribeAccountEvent()222 void AccountDelegateNormalImpl::UnsubscribeAccountEvent()
223 {
224     auto res = OsAccountManager::UnsubscribeOsAccount(accountSubscriber_);
225     if (res != ERR_OK) {
226         ZLOGW("unregister account event fail res:%d", res);
227     }
228 }
229 
Sha256AccountId(const std::string & plainText) const230 std::string AccountDelegateNormalImpl::Sha256AccountId(const std::string &plainText) const
231 {
232     std::regex pattern("^[0-9]+$");
233     if (!std::regex_match(plainText, pattern)) {
234         return plainText;
235     }
236 
237     int64_t plain;
238     std::string::size_type int64MaxLen(std::to_string(INT64_MAX).size());
239     // plain text length must be less than INT64_MAX string.
240     plain = atoll(plainText.c_str());
241     if (plain == 0) {
242         return plainText;
243     }
244     if (plain == INT64_MAX) {
245         plain = atoll(plainText.substr(plainText.size() - int64MaxLen + 1, int64MaxLen - 1).c_str());
246     }
247 
248     auto plainVal = htobe64(plain);
249     return DoHash(static_cast<void *>(&plainVal), sizeof(plainVal), true);
250 }
251 
BindExecutor(std::shared_ptr<ExecutorPool> executors)252 void AccountDelegateNormalImpl::BindExecutor(std::shared_ptr<ExecutorPool> executors)
253 {
254     executors_ = executors;
255 }
256 
GetUnencryptedAccountId(int32_t userId) const257 std::string AccountDelegateNormalImpl::GetUnencryptedAccountId(int32_t userId) const
258 {
259     AccountSA::OhosAccountInfo info;
260     auto ret = AccountSA::OhosAccountKits::GetInstance().GetOsAccountDistributedInfo(userId, info);
261     if (ret != ERR_OK) {
262         ZLOGE("GetUnencryptedAccountId failed: %{public}d", ret);
263         return "";
264     }
265     return Sha256AccountId(info.GetRawUid());
266 }
267 
QueryForegroundUserId(int & foregroundUserId)268 bool AccountDelegateNormalImpl::QueryForegroundUserId(int &foregroundUserId)
269 {
270     int32_t status = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(foregroundUserId);
271     if (status != ERR_OK) {
272         ZLOGE("GetForegroundOsAccountLocalId failed, status: %{public}d", status);
273         return false;
274     }
275     return true;
276 }
277 
Init()278 bool AccountDelegateNormalImpl::Init()
279 {
280     static AccountDelegateNormalImpl normalAccountDelegate;
281     static std::once_flag onceFlag;
282     std::call_once(onceFlag, [&]() {
283         AccountDelegate::RegisterAccountInstance(&normalAccountDelegate);
284     });
285     return true;
286 }
287 
IsUserForeground(int32_t userId)288 bool AccountDelegateNormalImpl::IsUserForeground(int32_t userId)
289 {
290     bool isForeground = false;
291     if (AccountSA::OsAccountManager::IsOsAccountForeground(userId, isForeground) != 0) {
292         ZLOGE("check foreground user error, userId:%{public}d", userId);
293         return false;
294     }
295     return isForeground;
296 }
297 
IsDeactivating(int userId)298 bool AccountDelegateNormalImpl::IsDeactivating(int userId)
299 {
300     auto [success, res] = userDeactivating_.Find(userId);
301     if (success && !res) {
302         return res;
303     }
304     auto status = AccountSA::OsAccountManager::IsOsAccountDeactivating(userId, res);
305     if (status != 0) {
306         ZLOGE("IsOsAccountDeactivating failed: %{public}d, user:%{public}d", status, userId);
307         return true;
308     }
309     userDeactivating_.InsertOrAssign(userId, res);
310     return res;
311 }
312 } // namespace DistributedData
313 } // namespace OHOS