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