• 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_factory.h"
22 #include "context_helper.h"
23 #include "context_pool.h"
24 #include "hdi_wrapper.h"
25 #include "iam_check.h"
26 #include "iam_logger.h"
27 #include "iam_para2str.h"
28 #include "iam_defines.h"
29 #include "ipc_common.h"
30 #include "ipc_skeleton.h"
31 #include "iam_common_defines.h"
32 #include "resource_node_pool.h"
33 #include "resource_node_utils.h"
34 #include "user_idm_callback_proxy.h"
35 #include "user_idm_database.h"
36 #include "user_idm_session_controller.h"
37 
38 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
39 namespace OHOS {
40 namespace UserIam {
41 namespace UserAuth {
42 REGISTER_SYSTEM_ABILITY_BY_ID(UserIdmService, SUBSYS_USERIAM_SYS_ABILITY_USERIDM, true);
43 constexpr int32_t USERIAM_IPC_THREAD_NUM = 4;
44 
UserIdmService(int32_t systemAbilityId,bool runOnCreate)45 UserIdmService::UserIdmService(int32_t systemAbilityId, bool runOnCreate) : SystemAbility(systemAbilityId, runOnCreate)
46 {
47 }
48 
OnStart()49 void UserIdmService::OnStart()
50 {
51     IAM_LOGI("start service");
52     IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
53     if (!Publish(this)) {
54         IAM_LOGE("failed to publish service");
55     }
56 }
57 
OnStop()58 void UserIdmService::OnStop()
59 {
60     IAM_LOGI("stop service");
61 }
62 
OpenSession(int32_t userId,std::vector<uint8_t> & challenge)63 int32_t UserIdmService::OpenSession(int32_t userId, std::vector<uint8_t> &challenge)
64 {
65     IAM_LOGI("start");
66     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
67         IAM_LOGE("failed to check permission");
68         return CHECK_PERMISSION_FAILED;
69     }
70 
71     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
72     for (const auto &context : contextList) {
73         if (auto ctx = context.lock(); ctx != nullptr) {
74             IAM_LOGE("force stop the old context ****%{public}hx", static_cast<uint16_t>(ctx->GetContextId()));
75             ctx->Stop();
76             ContextPool::Instance().Delete(ctx->GetContextId());
77         }
78     }
79 
80     if (!UserIdmSessionController::Instance().OpenSession(userId, challenge)) {
81         IAM_LOGE("failed to open session");
82         return GENERAL_ERROR;
83     }
84 
85     return SUCCESS;
86 }
87 
CloseSession(int32_t userId)88 void UserIdmService::CloseSession(int32_t userId)
89 {
90     IAM_LOGI("start");
91     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
92         IAM_LOGE("failed to check permission");
93         return;
94     }
95 
96     if (!UserIdmSessionController::Instance().CloseSession(userId)) {
97         IAM_LOGE("failed to get close session");
98     }
99 }
100 
GetCredentialInfoInner(int32_t userId,AuthType authType,std::vector<CredentialInfo> & credInfoList)101 int32_t UserIdmService::GetCredentialInfoInner(int32_t userId, AuthType authType,
102     std::vector<CredentialInfo> &credInfoList)
103 {
104     IAM_LOGI("start");
105     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
106         IAM_LOGE("failed to check permission");
107         return CHECK_PERMISSION_FAILED;
108     }
109     auto credInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
110     if (credInfos.empty()) {
111         IAM_LOGE("no cred enrolled");
112         return NOT_ENROLLED;
113     }
114     for (const auto &credInfo : credInfos) {
115         if (credInfo == nullptr) {
116             IAM_LOGE("credInfo is nullptr");
117             return GENERAL_ERROR;
118         }
119         CredentialInfo info = {};
120         info.credentialId = credInfo->GetCredentialId();
121         info.templateId = credInfo->GetTemplateId();
122         info.authType = credInfo->GetAuthType();
123         if (info.authType == PIN) {
124             auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(userId);
125             if (userInfo == nullptr) {
126                 IAM_LOGE("failed to get userInfo");
127                 return GENERAL_ERROR;
128             }
129             info.pinType = userInfo->GetPinSubType();
130         }
131         credInfoList.push_back(info);
132     }
133     return SUCCESS;
134 }
135 
GetCredentialInfo(int32_t userId,AuthType authType,const sptr<IdmGetCredInfoCallbackInterface> & callback)136 int32_t UserIdmService::GetCredentialInfo(int32_t userId, AuthType authType,
137     const sptr<IdmGetCredInfoCallbackInterface> &callback)
138 {
139     if (callback == nullptr) {
140         IAM_LOGE("callback is nullptr");
141         return INVALID_PARAMETERS;
142     }
143 
144     std::vector<CredentialInfo> credInfoList;
145     int32_t ret = GetCredentialInfoInner(userId, authType, credInfoList);
146     if (ret != SUCCESS) {
147         IAM_LOGE("GetCredentialInfoInner fail, ret: %{public}d", ret);
148         credInfoList.clear();
149     }
150     callback->OnCredentialInfos(credInfoList);
151 
152     return ret;
153 }
154 
GetSecInfoInner(int32_t userId,SecUserInfo & secUserInfo)155 int32_t UserIdmService::GetSecInfoInner(int32_t userId, SecUserInfo &secUserInfo)
156 {
157     IAM_LOGI("start");
158     if (!IpcCommon::CheckPermission(*this, USE_USER_IDM_PERMISSION)) {
159         IAM_LOGE("failed to check permission");
160         return CHECK_PERMISSION_FAILED;
161     }
162     auto userInfos = UserIdmDatabase::Instance().GetSecUserInfo(userId);
163     if (userInfos == nullptr) {
164         IAM_LOGE("current userid %{public}d is not existed", userId);
165         return INVALID_PARAMETERS;
166     }
167     std::vector<std::shared_ptr<EnrolledInfoInterface>> enrolledInfos = userInfos->GetEnrolledInfo();
168     for (const auto &enrolledInfo : enrolledInfos) {
169         if (enrolledInfo == nullptr) {
170             IAM_LOGE("enrolledInfo is nullptr");
171             return GENERAL_ERROR;
172         }
173         EnrolledInfo info = {enrolledInfo->GetAuthType(), enrolledInfo->GetEnrolledId()};
174         secUserInfo.enrolledInfo.push_back(info);
175     }
176     secUserInfo.secureUid = userInfos->GetSecUserId();
177     return SUCCESS;
178 }
179 
GetSecInfo(int32_t userId,const sptr<IdmGetSecureUserInfoCallbackInterface> & callback)180 int32_t UserIdmService::GetSecInfo(int32_t userId, const sptr<IdmGetSecureUserInfoCallbackInterface> &callback)
181 {
182     if (callback == nullptr) {
183         IAM_LOGE("callback is nullptr");
184         return INVALID_PARAMETERS;
185     }
186 
187     SecUserInfo secUserInfo = {};
188     int32_t ret = GetSecInfoInner(userId, secUserInfo);
189     if (ret != SUCCESS) {
190         IAM_LOGE("GetSecInfoInner fail, ret: %{public}d", ret);
191         secUserInfo.secureUid = 0;
192         secUserInfo.enrolledInfo.clear();
193     }
194     callback->OnSecureUserInfo(secUserInfo);
195 
196     return ret;
197 }
198 
AddCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback,bool isUpdate)199 void UserIdmService::AddCredential(int32_t userId, const CredentialPara &credPara,
200     const sptr<IdmCallbackInterface> &callback, bool isUpdate)
201 {
202     if (callback == nullptr) {
203         IAM_LOGE("callback is nullptr");
204         return;
205     }
206 
207     Attributes extraInfo;
208     auto contextCallback = ContextCallback::NewInstance(callback,
209         isUpdate ? TRACE_UPDATE_CREDENTIAL : TRACE_ADD_CREDENTIAL);
210     if (contextCallback == nullptr) {
211         IAM_LOGE("failed to construct context callback");
212         callback->OnResult(GENERAL_ERROR, extraInfo);
213         return;
214     }
215     uint64_t callingUid = static_cast<uint64_t>(this->GetCallingUid());
216     contextCallback->SetTraceAuthType(credPara.authType);
217     contextCallback->SetTraceCallingUid(callingUid);
218     contextCallback->SetTraceUserId(userId);
219 
220     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
221         IAM_LOGE("failed to check permission");
222         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
223         return;
224     }
225 
226     std::lock_guard<std::mutex> lock(mutex_);
227     CancelCurrentEnrollIfExist();
228     auto tokenId = IpcCommon::GetAccessTokenId(*this);
229     ContextFactory::EnrollContextPara para = {};
230     para.authType = credPara.authType;
231     para.userId = userId;
232     para.pinType = credPara.pinType;
233     para.tokenId = tokenId;
234     para.token = credPara.token;
235     para.isUpdate = isUpdate;
236     auto context = ContextFactory::CreateEnrollContext(para, contextCallback);
237     if (!ContextPool::Instance().Insert(context)) {
238         IAM_LOGE("failed to insert context");
239         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
240         return;
241     }
242 
243     auto cleaner = ContextHelper::Cleaner(context);
244     contextCallback->SetCleaner(cleaner);
245 
246     if (!context->Start()) {
247         IAM_LOGE("failed to start enroll");
248         contextCallback->OnResult(context->GetLatestError(), extraInfo);
249     }
250 }
251 
UpdateCredential(int32_t userId,const CredentialPara & credPara,const sptr<IdmCallbackInterface> & callback)252 void UserIdmService::UpdateCredential(int32_t userId, const CredentialPara &credPara,
253     const sptr<IdmCallbackInterface> &callback)
254 {
255     if (callback == nullptr) {
256         IAM_LOGE("callback is nullptr");
257         return;
258     }
259 
260     auto credInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, credPara.authType);
261     if (credInfos.empty()) {
262         IAM_LOGE("current userid %{public}d has no credential for type %{public}u", userId, credPara.authType);
263         Attributes extraInfo;
264         callback->OnResult(NOT_ENROLLED, extraInfo);
265         return;
266     }
267 
268     AddCredential(userId, credPara, callback, true);
269 }
270 
Cancel(int32_t userId)271 int32_t UserIdmService::Cancel(int32_t userId)
272 {
273     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
274         IAM_LOGE("failed to check permission");
275         return CHECK_PERMISSION_FAILED;
276     }
277     if (!UserIdmSessionController::Instance().IsSessionOpened(userId)) {
278         IAM_LOGE("both user id and challenge are invalid");
279         return GENERAL_ERROR;
280     }
281 
282     std::lock_guard<std::mutex> lock(mutex_);
283     return CancelCurrentEnroll();
284 }
285 
CancelCurrentEnrollIfExist()286 void UserIdmService::CancelCurrentEnrollIfExist()
287 {
288     if (ContextPool::Instance().Select(CONTEXT_ENROLL).size() == 0) {
289         return;
290     }
291 
292     IAM_LOGI("cancel current enroll due to new add credential request or delete");
293     CancelCurrentEnroll();
294 }
295 
CancelCurrentEnroll()296 int32_t UserIdmService::CancelCurrentEnroll()
297 {
298     IAM_LOGD("start");
299     auto contextList = ContextPool::Instance().Select(CONTEXT_ENROLL);
300     int32_t ret = GENERAL_ERROR;
301     for (const auto &context : contextList) {
302         if (auto ctx = context.lock(); ctx != nullptr) {
303             IAM_LOGE("stop the old context %{public}s", GET_MASKED_STRING(ctx->GetContextId()).c_str());
304             ctx->Stop();
305             ContextPool::Instance().Delete(ctx->GetContextId());
306             ret = SUCCESS;
307         }
308     }
309     IAM_LOGI("result %{public}d", ret);
310     return ret;
311 }
312 
EnforceDelUser(int32_t userId,const sptr<IdmCallbackInterface> & callback)313 int32_t UserIdmService::EnforceDelUser(int32_t userId, const sptr<IdmCallbackInterface> &callback)
314 {
315     IAM_LOGI("to delete userid: %{public}d", userId);
316     IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, INVALID_PARAMETERS);
317 
318     Attributes extraInfo;
319     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_ENFORCE_DELETE_USER);
320     if (contextCallback == nullptr) {
321         IAM_LOGE("failed to construct context callback");
322         callback->OnResult(GENERAL_ERROR, extraInfo);
323         return GENERAL_ERROR;
324     }
325     contextCallback->SetTraceUserId(userId);
326 
327     if (!IpcCommon::CheckPermission(*this, ENFORCE_USER_IDM)) {
328         IAM_LOGE("failed to check permission");
329         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
330         return CHECK_PERMISSION_FAILED;
331     }
332 
333     std::lock_guard<std::mutex> lock(mutex_);
334     CancelCurrentEnrollIfExist();
335 
336     auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(userId);
337     if (userInfo == nullptr) {
338         IAM_LOGE("current userid %{public}d is not existed", userId);
339         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
340         return INVALID_PARAMETERS;
341     }
342 
343     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
344     int32_t ret = UserIdmDatabase::Instance().DeleteUserEnforce(userId, credInfos);
345     if (ret != SUCCESS) {
346         IAM_LOGE("failed to enforce delete user");
347         static_cast<void>(extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, 0));
348         contextCallback->OnResult(ret, extraInfo);
349         return ret;
350     }
351 
352     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos);
353     if (ret != SUCCESS) {
354         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
355     }
356 
357     IAM_LOGI("delete user success");
358     contextCallback->OnResult(SUCCESS, extraInfo);
359     return SUCCESS;
360 }
361 
DelUser(int32_t userId,const std::vector<uint8_t> authToken,const sptr<IdmCallbackInterface> & callback)362 void UserIdmService::DelUser(int32_t userId, const std::vector<uint8_t> authToken,
363     const sptr<IdmCallbackInterface> &callback)
364 {
365     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
366 
367     Attributes extraInfo;
368     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_USER);
369     if (contextCallback == nullptr) {
370         IAM_LOGE("failed to construct context callback");
371         callback->OnResult(GENERAL_ERROR, extraInfo);
372         return;
373     }
374     contextCallback->SetTraceUserId(userId);
375 
376     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
377         IAM_LOGE("failed to check permission");
378         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
379         return;
380     }
381 
382     std::lock_guard<std::mutex> lock(mutex_);
383     CancelCurrentEnrollIfExist();
384 
385     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
386     int32_t ret = UserIdmDatabase::Instance().DeleteUser(userId, authToken, credInfos);
387     if (ret != SUCCESS) {
388         IAM_LOGE("failed to delete user");
389         contextCallback->OnResult(ret, extraInfo);
390         return;
391     }
392 
393     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(credInfos);
394     if (ret != SUCCESS) {
395         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
396     }
397     IAM_LOGI("delete user end");
398 
399     contextCallback->OnResult(ret, extraInfo);
400 }
401 
DelCredential(int32_t userId,uint64_t credentialId,const std::vector<uint8_t> & authToken,const sptr<IdmCallbackInterface> & callback)402 void UserIdmService::DelCredential(int32_t userId, uint64_t credentialId,
403     const std::vector<uint8_t> &authToken, const sptr<IdmCallbackInterface> &callback)
404 {
405     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
406 
407     Attributes extraInfo;
408     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_DELETE_CREDENTIAL);
409     if (contextCallback == nullptr) {
410         IAM_LOGE("failed to construct context callback");
411         callback->OnResult(GENERAL_ERROR, extraInfo);
412         return;
413     }
414     contextCallback->SetTraceUserId(userId);
415 
416     if (!IpcCommon::CheckPermission(*this, MANAGE_USER_IDM_PERMISSION)) {
417         IAM_LOGE("failed to check permission");
418         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
419         return;
420     }
421 
422     std::lock_guard<std::mutex> lock(mutex_);
423     CancelCurrentEnrollIfExist();
424 
425     std::shared_ptr<CredentialInfoInterface> oldInfo;
426     auto ret = UserIdmDatabase::Instance().DeleteCredentialInfo(userId, credentialId, authToken, oldInfo);
427     if (ret != SUCCESS) {
428         IAM_LOGE("failed to delete CredentialInfo");
429         contextCallback->OnResult(ret, extraInfo);
430         return;
431     }
432     if (oldInfo != nullptr) {
433         contextCallback->SetTraceAuthType(oldInfo->GetAuthType());
434     }
435 
436     IAM_LOGI("delete credentialInfo success");
437     std::vector<std::shared_ptr<CredentialInfoInterface>> list = {oldInfo};
438     ret = ResourceNodeUtils::NotifyExecutorToDeleteTemplates(list);
439     if (ret != SUCCESS) {
440         IAM_LOGE("failed to delete executor info, error code : %{public}d", ret);
441     }
442 
443     contextCallback->OnResult(ret, extraInfo);
444 }
445 
Dump(int fd,const std::vector<std::u16string> & args)446 int UserIdmService::Dump(int fd, const std::vector<std::u16string> &args)
447 {
448     IAM_LOGI("start");
449     if (fd < 0) {
450         IAM_LOGE("invalid parameters");
451         dprintf(fd, "Invalid parameters.\n");
452         return INVALID_PARAMETERS;
453     }
454     std::string arg0 = (args.empty() ? "" : Str16ToStr8(args[0]));
455     if (arg0.empty() || arg0.compare("-h") == 0) {
456         dprintf(fd, "Usage:\n");
457         dprintf(fd, "      -h: command help.\n");
458         dprintf(fd, "      -l: active user info dump.\n");
459         return SUCCESS;
460     }
461     if (arg0.compare("-l") != 0) {
462         IAM_LOGE("invalid option");
463         dprintf(fd, "Invalid option\n");
464         return GENERAL_ERROR;
465     }
466 
467     std::optional<int32_t> activeUserId;
468     if (IpcCommon::GetActiveUserId(activeUserId) != SUCCESS) {
469         dprintf(fd, "Internal error.\n");
470         IAM_LOGE("failed to get active id");
471         return GENERAL_ERROR;
472     }
473     dprintf(fd, "Active user is %d\n", activeUserId.value());
474     auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(activeUserId.value());
475     if (userInfo == nullptr) {
476         IAM_LOGE("userInfo is null");
477         return SUCCESS;
478     }
479     auto enrolledInfo = userInfo->GetEnrolledInfo();
480     for (auto &info : enrolledInfo) {
481         if (info != nullptr) {
482             dprintf(fd, "AuthType %s is enrolled.\n", Common::AuthTypeToStr(info->GetAuthType()));
483         }
484     }
485     return SUCCESS;
486 }
487 
488 } // namespace UserAuth
489 } // namespace UserIam
490 } // namespace OHOS