• 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_appstate_observer.h"
22 #include "context_helper.h"
23 #include "context_pool.h"
24 #include "event_listener_manager.h"
25 #include "hdi_wrapper.h"
26 #include "iam_callback_proxy.h"
27 #include "iam_check.h"
28 #include "iam_logger.h"
29 #include "iam_para2str.h"
30 #include "iam_defines.h"
31 #include "iam_time.h"
32 #include "ipc_common.h"
33 #include "ipc_skeleton.h"
34 #include "iam_common_defines.h"
35 #include "load_mode_handler.h"
36 #include "publish_event_adapter.h"
37 #include "resource_node_pool.h"
38 #include "resource_node_utils.h"
39 #include "service_init_manager.h"
40 #include "user_idm_database.h"
41 #include "xcollie_helper.h"
42 
43 #define LOG_TAG "USER_AUTH_SA"
44 
45 namespace OHOS {
46 namespace UserIam {
47 namespace UserAuth {
48 REGISTER_SYSTEM_ABILITY_BY_ID(UserIdmService, SUBSYS_USERIAM_SYS_ABILITY_USERIDM, true);
49 constexpr int32_t USERIAM_IPC_THREAD_NUM = 4;
UserIdmService(int32_t systemAbilityId,bool runOnCreate)50 UserIdmService::UserIdmService(int32_t systemAbilityId, bool runOnCreate)
51     : SystemAbility(systemAbilityId, runOnCreate), UserIdmStub(true)
52 {
53 }
54 
OnStart()55 void UserIdmService::OnStart()
56 {
57     IAM_LOGI("Sa start UserIdmService");
58     IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
59     if (!Publish(this)) {
60         IAM_LOGE("failed to publish service");
61     }
62     ServiceInitManager::GetInstance().OnIdmServiceStart();
63 }
64 
OnStop()65 void UserIdmService::OnStop()
66 {
67     IAM_LOGI("Sa stop UserIdmService");
68     ServiceInitManager::GetInstance().OnIdmServiceStop();
69 }
70 
OpenSession(int32_t userId,std::vector<uint8_t> & challenge)71 int32_t UserIdmService::OpenSession(int32_t userId, std::vector<uint8_t> &challenge)
72 {
73     IAM_LOGI("start");
74     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
75     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
76         IAM_LOGE("failed to check permission");
77         return CHECK_PERMISSION_FAILED;
78     }
79     CancelCurrentEnrollIfExist();
80 
81     auto hdi = HdiWrapper::GetHdiInstance();
82     if (hdi == nullptr) {
83         IAM_LOGE("bad hdi");
84         return GENERAL_ERROR;
85     }
86     std::lock_guard<std::mutex> lock(mutex_);
87     int32_t ret = hdi->OpenSession(userId, challenge);
88     if (ret != HDF_SUCCESS) {
89         IAM_LOGE("failed to open session, error code:%{public}d", ret);
90         return GENERAL_ERROR;
91     }
92     return SUCCESS;
93 }
94 
CloseSession(int32_t userId)95 int32_t UserIdmService::CloseSession(int32_t userId)
96 {
97     IAM_LOGI("start");
98     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
99     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
100         IAM_LOGE("failed to check permission");
101         return CHECK_PERMISSION_FAILED;
102     }
103     auto hdi = HdiWrapper::GetHdiInstance();
104     if (hdi == nullptr) {
105         IAM_LOGE("bad hdi");
106         return GENERAL_ERROR;
107     }
108     std::lock_guard<std::mutex> lock(mutex_);
109     int32_t ret = hdi->CloseSession(userId);
110     if (ret != HDF_SUCCESS) {
111         IAM_LOGE("failed to close session, error code:%{public}d", ret);
112         return GENERAL_ERROR;
113     }
114     return SUCCESS;
115 }
116 
GetCredentialInfoInner(int32_t userId,AuthType authType,std::vector<CredentialInfo> & credInfoList)117 int32_t UserIdmService::GetCredentialInfoInner(int32_t userId, AuthType authType,
118     std::vector<CredentialInfo> &credInfoList)
119 {
120     IAM_LOGD("start");
121     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
122         IAM_LOGE("failed to check permission");
123         return CHECK_PERMISSION_FAILED;
124     }
125 
126     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
127     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType, credInfos);
128     if (ret != SUCCESS) {
129         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
130             userId, authType);
131         return GENERAL_ERROR;
132     }
133 
134     if (credInfos.empty()) {
135         IAM_LOGI("no cred enrolled");
136         return NOT_ENROLLED;
137     }
138     for (const auto &credInfo : credInfos) {
139         if (credInfo == nullptr) {
140             IAM_LOGE("credInfo is nullptr");
141             return GENERAL_ERROR;
142         }
143         CredentialInfo info = {};
144         info.credentialId = credInfo->GetCredentialId();
145         info.templateId = credInfo->GetTemplateId();
146         info.authType = credInfo->GetAuthType();
147         info.pinType = credInfo->GetAuthSubType();
148         info.isAbandoned = credInfo->GetAbandonFlag();
149         info.validityPeriod = credInfo->GetValidPeriod();
150         credInfoList.push_back(info);
151     }
152     return SUCCESS;
153 }
154 
GetCredentialInfoImpl(int32_t userId,int32_t authType,const sptr<IIdmGetCredInfoCallback> & callback)155 int32_t UserIdmService::GetCredentialInfoImpl(int32_t userId, int32_t authType,
156     const sptr<IIdmGetCredInfoCallback> &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<IpcCredentialInfo> ipcCredInfoList;
165     std::vector<CredentialInfo> credInfoList;
166     int32_t ret = GetCredentialInfoInner(userId, static_cast<AuthType>(authType), credInfoList);
167     if (ret != SUCCESS) {
168         if (ret == NOT_ENROLLED) {
169             IAM_LOGI("credential is not enrolled");
170         } else {
171             IAM_LOGE("GetCredentialInfoInner fail, ret: %{public}d", ret);
172         }
173         credInfoList.clear();
174     }
175 
176     bool hasAbandonedCredential = false;
177     for (auto &iter : credInfoList) {
178         if (iter.isAbandoned && iter.validityPeriod == 0) {
179             hasAbandonedCredential = true;
180             continue;
181         }
182         IpcCredentialInfo ipcCredInfo;
183         ipcCredInfo.authType = static_cast<int32_t>(iter.authType);
184         ipcCredInfo.pinType = static_cast<int32_t>(iter.pinType.value_or(PIN_SIX));
185         ipcCredInfo.credentialId = iter.credentialId;
186         ipcCredInfo.templateId = iter.templateId;
187         ipcCredInfo.isAbandoned = iter.isAbandoned;
188         ipcCredInfo.validityPeriod = iter.validityPeriod;
189         ipcCredInfoList.push_back(ipcCredInfo);
190     }
191 
192     auto retCode = callback->OnCredentialInfos(ret, ipcCredInfoList);
193     if (retCode != SUCCESS) {
194         IAM_LOGE("OnCredentialInfos fail, ret: %{public}d", retCode);
195     }
196 
197     if (hasAbandonedCredential) {
198         ClearUnavailableCredential(userId);
199     }
200     return ret;
201 }
202 
GetCredentialInfo(int32_t userId,int32_t authType,const sptr<IIdmGetCredInfoCallback> & callback,int32_t & funcResult)203 int32_t UserIdmService::GetCredentialInfo(int32_t userId, int32_t authType,
204     const sptr<IIdmGetCredInfoCallback> &callback, int32_t &funcResult)
205 {
206     funcResult = GetCredentialInfoImpl(userId, authType, callback);
207     return SUCCESS;
208 }
209 
GetSecInfoInner(int32_t userId,SecUserInfo & secUserInfo)210 int32_t UserIdmService::GetSecInfoInner(int32_t userId, SecUserInfo &secUserInfo)
211 {
212     IAM_LOGI("start");
213     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
214         IAM_LOGE("failed to check permission");
215         return CHECK_PERMISSION_FAILED;
216     }
217     std::shared_ptr<SecureUserInfoInterface> userInfos = nullptr;
218     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfos);
219     if (ret != SUCCESS) {
220         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
221         return ret;
222     }
223     if (userInfos == nullptr) {
224         IAM_LOGE("current userid %{public}d is not existed", userId);
225         return GENERAL_ERROR;
226     }
227     std::vector<std::shared_ptr<EnrolledInfoInterface>> enrolledInfos = userInfos->GetEnrolledInfo();
228     for (const auto &enrolledInfo : enrolledInfos) {
229         if (enrolledInfo == nullptr) {
230             IAM_LOGE("enrolledInfo is nullptr");
231             return GENERAL_ERROR;
232         }
233         EnrolledInfo info = {enrolledInfo->GetAuthType(), enrolledInfo->GetEnrolledId()};
234         secUserInfo.enrolledInfo.push_back(info);
235     }
236     secUserInfo.secureUid = userInfos->GetSecUserId();
237     return SUCCESS;
238 }
239 
GetSecInfo(int32_t userId,const sptr<IIdmGetSecureUserInfoCallback> & callback)240 int32_t UserIdmService::GetSecInfo(int32_t userId, const sptr<IIdmGetSecureUserInfoCallback> &callback)
241 {
242     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
243     if (callback == nullptr) {
244         IAM_LOGE("callback is nullptr");
245         return INVALID_PARAMETERS;
246     }
247 
248     IpcSecUserInfo ipcSecUserInfo;
249     SecUserInfo secUserInfo = {};
250     int32_t ret = GetSecInfoInner(userId, secUserInfo);
251     if (ret != SUCCESS) {
252         IAM_LOGE("GetSecInfoInner fail, ret: %{public}d", ret);
253         secUserInfo.secureUid = 0;
254         secUserInfo.enrolledInfo.clear();
255     }
256 
257     for (auto &iter : secUserInfo.enrolledInfo) {
258         IpcEnrolledInfo ipcEnrolledInfo;
259         ipcEnrolledInfo.authType = static_cast<int32_t>(iter.authType);
260         ipcEnrolledInfo.enrolledId = iter.enrolledId;
261         ipcSecUserInfo.enrolledInfo.push_back(ipcEnrolledInfo);
262     }
263     ipcSecUserInfo.secureUid = secUserInfo.secureUid;
264     auto retCode = callback->OnSecureUserInfo(ret, ipcSecUserInfo);
265     if (retCode != SUCCESS) {
266         IAM_LOGE("OnSecureUserInfo fail, ret: %{public}d", retCode);
267     }
268     return ret;
269 }
270 
StartEnroll(Enrollment::EnrollmentPara & para,const std::shared_ptr<ContextCallback> & contextCallback,Attributes & extraInfo,bool needSubscribeAppState)271 int32_t UserIdmService::StartEnroll(Enrollment::EnrollmentPara &para,
272     const std::shared_ptr<ContextCallback> &contextCallback, Attributes &extraInfo, bool needSubscribeAppState)
273 {
274     if (!para.isUpdate && para.authType == PIN && !para.token.empty()) {
275         IAM_LOGI("auth type is pin, clear token");
276         para.token.clear();
277     }
278 
279     auto context = ContextFactory::CreateEnrollContext(para, contextCallback, needSubscribeAppState);
280     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
281         IAM_LOGE("failed to insert context");
282         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
283         return GENERAL_ERROR;
284     }
285     contextCallback->SetTraceRequestContextId(context->GetContextId());
286     auto cleaner = ContextHelper::Cleaner(context);
287     contextCallback->SetCleaner(cleaner);
288 
289     if (!context->Start()) {
290         IAM_LOGE("failed to start enroll");
291         contextCallback->OnResult(context->GetLatestError(), extraInfo);
292         return GENERAL_ERROR;
293     }
294     return SUCCESS;
295 }
296 
AddCredential(int32_t userId,const IpcCredentialPara & ipcCredentialPara,const sptr<IIamCallback> & idmCallback,bool isUpdate)297 int32_t UserIdmService::AddCredential(int32_t userId, const IpcCredentialPara &ipcCredentialPara,
298     const sptr<IIamCallback> &idmCallback, bool isUpdate)
299 {
300     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
301     IF_FALSE_LOGE_AND_RETURN_VAL(idmCallback != nullptr, INVALID_PARAMETERS);
302 
303     Attributes extraInfo;
304     auto contextCallback = ContextCallback::NewInstance(idmCallback,
305         isUpdate ? TRACE_UPDATE_CREDENTIAL : TRACE_ADD_CREDENTIAL);
306     if (contextCallback == nullptr) {
307         IAM_LOGE("failed to construct context callback");
308         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
309         return GENERAL_ERROR;
310     }
311     std::string callerName = "";
312     int32_t callerType = Security::AccessToken::TOKEN_INVALID;
313     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
314     contextCallback->SetTraceCallerName(callerName);
315     contextCallback->SetTraceCallerType(callerType);
316     contextCallback->SetTraceUserId(userId);
317     contextCallback->SetTraceAuthType(static_cast<AuthType>(ipcCredentialPara.authType));
318     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
319         IAM_LOGE("failed to check permission");
320         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
321         return CHECK_PERMISSION_FAILED;
322     }
323 
324     std::lock_guard<std::mutex> lock(mutex_);
325     CancelCurrentEnrollIfExist();
326     Enrollment::EnrollmentPara para = {};
327     para.authType = static_cast<AuthType>(ipcCredentialPara.authType);
328     para.userId = userId;
329     para.pinType = static_cast<PinSubType>(ipcCredentialPara.pinType);
330     para.tokenId = IpcCommon::GetAccessTokenId(*this);
331     para.token = ipcCredentialPara.token;
332     para.isUpdate = isUpdate;
333     para.sdkVersion = INNER_API_VERSION_10000;
334     para.callerName = callerName;
335     para.callerType = callerType;
336     bool needSubscribeAppState = !IpcCommon::CheckPermission(*this, USER_AUTH_FROM_BACKGROUND);
337     return StartEnroll(para, contextCallback, extraInfo, needSubscribeAppState);
338 }
339 
UpdateCredential(int32_t userId,const IpcCredentialPara & ipcCredentialPara,const sptr<IIamCallback> & idmCallback)340 int32_t UserIdmService::UpdateCredential(int32_t userId, const IpcCredentialPara &ipcCredentialPara,
341     const sptr<IIamCallback> &idmCallback)
342 {
343     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
344     if (idmCallback == nullptr) {
345         IAM_LOGE("callback is nullptr");
346         return INVALID_PARAMETERS;
347     }
348 
349     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
350     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId,
351         static_cast<AuthType>(ipcCredentialPara.authType), credInfos);
352     if (ret != SUCCESS) {
353         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d",
354             ret, userId, ipcCredentialPara.authType);
355         Attributes extraInfo;
356         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
357         return GENERAL_ERROR;
358     }
359 
360     if (credInfos.empty()) {
361         IAM_LOGE("current userid %{public}d has no credential for type %{public}u",
362             userId, ipcCredentialPara.authType);
363         Attributes extraInfo;
364         idmCallback->OnResult(NOT_ENROLLED, extraInfo.Serialize());
365         return SUCCESS;
366     }
367 
368     return AddCredential(userId, ipcCredentialPara, idmCallback, true);
369 }
370 
Cancel(int32_t userId)371 int32_t UserIdmService::Cancel(int32_t userId)
372 {
373     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
374     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
375         IAM_LOGE("failed to check permission");
376         return CHECK_PERMISSION_FAILED;
377     }
378 
379     std::lock_guard<std::mutex> lock(mutex_);
380     uint32_t tokenId = IpcCommon::GetAccessTokenId(*this);
381     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
382     int32_t ret = GENERAL_ERROR;
383     for (const auto &context : contextList) {
384         if (auto ctx = context.lock(); ctx != nullptr && userId == ctx->GetUserId() && tokenId == ctx->GetTokenId()) {
385             if (!ctx->Stop()) {
386                 IAM_LOGE("failed stop %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
387                 ret = ctx->GetLatestError();
388             }
389         }
390     }
391     return ret;
392 }
393 
CancelCurrentEnrollIfExist()394 void UserIdmService::CancelCurrentEnrollIfExist()
395 {
396     IAM_LOGD("start");
397     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
398     for (const auto &context : contextList) {
399         if (auto ctx = context.lock(); ctx != nullptr) {
400             IAM_LOGI("stop the old context %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
401             ctx->Stop();
402         }
403     }
404 }
405 
EnforceDelUser(int32_t userId,const sptr<IIamCallback> & idmCallback)406 int32_t UserIdmService::EnforceDelUser(int32_t userId, const sptr<IIamCallback> &idmCallback)
407 {
408     IAM_LOGI("to delete userid: %{public}d", userId);
409     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
410     IF_FALSE_LOGE_AND_RETURN_VAL(idmCallback != nullptr, INVALID_PARAMETERS);
411 
412     Attributes extraInfo;
413     auto contextCallback = ContextCallback::NewInstance(idmCallback, TRACE_ENFORCE_DELETE_USER);
414     if (contextCallback == nullptr) {
415         IAM_LOGE("failed to construct context callback");
416         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
417         return GENERAL_ERROR;
418     }
419     std::string callerName = "";
420     int32_t callerType = Security::AccessToken::TOKEN_INVALID;
421     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
422     contextCallback->SetTraceCallerType(callerType);
423     contextCallback->SetTraceCallerName(callerName);
424     contextCallback->SetTraceUserId(userId);
425 
426     if (!IpcCommon::CheckPermission(*this, ENFORCE_USER_IDM)) {
427         IAM_LOGE("failed to check permission");
428         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
429         return CHECK_PERMISSION_FAILED;
430     }
431 
432     std::lock_guard<std::mutex> lock(mutex_);
433     CancelCurrentEnrollIfExist();
434     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
435     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(userId, userInfo);
436     if (ret != SUCCESS) {
437         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, userId);
438         contextCallback->OnResult(ret, extraInfo);
439         return ret;
440     }
441     if (userInfo == nullptr) {
442         IAM_LOGE("current userid %{public}d is not existed", userId);
443         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
444         return GENERAL_ERROR;
445     }
446     CredChangeEventInfo changeInfo = {callerName, callerType, 0, 0, false};
447     ret = EnforceDelUserInner(userId, contextCallback, "EnforceDeleteUser", changeInfo);
448     if (ret != SUCCESS) {
449         IAM_LOGE("failed to enforce delete user");
450         static_cast<void>(extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, 0));
451         contextCallback->OnResult(ret, extraInfo);
452         return ret;
453     }
454 
455     IAM_LOGI("delete user success");
456     contextCallback->OnResult(SUCCESS, extraInfo);
457     return SUCCESS;
458 }
459 
DelUser(int32_t userId,const std::vector<uint8_t> & authToken,const sptr<IIamCallback> & idmCallback)460 int32_t UserIdmService::DelUser(int32_t userId, const std::vector<uint8_t> &authToken,
461     const sptr<IIamCallback> &idmCallback)
462 {
463     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
464     IF_FALSE_LOGE_AND_RETURN_VAL(idmCallback != nullptr, INVALID_PARAMETERS);
465 
466     Attributes extraInfo;
467     auto contextCallback = ContextCallback::NewInstance(idmCallback, TRACE_DELETE_USER);
468     if (contextCallback == nullptr) {
469         IAM_LOGE("failed to construct context callback");
470         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
471         return GENERAL_ERROR;
472     }
473     std::string callerName = "";
474     int32_t callerType = Security::AccessToken::TOKEN_INVALID;
475     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
476     contextCallback->SetTraceCallerName(callerName);
477     contextCallback->SetTraceCallerType(callerType);
478     contextCallback->SetTraceUserId(userId);
479 
480     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
481         IAM_LOGE("failed to check permission");
482         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
483         return CHECK_PERMISSION_FAILED;
484     }
485 
486     std::lock_guard<std::mutex> lock(mutex_);
487     CancelCurrentEnrollIfExist();
488 
489     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
490     std::vector<uint8_t> rootSecret;
491     int32_t ret = UserIdmDatabase::Instance().DeleteUser(userId, authToken, credInfos, rootSecret);
492     if (ret != SUCCESS) {
493         IAM_LOGE("failed to delete user");
494         contextCallback->OnResult(ret, extraInfo);
495         return ret;
496     }
497     if (!extraInfo.SetUint8ArrayValue(Attributes::ATTR_OLD_ROOT_SECRET, rootSecret)) {
498         IAM_LOGE("set rootsecret to extraInfo failed");
499         contextCallback->OnResult(ret, extraInfo);
500         return ret;
501     }
502     SetAuthTypeTrace(credInfos, contextCallback);
503     contextCallback->OnResult(ret, extraInfo);
504 
505     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, "DeleteUser");
506     if (ret != SUCCESS) {
507         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
508     }
509     IAM_LOGI("delete user end");
510     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
511     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
512     CredChangeEventInfo changeInfo = {callerName, callerType, 0, 0, false};
513     CredChangeEventListenerManager::GetInstance().OnNotifyCredChangeEvent(userId, PIN, DEL_USER, changeInfo);
514     return SUCCESS;
515 }
516 
StartDelete(Deletion::DeleteParam & para,const std::shared_ptr<ContextCallback> & contextCallback,Attributes & extraInfo)517 int32_t UserIdmService::StartDelete(Deletion::DeleteParam &para,
518     const std::shared_ptr<ContextCallback> &contextCallback, Attributes &extraInfo)
519 {
520     auto context = ContextFactory::CreateDeleteContext(para, contextCallback);
521     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
522         IAM_LOGE("failed to insert context");
523         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
524         return GENERAL_ERROR;
525     }
526     contextCallback->SetTraceRequestContextId(context->GetContextId());
527     auto cleaner = ContextHelper::Cleaner(context);
528     contextCallback->SetCleaner(cleaner);
529 
530     if (!context->Start()) {
531         IAM_LOGE("failed to start delete");
532         contextCallback->OnResult(context->GetLatestError(), extraInfo);
533         return context->GetLatestError();
534     }
535     return SUCCESS;
536 }
537 
DelCredential(int32_t userId,uint64_t credentialId,const std::vector<uint8_t> & authToken,const sptr<IIamCallback> & idmCallback)538 int32_t UserIdmService::DelCredential(int32_t userId, uint64_t credentialId,
539     const std::vector<uint8_t> &authToken, const sptr<IIamCallback> &idmCallback)
540 {
541     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
542     IF_FALSE_LOGE_AND_RETURN_VAL(idmCallback != nullptr, INVALID_PARAMETERS);
543 
544     Attributes extraInfo;
545     auto contextCallback = ContextCallback::NewInstance(idmCallback, TRACE_DELETE_CREDENTIAL);
546     if (contextCallback == nullptr) {
547         IAM_LOGE("failed to construct context callback");
548         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
549         return GENERAL_ERROR;
550     }
551     std::string callerName = "";
552     int32_t callerType = Security::AccessToken::TOKEN_INVALID;
553     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
554     contextCallback->SetTraceCallerName(callerName);
555     contextCallback->SetTraceCallerType(callerType);
556     contextCallback->SetTraceUserId(userId);
557 
558     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
559         IAM_LOGE("failed to check permission");
560         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
561         return CHECK_PERMISSION_FAILED;
562     }
563 
564     std::lock_guard<std::mutex> lock(mutex_);
565     CancelCurrentEnrollIfExist();
566     std::shared_ptr<CredentialInfoInterface> credInfo;
567     Deletion::DeleteParam deleteParam = {
568         .userId = userId,
569         .credentialId = credentialId,
570         .tokenId = IpcCommon::GetAccessTokenId(*this),
571         .callerName = callerName,
572         .callerType = callerType,
573         .token = authToken,
574     };
575     return StartDelete(deleteParam, contextCallback, extraInfo);
576 }
577 
Dump(int fd,const std::vector<std::u16string> & args)578 int UserIdmService::Dump(int fd, const std::vector<std::u16string> &args)
579 {
580     IAM_LOGI("start");
581     if (fd < 0) {
582         IAM_LOGE("invalid parameters");
583         return INVALID_PARAMETERS;
584     }
585     std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
586     if (arg0.empty() || arg0.compare("-h") == 0) {
587         dprintf(fd, "Usage:\n");
588         dprintf(fd, "      -h: command help.\n");
589         dprintf(fd, "      -l: active user info dump.\n");
590         return SUCCESS;
591     }
592     if (arg0.compare("-l") != 0) {
593         IAM_LOGE("invalid option");
594         dprintf(fd, "Invalid option\n");
595         return GENERAL_ERROR;
596     }
597 
598     std::optional<int32_t> activeUserId;
599     if (IpcCommon::GetActiveUserId(activeUserId) != SUCCESS) {
600         dprintf(fd, "Internal error.\n");
601         IAM_LOGE("failed to get active id");
602         return GENERAL_ERROR;
603     }
604     dprintf(fd, "Active user is %d\n", activeUserId.value());
605     std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
606     int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(activeUserId.value(), userInfo);
607     if (ret != SUCCESS) {
608         IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, activeUserId.value());
609         return GENERAL_ERROR;
610     }
611     if (userInfo == nullptr) {
612         IAM_LOGE("userInfo is null");
613         return SUCCESS;
614     }
615     auto enrolledInfo = userInfo->GetEnrolledInfo();
616     for (auto &info : enrolledInfo) {
617         if (info != nullptr) {
618             dprintf(fd, "AuthType %s is enrolled.\n", Common::AuthTypeToStr(info->GetAuthType()));
619         }
620     }
621     return SUCCESS;
622 }
623 
SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> & credInfos,const std::shared_ptr<ContextCallback> & contextCallback)624 void UserIdmService::SetAuthTypeTrace(const std::vector<std::shared_ptr<CredentialInfoInterface>> &credInfos,
625     const std::shared_ptr<ContextCallback> &contextCallback)
626 {
627     uint32_t authTypeTrace = 0;
628     for (const auto &credInfo : credInfos) {
629         if (credInfo == nullptr) {
630             IAM_LOGE("credInfo is nullptr");
631             continue;
632         }
633         authTypeTrace |= static_cast<uint32_t>(credInfo->GetAuthType());
634     }
635     contextCallback->SetTraceAuthType(static_cast<int32_t>(authTypeTrace));
636 }
637 
EnforceDelUserInner(int32_t userId,std::shared_ptr<ContextCallback> callbackForTrace,std::string changeReasonTrace,const CredChangeEventInfo & changeInfo)638 int32_t UserIdmService::EnforceDelUserInner(int32_t userId, std::shared_ptr<ContextCallback> callbackForTrace,
639     std::string changeReasonTrace, const CredChangeEventInfo &changeInfo)
640 {
641     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
642     int32_t ret = UserIdmDatabase::Instance().DeleteUserEnforce(userId, credInfos);
643     if (ret != SUCCESS) {
644         IAM_LOGE("failed to enforce delete user, ret:%{public}d", ret);
645         return ret;
646     }
647     SetAuthTypeTrace(credInfos, callbackForTrace);
648     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, changeReasonTrace);
649     if (ret != SUCCESS) {
650         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
651         // The caller doesn't need to care executor delete result.
652         return SUCCESS;
653     }
654 
655     PublishEventAdapter::GetInstance().PublishDeletedEvent(userId);
656     PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(userId, PIN, 0);
657     CredChangeEventListenerManager::GetInstance().OnNotifyCredChangeEvent(userId, PIN, ENFORCE_DEL_USER, changeInfo);
658     IAM_LOGI("delete user success, userId:%{public}d", userId);
659     return SUCCESS;
660 }
661 
ClearRedundancyCredentialInner(const std::string & callerName,int32_t callerType)662 int32_t UserIdmService::ClearRedundancyCredentialInner(const std::string &callerName, int32_t callerType)
663 {
664     IAM_LOGI("start");
665     std::vector<int32_t> accountInfo;
666     int32_t ret = IpcCommon::GetAllUserId(accountInfo);
667     if (ret != SUCCESS) {
668         IAM_LOGE("GetAllUserId failed");
669         return IPC_ERROR;
670     }
671 
672     std::vector<std::shared_ptr<UserInfoInterface>> userInfos;
673     ret = UserIdmDatabase::Instance().GetAllExtUserInfo(userInfos);
674     if (ret != SUCCESS) {
675         IAM_LOGE("GetAllExtUserInfo failed");
676         return INVALID_HDI_INTERFACE;
677     }
678 
679     if (userInfos.empty()) {
680         IAM_LOGE("no userInfo");
681         return SUCCESS;
682     }
683 
684     for (const auto &iter : userInfos) {
685         int32_t userId = iter->GetUserId();
686         auto callbackForTrace = ContextCallback::NewDummyInstance(TRACE_DELETE_REDUNDANCY);
687         if (callbackForTrace == nullptr) {
688             IAM_LOGE("failed to get callbackForTrace");
689             continue;
690         }
691         callbackForTrace->SetTraceUserId(userId);
692         callbackForTrace->SetTraceCallerName(callerName);
693         callbackForTrace->SetTraceCallerType(callerType);
694         std::vector<int32_t>::iterator it = std::find(accountInfo.begin(), accountInfo.end(), userId);
695         if (it == accountInfo.end()) {
696             CredChangeEventInfo changeInfo = {callerName, callerType, 0, 0, false};
697             ret = EnforceDelUserInner(userId, callbackForTrace, "DeleteRedundancy", changeInfo);
698             Attributes extraInfo;
699             callbackForTrace->OnResult(ret, extraInfo);
700             IAM_LOGE("ClearRedundancytCredential, userId: %{public}d", userId);
701         }
702     }
703     return SUCCESS;
704 }
705 
ClearRedundancyCredential(const sptr<IIamCallback> & idmCallback)706 int32_t UserIdmService::ClearRedundancyCredential(const sptr<IIamCallback> &idmCallback)
707 {
708     IAM_LOGI("start");
709     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
710     IF_FALSE_LOGE_AND_RETURN_VAL(idmCallback != nullptr, INVALID_PARAMETERS);
711 
712     Attributes extraInfo;
713     auto contextCallback = ContextCallback::NewInstance(idmCallback, TRACE_DELETE_REDUNDANCY);
714     if (contextCallback == nullptr) {
715         IAM_LOGE("failed to construct context callback");
716         idmCallback->OnResult(GENERAL_ERROR, extraInfo.Serialize());
717         return GENERAL_ERROR;
718     }
719 
720     std::string callerName = "";
721     int32_t callerType = Security::AccessToken::TOKEN_INVALID;
722     static_cast<void>(IpcCommon::GetCallerName(*this, callerName, callerType));
723     contextCallback->SetTraceCallerName(callerName);
724     contextCallback->SetTraceCallerType(callerType);
725 
726     if (!IpcCommon::CheckPermission(*this, CLEAR_REDUNDANCY_PERMISSION)) {
727         IAM_LOGE("failed to check permission");
728         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
729         return CHECK_PERMISSION_FAILED;
730     }
731 
732     std::lock_guard<std::mutex> lock(mutex_);
733     CancelCurrentEnrollIfExist();
734 
735     int32_t ret = ClearRedundancyCredentialInner(callerName, callerType);
736     if (ret != SUCCESS) {
737         IAM_LOGE("clearRedundancyCredentialInner fail, ret:%{public}d, ", ret);
738     }
739     contextCallback->OnResult(ret, extraInfo);
740     return ret;
741 }
742 
GetCredentialInfoSync(int32_t userId,int32_t authType,std::vector<IpcCredentialInfo> & ipcCredentialInfoList)743 int32_t UserIdmService::GetCredentialInfoSync(int32_t userId, int32_t authType,
744     std::vector<IpcCredentialInfo> &ipcCredentialInfoList)
745 {
746     IAM_LOGI("start");
747     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
748     std::vector<CredentialInfo> credentialInfoList;
749     int32_t ret = GetCredentialInfoInner(userId, static_cast<AuthType>(authType), credentialInfoList);
750     if (ret == NOT_ENROLLED) {
751         credentialInfoList.clear();
752         ret = SUCCESS;
753     }
754 
755     if (ret != SUCCESS) {
756         IAM_LOGE("GetCredentialInfoInner fail, ret: %{public}d", ret);
757         credentialInfoList.clear();
758     }
759 
760     bool hasAbandonedCredential = false;
761     for (auto &iter : credentialInfoList) {
762         if (iter.isAbandoned && iter.validityPeriod == 0) {
763             hasAbandonedCredential = true;
764             continue;
765         }
766         IpcCredentialInfo ipcCredInfo;
767         ipcCredInfo.authType = static_cast<int32_t>(iter.authType);
768         ipcCredInfo.pinType = static_cast<int32_t>(iter.pinType.value_or(PIN_SIX));
769         ipcCredInfo.credentialId = iter.credentialId;
770         ipcCredInfo.templateId = iter.templateId;
771         ipcCredInfo.isAbandoned = iter.isAbandoned;
772         ipcCredInfo.validityPeriod = iter.validityPeriod;
773         ipcCredentialInfoList.push_back(ipcCredInfo);
774     }
775 
776     if (hasAbandonedCredential) {
777         ClearUnavailableCredential(userId);
778     }
779     IAM_LOGI("GetCredentialInfoSync success, credential num:%{public}zu", ipcCredentialInfoList.size());
780     return ret;
781 }
782 
RegistCredChangeEventListener(const sptr<IEventListenerCallback> & listener)783 int32_t UserIdmService::RegistCredChangeEventListener(const sptr<IEventListenerCallback> &listener)
784 {
785     IAM_LOGI("start");
786     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
787     IF_FALSE_LOGE_AND_RETURN_VAL(listener != nullptr, INVALID_PARAMETERS);
788 
789     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
790         IAM_LOGE("failed to check permission");
791         return CHECK_PERMISSION_FAILED;
792     }
793 
794     int32_t result = CredChangeEventListenerManager::GetInstance().RegistEventListener(listener);
795     if (result != SUCCESS) {
796         IAM_LOGE("failed to regist cred change event listener");
797         return result;
798     }
799 
800     return SUCCESS;
801 }
802 
UnRegistCredChangeEventListener(const sptr<IEventListenerCallback> & listener)803 int32_t UserIdmService::UnRegistCredChangeEventListener(const sptr<IEventListenerCallback> &listener)
804 {
805     IAM_LOGI("start");
806     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
807     IF_FALSE_LOGE_AND_RETURN_VAL(listener != nullptr, INVALID_PARAMETERS);
808 
809     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
810         IAM_LOGE("failed to check permission");
811         return CHECK_PERMISSION_FAILED;
812     }
813 
814     int32_t result = CredChangeEventListenerManager::GetInstance().UnRegistEventListener(listener);
815     if (result != SUCCESS) {
816         IAM_LOGE("failed to unregist cred change event listener");
817         return result;
818     }
819     return SUCCESS;
820 }
821 
ClearUnavailableCredential(int32_t userId)822 void UserIdmService::ClearUnavailableCredential(int32_t userId)
823 {
824     IAM_LOGI("start");
825     Common::XCollieHelper xcollie(__FUNCTION__, Common::API_CALL_TIMEOUT);
826 
827     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
828     int32_t ret = UserIdmDatabase::Instance().ClearUnavailableCredential(userId, credInfos);
829     if (ret != SUCCESS) {
830         IAM_LOGE("clear expired credential fail, ret:%{public}d, userId:%{public}d", ret, userId);
831         return;
832     }
833 
834     if (credInfos.empty()) {
835         IAM_LOGI("no abandoned credential");
836         return;
837     }
838 
839     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos, "ClearExpiredTemplate");
840     if (ret != SUCCESS) {
841         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
842     }
843 
844     return;
845 }
846 
CallbackEnter(uint32_t code)847 int32_t UserIdmService::CallbackEnter([[maybe_unused]] uint32_t code)
848 {
849     IAM_LOGI("start, code:%{public}u", code);
850     return SUCCESS;
851 }
852 
CallbackExit(uint32_t code,int32_t result)853 int32_t UserIdmService::CallbackExit([[maybe_unused]] uint32_t code, [[maybe_unused]] int32_t result)
854 {
855     IAM_LOGI("leave, code:%{public}u, result:%{public}d", code, result);
856     return SUCCESS;
857 }
858 } // namespace UserAuth
859 } // namespace UserIam
860 } // namespace OHOS