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
47 using namespace OHOS::EventFwk;
48 #endif // HAS_CES_PART
49
50 namespace OHOS {
51 namespace AccountSA {
52 namespace {
53 constexpr unsigned int ITERATE_CNT = 1000;
54 constexpr std::int32_t OUTPUT_LENGTH_IN_BYTES = 32;
55 constexpr std::uint8_t TWO_BYTE_MASK = 0xF0;
56 constexpr std::int32_t MAX_RETRY_TIMES = 2; // give another chance when json file corrupted
57 constexpr std::uint32_t MAX_NAME_LENGTH = 256;
58 constexpr std::uint32_t MAX_UID_LENGTH = 512;
59 constexpr std::uint32_t HASH_LENGTH = 32;
60 constexpr std::uint32_t WIDTH_FOR_HEX = 2;
61 constexpr std::uint32_t OHOS_ACCOUNT_UDID_LENGTH = HASH_LENGTH * 2;
62 const std::string KEY_ACCOUNT_EVENT_LOGIN = "LOGIN";
63 const std::string KEY_ACCOUNT_EVENT_LOGOUT = "LOGOUT";
64 const std::string KEY_ACCOUNT_EVENT_TOKEN_INVALID = "TOKEN_INVALID";
65 const std::string KEY_ACCOUNT_EVENT_LOGOFF = "LOGOFF";
GetAccountEventStr(const std::map<std::string, std::string> &accountEventMap, const std::string &eventKey, const std::string &defaultValue)66 std::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
GetCallerBundleName(std::string &bundleName)76 bool 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
ReturnOhosUdidWithSha256(const std::string &uid)94 std::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
GenerateOhosUdidWithSha256(const std::string &name, const std::string &uid)115 std::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 */
OhosAccountStateChange(const std::string &name, const std::string &uid, const std::string &eventStr)173 ErrCode 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
OhosAccountStateChange( const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)188 ErrCode 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 */
ClearOhosAccount(AccountInfo &curOhosAccountInfo, std::int32_t clrStatus) const202 bool 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 */
SaveOhosAccountInfo(AccountInfo &ohosAccountInfo) const219 bool 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 */
GetCurrentOhosAccountInfo()234 AccountInfo 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
GetAccountInfoByUserId(std::int32_t userId, AccountInfo &info)247 ErrCode 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
SubscribeDistributedAccountEvent(const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)263 ErrCode OhosAccountManager::SubscribeDistributedAccountEvent(const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type,
264 const sptr<IRemoteObject> &eventListener)
265 {
266 return subscribeManager_.SubscribeDistributedAccountEvent(type, eventListener);
267 }
268
UnsubscribeDistributedAccountEvent(const DISTRIBUTED_ACCOUNT_SUBSCRIBE_TYPE type, const sptr<IRemoteObject> &eventListener)269 ErrCode 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 */
GetCurrentOhosAccountState()280 std::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 */
HandleEvent(AccountInfo &curOhosAccount, const std::string &eventStr)292 bool 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 */
LoginOhosAccount(const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)322 ErrCode 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 */
LogoutOhosAccount( const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)392 ErrCode 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 */
LogoffOhosAccount( const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)437 ErrCode 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 */
HandleOhosAccountTokenInvalidEvent( const int32_t userId, const OhosAccountInfo &ohosAccountInfo, const std::string &eventStr)481 ErrCode 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 */
BuildEventsMapper()521 void 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
GetInstance()553 OhosAccountManager &OhosAccountManager::GetInstance()
554 {
555 static OhosAccountManager *instance = new (std::nothrow) OhosAccountManager();
556 return *instance;
557 }
558
OhosAccountManager()559 OhosAccountManager::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 */
OnInitialize()570 bool 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
CreateCommonEventSubscribe()598 bool 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
OnPackageRemoved(const std::int32_t callingUid)612 void 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 */
HandleDevAccountSwitchEvent()636 void 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
CheckOhosAccountCanBind(const AccountInfo &currAccountInfo, const OhosAccountInfo &newOhosAccountInfo, const std::string &newOhosUid) const648 bool 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
GetCurOhosAccountAndCheckMatch(AccountInfo &curAccountInfo, const std::string &inputName, const std::string &inputUid, const std::int32_t callingUserId) const697 bool 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