• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_auth_service.h"
17 #include "hisysevent_adapter.h"
18 
19 #include <cinttypes>
20 
21 #include "accesstoken_kit.h"
22 #include "auth_common.h"
23 #include "auth_widget_helper.h"
24 #include "context_factory.h"
25 #include "auth_common.h"
26 #include "context_helper.h"
27 #include "hdi_wrapper.h"
28 #include "iam_check.h"
29 #include "iam_common_defines.h"
30 #include "iam_logger.h"
31 #include "iam_ptr.h"
32 #include "iam_time.h"
33 #include "ipc_common.h"
34 #include "ipc_skeleton.h"
35 #include "system_param_manager.h"
36 #include "widget_client.h"
37 
38 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
39 
40 namespace OHOS {
41 namespace UserIam {
42 namespace UserAuth {
43 namespace {
44 const uint64_t BAD_CONTEXT_ID = 0;
45 const int32_t MINIMUM_VERSION = 0;
46 const int32_t CURRENT_VERSION = 1;
47 const uint32_t AUTH_TRUST_LEVEL_SYS = 1;
48 const int32_t USERIAM_IPC_THREAD_NUM = 4;
49 const uint32_t MAX_AUTH_TYPE_SIZE = 3;
50 
GetTemplatesByAuthType(int32_t userId,AuthType authType,std::vector<uint64_t> & templateIds)51 void GetTemplatesByAuthType(int32_t userId, AuthType authType, std::vector<uint64_t> &templateIds)
52 {
53     templateIds.clear();
54     auto credentialInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
55     if (credentialInfos.empty()) {
56         IAM_LOGE("user %{public}d has no credential type %{public}d", userId, authType);
57         return;
58     }
59 
60     templateIds.reserve(credentialInfos.size());
61     for (auto &info : credentialInfos) {
62         if (info == nullptr) {
63             IAM_LOGE("info is nullptr");
64             continue;
65         }
66         templateIds.push_back(info->GetTemplateId());
67     }
68 }
69 
IsTemplateIdListRequired(const std::vector<Attributes::AttributeKey> & keys)70 bool IsTemplateIdListRequired(const std::vector<Attributes::AttributeKey> &keys)
71 {
72     for (const auto &key : keys) {
73         if (key == Attributes::AttributeKey::ATTR_PIN_SUB_TYPE ||
74             key == Attributes::AttributeKey::ATTR_REMAIN_TIMES ||
75             key == Attributes::AttributeKey::ATTR_FREEZING_TIME) {
76             return true;
77         }
78     }
79     return false;
80 }
81 
GetResourceNodeByType(AuthType authType,std::vector<std::weak_ptr<ResourceNode>> & authTypeNodes)82 void GetResourceNodeByType(AuthType authType, std::vector<std::weak_ptr<ResourceNode>> &authTypeNodes)
83 {
84     authTypeNodes.clear();
85     ResourceNodePool::Instance().Enumerate(
86         [&authTypeNodes, authType](const std::weak_ptr<ResourceNode> &weakNode) {
87             auto node = weakNode.lock();
88             if (node == nullptr) {
89                 return;
90             }
91             if (node->GetAuthType() == authType) {
92                 authTypeNodes.push_back(node);
93             }
94         });
95 }
96 } // namespace
97 
98 REGISTER_SYSTEM_ABILITY_BY_ID(UserAuthService, SUBSYS_USERIAM_SYS_ABILITY_USERAUTH, true);
99 
UserAuthService(int32_t systemAbilityId,bool runOnCreate)100 UserAuthService::UserAuthService(int32_t systemAbilityId, bool runOnCreate)
101     : SystemAbility(systemAbilityId, runOnCreate)
102 {
103 }
104 
OnStart()105 void UserAuthService::OnStart()
106 {
107     IAM_LOGI("start service");
108     IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
109     if (!Publish(this)) {
110         IAM_LOGE("failed to publish service");
111     }
112     SystemParamManager::GetInstance().Start();
113 }
114 
OnStop()115 void UserAuthService::OnStop()
116 {
117     IAM_LOGI("stop service");
118 }
119 
CheckAuthTrustLevel(AuthTrustLevel authTrustLevel)120 bool UserAuthService::CheckAuthTrustLevel(AuthTrustLevel authTrustLevel)
121 {
122     if ((authTrustLevel != ATL1) && (authTrustLevel != ATL2) &&
123         (authTrustLevel != ATL3) && (authTrustLevel != ATL4)) {
124         IAM_LOGE("authTrustLevel not support %{public}u", authTrustLevel);
125         return false;
126     }
127     return true;
128 }
129 
GetAvailableStatus(int32_t apiVersion,AuthType authType,AuthTrustLevel authTrustLevel)130 int32_t UserAuthService::GetAvailableStatus(int32_t apiVersion, AuthType authType, AuthTrustLevel authTrustLevel)
131 {
132     IAM_LOGI("start");
133     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
134         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
135         IAM_LOGE("failed to check permission");
136         return CHECK_PERMISSION_FAILED;
137     }
138     if ((apiVersion <= API_VERSION_8 && authType == PIN) ||
139         !SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
140         IAM_LOGE("authType not support");
141         return TYPE_NOT_SUPPORT;
142     }
143     if (!CheckAuthTrustLevel(authTrustLevel)) {
144         IAM_LOGE("authTrustLevel is not in correct range");
145         return TRUST_LEVEL_NOT_SUPPORT;
146     }
147     int32_t userId;
148     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
149         IAM_LOGE("failed to get callingUserId");
150         return GENERAL_ERROR;
151     }
152     auto hdi = HdiWrapper::GetHdiInstance();
153     if (hdi == nullptr) {
154         IAM_LOGE("hdi interface is nullptr");
155         return GENERAL_ERROR;
156     }
157     uint32_t supportedAtl = AUTH_TRUST_LEVEL_SYS;
158     int32_t result =
159         hdi->GetAuthTrustLevel(userId, static_cast<HdiAuthType>(authType), supportedAtl);
160     if (result != SUCCESS) {
161         IAM_LOGE("failed to get current supported authTrustLevel from hdi apiVersion:%{public}d result:%{public}d",
162             apiVersion, result);
163         return result;
164     }
165     if (authTrustLevel > supportedAtl) {
166         IAM_LOGE("the current authTrustLevel does not support");
167         return TRUST_LEVEL_NOT_SUPPORT;
168     }
169     return SUCCESS;
170 }
171 
GetProperty(int32_t userId,AuthType authType,const std::vector<Attributes::AttributeKey> & keys,sptr<GetExecutorPropertyCallbackInterface> & callback)172 void UserAuthService::GetProperty(int32_t userId, AuthType authType,
173     const std::vector<Attributes::AttributeKey> &keys, sptr<GetExecutorPropertyCallbackInterface> &callback)
174 {
175     IAM_LOGI("start");
176     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
177     Attributes values;
178 
179     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
180         IAM_LOGE("failed to check permission");
181         callback->OnGetExecutorPropertyResult(CHECK_PERMISSION_FAILED, values);
182         return;
183     }
184 
185     std::vector<uint64_t> templateIds;
186     if (IsTemplateIdListRequired(keys)) {
187         GetTemplatesByAuthType(userId, authType, templateIds);
188         if (templateIds.size() == 0) {
189             IAM_LOGE("template id list is required, but templateIds size is 0");
190             callback->OnGetExecutorPropertyResult(NOT_ENROLLED, values);
191             return;
192         }
193     }
194 
195     std::vector<std::weak_ptr<ResourceNode>> authTypeNodes;
196     GetResourceNodeByType(authType, authTypeNodes);
197     if (authTypeNodes.size() != 1) {
198         IAM_LOGE("auth type %{public}d resource node num %{public}zu is not expected",
199             authType, authTypeNodes.size());
200         callback->OnGetExecutorPropertyResult(GENERAL_ERROR, values);
201         return;
202     }
203 
204     auto resourceNode = authTypeNodes[0].lock();
205     if (resourceNode == nullptr) {
206         IAM_LOGE("resourceNode is nullptr");
207         callback->OnGetExecutorPropertyResult(GENERAL_ERROR, values);
208         return;
209     }
210 
211     std::vector<uint32_t> uint32Keys;
212     uint32Keys.reserve(keys.size());
213     for (auto &key : keys) {
214         uint32Keys.push_back(static_cast<uint32_t>(key));
215     }
216 
217     Attributes attr;
218     attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
219     attr.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIds);
220     attr.SetUint32ArrayValue(Attributes::ATTR_KEY_LIST, uint32Keys);
221 
222     int32_t result = resourceNode->GetProperty(attr, values);
223     if (result != SUCCESS) {
224         IAM_LOGE("failed to get property, result = %{public}d", result);
225     }
226     callback->OnGetExecutorPropertyResult(result, values);
227 }
228 
SetProperty(int32_t userId,AuthType authType,const Attributes & attributes,sptr<SetExecutorPropertyCallbackInterface> & callback)229 void UserAuthService::SetProperty(int32_t userId, AuthType authType, const Attributes &attributes,
230     sptr<SetExecutorPropertyCallbackInterface> &callback)
231 {
232     IAM_LOGI("start");
233     if (callback == nullptr) {
234         IAM_LOGE("callback is nullptr");
235         return;
236     }
237     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
238         IAM_LOGE("permission check failed");
239         callback->OnSetExecutorPropertyResult(CHECK_PERMISSION_FAILED);
240         return;
241     }
242 
243     std::vector<std::weak_ptr<ResourceNode>> authTypeNodes;
244     GetResourceNodeByType(authType, authTypeNodes);
245     if (authTypeNodes.size() != 1) {
246         IAM_LOGE("auth type %{public}d resource node num %{public}zu is not expected",
247             authType, authTypeNodes.size());
248         callback->OnSetExecutorPropertyResult(GENERAL_ERROR);
249         return;
250     }
251 
252     auto resourceNode = authTypeNodes[0].lock();
253     if (resourceNode == nullptr) {
254         IAM_LOGE("resourceNode is nullptr");
255         callback->OnSetExecutorPropertyResult(GENERAL_ERROR);
256         return;
257     }
258     int32_t result = resourceNode->SetProperty(attributes);
259     if (result != SUCCESS) {
260         IAM_LOGE("set property failed, result = %{public}d", result);
261     }
262     callback->OnSetExecutorPropertyResult(result);
263 }
264 
GetAuthContextCallback(int32_t apiVersion,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)265 std::shared_ptr<ContextCallback> UserAuthService::GetAuthContextCallback(int32_t apiVersion,
266     const std::vector<uint8_t> &challenge, AuthType authType,
267     AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
268 {
269     if (callback == nullptr) {
270         IAM_LOGE("callback is nullptr");
271         return nullptr;
272     }
273     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER_ALL);
274     if (contextCallback == nullptr) {
275         IAM_LOGE("failed to construct context callback");
276         Attributes extraInfo;
277         callback->OnResult(GENERAL_ERROR, extraInfo);
278         return nullptr;
279     }
280     contextCallback->SetTraceAuthType(authType);
281     contextCallback->SetTraceAuthTrustLevel(authTrustLevel);
282     contextCallback->SetTraceAuthWidgetType(authType);
283     contextCallback->SetTraceSdkVersion(apiVersion);
284     return contextCallback;
285 }
286 
CheckAuthPermissionAndParam(int32_t authType,bool isBundleName,const std::string & callerName,AuthTrustLevel authTrustLevel)287 int32_t UserAuthService::CheckAuthPermissionAndParam(int32_t authType, bool isBundleName,
288     const std::string &callerName, AuthTrustLevel authTrustLevel)
289 {
290     if (!IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
291         IAM_LOGE("failed to check permission");
292         return CHECK_PERMISSION_FAILED;
293     }
294     if (isBundleName && (!IpcCommon::CheckForegroundApplication(callerName))) {
295         IAM_LOGE("failed to check foreground application");
296         return CHECK_PERMISSION_FAILED;
297     }
298     if ((authType == PIN) || !SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
299         IAM_LOGE("authType not support");
300         return TYPE_NOT_SUPPORT;
301     }
302     if (!CheckAuthTrustLevel(authTrustLevel)) {
303         IAM_LOGE("authTrustLevel is not in correct range");
304         return TRUST_LEVEL_NOT_SUPPORT;
305     }
306     return SUCCESS;
307 }
308 
Auth(int32_t apiVersion,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)309 uint64_t UserAuthService::Auth(int32_t apiVersion, const std::vector<uint8_t> &challenge,
310     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
311 {
312     IAM_LOGI("start");
313     auto contextCallback = GetAuthContextCallback(apiVersion, challenge, authType, authTrustLevel, callback);
314     if (contextCallback == nullptr) {
315         IAM_LOGE("contextCallback is nullptr");
316         return BAD_CONTEXT_ID;
317     }
318     bool isBundleName = false;
319     std::string callerName = "";
320     Attributes extraInfo;
321     if ((!IpcCommon::GetCallerName(*this, isBundleName, callerName)) && isBundleName) {
322         IAM_LOGE("get bundle name fail");
323         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
324         return BAD_CONTEXT_ID;
325     }
326     contextCallback->SetTraceCallerName(callerName);
327     int32_t checkRet = CheckAuthPermissionAndParam(authType, isBundleName, callerName, authTrustLevel);
328     if (checkRet != SUCCESS) {
329         IAM_LOGE("check auth permission and param fail");
330         contextCallback->OnResult(checkRet, extraInfo);
331         return BAD_CONTEXT_ID;
332     }
333     int32_t userId;
334     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
335         IAM_LOGE("get callingUserId failed");
336         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
337         return BAD_CONTEXT_ID;
338     }
339     contextCallback->SetTraceUserId(userId);
340     Authentication::AuthenticationPara para = {};
341     para.tokenId = IpcCommon::GetAccessTokenId(*this);
342     para.userId = userId;
343     para.authType = authType;
344     para.atl = authTrustLevel;
345     para.challenge = std::move(challenge);
346     para.endAfterFirstFail = true;
347     if (isBundleName) {
348         para.callerName = callerName;
349     }
350     para.sdkVersion = apiVersion;
351     return StartAuthContext(apiVersion, para, contextCallback);
352 }
353 
StartAuthContext(int32_t apiVersion,Authentication::AuthenticationPara para,const std::shared_ptr<ContextCallback> & contextCallback)354 uint64_t UserAuthService::StartAuthContext(int32_t apiVersion, Authentication::AuthenticationPara para,
355     const std::shared_ptr<ContextCallback> &contextCallback)
356 {
357     Attributes extraInfo;
358     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
359     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
360         IAM_LOGE("failed to insert context");
361         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
362         return BAD_CONTEXT_ID;
363     }
364     contextCallback->SetTraceRequestContextId(context->GetContextId());
365     contextCallback->SetTraceAuthContextId(context->GetContextId());
366     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
367 
368     if (!context->Start()) {
369         int32_t errorCode = context->GetLatestError();
370         IAM_LOGE("failed to start auth apiVersion:%{public}d errorCode:%{public}d", apiVersion, errorCode);
371         contextCallback->OnResult(errorCode, extraInfo);
372         return BAD_CONTEXT_ID;
373     }
374     return context->GetContextId();
375 }
376 
AuthUser(int32_t userId,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)377 uint64_t UserAuthService::AuthUser(int32_t userId, const std::vector<uint8_t> &challenge,
378     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
379 {
380     IAM_LOGI("start");
381     auto contextCallback = GetAuthContextCallback(INNER_API_VERSION_10000, challenge, authType, authTrustLevel,
382         callback);
383     if (contextCallback == nullptr) {
384         IAM_LOGE("contextCallback is nullptr");
385         return BAD_CONTEXT_ID;
386     }
387     contextCallback->SetTraceUserId(userId);
388     Attributes extraInfo;
389     bool isBundleName = false;
390     std::string callerName = "";
391     if ((!IpcCommon::GetCallerName(*this, isBundleName, callerName)) && isBundleName) {
392         IAM_LOGE("get bundle name fail");
393         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
394         return BAD_CONTEXT_ID;
395     }
396     contextCallback->SetTraceCallerName(callerName);
397     if (!CheckAuthTrustLevel(authTrustLevel)) {
398         IAM_LOGE("authTrustLevel is not in correct range");
399         contextCallback->OnResult(TRUST_LEVEL_NOT_SUPPORT, extraInfo);
400         return BAD_CONTEXT_ID;
401     }
402     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
403         IAM_LOGE("failed to check permission");
404         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
405         return BAD_CONTEXT_ID;
406     }
407     if (!SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
408         IAM_LOGE("auth type not support");
409         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
410         return BAD_CONTEXT_ID;
411     }
412     Authentication::AuthenticationPara para = {};
413     para.tokenId = IpcCommon::GetAccessTokenId(*this);
414     para.userId = userId;
415     para.authType = authType;
416     para.atl = authTrustLevel;
417     para.challenge = std::move(challenge);
418     para.endAfterFirstFail = false;
419     if (isBundleName) {
420         para.callerName = callerName;
421     }
422     para.sdkVersion = INNER_API_VERSION_10000;
423     return StartAuthContext(INNER_API_VERSION_10000, para, contextCallback);
424 }
425 
Identify(const std::vector<uint8_t> & challenge,AuthType authType,sptr<UserAuthCallbackInterface> & callback)426 uint64_t UserAuthService::Identify(const std::vector<uint8_t> &challenge, AuthType authType,
427     sptr<UserAuthCallbackInterface> &callback)
428 {
429     IAM_LOGI("start");
430 
431     if (callback == nullptr) {
432         IAM_LOGE("callback is nullptr");
433         return BAD_CONTEXT_ID;
434     }
435     Attributes extraInfo;
436     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_IDENTIFY);
437     if (contextCallback == nullptr) {
438         IAM_LOGE("failed to construct context callback");
439         callback->OnResult(GENERAL_ERROR, extraInfo);
440         return BAD_CONTEXT_ID;
441     }
442     if ((authType == PIN) || !SystemParamManager::GetInstance().IsAuthTypeEnable(authType)) {
443         IAM_LOGE("type not support %{public}d", authType);
444         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
445         return BAD_CONTEXT_ID;
446     }
447     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
448         IAM_LOGE("failed to check permission");
449         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
450         return BAD_CONTEXT_ID;
451     }
452 
453     Identification::IdentificationPara para = {};
454     para.tokenId = IpcCommon::GetAccessTokenId(*this);
455     para.authType = authType;
456     para.challenge = std::move(challenge);
457     auto context = ContextFactory::CreateIdentifyContext(para, contextCallback);
458     if (!ContextPool::Instance().Insert(context)) {
459         IAM_LOGE("failed to insert context");
460         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
461         return BAD_CONTEXT_ID;
462     }
463 
464     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
465 
466     if (!context->Start()) {
467         IAM_LOGE("failed to start identify");
468         contextCallback->OnResult(context->GetLatestError(), extraInfo);
469         return BAD_CONTEXT_ID;
470     }
471     return context->GetContextId();
472 }
473 
CancelAuthOrIdentify(uint64_t contextId)474 int32_t UserAuthService::CancelAuthOrIdentify(uint64_t contextId)
475 {
476     IAM_LOGI("start");
477     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
478         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
479     if (checkRet) {
480         IAM_LOGE("failed to check permission");
481         return CHECK_PERMISSION_FAILED;
482     }
483     auto context = ContextPool::Instance().Select(contextId).lock();
484     if (context == nullptr) {
485         IAM_LOGE("context not exist");
486         return GENERAL_ERROR;
487     }
488 
489     if (context->GetTokenId() != IpcCommon::GetAccessTokenId(*this)) {
490         IAM_LOGE("failed to check tokenId");
491         return INVALID_CONTEXT_ID;
492     }
493 
494     if (!context->Stop()) {
495         IAM_LOGE("failed to cancel auth or identify");
496         return context->GetLatestError();
497     }
498 
499     return SUCCESS;
500 }
501 
GetVersion(int32_t & version)502 int32_t UserAuthService::GetVersion(int32_t &version)
503 {
504     IAM_LOGI("start");
505     version = MINIMUM_VERSION;
506     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
507         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
508     if (checkRet) {
509         IAM_LOGE("failed to check permission");
510         return CHECK_PERMISSION_FAILED;
511     }
512     version = CURRENT_VERSION;
513     return SUCCESS;
514 }
515 
CheckAuthWidgetType(const std::vector<AuthType> & authType)516 int32_t UserAuthService::CheckAuthWidgetType(const std::vector<AuthType> &authType)
517 {
518     if (authType.empty() || (authType.size() > MAX_AUTH_TYPE_SIZE)) {
519         IAM_LOGE("invalid authType size:%{public}zu", authType.size());
520         return INVALID_PARAMETERS;
521     }
522     for (auto &type : authType) {
523         if ((type != AuthType::PIN) && (type != AuthType::FACE) && (type != AuthType::FINGERPRINT)) {
524             IAM_LOGE("unsupport auth type %{public}d", type);
525             return TYPE_NOT_SUPPORT;
526         }
527     }
528     std::set<AuthType> typeChecker(authType.begin(), authType.end());
529     if (typeChecker.size() != authType.size()) {
530         IAM_LOGE("duplicate auth type");
531         return INVALID_PARAMETERS;
532     }
533     return SUCCESS;
534 }
535 
CheckSingeFaceOrFinger(const std::vector<AuthType> & authType)536 bool UserAuthService::CheckSingeFaceOrFinger(const std::vector<AuthType> &authType)
537 {
538     const size_t sizeOne = 1;
539     const size_t type0 = 0;
540     if (authType.size() != sizeOne) {
541         return false;
542     }
543     if (authType[type0] == AuthType::FACE) {
544         return true;
545     }
546     if (authType[type0] == AuthType::FINGERPRINT) {
547         return true;
548     }
549     return false;
550 }
551 
CheckAuthWidgetParam(int32_t userId,const AuthParam & authParam,const WidgetParam & widgetParam,std::vector<AuthType> & validType)552 int32_t UserAuthService::CheckAuthWidgetParam(
553     int32_t userId, const AuthParam &authParam, const WidgetParam &widgetParam, std::vector<AuthType> &validType)
554 {
555     int32_t ret = CheckAuthWidgetType(authParam.authType);
556     if (ret != SUCCESS) {
557         IAM_LOGE("CheckAuthWidgetType fail.");
558         return ret;
559     }
560     if (!CheckAuthTrustLevel(authParam.authTrustLevel)) {
561         IAM_LOGE("authTrustLevel is not in correct range");
562         return ResultCode::TRUST_LEVEL_NOT_SUPPORT;
563     }
564     ret = AuthWidgetHelper::CheckValidSolution(
565         userId, authParam.authType, authParam.authTrustLevel, validType);
566     if (ret != SUCCESS) {
567         IAM_LOGE("CheckValidSolution fail %{public}d", ret);
568         return ret;
569     }
570     static const size_t authTypeTwo = 2;
571     static const size_t authType0 = 0;
572     static const size_t authType1 = 1;
573     std::vector<AuthType> authType = authParam.authType;
574     if (((authType.size() == authTypeTwo) &&
575             (authType[authType0] == AuthType::FACE) && (authType[authType1] == AuthType::FINGERPRINT)) ||
576         ((authType.size() == authTypeTwo) &&
577             (authType[authType0] == AuthType::FINGERPRINT) && (authType[authType1] == AuthType::FACE))) {
578         IAM_LOGE("only face and finger not support");
579         return INVALID_PARAMETERS;
580     }
581 
582     if (widgetParam.title.empty()) {
583         IAM_LOGE("title is empty");
584         return INVALID_PARAMETERS;
585     }
586     if (!widgetParam.navigationButtonText.empty() && !CheckSingeFaceOrFinger(validType)) {
587         IAM_LOGE("navigationButtonText check fail, validType.size:%{public}zu", validType.size());
588         return INVALID_PARAMETERS;
589     }
590 
591     if (widgetParam.windowMode == FULLSCREEN && CheckSingeFaceOrFinger(validType)) {
592         IAM_LOGE("Single fingerprint or single face does not support full screen");
593         return INVALID_PARAMETERS;
594     }
595     return SUCCESS;
596 }
597 
StartWidgetContext(const std::shared_ptr<ContextCallback> & contextCallback,const AuthParam & authParam,const WidgetParam & widgetParam,std::vector<AuthType> & validType,ContextFactory::AuthWidgetContextPara & para)598 uint64_t UserAuthService::StartWidgetContext(const std::shared_ptr<ContextCallback> &contextCallback,
599     const AuthParam &authParam, const WidgetParam &widgetParam, std::vector<AuthType> &validType,
600     ContextFactory::AuthWidgetContextPara &para)
601 {
602     Attributes extraInfo;
603     para.tokenId = IpcCommon::GetAccessTokenId(*this);
604     if (!AuthWidgetHelper::InitWidgetContextParam(authParam, validType, widgetParam, para)) {
605         IAM_LOGE("init widgetContext failed");
606         contextCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
607         return BAD_CONTEXT_ID;
608     }
609     auto context = ContextFactory::CreateWidgetContext(para, contextCallback);
610     if (context == nullptr || !Insert2ContextPool(context)) {
611         contextCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
612         return BAD_CONTEXT_ID;
613     }
614     contextCallback->SetTraceRequestContextId(context->GetContextId());
615     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
616     if (!context->Start()) {
617         int32_t errorCode = context->GetLatestError();
618         IAM_LOGE("start widget context fail %{public}d", errorCode);
619         contextCallback->OnResult(errorCode, extraInfo);
620         return BAD_CONTEXT_ID;
621     }
622     return context->GetContextId();
623 }
624 
AuthWidget(int32_t apiVersion,const AuthParam & authParam,const WidgetParam & widgetParam,sptr<UserAuthCallbackInterface> & callback)625 uint64_t UserAuthService::AuthWidget(int32_t apiVersion, const AuthParam &authParam,
626     const WidgetParam &widgetParam, sptr<UserAuthCallbackInterface> &callback)
627 {
628     IAM_LOGI("start %{public}d authTrustLevel:%{public}u", apiVersion, authParam.authTrustLevel);
629     auto contextCallback = GetAuthContextCallback(apiVersion, authParam, widgetParam, callback);
630     if (contextCallback == nullptr) {
631         IAM_LOGE("contextCallback is nullptr");
632         return BAD_CONTEXT_ID;
633     }
634     bool isBundleName = false;
635     std::string callerName = "";
636     static_cast<void>(IpcCommon::GetCallerName(*this, isBundleName, callerName));
637     contextCallback->SetTraceCallerName(callerName);
638     Attributes extraInfo;
639     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP) &&
640         (widgetParam.windowMode != WindowModeType::UNKNOWN_WINDOW_MODE)) {
641         IAM_LOGE("normal app can't set window mode.");
642         contextCallback->OnResult(INVALID_PARAMETERS, extraInfo);
643         return BAD_CONTEXT_ID;
644     }
645     if (!IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
646         IAM_LOGE("CheckPermission failed");
647         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
648         return BAD_CONTEXT_ID;
649     }
650     int32_t userId;
651     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
652         IAM_LOGE("get callingUserId failed");
653         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
654         return BAD_CONTEXT_ID;
655     }
656     contextCallback->SetTraceUserId(userId);
657     std::vector<AuthType> validType;
658     int32_t checkRet = CheckAuthWidgetParam(userId, authParam, widgetParam, validType);
659     if (checkRet != SUCCESS) {
660         contextCallback->OnResult(checkRet, extraInfo);
661         return BAD_CONTEXT_ID;
662     }
663     ContextFactory::AuthWidgetContextPara para;
664     para.userId = userId;
665     if (isBundleName) {
666         para.callingBundleName = callerName;
667         para.callerName = callerName;
668     }
669     para.sdkVersion = apiVersion;
670     return StartWidgetContext(contextCallback, authParam, widgetParam, validType, para);
671 }
672 
Insert2ContextPool(const std::shared_ptr<Context> & context)673 bool UserAuthService::Insert2ContextPool(const std::shared_ptr<Context> &context)
674 {
675     bool ret = false;
676     const int32_t retryTimes = 3;
677     for (auto i = 0; i < retryTimes; i++) {
678         ret = ContextPool::Instance().Insert(context);
679         if (ret) {
680             break;
681         }
682     }
683     IAM_LOGI("insert context to pool, retry %{public}d times", retryTimes);
684     return ret;
685 }
686 
GetAuthContextCallback(int32_t apiVersion,const AuthParam & authParam,const WidgetParam & widgetParam,sptr<UserAuthCallbackInterface> & callback)687 std::shared_ptr<ContextCallback> UserAuthService::GetAuthContextCallback(int32_t apiVersion,
688     const AuthParam &authParam, const WidgetParam &widgetParam, sptr<UserAuthCallbackInterface> &callback)
689 {
690     if (callback == nullptr) {
691         IAM_LOGE("callback is nullptr");
692         return nullptr;
693     }
694     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER_BEHAVIOR);
695     if (contextCallback == nullptr) {
696         IAM_LOGE("failed to construct context callback");
697         Attributes extraInfo;
698         callback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
699         return nullptr;
700     }
701     contextCallback->SetTraceSdkVersion(apiVersion);
702     contextCallback->SetTraceAuthTrustLevel(authParam.authTrustLevel);
703 
704     uint32_t authWidgetType = 0;
705     for (const auto authType : authParam.authType) {
706         authWidgetType |= static_cast<uint32_t>(authType);
707     }
708     static const uint32_t bitWindowMode = 0x40000000;
709     if (widgetParam.windowMode == FULLSCREEN) {
710         authWidgetType |= bitWindowMode;
711     }
712     static const uint32_t bitNavigation = 0x80000000;
713     if (!widgetParam.navigationButtonText.empty()) {
714         authWidgetType |= bitNavigation;
715     }
716     IAM_LOGI("SetTraceAuthWidgetType %{public}08x", authWidgetType);
717     contextCallback->SetTraceAuthWidgetType(authWidgetType);
718 
719     return contextCallback;
720 }
721 
Notice(NoticeType noticeType,const std::string & eventData)722 int32_t UserAuthService::Notice(NoticeType noticeType, const std::string &eventData)
723 {
724     IAM_LOGI("start");
725     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP)) {
726         IAM_LOGE("the caller is not a system application");
727         return ResultCode::CHECK_SYSTEM_APP_FAILED;
728     }
729 
730     if (!IpcCommon::CheckPermission(*this, SUPPORT_USER_AUTH)) {
731         IAM_LOGE("failed to check permission");
732         return ResultCode::CHECK_PERMISSION_FAILED;
733     }
734     return WidgetClient::Instance().OnNotice(noticeType, eventData);
735 }
736 
RegisterWidgetCallback(int32_t version,sptr<WidgetCallbackInterface> & callback)737 int32_t UserAuthService::RegisterWidgetCallback(int32_t version, sptr<WidgetCallbackInterface> &callback)
738 {
739     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP)) {
740         IAM_LOGE("the caller is not a system application");
741         return ResultCode::CHECK_SYSTEM_APP_FAILED;
742     }
743 
744     if (!IpcCommon::CheckPermission(*this, SUPPORT_USER_AUTH)) {
745         IAM_LOGE("CheckPermission failed, no permission");
746         return ResultCode::CHECK_PERMISSION_FAILED;
747     }
748 
749     uint32_t tokenId = IpcCommon::GetTokenId(*this);
750     IAM_LOGE("RegisterWidgetCallback tokenId %{public}u", tokenId);
751 
752     int32_t curVersion = std::stoi(NOTICE_VERSION_STR);
753     if (version != curVersion) {
754         return ResultCode::INVALID_PARAMETERS;
755     }
756     if (callback == nullptr) {
757         IAM_LOGE("callback is nullptr");
758         return ResultCode::INVALID_PARAMETERS;
759     }
760     WidgetClient::Instance().SetWidgetCallback(callback);
761     WidgetClient::Instance().SetAuthTokenId(tokenId);
762     return ResultCode::SUCCESS;
763 }
764 
765 } // namespace UserAuth
766 } // namespace UserIam
767 } // namespace OHOS