• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 #include "simple_auth_context.h"
16 
17 #include <set>
18 #include <vector>
19 
20 #include "auth_common.h"
21 #include "iam_check.h"
22 #include "iam_logger.h"
23 #include "iam_para2str.h"
24 #include "publish_event_adapter.h"
25 #include "resource_node.h"
26 #include "resource_node_utils.h"
27 #include "schedule_node.h"
28 #include "schedule_node_callback.h"
29 #include "thread_handler_manager.h"
30 #include "user_idm_database.h"
31 
32 #define LOG_TAG "USER_AUTH_SA"
33 namespace OHOS {
34 namespace UserIam {
35 namespace UserAuth {
GetPropertyTemplateIds(Authentication::AuthResultInfo & resultInfo)36 std::optional<std::vector<uint64_t>> SimpleAuthContext::GetPropertyTemplateIds(
37     Authentication::AuthResultInfo &resultInfo)
38 {
39     IAM_LOGI("start");
40     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_.size() == 1, std::nullopt);
41     auto scheduleNode = scheduleList_[0];
42     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleNode != nullptr, std::nullopt);
43     if (scheduleNode->GetAuthType() != PRIVATE_PIN) {
44         return scheduleNode->GetTemplateIdList();
45     }
46 
47     std::vector<uint64_t> templateIds;
48     std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
49     int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(resultInfo.userId, scheduleNode->GetAuthType(),
50         credInfos);
51     if (ret != SUCCESS) {
52         IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
53             resultInfo.userId, scheduleNode->GetAuthType());
54         return std::nullopt;
55     }
56 
57     for (auto &iter : credInfos) {
58         if (scheduleNode->GetAuthIntent() == QUESTION_AUTH) {
59             if (iter->GetAuthSubType() == PIN_QUESTION) {
60                 templateIds.push_back(iter->GetTemplateId());
61                 break;
62             }
63         } else {
64             if (iter->GetAuthSubType() != PIN_QUESTION) {
65                 templateIds.push_back(iter->GetTemplateId());
66                 break;
67             }
68         }
69     }
70 
71     return templateIds;
72 }
73 
GetPropertyForAuthResult(Authentication::AuthResultInfo & resultInfo)74 ResultCode SimpleAuthContext::GetPropertyForAuthResult(Authentication::AuthResultInfo &resultInfo)
75 {
76     IAM_LOGD("start");
77     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_.size() == 1, GENERAL_ERROR);
78     auto scheduleNode = scheduleList_[0];
79     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleNode != nullptr, GENERAL_ERROR);
80     if (scheduleNode->GetAuthType() == PIN) {
81         resultInfo.nextFailLockoutDuration = FIRST_LOCKOUT_DURATION_OF_PIN;
82     } else {
83         resultInfo.nextFailLockoutDuration = FIRST_LOCKOUT_DURATION_EXCEPT_PIN;
84     }
85     if (resultInfo.result != FAIL && resultInfo.result != LOCKED) {
86         IAM_LOGI("no need GetPropertyFromExecutor, nextLockDuration:%{public}d", resultInfo.nextFailLockoutDuration);
87         return SUCCESS;
88     }
89 
90     auto resourceNode = scheduleNode->GetVerifyExecutor().lock();
91     IF_FALSE_LOGE_AND_RETURN_VAL(resourceNode != nullptr, GENERAL_ERROR);
92     auto optionalTemplateIdList = GetPropertyTemplateIds(resultInfo);
93     IF_FALSE_LOGE_AND_RETURN_VAL(optionalTemplateIdList.has_value(), GENERAL_ERROR);
94     std::vector<uint64_t> templateIdList = optionalTemplateIdList.value();
95     std::vector<uint32_t> keys = { Attributes::ATTR_FREEZING_TIME, Attributes::ATTR_REMAIN_TIMES};
96     if (scheduleNode->GetAuthType() == PIN) {
97         keys.push_back(Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION);
98     }
99     Attributes attr;
100     attr.SetUint32ArrayValue(Attributes::ATTR_KEY_LIST, keys);
101     attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
102     attr.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIdList);
103 
104     Attributes values;
105     int32_t ret = resourceNode->GetProperty(attr, values);
106     IF_FALSE_LOGE_AND_RETURN_VAL(ret == SUCCESS, GENERAL_ERROR);
107 
108     if (scheduleNode->GetAuthType() == PIN) {
109         bool getNextDurationRet = values.GetInt32Value(Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
110             resultInfo.nextFailLockoutDuration);
111         IF_FALSE_LOGE_AND_RETURN_VAL(getNextDurationRet == true, GENERAL_ERROR);
112     }
113     bool getFreezingTimeRet = values.GetInt32Value(Attributes::ATTR_FREEZING_TIME, resultInfo.freezingTime);
114     IF_FALSE_LOGE_AND_RETURN_VAL(getFreezingTimeRet == true, GENERAL_ERROR);
115     bool getRemainTimesRet = values.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, resultInfo.remainTimes);
116     IF_FALSE_LOGE_AND_RETURN_VAL(getRemainTimesRet == true, GENERAL_ERROR);
117 
118     IAM_LOGI("success, nextFailLockoutDuration:%{public}d, freezingTime:%{public}d, remainTime:%{public}d",
119         resultInfo.nextFailLockoutDuration, resultInfo.freezingTime, resultInfo.remainTimes);
120     return SUCCESS;
121 }
122 
SimpleAuthContext(uint64_t contextId,std::shared_ptr<Authentication> auth,std::shared_ptr<ContextCallback> callback,bool needSubscribeAppState)123 SimpleAuthContext::SimpleAuthContext(uint64_t contextId, std::shared_ptr<Authentication> auth,
124     std::shared_ptr<ContextCallback> callback, bool needSubscribeAppState)
125     : BaseContext("SimpleAuth", contextId, callback, needSubscribeAppState),
126       auth_(auth)
127 {
128 }
129 
SimpleAuthContext(const std::string & type,uint64_t contextId,std::shared_ptr<Authentication> auth,std::shared_ptr<ContextCallback> callback)130 SimpleAuthContext::SimpleAuthContext(const std::string &type, uint64_t contextId, std::shared_ptr<Authentication> auth,
131     std::shared_ptr<ContextCallback> callback)
132     : BaseContext(type, contextId, callback, true),
133       auth_(auth)
134 {
135 }
136 
GetContextType() const137 ContextType SimpleAuthContext::GetContextType() const
138 {
139     return CONTEXT_SIMPLE_AUTH;
140 }
141 
GetTokenId() const142 uint32_t SimpleAuthContext::GetTokenId() const
143 {
144     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, 0);
145     return auth_->GetAccessTokenId();
146 }
147 
GetUserId() const148 int32_t SimpleAuthContext::GetUserId() const
149 {
150     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, INVALID_USER_ID);
151     return auth_->GetUserId();
152 }
153 
GetAuthType() const154 int32_t SimpleAuthContext::GetAuthType() const
155 {
156     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, INVALID_AUTH_TYPE);
157     return auth_->GetAuthType();
158 }
159 
GetCallerName() const160 std::string SimpleAuthContext::GetCallerName() const
161 {
162     IF_FALSE_LOGE_AND_RETURN_VAL(callback_ != nullptr, "");
163     return callback_->GetCallerName();
164 }
165 
OnStart()166 bool SimpleAuthContext::OnStart()
167 {
168     IAM_LOGD("%{public}s start", GetDescription());
169     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, false);
170     bool startRet = auth_->Start(scheduleList_, shared_from_this());
171     if (!startRet) {
172         IAM_LOGE("%{public}s auth start fail", GetDescription());
173         SetLatestError(auth_->GetLatestError());
174         return startRet;
175     }
176     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_.size() == 1, false);
177     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_[0] != nullptr, false);
178     bool startScheduleRet = scheduleList_[0]->StartSchedule();
179     IF_FALSE_LOGE_AND_RETURN_VAL(startScheduleRet, false);
180     IAM_LOGI("%{public}s Schedule:%{public}s Type:%{public}d success", GetDescription(),
181         GET_MASKED_STRING(scheduleList_[0]->GetScheduleId()).c_str(), scheduleList_[0]->GetAuthType());
182     return true;
183 }
184 
OnResult(int32_t resultCode,const std::shared_ptr<Attributes> & scheduleResultAttr)185 void SimpleAuthContext::OnResult(int32_t resultCode, const std::shared_ptr<Attributes> &scheduleResultAttr)
186 {
187     IAM_LOGI("%{public}s receive result code %{public}d", GetDescription(), resultCode);
188     Authentication::AuthResultInfo resultInfo = {};
189     bool updateRet = UpdateScheduleResult(scheduleResultAttr, resultInfo);
190     IAM_LOGI("update result %{public}d, resultInfo result %{public}d", updateRet, resultInfo.result);
191     if (!updateRet) {
192         IAM_LOGE("%{public}s UpdateScheduleResult fail", GetDescription());
193         if (resultCode == SUCCESS) {
194             resultCode = GetLatestError();
195         }
196         resultInfo.result = resultCode;
197     } else if (resultCode != resultInfo.result) {
198         resultInfo.result = (resultInfo.result == SUCCESS ? resultCode : resultInfo.result);
199     }
200     if (GetPropertyForAuthResult(resultInfo) != SUCCESS) {
201         IAM_LOGE("GetPropertyForAuthResult failed");
202     }
203 
204     if (resultInfo.result == SUCCESS && GetAuthType() == PIN) {
205         PublishEventAdapter::GetInstance().CachePinUpdateParam(resultInfo.reEnrollFlag);
206     }
207     SendAuthExecutorMsg();
208     InvokeResultCallback(resultInfo);
209     IAM_LOGI("%{public}s on result %{public}d finish", GetDescription(), resultInfo.result);
210 }
211 
OnStop()212 bool SimpleAuthContext::OnStop()
213 {
214     IAM_LOGI("%{public}s start", GetDescription());
215     if (scheduleList_.size() == 1 && scheduleList_[0] != nullptr) {
216         scheduleList_[0]->StopSchedule();
217     }
218 
219     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, false);
220     bool cancelRet = auth_->Cancel();
221     if (!cancelRet) {
222         IAM_LOGE("%{public}s auth stop fail", GetDescription());
223         SetLatestError(auth_->GetLatestError());
224         return cancelRet;
225     }
226     return true;
227 }
228 
SendAuthExecutorMsg()229 void SimpleAuthContext::SendAuthExecutorMsg()
230 {
231     IAM_LOGI("begin");
232     IF_FALSE_LOGE_AND_RETURN(auth_ != nullptr);
233     auto authExecutorMsgs = auth_->GetAuthExecutorMsgs();
234     auto &threadManager = ThreadHandlerManager::GetInstance();
235 
236     for (uint32_t msgIndex = 0; msgIndex < authExecutorMsgs.size(); msgIndex++) {
237         auto authExecutorMsg = authExecutorMsgs[msgIndex];
238         std::string threadName = std::to_string(GetContextId()) + "_msg_" + std::to_string(msgIndex);
239         if (!threadManager.CreateThreadHandler(threadName)) {
240             IAM_LOGE("Failed to create thread handler for executor message");
241             continue;
242         }
243 
244         threadManager.PostTask(threadName, [authExecutorMsg, threadName]() {
245             ResourceNodeUtils::SendMsgToExecutor(
246                 authExecutorMsg.executorIndex, authExecutorMsg.commandId, authExecutorMsg.msg);
247         });
248 
249         threadManager.DestroyThreadHandler(threadName);
250     }
251     IAM_LOGI("end");
252 }
253 
UpdateScheduleResult(const std::shared_ptr<Attributes> & scheduleResultAttr,Authentication::AuthResultInfo & resultInfo)254 bool SimpleAuthContext::UpdateScheduleResult(const std::shared_ptr<Attributes> &scheduleResultAttr,
255     Authentication::AuthResultInfo &resultInfo)
256 {
257     IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, false);
258     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleResultAttr != nullptr, false);
259     std::vector<uint8_t> scheduleResult;
260     bool getResultCodeRet = scheduleResultAttr->GetUint8ArrayValue(Attributes::ATTR_RESULT, scheduleResult);
261     IF_FALSE_LOGE_AND_RETURN_VAL(getResultCodeRet == true, false);
262     bool updateRet = auth_->Update(scheduleResult, resultInfo);
263     if (!updateRet) {
264         IAM_LOGE("%{public}s auth update fail", GetDescription());
265         SetLatestError(auth_->GetLatestError());
266         return updateRet;
267     }
268     return true;
269 }
270 
SetCredentialDigest(const Authentication::AuthResultInfo & resultInfo,Attributes & finalResult) const271 bool SimpleAuthContext::SetCredentialDigest(const Authentication::AuthResultInfo &resultInfo,
272     Attributes &finalResult) const
273 {
274     uint64_t credentialDigest = resultInfo.credentialDigest;
275     if (resultInfo.sdkVersion < INNER_API_VERSION_10000) {
276         credentialDigest = resultInfo.credentialDigest & UINT16_MAX;
277     }
278     bool setCredentialDigestRet = finalResult.SetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST,
279         credentialDigest);
280     IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialDigestRet == true, false);
281     bool setCredentialCountRet = finalResult.SetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT,
282         resultInfo.credentialCount);
283     IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialCountRet == true, false);
284 
285     return true;
286 }
287 
InvokeResultCallback(const Authentication::AuthResultInfo & resultInfo) const288 void SimpleAuthContext::InvokeResultCallback(const Authentication::AuthResultInfo &resultInfo) const
289 {
290     IAM_LOGD("%{public}s start", GetDescription());
291     IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
292     Attributes finalResult;
293     bool setResultCodeRet = finalResult.SetInt32Value(Attributes::ATTR_RESULT_CODE, resultInfo.result);
294     IF_FALSE_LOGE_AND_RETURN(setResultCodeRet == true);
295     bool setNextDurationRet = finalResult.SetInt32Value(Attributes::ATTR_NEXT_FAIL_LOCKOUT_DURATION,
296         resultInfo.nextFailLockoutDuration);
297     IF_FALSE_LOGE_AND_RETURN(setNextDurationRet == true);
298     if (resultInfo.result == FAIL || resultInfo.result == LOCKED || resultInfo.result == SUCCESS) {
299         bool setFreezingTimeRet = finalResult.SetInt32Value(Attributes::ATTR_FREEZING_TIME, resultInfo.freezingTime);
300         IF_FALSE_LOGE_AND_RETURN(setFreezingTimeRet == true);
301         bool setRemainTimesRet = finalResult.SetInt32Value(Attributes::ATTR_REMAIN_TIMES, resultInfo.remainTimes);
302         IF_FALSE_LOGE_AND_RETURN(setRemainTimesRet == true);
303     }
304     if ((resultInfo.result == SUCCESS || resultInfo.token.size() != 0) && resultInfo.sdkVersion > API_VERSION_9) {
305         bool credentialDigest = SetCredentialDigest(resultInfo, finalResult);
306         IF_FALSE_LOGE_AND_RETURN(credentialDigest == true);
307     }
308     if (resultInfo.result == SUCCESS) {
309         bool setUserIdRet = finalResult.SetInt32Value(Attributes::ATTR_USER_ID, resultInfo.userId);
310         IF_FALSE_LOGE_AND_RETURN(setUserIdRet == true);
311         bool setCredentialIdRet = finalResult.SetUint64Value(Attributes::ATTR_CREDENTIAL_ID, resultInfo.credentialId);
312         IF_FALSE_LOGE_AND_RETURN(setCredentialIdRet == true);
313         IAM_LOGI("matched userId: %{public}d, credentialId: %{public}s.", resultInfo.userId,
314             GET_MASKED_STRING(resultInfo.credentialId).c_str());
315         bool setExpiredRet = finalResult.SetInt64Value(Attributes::ATTR_PIN_EXPIRED_INFO, resultInfo.pinExpiredInfo);
316         IF_FALSE_LOGE_AND_RETURN(setExpiredRet == true);
317     }
318     if (resultInfo.token.size() != 0) {
319         IAM_LOGI("result token size: %{public}zu.", resultInfo.token.size());
320         bool setSignatureResult = finalResult.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, resultInfo.token);
321         IF_FALSE_LOGE_AND_RETURN(setSignatureResult == true);
322     }
323     if (resultInfo.rootSecret.size() != 0) {
324         bool setRootSecret = finalResult.SetUint8ArrayValue(Attributes::ATTR_ROOT_SECRET, resultInfo.rootSecret);
325         IF_FALSE_LOGE_AND_RETURN(setRootSecret == true);
326     }
327     if (resultInfo.remoteAuthResultMsg.size() != 0) {
328         bool setRemoteAuthResultMsg = finalResult.SetUint8ArrayValue(Attributes::ATTR_SIGNED_AUTH_RESULT,
329             resultInfo.remoteAuthResultMsg);
330         IF_FALSE_LOGE_AND_RETURN(setRemoteAuthResultMsg == true);
331     }
332     bool setReEnrollFlagRet = finalResult.SetBoolValue(Attributes::ATTR_RE_ENROLL_FLAG, resultInfo.reEnrollFlag);
333     IF_FALSE_LOGE_AND_RETURN(setReEnrollFlagRet == true);
334 
335     callback_->SetTraceAuthFinishReason("SimpleAuthContext InvokeResultCallback");
336     callback_->OnResult(resultInfo.result, finalResult);
337     IAM_LOGI("%{public}s invoke result callback success, result %{public}d", GetDescription(), resultInfo.result);
338 }
339 } // namespace UserAuth
340 } // namespace UserIam
341 } // namespace OHOS
342