• 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"), callback_(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> & callback)119 std::shared_ptr<ContextCallback> WidgetContext::GetAuthContextCallback(AuthType authType,
120     AuthTrustLevel authTrustLevel, sptr<IamCallbackInterface> &callback)
121 {
122     if (callback == nullptr) {
123         IAM_LOGE("callback is nullptr");
124         return nullptr;
125     }
126     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER);
127     if (contextCallback == nullptr) {
128         IAM_LOGE("failed to construct context callback");
129         Attributes extraInfo;
130         callback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
131         return nullptr;
132     }
133     auto callingUid = static_cast<uint64_t>(para_.callingUid);
134     contextCallback->SetTraceCallingUid(callingUid);
135     contextCallback->SetTraceAuthTrustLevel(authTrustLevel);
136     return contextCallback;
137 }
138 
BuildTask(const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel)139 std::shared_ptr<Context> WidgetContext::BuildTask(const std::vector<uint8_t> &challenge,
140     AuthType authType, AuthTrustLevel authTrustLevel)
141 {
142     if (callback_ == nullptr) {
143         IAM_LOGE("invalid widget context callback, failed to build task");
144         return nullptr;
145     }
146     auto userId = para_.userId;
147     auto tokenId = WidgetClient::Instance().GetAuthTokenId();
148     IAM_LOGI("Real userId: %{public}d, Real tokenId: %{public}u", userId, tokenId);
149     sptr<IamCallbackInterface> iamCallback(new (std::nothrow) WidgetContextCallbackImpl(weak_from_this(),
150         static_cast<int32_t>(authType)));
151     auto contextCallback = GetAuthContextCallback(authType, authTrustLevel, iamCallback);
152     if (contextCallback == nullptr) {
153         IAM_LOGE("failed to get simple context callback");
154         return nullptr;
155     }
156     callback_->SetTraceUserId(userId);
157     ContextFactory::AuthContextPara para = {};
158     para.tokenId = tokenId;
159     para.userId = userId;
160     para.authType = authType;
161     para.atl = authTrustLevel;
162     para.challenge = challenge;
163     para.endAfterFirstFail = true;
164     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
165     if (!ContextPool::Instance().Insert(context)) {
166         IAM_LOGE("failed to insert context");
167         Attributes extraInfo;
168         callback_->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
169         return nullptr;
170     }
171     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
172     std::lock_guard<std::recursive_mutex> lock(mutex_);
173     return context;
174 }
175 
OnStart()176 bool WidgetContext::OnStart()
177 {
178     IAM_LOGI("%{public}s start", description_.c_str());
179     if (!BuildSchedule()) {
180         IAM_LOGE("failed to create widget schedule");
181         return false;
182     }
183     WidgetClient::Instance().SetWidgetContextId(GetContextId());
184     WidgetClient::Instance().SetWidgetParam(para_.widgetParam);
185     WidgetClient::Instance().SetAuthTypeList(para_.authTypeList);
186     WidgetClient::Instance().SetWidgetSchedule(schedule_);
187     schedule_->StartSchedule();
188 
189     IAM_LOGI("WidgetContext start success.");
190     return true;
191 }
192 
OnResult(int32_t resultCode,const std::shared_ptr<Attributes> & scheduleResultAttr)193 void WidgetContext::OnResult(int32_t resultCode, const std::shared_ptr<Attributes> &scheduleResultAttr)
194 {
195     IAM_LOGI("%{public}s receive result code %{public}d", description_.c_str(), resultCode);
196 }
197 
OnStop()198 bool WidgetContext::OnStop()
199 {
200     // response app.cancel()
201     IAM_LOGI("%{public}s start", description_.c_str());
202     End(ResultCode::CANCELED);
203     return true;
204 }
205 
AuthResult(int32_t resultCode,int32_t at,const Attributes & finalResult)206 void WidgetContext::AuthResult(int32_t resultCode, int32_t at, const Attributes &finalResult)
207 {
208     IAM_LOGI("recv task result: %{public}d, authType: %{public}d", resultCode, at);
209     int32_t remainTimes = -1;
210     int32_t freezingTime = -1;
211     if (!finalResult.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, remainTimes)) {
212         IAM_LOGE("get remainTimes failed.");
213         return;
214     }
215     if (!finalResult.GetInt32Value(Attributes::ATTR_FREEZING_TIME, freezingTime)) {
216         IAM_LOGE("get freezingTime failed.");
217         return;
218     }
219     AuthType authType = static_cast<AuthType>(at);
220     WidgetClient::Instance().ReportWidgetResult(resultCode, authType, freezingTime, remainTimes);
221     if (schedule_ == nullptr) {
222         IAM_LOGE("schedule is nullptr.");
223         return;
224     }
225 
226     IAM_LOGI("call schedule:");
227     if (resultCode == ResultCode::SUCCESS) {
228         finalResult.GetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token);
229         authResultInfo_.authType = authType;
230         schedule_->SuccessAuth(authType);
231     } else {
232         // failed
233         SetLatestError(resultCode);
234         schedule_->StopAuthList({authType});
235     }
236 }
237 
238 // WidgetScheduleNodeCallback
LaunchWidget()239 bool WidgetContext::LaunchWidget()
240 {
241     IAM_LOGI("launch widget");
242     if (!ConnectExtension()) {
243         IAM_LOGE("failed to launch widget.");
244         return false;
245     }
246     return true;
247 }
248 
ExecuteAuthList(const std::set<AuthType> & authTypeList)249 void WidgetContext::ExecuteAuthList(const std::set<AuthType> &authTypeList)
250 {
251     IAM_LOGI("execute auth list");
252     // create task, and start it
253     std::lock_guard<std::recursive_mutex> lock(mutex_);
254     for (auto &authType : authTypeList) {
255         auto task = BuildTask(para_.challenge, authType, para_.atl);
256         if (task == nullptr) {
257             IAM_LOGE("failed to create task, authType: %{public}s", AuthType2Str(authType).c_str());
258             continue;
259         }
260         task->Start();
261         TaskInfo taskInfo {
262             .authType = authType,
263             .task = task
264         };
265         runTaskInfoList_.push_back(taskInfo);
266     }
267 }
268 
EndAuthAsCancel()269 void WidgetContext::EndAuthAsCancel()
270 {
271     IAM_LOGI("end auth as cancel");
272     std::lock_guard<std::recursive_mutex> lock(mutex_);
273     // report CANCELED to App
274     End(ResultCode::CANCELED);
275 }
276 
EndAuthAsNaviPin()277 void WidgetContext::EndAuthAsNaviPin()
278 {
279     IAM_LOGI("end auth as navi pin");
280     std::lock_guard<std::recursive_mutex> lock(mutex_);
281     // report CANCELED_FROM_WIDGET to App
282     End(ResultCode::CANCELED_FROM_WIDGET);
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 (callback_ == nullptr) {
378         IAM_LOGE("invalid callback");
379         return;
380     }
381     Attributes attr;
382     if (resultCode == ResultCode::SUCCESS) {
383         if (!attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authResultInfo_.authType)) {
384             IAM_LOGE("set auth type failed.");
385             callback_->OnResult(ResultCode::GENERAL_ERROR, attr);
386             return;
387         }
388         if (authResultInfo_.token.size() > 0) {
389             if (!attr.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo_.token)) {
390                 IAM_LOGE("set signature token failed.");
391                 callback_->OnResult(ResultCode::GENERAL_ERROR, attr);
392                 return;
393             }
394         }
395     }
396     callback_->OnResult(resultCode, attr);
397 }
398 
StopAllRunTask()399 void WidgetContext::StopAllRunTask()
400 {
401     std::lock_guard<std::recursive_mutex> lock(mutex_);
402     for (auto &taskInfo : runTaskInfoList_) {
403         IAM_LOGI("stop task");
404         taskInfo.task->Stop();
405     }
406     runTaskInfoList_.clear();
407 }
408 
BuildStartCommand()409 std::string WidgetContext::BuildStartCommand()
410 {
411     WidgetCmdParameters widgetCmdParameters;
412     widgetCmdParameters.uiExtensionType = UI_EXTENSION_TYPE_SET;
413     widgetCmdParameters.useriamCmdData.widgetContextId = GetContextId();
414     widgetCmdParameters.useriamCmdData.title = para_.widgetParam.title;
415     widgetCmdParameters.useriamCmdData.windowModeType = WinModeType2Str(para_.widgetParam.windowMode);
416     widgetCmdParameters.useriamCmdData.navigationButtonText = para_.widgetParam.navigationButtonText;
417     auto it = para_.authProfileMap.find(AuthType::PIN);
418     if (it != para_.authProfileMap.end()) {
419         widgetCmdParameters.useriamCmdData.pinSubType = PinSubType2Str(static_cast<PinSubType>(it->second.pinSubType));
420     }
421     std::vector<std::string> typeList;
422     for (auto &item : para_.authProfileMap) {
423         auto &at = item.first;
424         auto &profile = item.second;
425         typeList.push_back(AuthType2Str(at));
426         WidgetCommand::Cmd cmd {
427             .event = CMD_NOTIFY_AUTH_START,
428             .version = NOTICE_VERSION_STR,
429             .type = AuthType2Str(at)
430         };
431         if (at == AuthType::FINGERPRINT && !profile.sensorInfo.empty()) {
432             cmd.sensorInfo = profile.sensorInfo;
433         }
434         cmd.remainAttempts = profile.remainTimes;
435         cmd.lockoutDuration = profile.freezingTime;
436         widgetCmdParameters.useriamCmdData.cmdList.push_back(cmd);
437     }
438     widgetCmdParameters.useriamCmdData.typeList = typeList;
439 
440     nlohmann::json root = widgetCmdParameters;
441     std::string cmdData = root.dump();
442     return cmdData;
443 }
444 } // namespace UserAuth
445 } // namespace UserIam
446 } // namespace OHOS
447