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         info.pinType = credInfo->GetAuthSubType();
138         credInfoList.push_back(info);
139     }
140     return SUCCESS;
141 }
142 
GetCredentialInfo(int32_t userId,AuthType authType,const sptr<IdmGetCredInfoCallbackInterface> & callback)143 int32_t UserIdmService::GetCredentialInfo(int32_t userId, AuthType authType,
144     const sptr<IdmGetCredInfoCallbackInterface> &callback)
145 {
146     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
147     if (callback == nullptr) {
148         IAM_LOGE("callback is nullptr");
149         return INVALID_PARAMETERS;
150     }
151 
152     std::vector<CredentialInfo> credInfoList;
153     int32_t ret = GetCredentialInfoInner(userId, authType, credInfoList);
154     if (ret != SUCCESS) {
155         IAM_LOGE("GetCredentialInfoInner fail, ret: %{public}d", ret);
156         credInfoList.clear();
157     }
158     callback->OnCredentialInfos(credInfoList);
159 
160     return ret;
161 }
162 
GetSecInfoInner(int32_t userId,SecUserInfo & secUserInfo)163 int32_t UserIdmService::GetSecInfoInner(int32_t userId, SecUserInfo &secUserInfo)
164 {
165     IAM_LOGI("start");
166     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
167         IAM_LOGE("failed to check permission");
168         return CHECK_PERMISSION_FAILED;
169     }
170     std::shared_ptr<SecureUserInfoInterface> userInfos = nullptr;
171     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfos);
172     if (ret != SUCCESS) {
173         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
174         return GENERAL_ERROR;
175     }
176     if (userInfos == nullptr) {
177         IAM_LOGE("current userid %{public}d is not existed", userId);
178         return INVALID_PARAMETERS;
179     }
180     std::vector<std::shared_ptr<EnrolledInfoInterface>> enrolledInfos = userInfos->GetEnrolledInfo();
181     for (const auto &enrolledInfo : enrolledInfos) {
182         if (enrolledInfo == nullptr) {
183             IAM_LOGE("enrolledInfo is nullptr");
184             return GENERAL_ERROR;
185         }
186         EnrolledInfo info = {enrolledInfo->GetAuthType(), enrolledInfo->GetEnrolledId()};
187         secUserInfo.enrolledInfo.push_back(info);
188     }
189     secUserInfo.secureUid = userInfos->GetSecUserId();
190     return SUCCESS;
191 }
192 
GetSecInfo(int32_t userId,const sptr<IdmGetSecureUserInfoCallbackInterface> & callback)193 int32_t UserIdmService::GetSecInfo(int32_t userId, const sptr<IdmGetSecureUserInfoCallbackInterface> &callback)
194 {
195     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
196     if (callback == nullptr) {
197         IAM_LOGE("callback is nullptr");
198         return INVALID_PARAMETERS;
199     }
200 
201     SecUserInfo secUserInfo = {};
202     int32_t ret = GetSecInfoInner(userId, secUserInfo);
203     if (ret != SUCCESS) {
204         IAM_LOGE("GetSecInfoInner fail, ret: %{public}d", ret);
205         secUserInfo.secureUid = 0;
206         secUserInfo.enrolledInfo.clear();
207     }
208     callback->OnSecureUserInfo(secUserInfo);
209 
210     return ret;
211 }
212 
CheckEnrollPermissionAndEnableStatus(const std::shared_ptr<ContextCallback> & contextCallback,AuthType authType)213 bool UserIdmService::CheckEnrollPermissionAndEnableStatus(
214     const std::shared_ptr<ContextCallback> &contextCallback, AuthType authType)
215 {
216     Attributes extraInfo;
217     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
218         IAM_LOGE("failed to check permission");
219         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
220         return false;
221     }
222 
223     if (!SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
224         IAM_LOGE("authType not support");
225         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
226         return false;
227     }
228     return true;
229 }
230 
StartEnroll(Enrollment::EnrollmentPara & para,const std::shared_ptr<ContextCallback> & contextCallback,Attributes & extraInfo)231 void UserIdmService::StartEnroll(Enrollment::EnrollmentPara &para,
232     const std::shared_ptr<ContextCallback> &contextCallback, Attributes &extraInfo)
233 {
234     auto context = ContextFactory::CreateEnrollContext(para, contextCallback);
235     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
236         IAM_LOGE("failed to insert context");
237         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
238         return;
239     }
240     contextCallback->SetTraceRequestContextId(context->GetContextId());
241     auto cleaner = ContextHelper::Cleaner(context);
242     contextCallback->SetCleaner(cleaner);
243 
244     if (!context->Start()) {
245         IAM_LOGE("failed to start enroll");
246         contextCallback->OnResult(context->GetLatestError(), extraInfo);
247     }
248 }
249 
AddCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback,bool isUpdate)250 void UserIdmService::AddCredential(int32_t userId, const CredentialPara &credPara,
251     const sptr<IdmCallbackInterface> &callback, bool isUpdate)
252 {
253     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
254     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
255 
256     Attributes extraInfo;
257     auto contextCallback = ContextCallback::NewInstance(callback,
258         isUpdate ? TRACE_UPDATE_CREDENTIAL : TRACE_ADD_CREDENTIAL);
259     if (contextCallback == nullptr) {
260         IAM_LOGE("failed to construct context callback");
261         callback->OnResult(GENERAL_ERROR, extraInfo);
262         return;
263     }
264     std::string callerName = "";
265     int32_t callerType = 0;
266     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
267     contextCallback->SetTraceCallerName(callerName);
268     contextCallback->SetTraceCallerType(callerType);
269     contextCallback->SetTraceUserId(userId);
270     contextCallback->SetTraceAuthType(credPara.authType);
271 
272     if (!CheckEnrollPermissionAndEnableStatus(contextCallback, credPara.authType)) {
273         IAM_LOGE("CheckEnrollPermissionAndEnableStatus fail");
274         return;
275     }
276 
277     std::lock_guard<std::mutex> lock(mutex_);
278     CancelCurrentEnrollIfExist();
279     Enrollment::EnrollmentPara para = {};
280     para.authType = credPara.authType;
281     para.userId = userId;
282     para.pinType = credPara.pinType;
283     para.tokenId = IpcCommon::GetAccessTokenId(*this);
284     para.token = credPara.token;
285     para.isUpdate = isUpdate;
286     para.sdkVersion = INNER_API_VERSION_10000;
287     para.callerName = callerName;
288     para.callerType = callerType;
289     StartEnroll(para, contextCallback, extraInfo);
290 }
291 
UpdateCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback)292 void UserIdmService::UpdateCredential(int32_t userId, const CredentialPara &credPara,
293     const sptr<IdmCallbackInterface> &callback)
294 {
295     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
296     if (callback == nullptr) {
297         IAM_LOGE("callback is nullptr");
298         return;
299     }
300 
301     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
302     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, credPara.authType, credInfos);
303     if (ret != SUCCESS) {
304         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
305             userId, credPara.authType);
306         Attributes extraInfo;
307         callback->OnResult(GENERAL_ERROR, extraInfo);
308         return;
309     }
310 
311     if (credInfos.empty()) {
312         IAM_LOGE("current userid %{public}d has no credential for type %{public}u", userId, credPara.authType);
313         Attributes extraInfo;
314         callback->OnResult(NOT_ENROLLED, extraInfo);
315         return;
316     }
317 
318     AddCredential(userId, credPara, callback, true);
319 }
320 
Cancel(int32_t userId)321 int32_t UserIdmService::Cancel(int32_t userId)
322 {
323     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
324     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
325         IAM_LOGE("failed to check permission");
326         return CHECK_PERMISSION_FAILED;
327     }
328     if (!UserIdmSessionController::Instance().IsSessionOpened(userId)) {
329         IAM_LOGE("both user id and challenge are invalid");
330         return GENERAL_ERROR;
331     }
332 
333     std::lock_guard<std::mutex> lock(mutex_);
334     return CancelCurrentEnroll();
335 }
336 
CancelCurrentEnrollIfExist()337 void UserIdmService::CancelCurrentEnrollIfExist()
338 {
339     if (ContextPool::Instance().Select(CONTEXT_ENROLL).size() == 0) {
340         return;
341     }
342 
343     IAM_LOGI("cancel current enroll due to new add credential request or delete");
344     CancelCurrentEnroll();
345 }
346 
CancelCurrentEnroll()347 int32_t UserIdmService::CancelCurrentEnroll()
348 {
349     IAM_LOGD("start");
350     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
351     int32_t ret = GENERAL_ERROR;
352     for (const auto &context : contextList) {
353         if (auto ctx = context.lock(); ctx != nullptr) {
354             IAM_LOGI("stop the old context %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
355             ctx->Stop();
356             ContextPool::Instance().Delete(ctx->GetContextId());
357             ret = SUCCESS;
358         }
359     }
360     IAM_LOGI("result %{public}d", ret);
361     return ret;
362 }
363 
EnforceDelUser(int32_t userId,const sptr<IdmCallbackInterface> & callback)364 int32_t UserIdmService::EnforceDelUser(int32_t userId, const sptr<IdmCallbackInterface> &callback)
365 {
366     IAM_LOGI("to delete userid: %{public}d", userId);
367     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
368     IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, INVALID_PARAMETERS);
369 
370     Attributes extraInfo;
371     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_ENFORCE_DELETE_USER);
372     if (contextCallback == nullptr) {
373         IAM_LOGE("failed to construct context callback");
374         callback->OnResult(GENERAL_ERROR, extraInfo);
375         return GENERAL_ERROR;
376     }
377     std::string callerName = "";
378     int32_t callerType = 0;
379     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
380     contextCallback->SetTraceCallerType(callerType);
381     contextCallback->SetTraceCallerName(callerName);
382     contextCallback->SetTraceUserId(userId);
383 
384     if (!IpcCommon::CheckPermission(*this, ENFORCE_USER_IDM)) {
385         IAM_LOGE("failed to check permission");
386         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
387         return CHECK_PERMISSION_FAILED;
388     }
389 
390     std::lock_guard<std::mutex> lock(mutex_);
391     CancelCurrentEnrollIfExist();
392     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
393     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfo);
394     if (ret != SUCCESS) {
395         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
396         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
397         return ret;
398     }
399     if (userInfo == nullptr) {
400         IAM_LOGE("current userid %{public}d is not existed", userId);
401         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
402         return INVALID_PARAMETERS;
403     }
404     ret = EnforceDelUserInner(userId, contextCallback, "EnforceDeleteUser");
405     if (ret != SUCCESS) {
406         IAM_LOGE("failed to enforce delete user");
407         static_cast<void>(extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, 0));
408         contextCallback->OnResult(ret, extraInfo);
409         return ret;
410     }
411 
412     IAM_LOGI("delete user success");
413     contextCallback->OnResult(SUCCESS, extraInfo);
414     return SUCCESS;
415 }
416 
DelUser(int32_t userId,const std::vector<uint8_t> authToken,const sptr<IdmCallbackInterface> & callback)417 void UserIdmService::DelUser(int32_t userId, const std::vector<uint8_t> authToken,
418     const sptr<IdmCallbackInterface> &callback)
419 {
420     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
421     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
422 
423     Attributes extraInfo;
424     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_USER);
425     if (contextCallback == nullptr) {
426         IAM_LOGE("failed to construct context callback");
427         callback->OnResult(GENERAL_ERROR, extraInfo);
428         return;
429     }
430     std::string callerName = "";
431     int32_t callerType = 0;
432     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
433     contextCallback->SetTraceCallerName(callerName);
434     contextCallback->SetTraceCallerType(callerType);
435     contextCallback->SetTraceUserId(userId);
436 
437     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
438         IAM_LOGE("failed to check permission");
439         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
440         return;
441     }
442 
443     std::lock_guard<std::mutex> lock(mutex_);
444     CancelCurrentEnrollIfExist();
445 
446     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
447     std::vector<uint8_t> rootSecret;
448     int32_t ret = UserIdmDatabase::Instance().DeleteUser(userId, authToken, credInfos, rootSecret);
449     if (ret != SUCCESS) {
450         IAM_LOGE("failed to delete user");
451         contextCallback->OnResult(ret, extraInfo);
452         return;
453     }
454     if (!extraInfo.SetUint8ArrayValue(Attributes::ATTR_OLD_ROOT_SECRET, rootSecret)) {
455         IAM_LOGE("set rootsecret to extraInfo failed");
456         contextCallback->OnResult(ret, extraInfo);
457         return;
458     }
459     SetAuthTypeTrace(credInfos, contextCallback);
460     contextCallback->OnResult(ret, extraInfo);
461 
462     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, "DeleteUser");
463     if (ret != SUCCESS) {
464         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
465     }
466     IAM_LOGI("delete user end");
467     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
468     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
469 }
470 
DelCredential(int32_t userId,uint64_t credentialId,const std::vector<uint8_t> & authToken,const sptr<IdmCallbackInterface> & callback)471 void UserIdmService::DelCredential(int32_t userId, uint64_t credentialId,
472     const std::vector<uint8_t> &authToken, const sptr<IdmCallbackInterface> &callback)
473 {
474     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
475     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
476 
477     Attributes extraInfo;
478     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_CREDENTIAL);
479     if (contextCallback == nullptr) {
480         IAM_LOGE("failed to construct context callback");
481         callback->OnResult(GENERAL_ERROR, extraInfo);
482         return;
483     }
484     std::string callerName = "";
485     int32_t callerType = 0;
486     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
487     contextCallback->SetTraceCallerName(callerName);
488     contextCallback->SetTraceCallerType(callerType);
489     contextCallback->SetTraceUserId(userId);
490 
491     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
492         IAM_LOGE("failed to check permission");
493         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
494         return;
495     }
496 
497     std::lock_guard<std::mutex> lock(mutex_);
498     CancelCurrentEnrollIfExist();
499 
500     std::shared_ptr<CredentialInfoInterface> oldInfo;
501     auto ret = UserIdmDatabase::Instance().DeleteCredentialInfo(userId, credentialId, authToken, oldInfo);
502     if (ret != SUCCESS) {
503         IAM_LOGE("failed to delete CredentialInfo");
504         contextCallback->OnResult(ret, extraInfo);
505         return;
506     }
507     if (oldInfo != nullptr) {
508         contextCallback->SetTraceAuthType(oldInfo->GetAuthType());
509     }
510 
511     IAM_LOGI("delete credentialInfo success");
512     std::vector<std::shared_ptr<CredentialInfoInterface>> list = {oldInfo};
513     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(list, "DeleteTemplate");
514     if (ret != SUCCESS) {
515         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
516     }
517 
518     contextCallback->OnResult(ret, extraInfo);
519     if (oldInfo != nullptr) {
520         PublishCommonEvent(userId, credentialId, oldInfo->GetAuthType());
521     }
522 }
523 
Dump(int fd,const std::vector<std::u16string> & args)524 int UserIdmService::Dump(int fd, const std::vector<std::u16string> &args)
525 {
526     IAM_LOGI("start");
527     if (fd < 0) {
528         IAM_LOGE("invalid parameters");
529         dprintf(fd, "Invalid parameters.\n");
530         return INVALID_PARAMETERS;
531     }
532     std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
533     if (arg0.empty() || arg0.compare("-h") == 0) {
534         dprintf(fd, "Usage:\n");
535         dprintf(fd, "      -h: command help.\n");
536         dprintf(fd, "      -l: active user info dump.\n");
537         return SUCCESS;
538     }
539     if (arg0.compare("-l") != 0) {
540         IAM_LOGE("invalid option");
541         dprintf(fd, "Invalid option\n");
542         return GENERAL_ERROR;
543     }
544 
545     std::optional<int32_t> activeUserId;
546     if (IpcCommon::GetActiveUserId(activeUserId) != SUCCESS) {
547         dprintf(fd, "Internal error.\n");
548         IAM_LOGE("failed to get active id");
549         return GENERAL_ERROR;
550     }
551     dprintf(fd, "Active user is %d\n", activeUserId.value());
552     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
553     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(activeUserId.value(), userInfo);
554     if (ret != SUCCESS) {
555         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, activeUserId.value());
556         return GENERAL_ERROR;
557     }
558     if (userInfo == nullptr) {
559         IAM_LOGE("userInfo is null");
560         return SUCCESS;
561     }
562     auto enrolledInfo = userInfo->GetEnrolledInfo();
563     for (auto &info : enrolledInfo) {
564         if (info != nullptr) {
565             dprintf(fd, "AuthType %s is enrolled.\n", Common::AuthTypeToStr(info->GetAuthType()));
566         }
567     }
568     return SUCCESS;
569 }
570 
SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> & credInfos,const std::shared_ptr<ContextCallback> & contextCallback)571 void UserIdmService::SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> &credInfos,
572     const std::shared_ptr<ContextCallback> &contextCallback)
573 {
574     uint32_t authTypeTrace = 0;
575     for (const auto &credInfo : credInfos) {
576         if (credInfo == nullptr) {
577             IAM_LOGE("credInfo is nullptr");
578             continue;
579         }
580         authTypeTrace |= static_cast<uint32_t>(credInfo->GetAuthType());
581     }
582     contextCallback->SetTraceAuthType(static_cast<int32_t>(authTypeTrace));
583 }
584 
EnforceDelUserInner(int32_t userId,std::shared_ptr<ContextCallback> callbackForTrace,std::string changeReasonTrace)585 int32_t UserIdmService::EnforceDelUserInner(int32_t userId, std::shared_ptr<ContextCallback> callbackForTrace,
586     std::string changeReasonTrace)
587 {
588     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
589     int32_t ret = UserIdmDatabase::Instance().DeleteUserEnforce(userId, credInfos);
590     if (ret != SUCCESS) {
591         IAM_LOGE("failed to enforce delete user, ret:%{public}d", ret);
592         return ret;
593     }
594     SetAuthTypeTrace(credInfos, callbackForTrace);
595     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, changeReasonTrace);
596     if (ret != SUCCESS) {
597         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
598         // The caller doesn't need to care executor delete result.
599         return SUCCESS;
600     }
601 
602     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
603     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
604     IAM_LOGI("delete user success, userId:%{public}d", userId);
605     return SUCCESS;
606 }
607 
ClearRedundancyCredentialInner()608 void UserIdmService::ClearRedundancyCredentialInner()
609 {
610     IAM_LOGI("start");
611     std::vector<int32_t> accountInfo;
612     int32_t ret = IpcCommon::GetAllUserId(accountInfo);
613     if (ret != SUCCESS) {
614         IAM_LOGE("GetAllUserId failed");
615         return;
616     }
617 
618     auto userInfos = UserIdmDatabase::Instance().GetAllExtUserInfo();
619     if (userInfos.empty()) {
620         IAM_LOGE("no userInfo");
621         return;
622     }
623     std::string callerName = "";
624     int32_t callerType = 0;
625     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
626 
627     for (const auto &iter : userInfos) {
628         int32_t userId = iter->GetUserId();
629         auto callbackForTrace = ContextCallback::NewDummyInstance(TRACE_DELETE_REDUNDANCY);
630         if (callbackForTrace == nullptr) {
631             IAM_LOGE("failed to get callbackForTrace");
632             continue;
633         }
634         callbackForTrace->SetTraceUserId(userId);
635         callbackForTrace->SetTraceCallerName(callerName);
636         callbackForTrace->SetTraceCallerType(callerType);
637         std::vector<int32_t>::iterator it = std::find(accountInfo.begin(), accountInfo.end(), userId);
638         if (it == accountInfo.end()) {
639             ret = EnforceDelUserInner(userId, callbackForTrace, "DeleteRedundancy");
640             Attributes extraInfo;
641             callbackForTrace->OnResult(ret, extraInfo);
642             IAM_LOGE("ClearRedundancytCredential, userId: %{public}d", userId);
643         }
644     }
645 }
646 
ClearRedundancyCredential(const sptr<IdmCallbackInterface> & callback)647 void UserIdmService::ClearRedundancyCredential(const sptr<IdmCallbackInterface> &callback)
648 {
649     IAM_LOGI("start");
650     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
651     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
652 
653     Attributes extraInfo;
654     auto contextCallback = ContextCallback::NewInstance(callback, NO_NEED_TRACE);
655     if (contextCallback == nullptr) {
656         IAM_LOGE("failed to construct context callback");
657         callback->OnResult(GENERAL_ERROR, extraInfo);
658         return;
659     }
660 
661     if (!IpcCommon::CheckPermission(*this, CLEAR_REDUNDANCY_PERMISSION)) {
662         IAM_LOGE("failed to check permission");
663         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
664         return;
665     }
666 
667     std::lock_guard<std::mutex> lock(mutex_);
668     CancelCurrentEnrollIfExist();
669 
670     this->ClearRedundancyCredentialInner();
671     contextCallback->OnResult(SUCCESS, extraInfo);
672 }
673 
PublishCommonEvent(int32_t userId,uint64_t credentialId,AuthType authType)674 void UserIdmService::PublishCommonEvent(int32_t userId, uint64_t credentialId, AuthType authType)
675 {
676     std::vector<std::shared_ptr<CredentialInfoInterface>> credentialInfos;
677     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType, credentialInfos);
678     if (ret != SUCCESS) {
679         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret, userId, authType);
680         return;
681     }
682     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, authType, credentialInfos.size());
683     PublishEventAdapter::GetInstance().PublishUpdatedEvent(userId, credentialId);
684 }
685 } // namespace UserAuth
686 } // namespace UserIam
687 } // namespace OHOS