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 ¶,
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 ¶,
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