• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "ohos_account_manager.h"
17 #include <cerrno>
18 #include <dirent.h>
19 #include <iomanip>
20 #include <sstream>
21 #include <sys/types.h>
22 #include "account_event_provider.h"
23 #include "account_event_subscribe.h"
24 #include "account_helper_data.h"
25 #include "account_info.h"
26 #include "account_log_wrapper.h"
27 #include "account_mgr_service.h"
28 #ifdef HAS_CES_PART
29 #include "common_event_support.h"
30 #endif // HAS_CES_PART
31 #include "hisysevent_adapter.h"
32 #include "ipc_skeleton.h"
33 #include "mbedtls/sha256.h"
34 #include "system_ability_definition.h"
35 
36 #ifdef HAS_CES_PART
37 using namespace OHOS::EventFwk;
38 #endif // HAS_CES_PART
39 
40 namespace OHOS {
41 namespace AccountSA {
42 namespace {
43 constexpr std::int32_t MAX_RETRY_TIMES = 2; // give another chance when json file corrupted
44 constexpr std::uint32_t MAX_NAME_LENGTH = 256;
45 constexpr std::uint32_t MAX_UID_LENGTH = 512;
46 constexpr std::uint32_t HASH_LENGTH = 32;
47 constexpr std::uint32_t OHOS_ACCOUNT_UDID_LENGTH = HASH_LENGTH * 2;
48 constexpr std::uint32_t WIDTH_FOR_HEX = 2;
49 const std::string KEY_ACCOUNT_EVENT_LOGIN = "LOGIN";
50 const std::string KEY_ACCOUNT_EVENT_LOGOUT = "LOGOUT";
51 const std::string KEY_ACCOUNT_EVENT_TOKEN_INVALID = "TOKEN_INVALID";
52 const std::string KEY_ACCOUNT_EVENT_LOGOFF = "LOGOFF";
53 
GetAccountEventStr(const std::map<std::string,std::string> & accountEventMap,const std::string & eventKey,const std::string & defaultValue)54 std::string GetAccountEventStr(const std::map<std::string, std::string> &accountEventMap,
55     const std::string &eventKey, const std::string &defaultValue)
56 {
57     const auto &it = accountEventMap.find(eventKey);
58     if (it != accountEventMap.end()) {
59         return it->second;
60     }
61     return defaultValue;
62 }
63 
GenerateOhosUdidWithSha256(const std::string & name,const std::string & uid)64 std::string GenerateOhosUdidWithSha256(const std::string &name, const std::string &uid)
65 {
66     if (name.empty() || name.length() > MAX_NAME_LENGTH) {
67         ACCOUNT_LOGE("input name empty or too long, length %{public}zu", name.length());
68         return std::string("");
69     }
70 
71     if (uid.empty() || uid.length() > MAX_UID_LENGTH) {
72         ACCOUNT_LOGE("input uid empty or too long, length %{public}zu", uid.length());
73         return std::string("");
74     }
75 
76     unsigned char hash[HASH_LENGTH] = { 0 };
77     mbedtls_sha256_context context;
78     mbedtls_sha256_init(&context);
79     mbedtls_sha256_starts(&context, 0);
80 
81     std::string plainStr = uid;
82     mbedtls_sha256_update(&context, reinterpret_cast<const unsigned char*>(plainStr.c_str()), plainStr.length());
83     mbedtls_sha256_finish(&context, hash);
84     mbedtls_sha256_free(&context);
85 
86     std::stringstream ss;
87     for (std::uint32_t i = 0; i < HASH_LENGTH; ++i) {
88         ss << std::hex << std::uppercase << std::setw(WIDTH_FOR_HEX) << std::setfill('0') << std::uint16_t(hash[i]);
89     }
90 
91     std::string ohosUidStr;
92     ss >> ohosUidStr;
93     return ohosUidStr;
94 }
95 }
96 
97 /**
98  * Ohos account state change.
99  *
100  * @param name ohos account name
101  * @param uid ohos account uid
102  * @param eventStr ohos account state change event
103  * @return true if the processing was completed, otherwise false
104  */
OhosAccountStateChange(const std::string & name,const std::string & uid,const std::string & eventStr)105 bool OhosAccountManager::OhosAccountStateChange(const std::string &name, const std::string &uid,
106     const std::string &eventStr)
107 {
108     auto itFunc = eventFuncMap_.find(eventStr);
109     if (itFunc == eventFuncMap_.end()) {
110         ACCOUNT_LOGE("invalid event: %{public}s", eventStr.c_str());
111         return false;
112     }
113     OhosAccountInfo ohosAccountInfo;
114     ohosAccountInfo.name_ = name;
115     ohosAccountInfo.uid_ = uid;
116     std::int32_t userId = AccountMgrService::GetInstance().GetCallingUserID();
117     return (this->*(itFunc->second))(userId, ohosAccountInfo, eventStr);
118 }
119 
OhosAccountStateChange(const int32_t userId,const OhosAccountInfo & ohosAccountInfo,const std::string & eventStr)120 bool OhosAccountManager::OhosAccountStateChange(
121     const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)
122 {
123     auto itFunc = eventFuncMap_.find(eventStr);
124     if (itFunc == eventFuncMap_.end()) {
125         ACCOUNT_LOGE("invalid event: %{public}s", eventStr.c_str());
126         return false;
127     }
128     return (this->*(itFunc->second))(userId, ohosAccountInfo, eventStr);
129 }
130 
131 /**
132  * Clear current account information
133  */
ClearOhosAccount(AccountInfo & curOhosAccountInfo,std::int32_t clrStatus) const134 bool OhosAccountManager::ClearOhosAccount(AccountInfo &curOhosAccountInfo, std::int32_t clrStatus) const
135 {
136     curOhosAccountInfo.clear(clrStatus);
137     ErrCode errCode = dataDealer_->AccountInfoToJson(curOhosAccountInfo);
138     if (errCode != ERR_OK) {
139         ACCOUNT_LOGE("AccountInfoToJson error");
140         return false;
141     }
142     return true;
143 }
144 
145 /**
146  * Config current account config.
147  *
148  * @param ohosAccountInfo distribute account information.
149  * @return true if success.
150  */
SaveOhosAccountInfo(AccountInfo & ohosAccountInfo) const151 bool OhosAccountManager::SaveOhosAccountInfo(AccountInfo &ohosAccountInfo) const
152 {
153     ErrCode errCode = dataDealer_->AccountInfoToJson(ohosAccountInfo);
154     if (errCode != ERR_OK) {
155         ACCOUNT_LOGE("AccountInfoToJson error.");
156         return false;
157     }
158     return true;
159 }
160 
161 /**
162  * Get current account information.
163  *
164  * @return current account information.
165  */
GetCurrentOhosAccountInfo()166 AccountInfo OhosAccountManager::GetCurrentOhosAccountInfo()
167 {
168     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
169 
170     AccountInfo currOhosAccountInfo;
171     std::int32_t callingUserId = AccountMgrService::GetInstance().GetCallingUserID();
172     if (dataDealer_->AccountInfoFromJson(currOhosAccountInfo, callingUserId) != ERR_OK) {
173         ACCOUNT_LOGE("get current ohos account info failed, callingUserId %{public}d.", callingUserId);
174         currOhosAccountInfo.clear();
175     }
176     return currOhosAccountInfo;
177 }
178 
GetAccountInfoByUserId(std::int32_t userId,AccountInfo & info)179 ErrCode OhosAccountManager::GetAccountInfoByUserId(std::int32_t userId, AccountInfo &info)
180 {
181     if (userId == 0) {
182         userId = AccountMgrService::GetInstance().GetCallingUserID();
183     }
184     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
185 
186     ErrCode ret = dataDealer_->AccountInfoFromJson(info, userId);
187     if (ret != ERR_OK) {
188         ACCOUNT_LOGE("get ohos account info failed, userId %{public}d.", userId);
189         info.clear();
190         return ret;
191     }
192     return ERR_OK;
193 }
194 
195 /**
196  * Get current account state.
197  *
198  * @return current account state id.
199  */
GetCurrentOhosAccountState()200 std::int32_t OhosAccountManager::GetCurrentOhosAccountState()
201 {
202     AccountInfo currOhosAccountInfo = GetCurrentOhosAccountInfo();
203     return currOhosAccountInfo.ohosAccountInfo_.status_;
204 }
205 
206 /**
207  * Process an account event.
208  * @param curOhosAccount current ohos account info
209  * @param eventStr ohos account state change event
210  * @return true if the processing was completed, otherwise false
211  */
HandleEvent(AccountInfo & curOhosAccount,const std::string & eventStr)212 bool OhosAccountManager::HandleEvent(AccountInfo &curOhosAccount, const std::string &eventStr)
213 {
214     auto iter = eventMap_.find(eventStr);
215     if (iter == eventMap_.end()) {
216         ACCOUNT_LOGE("invalid event: %{public}s", eventStr.c_str());
217         return false;
218     }
219     int event = iter->second;
220     accountState_->SetAccountState(curOhosAccount.ohosAccountInfo_.status_);
221     bool ret = accountState_->StateChangeProcess(event);
222     if (!ret) {
223         ACCOUNT_LOGE("Handle event %{public}d failed", event);
224         return false;
225     }
226     std::int32_t newState = accountState_->GetAccountState();
227     if (newState != curOhosAccount.ohosAccountInfo_.status_) {
228         ReportOhosAccountStateChange(curOhosAccount.userId_, event, curOhosAccount.ohosAccountInfo_.status_, newState);
229         curOhosAccount.ohosAccountInfo_.status_ = newState;
230     }
231     return true;
232 }
233 
234 /**
235  * login ohos (for distributed network) account.
236  *
237  * @param userId target local account id.
238  * @param ohosAccountInfo ohos account information
239  * @param eventStr ohos account state change event
240  * @return true if the processing was completed, otherwise false
241  */
LoginOhosAccount(const int32_t userId,const OhosAccountInfo & ohosAccountInfo,const std::string & eventStr)242 bool OhosAccountManager::LoginOhosAccount(
243     const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)
244 {
245     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
246 
247     AccountInfo currAccountInfo;
248     if (dataDealer_->AccountInfoFromJson(currAccountInfo, userId) != ERR_OK) {
249         ACCOUNT_LOGE("get current ohos account info failed, userId %{public}d.", userId);
250         return false;
251     }
252     std::string ohosAccountUid = GenerateOhosUdidWithSha256(ohosAccountInfo.name_, ohosAccountInfo.uid_);
253     // current local user cannot be bound again when it has already been bound to an ohos account
254     if (!CheckOhosAccountCanBind(currAccountInfo, ohosAccountInfo, ohosAccountUid)) {
255         ACCOUNT_LOGE("check can be bound failed, userId %{public}d.", userId);
256         return false;
257     }
258 
259 #ifdef HAS_CES_PART
260     // check whether need to publish event or not
261     bool isPubLoginEvent = false;
262     if (currAccountInfo.ohosAccountInfo_.status_ != ACCOUNT_STATE_LOGIN) {
263         isPubLoginEvent = true;
264     }
265 #endif // HAS_CES_PART
266     // update account status
267     if (!HandleEvent(currAccountInfo, eventStr)) {
268         ACCOUNT_LOGE("HandleEvent %{public}s failed! userId %{public}d.", eventStr.c_str(), userId);
269         return false;
270     }
271 
272     // update account info
273     currAccountInfo.ohosAccountInfo_ = ohosAccountInfo;
274     currAccountInfo.ohosAccountInfo_.SetRawUid(ohosAccountInfo.uid_);
275     currAccountInfo.ohosAccountInfo_.uid_ = ohosAccountUid;
276     currAccountInfo.ohosAccountInfo_.status_ = ACCOUNT_STATE_LOGIN;
277     currAccountInfo.bindTime_ = std::time(nullptr);
278     currAccountInfo.ohosAccountInfo_.callingUid_ = IPCSkeleton::GetCallingUid();
279 
280     if (!SaveOhosAccountInfo(currAccountInfo)) {
281         ACCOUNT_LOGE("SaveOhosAccountInfo failed! userId %{public}d.", userId);
282         return false;
283     }
284 
285 #ifdef HAS_CES_PART
286     if (!isPubLoginEvent) {
287         AccountEventProvider::EventPublish(EventFwk::CommonEventSupport::COMMON_EVENT_USER_INFO_UPDATED,
288             userId, nullptr);
289         (void)CreateCommonEventSubscribe();
290         return true;
291     }
292     AccountEventProvider::EventPublish(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGIN, userId, nullptr);
293     AccountEventProvider::EventPublish(
294         EventFwk::CommonEventSupport::COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGIN, userId, nullptr);
295 #else  // HAS_CES_PART
296     ACCOUNT_LOGI("No common event part, publish nothing!");
297 #endif // HAS_CES_PART
298     (void)CreateCommonEventSubscribe();
299     ACCOUNT_LOGI("LoginOhosAccount success! userId %{public}d", userId);
300     return true;
301 }
302 
303 /**
304  * logout ohos (for distributed network) account.
305  *
306  * @param userId target local account id.
307  * @param ohosAccountInfo ohos account information
308  * @param eventStr ohos account state change event
309  * @return true if the processing was completed, otherwise false
310  */
LogoutOhosAccount(const int32_t userId,const OhosAccountInfo & ohosAccountInfo,const std::string & eventStr)311 bool OhosAccountManager::LogoutOhosAccount(
312     const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)
313 {
314     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
315 
316     AccountInfo currentAccount;
317     if (!GetCurOhosAccountAndCheckMatch(currentAccount, ohosAccountInfo.name_,
318                                         ohosAccountInfo.uid_, userId)) {
319         ACCOUNT_LOGE("check match failed, userId %{public}d.", userId);
320         return false;
321     }
322 
323     bool ret = HandleEvent(currentAccount, eventStr); // update account status
324     if (!ret) {
325         ACCOUNT_LOGE("HandleEvent %{public}s failed, userId %{public}d.", eventStr.c_str(), userId);
326         return false;
327     }
328 
329     ret = ClearOhosAccount(currentAccount); // clear account info with ACCOUNT_STATE_UNBOUND
330     if (!ret) {
331         ACCOUNT_LOGE("ClearOhosAccount failed! userId %{public}d.", userId);
332         return false;
333     }
334 
335 #ifdef HAS_CES_PART
336     AccountEventProvider::EventPublish(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGOUT, userId, nullptr);
337     AccountEventProvider::EventPublish(
338         EventFwk::CommonEventSupport::COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT, userId, nullptr);
339 #else  // HAS_CES_PART
340     ACCOUNT_LOGI("No common event part! Publish nothing!");
341 #endif // HAS_CES_PART
342     ACCOUNT_LOGI("LogoutOhosAccount success, userId %{public}d.", userId);
343     return true;
344 }
345 
346 /**
347  * logoff ohos (for distributed network) account.
348  *
349  * @param userId target local account id.
350  * @param ohosAccountInfo ohos account information
351  * @param eventStr ohos account state change event
352  * @return true if the processing was completed, otherwise false
353  */
LogoffOhosAccount(const int32_t userId,const OhosAccountInfo & ohosAccountInfo,const std::string & eventStr)354 bool OhosAccountManager::LogoffOhosAccount(
355     const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)
356 {
357     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
358 
359     AccountInfo currentAccount;
360     if (!GetCurOhosAccountAndCheckMatch(currentAccount, ohosAccountInfo.name_, ohosAccountInfo.uid_, userId)) {
361         ACCOUNT_LOGE("check match failed, userId %{public}d.", userId);
362         return false;
363     }
364 
365     bool ret = HandleEvent(currentAccount, eventStr); // update account status
366     if (!ret) {
367         ACCOUNT_LOGE("HandleEvent %{public}s failed, userId %{public}d.", eventStr.c_str(), userId);
368         return false;
369     }
370 
371     ret = ClearOhosAccount(currentAccount); // clear account info with ACCOUNT_STATE_UNBOUND
372     if (!ret) {
373         ACCOUNT_LOGE("ClearOhosAccount failed, userId %{public}d.", userId);
374         return false;
375     }
376 #ifdef HAS_CES_PART
377     AccountEventProvider::EventPublish(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGOFF, userId, nullptr);
378     AccountEventProvider::EventPublish(
379         EventFwk::CommonEventSupport::COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOFF, userId, nullptr);
380 #else  // HAS_CES_PART
381     ACCOUNT_LOGI("No common event part, publish nothing for logoff!");
382 #endif // HAS_CES_PART
383     ACCOUNT_LOGI("LogoffOhosAccount success, userId %{public}d.", userId);
384     return true;
385 }
386 
387 /**
388  * Handle token_invalid event.
389  *
390  * @param userId target local account id.
391  * @param ohosAccountInfo ohos account information
392  * @param eventStr ohos account state change event
393  * @return true if the processing was completed, otherwise false
394  */
HandleOhosAccountTokenInvalidEvent(const int32_t userId,const OhosAccountInfo & ohosAccountInfo,const std::string & eventStr)395 bool OhosAccountManager::HandleOhosAccountTokenInvalidEvent(
396     const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)
397 {
398     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
399 
400     AccountInfo currentOhosAccount;
401     if (!GetCurOhosAccountAndCheckMatch(currentOhosAccount, ohosAccountInfo.name_,
402                                         ohosAccountInfo.uid_, userId)) {
403         ACCOUNT_LOGE("check match failed, userId %{public}d.", userId);
404         return false;
405     }
406 
407     bool ret = HandleEvent(currentOhosAccount, eventStr); // update account status
408     if (!ret) {
409         ACCOUNT_LOGE("HandleEvent %{public}s failed, userId %{public}d.", eventStr.c_str(), userId);
410         return false;
411     }
412 
413     ret = SaveOhosAccountInfo(currentOhosAccount);
414     if (!ret) {
415         // moving on even if failed to update account info
416         ACCOUNT_LOGW("SaveOhosAccountInfo failed, userId %{public}d.", userId);
417     }
418 #ifdef HAS_CES_PART
419     AccountEventProvider::EventPublish(EventFwk::CommonEventSupport::COMMON_EVENT_HWID_TOKEN_INVALID,
420         userId, nullptr);
421     AccountEventProvider::EventPublish(
422         EventFwk::CommonEventSupport::COMMON_EVENT_DISTRIBUTED_ACCOUNT_TOKEN_INVALID, userId, nullptr);
423 #else  // HAS_CES_PART
424     ACCOUNT_LOGI("No common event part, publish nothing for token invalid event.");
425 #endif // HAS_CES_PART
426     ACCOUNT_LOGI("success, userId %{public}d.", userId);
427     return true;
428 }
429 
430 /**
431  * Init event mapper.
432  */
BuildEventsMapper()433 void OhosAccountManager::BuildEventsMapper()
434 {
435     const std::map<std::string, std::string> accountEventMap = AccountHelperData::GetAccountEventMap();
436     std::string eventLogin = GetAccountEventStr(accountEventMap, KEY_ACCOUNT_EVENT_LOGIN, OHOS_ACCOUNT_EVENT_LOGIN);
437     std::string eventLogout = GetAccountEventStr(accountEventMap, KEY_ACCOUNT_EVENT_LOGOUT, OHOS_ACCOUNT_EVENT_LOGOUT);
438     std::string eventTokenInvalid = GetAccountEventStr(accountEventMap, KEY_ACCOUNT_EVENT_TOKEN_INVALID,
439         OHOS_ACCOUNT_EVENT_TOKEN_INVALID);
440     std::string eventLogoff = GetAccountEventStr(accountEventMap, KEY_ACCOUNT_EVENT_LOGOFF, OHOS_ACCOUNT_EVENT_LOGOFF);
441 
442     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(eventLogin, ACCOUNT_BIND_SUCCESS_EVT));
443     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(eventLogout, ACCOUNT_MANUAL_UNBOUND_EVT));
444     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(eventTokenInvalid, ACCOUNT_TOKEN_EXPIRED_EVT));
445     eventMap_.insert(std::pair<std::string, ACCOUNT_INNER_EVENT_TYPE>(eventLogoff, ACCOUNT_MANUAL_LOGOFF_EVT));
446 
447     eventFuncMap_.insert(std::make_pair(eventLogin, &OhosAccountManager::LoginOhosAccount));
448     eventFuncMap_.insert(std::make_pair(eventLogout, &OhosAccountManager::LogoutOhosAccount));
449     eventFuncMap_.insert(std::make_pair(eventLogoff, &OhosAccountManager::LogoffOhosAccount));
450     eventFuncMap_.insert(std::make_pair(eventTokenInvalid, &OhosAccountManager::HandleOhosAccountTokenInvalidEvent));
451 }
452 
GetInstance()453 OhosAccountManager &OhosAccountManager::GetInstance()
454 {
455     static OhosAccountManager *instance = new (std::nothrow) OhosAccountManager();
456     return *instance;
457 }
458 
OhosAccountManager()459 OhosAccountManager::OhosAccountManager()
460 {
461     accountState_ = std::make_unique<AccountStateMachine>();
462     dataDealer_ = std::make_unique<OhosAccountDataDeal>(ACCOUNT_CFG_DIR_ROOT_PATH);
463 }
464 
465 /**
466  * Init ohos account manager.
467  *
468  */
OnInitialize()469 bool OhosAccountManager::OnInitialize()
470 {
471     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
472     if (isInit_) {
473         return true;
474     }
475     BuildEventsMapper();
476 
477     std::int32_t tryTimes = 0;
478     while (tryTimes < MAX_RETRY_TIMES) {
479         tryTimes++;
480         ErrCode errCode = dataDealer_->Init(DEVICE_ACCOUNT_OWNER);
481         if (errCode == ERR_OK) {
482             break;
483         }
484 
485         // when json file corrupted, have it another try
486         if ((tryTimes == MAX_RETRY_TIMES) || (errCode != ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION)) {
487             ACCOUNT_LOGE("parse json file failed: %{public}d, tryTime: %{public}d", errCode, tryTimes);
488             eventMap_.clear();
489             eventFuncMap_.clear();
490             return false;
491         }
492     }
493     isInit_ = true;
494     return true;
495 }
496 
497 #ifdef HAS_CES_PART
CreateCommonEventSubscribe()498 bool OhosAccountManager::CreateCommonEventSubscribe()
499 {
500     if (accountEventSubscribe_ == nullptr) {
501         AccountCommonEventCallback callback = {
502             std::bind(&OhosAccountManager::OnPackageRemoved, this, std::placeholders::_1)};
503         accountEventSubscribe_ = std::make_shared<AccountEventSubscriber>(callback);
504         if (!accountEventSubscribe_->CreateEventSubscribe()) {
505             ACCOUNT_LOGE("CreateEventSubscribe is failed");
506             return false;
507         }
508     }
509     return true;
510 }
511 
OnPackageRemoved(const std::int32_t callingUid)512 void OhosAccountManager::OnPackageRemoved(const std::int32_t callingUid)
513 {
514     std::vector<OsAccountInfo> osAccountInfos;
515     (void)IInnerOsAccountManager::GetInstance().QueryAllCreatedOsAccounts(osAccountInfos);
516     for (const auto &info : osAccountInfos) {
517         AccountInfo accountInfo;
518         (void)GetAccountInfoByUserId(info.GetLocalId(), accountInfo);
519         if (accountInfo.ohosAccountInfo_.callingUid_ == callingUid) {
520             (void)ClearOhosAccount(accountInfo);
521             AccountEventProvider::EventPublish(
522                 EventFwk::CommonEventSupport::COMMON_EVENT_HWID_LOGOUT, info.GetLocalId(), nullptr);
523             AccountEventProvider::EventPublish(
524                 EventFwk::CommonEventSupport::COMMON_EVENT_DISTRIBUTED_ACCOUNT_LOGOUT, info.GetLocalId(), nullptr);
525         }
526     }
527 }
528 #endif // HAS_CES_PART
529 
530 /**
531  * Handle device account switch event.
532  *
533  * @param None
534  * @return None
535  */
HandleDevAccountSwitchEvent()536 void OhosAccountManager::HandleDevAccountSwitchEvent()
537 {
538     std::lock_guard<std::mutex> mutexLock(mgrMutex_);
539     eventMap_.clear();
540     eventFuncMap_.clear();
541 
542     // Re-Init
543     if (!OnInitialize()) {
544         ACCOUNT_LOGE("Handle dev Account SwitchEvent failed");
545     }
546 }
547 
CheckOhosAccountCanBind(const AccountInfo & currAccountInfo,const OhosAccountInfo & newOhosAccountInfo,const std::string & newOhosUid) const548 bool OhosAccountManager::CheckOhosAccountCanBind(const AccountInfo &currAccountInfo,
549     const OhosAccountInfo &newOhosAccountInfo, const std::string &newOhosUid) const
550 {
551     if (newOhosUid.length() != OHOS_ACCOUNT_UDID_LENGTH) {
552         ACCOUNT_LOGE("newOhosUid invalid length, %{public}s.", newOhosUid.c_str());
553         return false;
554     }
555 
556     // check if current account has been bound or not
557     if ((currAccountInfo.ohosAccountInfo_.status_ == ACCOUNT_STATE_LOGIN) &&
558         ((currAccountInfo.ohosAccountInfo_.uid_ != newOhosUid) ||
559         (currAccountInfo.ohosAccountInfo_.name_ != newOhosAccountInfo.name_))) {
560         ACCOUNT_LOGE("current account has already been bounded. callingUserId %{public}d.",
561             AccountMgrService::GetInstance().GetCallingUserID());
562         return false;
563     }
564 
565     // check whether newOhosUid has been already bound to another account or not
566     DIR* rootDir = opendir(ACCOUNT_CFG_DIR_ROOT_PATH.c_str());
567     if (rootDir == nullptr) {
568         ACCOUNT_LOGE("cannot open dir %{public}s, err %{public}d.", ACCOUNT_CFG_DIR_ROOT_PATH.c_str(), errno);
569         return false;
570     }
571     struct dirent* curDir = nullptr;
572     while ((curDir = readdir(rootDir)) != nullptr) {
573         std::string curDirName(curDir->d_name);
574         if (curDirName == "." || curDirName == ".." || curDir->d_type != DT_DIR) {
575             continue;
576         }
577 
578         AccountInfo curInfo;
579         std::stringstream sstream;
580         sstream << curDirName;
581         std::int32_t userId = -1;
582         sstream >> userId;
583         if (dataDealer_->AccountInfoFromJson(curInfo, userId) != ERR_OK) {
584             ACCOUNT_LOGI("get ohos account info from user %{public}s failed.", curDirName.c_str());
585             continue;
586         }
587 
588         if (curInfo.ohosAccountInfo_.status_ != ACCOUNT_STATE_LOGIN) {
589             continue; // account not bind, skip check
590         }
591     }
592 
593     (void)closedir(rootDir);
594     return true;
595 }
596 
GetCurOhosAccountAndCheckMatch(AccountInfo & curAccountInfo,const std::string & inputName,const std::string & inputUid,const std::int32_t callingUserId) const597 bool OhosAccountManager::GetCurOhosAccountAndCheckMatch(AccountInfo &curAccountInfo,
598                                                         const std::string &inputName,
599                                                         const std::string &inputUid,
600                                                         const std::int32_t callingUserId) const
601 {
602     if (dataDealer_->AccountInfoFromJson(curAccountInfo, callingUserId) != ERR_OK) {
603         ACCOUNT_LOGE("cannot read from config, inputName %{public}s.", inputName.c_str());
604         return false;
605     }
606 
607     std::string ohosAccountUid = GenerateOhosUdidWithSha256(inputName, inputUid);
608     if (inputName != curAccountInfo.ohosAccountInfo_.name_ ||
609         ohosAccountUid != curAccountInfo.ohosAccountInfo_.uid_) {
610         ACCOUNT_LOGE("account name %{public}s or ohosAccountUid %{public}s mismatch, calling user %{public}d.",
611             inputName.c_str(), ohosAccountUid.c_str(), callingUserId);
612         return false;
613     }
614     return true;
615 }
616 } // namespace AccountSA
617 } // namespace OHOS
618