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