• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "widget_context.h"
16 
17 #include <algorithm>
18 
19 #include "context_helper.h"
20 #include "context_pool.h"
21 #include "iam_check.h"
22 #include "iam_logger.h"
23 #include "iam_ptr.h"
24 #include "iam_time.h"
25 #include "schedule_node.h"
26 #include "schedule_node_callback.h"
27 #include "widget_schedule_node_impl.h"
28 #include "widget_context_callback_impl.h"
29 #include "widget_client.h"
30 #include "widget_json.h"
31 #include "bool_wrapper.h"
32 #include "double_wrapper.h"
33 #include "int_wrapper.h"
34 #include "string_wrapper.h"
35 #include "want_params_wrapper.h"
36 #include "ability_connection.h"
37 #include "ability_connect_callback.h"
38 #include "refbase.h"
39 #include "hisysevent_adapter.h"
40 
41 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
42 
43 namespace OHOS {
44 namespace UserIam {
45 namespace UserAuth {
46 constexpr int32_t DEFAULT_VALUE = -1;
47 const std::string UI_EXTENSION_TYPE_SET = "sysDialog/userAuth";
48 
WidgetContext(uint64_t contextId,const ContextFactory::AuthWidgetContextPara & para,std::shared_ptr<ContextCallback> callback)49 WidgetContext::WidgetContext(uint64_t contextId, const ContextFactory::AuthWidgetContextPara &para,
50     std::shared_ptr<ContextCallback> callback)
51     : contextId_(contextId), description_("UserAuthWidget"), callerCallback_(callback), hasStarted_(false),
52     latestError_(ResultCode::GENERAL_ERROR), para_(para), schedule_(nullptr), connection_(nullptr)
53 {
54 }
55 
~WidgetContext()56 WidgetContext::~WidgetContext()
57 {
58     IAM_LOGI("release WidgetContext");
59 }
60 
Start()61 bool WidgetContext::Start()
62 {
63     std::lock_guard<std::recursive_mutex> lock(mutex_);
64     IAM_LOGI("%{public}s start", description_.c_str());
65     if (hasStarted_) {
66         IAM_LOGI("%{public}s context has started, cannot start again", description_.c_str());
67         return false;
68     }
69     hasStarted_ = true;
70     return OnStart();
71 }
72 
Stop()73 bool WidgetContext::Stop()
74 {
75     IAM_LOGI("%{public}s start", description_.c_str());
76     return OnStop();
77 }
78 
GetContextId() const79 uint64_t WidgetContext::GetContextId() const
80 {
81     return contextId_;
82 }
83 
GetContextType() const84 ContextType WidgetContext::GetContextType() const
85 {
86     return WIDGET_AUTH_CONTEXT;
87 }
88 
GetScheduleNode(uint64_t scheduleId) const89 std::shared_ptr<ScheduleNode> WidgetContext::GetScheduleNode(uint64_t scheduleId) const
90 {
91     return nullptr;
92 }
93 
GetTokenId() const94 uint32_t WidgetContext::GetTokenId() const
95 {
96     return para_.tokenId;
97 }
98 
GetLatestError() const99 int32_t WidgetContext::GetLatestError() const
100 {
101     return latestError_;
102 }
103 
SetLatestError(int32_t error)104 void WidgetContext::SetLatestError(int32_t error)
105 {
106     if (error != ResultCode::SUCCESS) {
107         latestError_ = error;
108     }
109 }
110 
BuildSchedule()111 bool WidgetContext::BuildSchedule()
112 {
113     schedule_ = Common::MakeShared<WidgetScheduleNodeImpl>();
114     IF_FALSE_LOGE_AND_RETURN_VAL(schedule_ != nullptr, false);
115     schedule_->SetCallback(shared_from_this());
116     return true;
117 }
118 
GetAuthContextCallback(AuthType authType,AuthTrustLevel authTrustLevel,sptr<IamCallbackInterface> & iamCallback)119 std::shared_ptr<ContextCallback> WidgetContext::GetAuthContextCallback(AuthType authType,
120     AuthTrustLevel authTrustLevel, sptr<IamCallbackInterface> &iamCallback)
121 {
122     auto widgetCallback = ContextCallback::NewInstance(iamCallback, TRACE_AUTH_USER_SECURITY);
123     if (widgetCallback == nullptr) {
124         IAM_LOGE("failed to construct context callback");
125         Attributes extraInfo;
126         iamCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
127         return nullptr;
128     }
129     widgetCallback->SetTraceCallerName(para_.callerName);
130     widgetCallback->SetTraceRequestContextId(contextId_);
131     widgetCallback->SetTraceAuthTrustLevel(authTrustLevel);
132     widgetCallback->SetTraceAuthType(authType);
133     return widgetCallback;
134 }
135 
BuildTask(const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel)136 std::shared_ptr<Context> WidgetContext::BuildTask(const std::vector<uint8_t> &challenge,
137     AuthType authType, AuthTrustLevel authTrustLevel)
138 {
139     IF_FALSE_LOGE_AND_RETURN_VAL(callerCallback_ != nullptr, nullptr);
140     auto userId = para_.userId;
141     auto tokenId = WidgetClient::Instance().GetAuthTokenId();
142     IAM_LOGI("Real userId: %{public}d, Real tokenId: %{public}u", userId, tokenId);
143     sptr<IamCallbackInterface> iamCallback(new (std::nothrow) WidgetContextCallbackImpl(weak_from_this(),
144         static_cast<int32_t>(authType)));
145     IF_FALSE_LOGE_AND_RETURN_VAL(iamCallback != nullptr, nullptr);
146     auto widgetCallback = GetAuthContextCallback(authType, authTrustLevel, iamCallback);
147     IF_FALSE_LOGE_AND_RETURN_VAL(widgetCallback != nullptr, nullptr);
148 
149     Authentication::AuthenticationPara para = {};
150     para.tokenId = tokenId;
151     para.userId = userId;
152     para.authType = authType;
153     para.atl = authTrustLevel;
154     para.challenge = challenge;
155     para.endAfterFirstFail = true;
156     para.callerName = para_.callerName;
157     para.sdkVersion = para_.sdkVersion;
158     auto context = ContextFactory::CreateSimpleAuthContext(para, widgetCallback);
159     if (context == nullptr || !ContextPool::Instance().Insert(context)) {
160         IAM_LOGE("failed to insert context");
161         Attributes extraInfo;
162         widgetCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
163         return nullptr;
164     }
165     widgetCallback->SetTraceAuthContextId(context->GetContextId());
166     widgetCallback->SetCleaner(ContextHelper::Cleaner(context));
167     std::lock_guard<std::recursive_mutex> lock(mutex_);
168     return context;
169 }
170 
OnStart()171 bool WidgetContext::OnStart()
172 {
173     IAM_LOGI("%{public}s start", description_.c_str());
174     if (!BuildSchedule()) {
175         IAM_LOGE("failed to create widget schedule");
176         return false;
177     }
178     WidgetClient::Instance().SetWidgetContextId(GetContextId());
179     WidgetClient::Instance().SetWidgetParam(para_.widgetParam);
180     WidgetClient::Instance().SetAuthTypeList(para_.authTypeList);
181     WidgetClient::Instance().SetWidgetSchedule(schedule_);
182     WidgetClient::Instance().SetChallenge(para_.challenge);
183     WidgetClient::Instance().SetCallingBundleName(para_.callingBundleName);
184     schedule_->StartSchedule();
185 
186     IAM_LOGI("WidgetContext start success.");
187     return true;
188 }
189 
OnResult(int32_t resultCode,const std::shared_ptr<Attributes> & scheduleResultAttr)190 void WidgetContext::OnResult(int32_t resultCode, const std::shared_ptr<Attributes> &scheduleResultAttr)
191 {
192     IAM_LOGI("%{public}s receive result code %{public}d", description_.c_str(), resultCode);
193 }
194 
OnStop()195 bool WidgetContext::OnStop()
196 {
197     // response app.cancel()
198     IAM_LOGI("%{public}s start", description_.c_str());
199     End(ResultCode::CANCELED);
200     return true;
201 }
202 
AuthResult(int32_t resultCode,int32_t at,const Attributes & finalResult)203 void WidgetContext::AuthResult(int32_t resultCode, int32_t at, const Attributes &finalResult)
204 {
205     IAM_LOGI("recv task result: %{public}d, authType: %{public}d", resultCode, at);
206     int32_t remainTimes = -1;
207     int32_t freezingTime = -1;
208     if (!finalResult.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, remainTimes)) {
209         IAM_LOGI("get remainTimes failed.");
210     }
211     if (!finalResult.GetInt32Value(Attributes::ATTR_FREEZING_TIME, freezingTime)) {
212         IAM_LOGI("get freezingTime failed.");
213     }
214     AuthType authType = static_cast<AuthType>(at);
215     WidgetClient::Instance().ReportWidgetResult(resultCode, authType, freezingTime, remainTimes);
216     IF_FALSE_LOGE_AND_RETURN(schedule_ != nullptr);
217     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
218     callerCallback_->SetTraceAuthType(authType);
219     IAM_LOGI("call schedule:");
220     if (resultCode == ResultCode::SUCCESS) {
221         finalResult.GetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token);
222         authResultInfo_.authType = authType;
223         schedule_->SuccessAuth(authType);
224     } else {
225         // failed
226         SetLatestError(resultCode);
227         schedule_->StopAuthList({authType});
228     }
229 }
230 
231 // WidgetScheduleNodeCallback
LaunchWidget()232 bool WidgetContext::LaunchWidget()
233 {
234     IAM_LOGI("launch widget");
235     if (!ConnectExtension()) {
236         IAM_LOGE("failed to launch widget.");
237         return false;
238     }
239     return true;
240 }
241 
ExecuteAuthList(const std::set<AuthType> & authTypeList)242 void WidgetContext::ExecuteAuthList(const std::set<AuthType> &authTypeList)
243 {
244     IAM_LOGI("execute auth list");
245     // create task, and start it
246     std::lock_guard<std::recursive_mutex> lock(mutex_);
247     for (auto &authType : authTypeList) {
248         auto task = BuildTask(para_.challenge, authType, para_.atl);
249         if (task == nullptr) {
250             IAM_LOGE("failed to create task, authType: %{public}s", AuthType2Str(authType).c_str());
251             continue;
252         }
253         task->Start();
254         TaskInfo taskInfo {
255             .authType = authType,
256             .task = task
257         };
258         runTaskInfoList_.push_back(taskInfo);
259     }
260 }
261 
EndAuthAsCancel()262 void WidgetContext::EndAuthAsCancel()
263 {
264     IAM_LOGI("end auth as cancel");
265     std::lock_guard<std::recursive_mutex> lock(mutex_);
266     // report CANCELED to App
267     End(ResultCode::CANCELED);
268 }
269 
EndAuthAsNaviPin()270 void WidgetContext::EndAuthAsNaviPin()
271 {
272     IAM_LOGI("end auth as navi pin");
273     std::lock_guard<std::recursive_mutex> lock(mutex_);
274     // report CANCELED_FROM_WIDGET to App
275     End(ResultCode::CANCELED_FROM_WIDGET);
276 }
277 
EndAuthAsWidgetParaInvalid()278 void WidgetContext::EndAuthAsWidgetParaInvalid()
279 {
280     IAM_LOGI("end auth as widget para invalid");
281     std::lock_guard<std::recursive_mutex> lock(mutex_);
282     End(ResultCode::INVALID_PARAMETERS);
283 }
284 
StopAuthList(const std::vector<AuthType> & authTypeList)285 void WidgetContext::StopAuthList(const std::vector<AuthType> &authTypeList)
286 {
287     IAM_LOGI("stop auth list");
288     std::lock_guard<std::recursive_mutex> lock(mutex_);
289     for (auto &authType : authTypeList) {
290         auto it = std::find_if(runTaskInfoList_.begin(),
291             runTaskInfoList_.end(), [authType] (const TaskInfo &taskInfo) {
292             return (taskInfo.authType == authType);
293         });
294         if (it != runTaskInfoList_.end()) {
295             if (it->task == nullptr) {
296                 IAM_LOGE("task is nullptr");
297                 return;
298             }
299             it->task->Stop();
300             runTaskInfoList_.erase(it);
301         }
302     }
303 }
304 
SuccessAuth(AuthType authType)305 void WidgetContext::SuccessAuth(AuthType authType)
306 {
307     IAM_LOGI("success auth. authType:%{public}d", static_cast<int32_t>(authType));
308     std::lock_guard<std::recursive_mutex> lock(mutex_);
309     // report success to App
310     End(ResultCode::SUCCESS);
311 }
312 
ConnectExtensionAbility(const AAFwk::Want & want,const std::string commandStr)313 int32_t WidgetContext::ConnectExtensionAbility(const AAFwk::Want &want, const std::string commandStr)
314 {
315     IAM_LOGI("ConnectExtensionAbility start");
316     if (connection_ != nullptr) {
317         IAM_LOGE("invalid connection_");
318         return ERR_INVALID_OPERATION;
319     }
320     connection_ = sptr<UIExtensionAbilityConnection>(new (std::nothrow) UIExtensionAbilityConnection(commandStr));
321     if (connection_ == nullptr) {
322         IAM_LOGE("new connection error.");
323         return ERR_NO_MEMORY;
324     }
325 
326     std::string identity = IPCSkeleton::ResetCallingIdentity();
327     auto ret = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want, connection_, nullptr,
328         DEFAULT_VALUE);
329     IPCSkeleton::SetCallingIdentity(identity);
330     IAM_LOGI("ConnectExtensionAbility errCode=%{public}d", ret);
331     return ret;
332 }
333 
ConnectExtension()334 bool WidgetContext::ConnectExtension()
335 {
336     std::string tmp = BuildStartCommand();
337     IAM_LOGI("start command: %{public}s", tmp.c_str());
338 
339     AAFwk::Want want;
340     std::string bundleName = "com.ohos.systemui";
341     std::string abilityName = "com.ohos.systemui.dialog";
342     want.SetElementName(bundleName, abilityName);
343     auto ret = ConnectExtensionAbility(want, tmp);
344     if (ret != ERR_OK) {
345         UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), "userauthservice");
346         IAM_LOGE("ConnectExtensionAbility failed.");
347         return false;
348     }
349     return true;
350 }
351 
DisconnectExtension()352 bool WidgetContext::DisconnectExtension()
353 {
354     if (connection_ == nullptr) {
355         IAM_LOGE("invalid connection handle");
356         return false;
357     }
358     ErrCode ret = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(connection_);
359     if (ret != ERR_OK) {
360         IAM_LOGE("disconnect extension ability failed ret: %{public}d.", ret);
361         return false;
362     }
363     return true;
364 }
365 
End(const ResultCode & resultCode)366 void WidgetContext::End(const ResultCode &resultCode)
367 {
368     IAM_LOGI("in End, resultCode: %{public}d", static_cast<int32_t>(resultCode));
369     WidgetClient::Instance().Reset();
370     StopAllRunTask();
371     if (resultCode != ResultCode::SUCCESS) {
372         IAM_LOGI("Try to disconnect extesnion");
373         if (!DisconnectExtension()) {
374             IAM_LOGE("failed to release launch widget.");
375         }
376     }
377     IF_FALSE_LOGE_AND_RETURN(callerCallback_ != nullptr);
378     Attributes attr;
379     if (resultCode == ResultCode::SUCCESS) {
380         if (!attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authResultInfo_.authType)) {
381             IAM_LOGE("set auth type failed.");
382             callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
383             return;
384         }
385         if (authResultInfo_.token.size() > 0) {
386             if (!attr.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token)) {
387                 IAM_LOGE("set signature token failed.");
388                 callerCallback_->OnResult(ResultCode::GENERAL_ERROR, attr);
389                 return;
390             }
391         }
392     }
393     callerCallback_->OnResult(resultCode, attr);
394 }
395 
StopAllRunTask()396 void WidgetContext::StopAllRunTask()
397 {
398     std::lock_guard<std::recursive_mutex> lock(mutex_);
399     for (auto &taskInfo : runTaskInfoList_) {
400         IAM_LOGI("stop task");
401         taskInfo.task->Stop();
402     }
403     runTaskInfoList_.clear();
404 }
405 
BuildStartCommand()406 std::string WidgetContext::BuildStartCommand()
407 {
408     WidgetCmdParameters widgetCmdParameters;
409     widgetCmdParameters.uiExtensionType = UI_EXTENSION_TYPE_SET;
410     widgetCmdParameters.useriamCmdData.widgetContextId = GetContextId();
411     widgetCmdParameters.useriamCmdData.title = para_.widgetParam.title;
412     widgetCmdParameters.useriamCmdData.windowModeType = WinModeType2Str(para_.widgetParam.windowMode);
413     widgetCmdParameters.useriamCmdData.navigationButtonText = para_.widgetParam.navigationButtonText;
414     auto it = para_.authProfileMap.find(AuthType::PIN);
415     if (it != para_.authProfileMap.end()) {
416         widgetCmdParameters.useriamCmdData.pinSubType = PinSubType2Str(static_cast<PinSubType>(it->second.pinSubType));
417     }
418     std::vector<std::string> typeList;
419     for (auto &item : para_.authProfileMap) {
420         auto &at = item.first;
421         auto &profile = item.second;
422         typeList.push_back(AuthType2Str(at));
423         WidgetCommand::Cmd cmd {
424             .event = CMD_NOTIFY_AUTH_START,
425             .version = NOTICE_VERSION_STR,
426             .type = AuthType2Str(at)
427         };
428         if (at == AuthType::FINGERPRINT && !profile.sensorInfo.empty()) {
429             cmd.sensorInfo = profile.sensorInfo;
430         }
431         cmd.remainAttempts = profile.remainTimes;
432         cmd.lockoutDuration = profile.freezingTime;
433         widgetCmdParameters.useriamCmdData.cmdList.push_back(cmd);
434     }
435     widgetCmdParameters.useriamCmdData.typeList = typeList;
436 
437     nlohmann::json root = widgetCmdParameters;
438     std::string cmdData = root.dump();
439     return cmdData;
440 }
441 } // namespace UserAuth
442 } // namespace UserIam
443 } // namespace OHOS
444