• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "user_idm_service.h"
17 
18 #include "string_ex.h"
19 #include "accesstoken_kit.h"
20 
21 #include "context_helper.h"
22 #include "context_pool.h"
23 #include "hdi_wrapper.h"
24 #include "iam_check.h"
25 #include "iam_logger.h"
26 #include "iam_para2str.h"
27 #include "iam_defines.h"
28 #include "iam_time.h"
29 #include "ipc_common.h"
30 #include "ipc_skeleton.h"
31 #include "iam_common_defines.h"
32 #include "publish_event_adapter.h"
33 #include "resource_node_pool.h"
34 #include "resource_node_utils.h"
35 #include "system_param_manager.h"
36 #include "user_idm_callback_proxy.h"
37 #include "user_idm_database.h"
38 #include "user_idm_session_controller.h"
39 #include "xcollie_helper.h"
40 
41 #define LOG_TAG "USER_AUTH_SA"
42 
43 namespace OHOS {
44 namespace UserIam {
45 namespace UserAuth {
46 REGISTER_SYSTEM_ABILITY_BY_ID(UserIdmService, SUBSYS_USERIAM_SYS_ABILITY_USERIDM, true);
47 constexpr int32_t USERIAM_IPC_THREAD_NUM = 4;
48 
UserIdmService(int32_t systemAbilityId,bool runOnCreate)49 UserIdmService::UserIdmService(int32_t systemAbilityId, bool runOnCreate) : SystemAbility(systemAbilityId, runOnCreate)
50 {
51 }
52 
OnStart()53 void UserIdmService::OnStart()
54 {
55     IAM_LOGI("start service");
56     IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
57     if (!Publish(this)) {
58         IAM_LOGE("failed to publish service");
59     }
60 }
61 
OnStop()62 void UserIdmService::OnStop()
63 {
64     IAM_LOGI("stop service");
65 }
66 
OpenSession(int32_t userId,std::vector<uint8_t> & challenge)67 int32_t UserIdmService::OpenSession(int32_t userId, std::vector<uint8_t> &challenge)
68 {
69     IAM_LOGI("start");
70     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
71     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
72         IAM_LOGE("failed to check permission");
73         return CHECK_PERMISSION_FAILED;
74     }
75 
76     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
77     for (const auto &context : contextList) {
78         if (auto ctx = context.lock(); ctx != nullptr) {
79             IAM_LOGE("force stop the old context ****%{public}hx", static_cast<uint16_t>(ctx->GetContextId()));
80             ctx->Stop();
81             ContextPool::Instance().Delete(ctx->GetContextId());
82         }
83     }
84 
85     if (!UserIdmSessionController::Instance().OpenSession(userId, challenge)) {
86         IAM_LOGE("failed to open session");
87         return GENERAL_ERROR;
88     }
89 
90     return SUCCESS;
91 }
92 
CloseSession(int32_t userId)93 void UserIdmService::CloseSession(int32_t userId)
94 {
95     IAM_LOGI("start");
96     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
97     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
98         IAM_LOGE("failed to check permission");
99         return;
100     }
101 
102     if (!UserIdmSessionController::Instance().CloseSession(userId)) {
103         IAM_LOGE("failed to get close session");
104     }
105 }
106 
GetCredentialInfoInner(int32_t userId,AuthType authType,std::vector<CredentialInfo> & credInfoList)107 int32_t UserIdmService::GetCredentialInfoInner(int32_t userId, AuthType authType,
108     std::vector<CredentialInfo> &credInfoList)
109 {
110     IAM_LOGI("start");
111     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
112         IAM_LOGE("failed to check permission");
113         return CHECK_PERMISSION_FAILED;
114     }
115 
116     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
117     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType, credInfos);
118     if (ret != SUCCESS) {
119         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
120             userId, authType);
121         return GENERAL_ERROR;
122     }
123 
124     if (credInfos.empty()) {
125         IAM_LOGE("no cred enrolled");
126         return NOT_ENROLLED;
127     }
128     for (const auto &credInfo : credInfos) {
129         if (credInfo == nullptr) {
130             IAM_LOGE("credInfo is nullptr");
131             return GENERAL_ERROR;
132         }
133         CredentialInfo info = {};
134         info.credentialId = credInfo->GetCredentialId();
135         info.templateId = credInfo->GetTemplateId();
136         info.authType = credInfo->GetAuthType();
137         if (info.authType == PIN) {
138             std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
139             int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfo);
140             if (ret != SUCCESS) {
141                 IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
142                 return GENERAL_ERROR;
143             }
144             if (userInfo == nullptr) {
145                 IAM_LOGE("failed to get userInfo");
146                 return GENERAL_ERROR;
147             }
148             info.pinType = userInfo->GetPinSubType();
149         }
150         credInfoList.push_back(info);
151     }
152     return SUCCESS;
153 }
154 
GetCredentialInfo(int32_t userId,AuthType authType,const sptr<IdmGetCredInfoCallbackInterface> & callback)155 int32_t UserIdmService::GetCredentialInfo(int32_t userId, AuthType authType,
156     const sptr<IdmGetCredInfoCallbackInterface> &callback)
157 {
158     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
159     if (callback == nullptr) {
160         IAM_LOGE("callback is nullptr");
161         return INVALID_PARAMETERS;
162     }
163 
164     std::vector<CredentialInfo> credInfoList;
165     int32_t ret = GetCredentialInfoInner(userId, authType, credInfoList);
166     if (ret != SUCCESS) {
167         IAM_LOGE("GetCredentialInfoInner fail, ret: %{public}d", ret);
168         credInfoList.clear();
169     }
170     callback->OnCredentialInfos(credInfoList);
171 
172     return ret;
173 }
174 
GetSecInfoInner(int32_t userId,SecUserInfo & secUserInfo)175 int32_t UserIdmService::GetSecInfoInner(int32_t userId, SecUserInfo &secUserInfo)
176 {
177     IAM_LOGI("start");
178     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
179         IAM_LOGE("failed to check permission");
180         return CHECK_PERMISSION_FAILED;
181     }
182     std::shared_ptr<SecureUserInfoInterface> userInfos = nullptr;
183     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfos);
184     if (ret != SUCCESS) {
185         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
186         return GENERAL_ERROR;
187     }
188     if (userInfos == nullptr) {
189         IAM_LOGE("current userid %{public}d is not existed", userId);
190         return INVALID_PARAMETERS;
191     }
192     std::vector<std::shared_ptr<EnrolledInfoInterface>> enrolledInfos = userInfos->GetEnrolledInfo();
193     for (const auto &enrolledInfo : enrolledInfos) {
194         if (enrolledInfo == nullptr) {
195             IAM_LOGE("enrolledInfo is nullptr");
196             return GENERAL_ERROR;
197         }
198         EnrolledInfo info = {enrolledInfo->GetAuthType(), enrolledInfo->GetEnrolledId()};
199         secUserInfo.enrolledInfo.push_back(info);
200     }
201     secUserInfo.secureUid = userInfos->GetSecUserId();
202     return SUCCESS;
203 }
204 
GetSecInfo(int32_t userId,const sptr<IdmGetSecureUserInfoCallbackInterface> & callback)205 int32_t UserIdmService::GetSecInfo(int32_t userId, const sptr<IdmGetSecureUserInfoCallbackInterface> &callback)
206 {
207     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
208     if (callback == nullptr) {
209         IAM_LOGE("callback is nullptr");
210         return INVALID_PARAMETERS;
211     }
212 
213     SecUserInfo secUserInfo = {};
214     int32_t ret = GetSecInfoInner(userId, secUserInfo);
215     if (ret != SUCCESS) {
216         IAM_LOGE("GetSecInfoInner fail, ret: %{public}d", ret);
217         secUserInfo.secureUid = 0;
218         secUserInfo.enrolledInfo.clear();
219     }
220     callback->OnSecureUserInfo(secUserInfo);
221 
222     return ret;
223 }
224 
CheckEnrollPermissionAndEnableStatus(const std::shared_ptr<ContextCallback> & contextCallback,AuthType authType)225 bool UserIdmService::CheckEnrollPermissionAndEnableStatus(
226     const std::shared_ptr<ContextCallback> &contextCallback, AuthType authType)
227 {
228     Attributes extraInfo;
229     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
230         IAM_LOGE("failed to check permission");
231         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
232         return false;
233     }
234 
235     if (!SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
236         IAM_LOGE("authType not support");
237         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
238         return false;
239     }
240     return true;
241 }
242 
StartEnroll(Enrollment::EnrollmentPara & para,const std::shared_ptr<ContextCallback> & contextCallback,Attributes & extraInfo)243 void UserIdmService::StartEnroll(Enrollment::EnrollmentPara &para,
244     const std::shared_ptr<ContextCallback> &contextCallback, Attributes &extraInfo)
245 {
246     auto context = ContextFactory::CreateEnrollContext(para, contextCallback);
247     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
248         IAM_LOGE("failed to insert context");
249         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
250         return;
251     }
252     contextCallback->SetTraceRequestContextId(context->GetContextId());
253     auto cleaner = ContextHelper::Cleaner(context);
254     contextCallback->SetCleaner(cleaner);
255 
256     if (!context->Start()) {
257         IAM_LOGE("failed to start enroll");
258         contextCallback->OnResult(context->GetLatestError(), extraInfo);
259     }
260 }
261 
AddCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback,bool isUpdate)262 void UserIdmService::AddCredential(int32_t userId, const CredentialPara &credPara,
263     const sptr<IdmCallbackInterface> &callback, bool isUpdate)
264 {
265     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
266     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
267 
268     Attributes extraInfo;
269     auto contextCallback = ContextCallback::NewInstance(callback,
270         isUpdate ? TRACE_UPDATE_CREDENTIAL : TRACE_ADD_CREDENTIAL);
271     if (contextCallback == nullptr) {
272         IAM_LOGE("failed to construct context callback");
273         callback->OnResult(GENERAL_ERROR, extraInfo);
274         return;
275     }
276     std::string callerName = "";
277     int32_t callerType = 0;
278     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
279     contextCallback->SetTraceCallerName(callerName);
280     contextCallback->SetTraceCallerType(callerType);
281     contextCallback->SetTraceUserId(userId);
282     contextCallback->SetTraceAuthType(credPara.authType);
283 
284     if (!CheckEnrollPermissionAndEnableStatus(contextCallback, credPara.authType)) {
285         IAM_LOGE("CheckEnrollPermissionAndEnableStatus fail");
286         return;
287     }
288 
289     std::lock_guard<std::mutex> lock(mutex_);
290     CancelCurrentEnrollIfExist();
291     Enrollment::EnrollmentPara para = {};
292     para.authType = credPara.authType;
293     para.userId = userId;
294     para.pinType = credPara.pinType;
295     para.tokenId = IpcCommon::GetAccessTokenId(*this);
296     para.token = credPara.token;
297     para.isUpdate = isUpdate;
298     para.sdkVersion = INNER_API_VERSION_10000;
299     para.callerName = callerName;
300     para.callerType = callerType;
301     StartEnroll(para, contextCallback, extraInfo);
302 }
303 
UpdateCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback)304 void UserIdmService::UpdateCredential(int32_t userId, const CredentialPara &credPara,
305     const sptr<IdmCallbackInterface> &callback)
306 {
307     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
308     if (callback == nullptr) {
309         IAM_LOGE("callback is nullptr");
310         return;
311     }
312 
313     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
314     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, credPara.authType, credInfos);
315     if (ret != SUCCESS) {
316         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
317             userId, credPara.authType);
318         Attributes extraInfo;
319         callback->OnResult(GENERAL_ERROR, extraInfo);
320         return;
321     }
322 
323     if (credInfos.empty()) {
324         IAM_LOGE("current userid %{public}d has no credential for type %{public}u", userId, credPara.authType);
325         Attributes extraInfo;
326         callback->OnResult(NOT_ENROLLED, extraInfo);
327         return;
328     }
329 
330     AddCredential(userId, credPara, callback, true);
331 }
332 
Cancel(int32_t userId)333 int32_t UserIdmService::Cancel(int32_t userId)
334 {
335     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
336     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
337         IAM_LOGE("failed to check permission");
338         return CHECK_PERMISSION_FAILED;
339     }
340     if (!UserIdmSessionController::Instance().IsSessionOpened(userId)) {
341         IAM_LOGE("both user id and challenge are invalid");
342         return GENERAL_ERROR;
343     }
344 
345     std::lock_guard<std::mutex> lock(mutex_);
346     return CancelCurrentEnroll();
347 }
348 
CancelCurrentEnrollIfExist()349 void UserIdmService::CancelCurrentEnrollIfExist()
350 {
351     if (ContextPool::Instance().Select(CONTEXT_ENROLL).size() == 0) {
352         return;
353     }
354 
355     IAM_LOGI("cancel current enroll due to new add credential request or delete");
356     CancelCurrentEnroll();
357 }
358 
CancelCurrentEnroll()359 int32_t UserIdmService::CancelCurrentEnroll()
360 {
361     IAM_LOGD("start");
362     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
363     int32_t ret = GENERAL_ERROR;
364     for (const auto &context : contextList) {
365         if (auto ctx = context.lock(); ctx != nullptr) {
366             IAM_LOGI("stop the old context %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
367             ctx->Stop();
368             ContextPool::Instance().Delete(ctx->GetContextId());
369             ret = SUCCESS;
370         }
371     }
372     IAM_LOGI("result %{public}d", ret);
373     return ret;
374 }
375 
EnforceDelUser(int32_t userId,const sptr<IdmCallbackInterface> & callback)376 int32_t UserIdmService::EnforceDelUser(int32_t userId, const sptr<IdmCallbackInterface> &callback)
377 {
378     IAM_LOGI("to delete userid: %{public}d", userId);
379     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
380     IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, INVALID_PARAMETERS);
381 
382     Attributes extraInfo;
383     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_ENFORCE_DELETE_USER);
384     if (contextCallback == nullptr) {
385         IAM_LOGE("failed to construct context callback");
386         callback->OnResult(GENERAL_ERROR, extraInfo);
387         return GENERAL_ERROR;
388     }
389     std::string callerName = "";
390     int32_t callerType = 0;
391     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
392     contextCallback->SetTraceCallerType(callerType);
393     contextCallback->SetTraceCallerName(callerName);
394     contextCallback->SetTraceUserId(userId);
395 
396     if (!IpcCommon::CheckPermission(*this, ENFORCE_USER_IDM)) {
397         IAM_LOGE("failed to check permission");
398         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
399         return CHECK_PERMISSION_FAILED;
400     }
401 
402     std::lock_guard<std::mutex> lock(mutex_);
403     CancelCurrentEnrollIfExist();
404     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
405     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfo);
406     if (ret != SUCCESS) {
407         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
408         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
409         return ret;
410     }
411     if (userInfo == nullptr) {
412         IAM_LOGE("current userid %{public}d is not existed", userId);
413         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
414         return INVALID_PARAMETERS;
415     }
416     ret = EnforceDelUserInner(userId, contextCallback, "EnforceDeleteUser");
417     if (ret != SUCCESS) {
418         IAM_LOGE("failed to enforce delete user");
419         static_cast<void>(extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, 0));
420         contextCallback->OnResult(ret, extraInfo);
421         return ret;
422     }
423 
424     IAM_LOGI("delete user success");
425     contextCallback->OnResult(SUCCESS, extraInfo);
426     return SUCCESS;
427 }
428 
DelUser(int32_t userId,const std::vector<uint8_t> authToken,const sptr<IdmCallbackInterface> & callback)429 void UserIdmService::DelUser(int32_t userId, const std::vector<uint8_t> authToken,
430     const sptr<IdmCallbackInterface> &callback)
431 {
432     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
433     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
434 
435     Attributes extraInfo;
436     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_USER);
437     if (contextCallback == nullptr) {
438         IAM_LOGE("failed to construct context callback");
439         callback->OnResult(GENERAL_ERROR, extraInfo);
440         return;
441     }
442     std::string callerName = "";
443     int32_t callerType = 0;
444     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
445     contextCallback->SetTraceCallerName(callerName);
446     contextCallback->SetTraceCallerType(callerType);
447     contextCallback->SetTraceUserId(userId);
448 
449     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
450         IAM_LOGE("failed to check permission");
451         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
452         return;
453     }
454 
455     std::lock_guard<std::mutex> lock(mutex_);
456     CancelCurrentEnrollIfExist();
457 
458     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
459     std::vector<uint8_t> rootSecret;
460     int32_t ret = UserIdmDatabase::Instance().DeleteUser(userId, authToken, credInfos, rootSecret);
461     if (ret != SUCCESS) {
462         IAM_LOGE("failed to delete user");
463         contextCallback->OnResult(ret, extraInfo);
464         return;
465     }
466     if (!extraInfo.SetUint8ArrayValue(Attributes::ATTR_OLD_ROOT_SECRET, rootSecret)) {
467         IAM_LOGE("set rootsecret to extraInfo failed");
468         contextCallback->OnResult(ret, extraInfo);
469         return;
470     }
471     SetAuthTypeTrace(credInfos, contextCallback);
472     contextCallback->OnResult(ret, extraInfo);
473 
474     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, "DeleteUser");
475     if (ret != SUCCESS) {
476         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
477     }
478     IAM_LOGI("delete user end");
479     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
480     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
481 }
482 
DelCredential(int32_t userId,uint64_t credentialId,const std::vector<uint8_t> & authToken,const sptr<IdmCallbackInterface> & callback)483 void UserIdmService::DelCredential(int32_t userId, uint64_t credentialId,
484     const std::vector<uint8_t> &authToken, const sptr<IdmCallbackInterface> &callback)
485 {
486     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
487     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
488 
489     Attributes extraInfo;
490     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_CREDENTIAL);
491     if (contextCallback == nullptr) {
492         IAM_LOGE("failed to construct context callback");
493         callback->OnResult(GENERAL_ERROR, extraInfo);
494         return;
495     }
496     std::string callerName = "";
497     int32_t callerType = 0;
498     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
499     contextCallback->SetTraceCallerName(callerName);
500     contextCallback->SetTraceCallerType(callerType);
501     contextCallback->SetTraceUserId(userId);
502 
503     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
504         IAM_LOGE("failed to check permission");
505         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
506         return;
507     }
508 
509     std::lock_guard<std::mutex> lock(mutex_);
510     CancelCurrentEnrollIfExist();
511 
512     std::shared_ptr<CredentialInfoInterface> oldInfo;
513     auto ret = UserIdmDatabase::Instance().DeleteCredentialInfo(userId, credentialId, authToken, oldInfo);
514     if (ret != SUCCESS) {
515         IAM_LOGE("failed to delete CredentialInfo");
516         contextCallback->OnResult(ret, extraInfo);
517         return;
518     }
519     if (oldInfo != nullptr) {
520         contextCallback->SetTraceAuthType(oldInfo->GetAuthType());
521     }
522 
523     IAM_LOGI("delete credentialInfo success");
524     std::vector<std::shared_ptr<CredentialInfoInterface>> list = {oldInfo};
525     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(list, "DeleteTemplate");
526     if (ret != SUCCESS) {
527         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
528     }
529 
530     contextCallback->OnResult(ret, extraInfo);
531     if (oldInfo != nullptr) {
532         PublishCommonEvent(userId, credentialId, oldInfo->GetAuthType());
533     }
534 }
535 
Dump(int fd,const std::vector<std::u16string> & args)536 int UserIdmService::Dump(int fd, const std::vector<std::u16string> &args)
537 {
538     IAM_LOGI("start");
539     if (fd < 0) {
540         IAM_LOGE("invalid parameters");
541         dprintf(fd, "Invalid parameters.\n");
542         return INVALID_PARAMETERS;
543     }
544     std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
545     if (arg0.empty() || arg0.compare("-h") == 0) {
546         dprintf(fd, "Usage:\n");
547         dprintf(fd, "      -h: command help.\n");
548         dprintf(fd, "      -l: active user info dump.\n");
549         return SUCCESS;
550     }
551     if (arg0.compare("-l") != 0) {
552         IAM_LOGE("invalid option");
553         dprintf(fd, "Invalid option\n");
554         return GENERAL_ERROR;
555     }
556 
557     std::optional<int32_t> activeUserId;
558     if (IpcCommon::GetActiveUserId(activeUserId) != SUCCESS) {
559         dprintf(fd, "Internal error.\n");
560         IAM_LOGE("failed to get active id");
561         return GENERAL_ERROR;
562     }
563     dprintf(fd, "Active user is %d\n", activeUserId.value());
564     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
565     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(activeUserId.value(), userInfo);
566     if (ret != SUCCESS) {
567         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, activeUserId.value());
568         return GENERAL_ERROR;
569     }
570     if (userInfo == nullptr) {
571         IAM_LOGE("userInfo is null");
572         return SUCCESS;
573     }
574     auto enrolledInfo = userInfo->GetEnrolledInfo();
575     for (auto &info : enrolledInfo) {
576         if (info != nullptr) {
577             dprintf(fd, "AuthType %s is enrolled.\n", Common::AuthTypeToStr(info->GetAuthType()));
578         }
579     }
580     return SUCCESS;
581 }
582 
SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> & credInfos,const std::shared_ptr<ContextCallback> & contextCallback)583 void UserIdmService::SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> &credInfos,
584     const std::shared_ptr<ContextCallback> &contextCallback)
585 {
586     uint32_t authTypeTrace = 0;
587     for (const auto &credInfo : credInfos) {
588         if (credInfo == nullptr) {
589             IAM_LOGE("credInfo is nullptr");
590             continue;
591         }
592         authTypeTrace |= static_cast<uint32_t>(credInfo->GetAuthType());
593     }
594     contextCallback->SetTraceAuthType(static_cast<int32_t>(authTypeTrace));
595 }
596 
EnforceDelUserInner(int32_t userId,std::shared_ptr<ContextCallback> callbackForTrace,std::string changeReasonTrace)597 int32_t UserIdmService::EnforceDelUserInner(int32_t userId, std::shared_ptr<ContextCallback> callbackForTrace,
598     std::string changeReasonTrace)
599 {
600     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
601     int32_t ret = UserIdmDatabase::Instance().DeleteUserEnforce(userId, credInfos);
602     if (ret != SUCCESS) {
603         IAM_LOGE("failed to enforce delete user, ret:%{public}d", ret);
604         return ret;
605     }
606     SetAuthTypeTrace(credInfos, callbackForTrace);
607     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, changeReasonTrace);
608     if (ret != SUCCESS) {
609         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
610         // The caller doesn't need to care executor delete result.
611         return SUCCESS;
612     }
613 
614     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
615     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
616     IAM_LOGI("delete user success, userId:%{public}d", userId);
617     return SUCCESS;
618 }
619 
ClearRedundancyCredentialInner()620 void UserIdmService::ClearRedundancyCredentialInner()
621 {
622     IAM_LOGI("start");
623     std::vector<int32_t> accountInfo;
624     int32_t ret = IpcCommon::GetAllUserId(accountInfo);
625     if (ret != SUCCESS) {
626         IAM_LOGE("GetAllUserId failed");
627         return;
628     }
629 
630     auto userInfos = UserIdmDatabase::Instance().GetAllExtUserInfo();
631     if (userInfos.empty()) {
632         IAM_LOGE("no userInfo");
633         return;
634     }
635     std::string callerName = "";
636     int32_t callerType = 0;
637     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
638 
639     for (const auto &iter : userInfos) {
640         int32_t userId = iter->GetUserId();
641         auto callbackForTrace = ContextCallback::NewDummyInstance(TRACE_DELETE_REDUNDANCY);
642         if (callbackForTrace == nullptr) {
643             IAM_LOGE("failed to get callbackForTrace");
644             continue;
645         }
646         callbackForTrace->SetTraceUserId(userId);
647         callbackForTrace->SetTraceCallerName(callerName);
648         callbackForTrace->SetTraceCallerType(callerType);
649         std::vector<int32_t>::iterator it = std::find(accountInfo.begin(), accountInfo.end(), userId);
650         if (it == accountInfo.end()) {
651             ret = EnforceDelUserInner(userId, callbackForTrace, "DeleteRedundancy");
652             Attributes extraInfo;
653             callbackForTrace->OnResult(ret, extraInfo);
654             IAM_LOGE("ClearRedundancytCredential, userId: %{public}d", userId);
655         }
656     }
657 }
658 
ClearRedundancyCredential(const sptr<IdmCallbackInterface> & callback)659 void UserIdmService::ClearRedundancyCredential(const sptr<IdmCallbackInterface> &callback)
660 {
661     IAM_LOGI("start");
662     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
663     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
664 
665     Attributes extraInfo;
666     auto contextCallback = ContextCallback::NewInstance(callback, NO_NEED_TRACE);
667     if (contextCallback == nullptr) {
668         IAM_LOGE("failed to construct context callback");
669         callback->OnResult(GENERAL_ERROR, extraInfo);
670         return;
671     }
672 
673     if (!IpcCommon::CheckPermission(*this, CLEAR_REDUNDANCY_PERMISSION)) {
674         IAM_LOGE("failed to check permission");
675         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
676         return;
677     }
678 
679     std::lock_guard<std::mutex> lock(mutex_);
680     CancelCurrentEnrollIfExist();
681 
682     this->ClearRedundancyCredentialInner();
683     contextCallback->OnResult(SUCCESS, extraInfo);
684 }
685 
PublishCommonEvent(int32_t userId,uint64_t credentialId,AuthType authType)686 void UserIdmService::PublishCommonEvent(int32_t userId, uint64_t credentialId, AuthType authType)
687 {
688     std::vector<std::shared_ptr<CredentialInfoInterface>> credentialInfos;
689     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType, credentialInfos);
690     if (ret != SUCCESS) {
691         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret, userId, authType);
692         return;
693     }
694     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, authType, credentialInfos.size());
695     PublishEventAdapter::GetInstance().PublishUpdatedEvent(userId, credentialId);
696 }
697 } // namespace UserAuth
698 } // namespace UserIam
699 } // namespace OHOS