• 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 
16 #include "widget_client.h"
17 
18 #include "system_ability_definition.h"
19 
20 #include "auth_common.h"
21 #include "iam_check.h"
22 #include "iam_logger.h"
23 #include "iam_para2str.h"
24 #include "iam_time.h"
25 #include "nlohmann/json.hpp"
26 #include "iwidget_callback.h"
27 #include "hisysevent_adapter.h"
28 
29 #define LOG_TAG "USER_AUTH_SA"
30 
31 namespace OHOS {
32 namespace UserIam {
33 namespace UserAuth {
34 
35 const std::string PIN_SUB_TYPE_SIX = "PIN_SIX";
36 const std::string PIN_SUB_TYPE_NUMBER = "PIN_NUMBER";
37 const std::string PIN_SUB_TYPE_MIXED = "PIN_MIXED";
38 const std::string PIN_SUB_TYPE_FOUR = "PIN_FOUR";
39 const std::string PIN_SUB_TYPE_PATTERN = "PIN_PATTERN";
40 const std::string PIN_SUB_TYPE_MAX = "PIN_MAX";
41 
Instance()42 WidgetClient &WidgetClient::Instance()
43 {
44     static WidgetClient widgetClient;
45     return widgetClient;
46 }
47 
SetWidgetSchedule(uint64_t contextId,const std::shared_ptr<WidgetScheduleNode> & schedule)48 void WidgetClient::SetWidgetSchedule(uint64_t contextId, const std::shared_ptr<WidgetScheduleNode> &schedule)
49 {
50     IF_FALSE_LOGE_AND_RETURN(schedule != nullptr);
51     std::lock_guard<std::recursive_mutex> lock(mutex_);
52     widgetContextId_ = contextId;
53     schedule_ = schedule;
54     InsertScheduleNode(widgetContextId_, schedule_);
55 }
56 
OnNotice(NoticeType type,const std::string & eventData)57 ResultCode WidgetClient::OnNotice(NoticeType type, const std::string &eventData)
58 {
59     // handle notice from widget
60     if (type != WIDGET_NOTICE) {
61         IAM_LOGE("Invalid notice type");
62         return ResultCode::INVALID_PARAMETERS;
63     }
64     if (eventData.empty()) {
65         IAM_LOGE("Invalid notice event data");
66         return ResultCode::INVALID_PARAMETERS;
67     }
68     IAM_LOGI("recv notice eventData: %{public}s", eventData.c_str());
69     auto root = nlohmann::json::parse(eventData.c_str(), nullptr, false);
70     if (root.is_null() || root.is_discarded()) {
71         IAM_LOGE("OnNotice eventData is not json format");
72         return ResultCode::INVALID_PARAMETERS;
73     }
74     WidgetNotice notice = root.get<WidgetNotice>();
75     if (notice.widgetContextId == 0) {
76         IAM_LOGE("Invalid widget context id");
77         return ResultCode::INVALID_PARAMETERS;
78     }
79     if (!IsValidNoticeType(notice)) {
80         IAM_LOGE("Not support notice event");
81         return ResultCode::INVALID_PARAMETERS;
82     }
83     if (schedule_ == nullptr) {
84         IAM_LOGE("Invalid schedule node, report auth false");
85         return ResultCode::GENERAL_ERROR;
86     }
87     std::vector<AuthType> authTypeList = {};
88     if (!GetAuthTypeList(notice, authTypeList)) {
89         IAM_LOGE("Invalid auth type list");
90         return ResultCode::INVALID_PARAMETERS;
91     }
92     ProcessNotice(notice, authTypeList);
93     return ResultCode::SUCCESS;
94 }
95 
ProcessNotice(const WidgetNotice & notice,std::vector<AuthType> & authTypeList)96 void WidgetClient::ProcessNotice(const WidgetNotice &notice, std::vector<AuthType> &authTypeList)
97 {
98     IAM_LOGI("start, event:%{public}s", notice.event.c_str());
99     std::lock_guard<std::recursive_mutex> lock(mutex_);
100     if (notice.event == NOTICE_EVENT_AUTH_READY) {
101         schedule_->StartAuthList(authTypeList, notice.endAfterFirstFail, notice.authIntent);
102     } else if (notice.event == NOTICE_EVENT_CANCEL_AUTH) {
103         if (notice.widgetContextId != widgetContextId_) {
104             IAM_LOGE("Invalid widgetContextId ****%{public}hx", static_cast<uint16_t>(widgetContextId_));
105             return;
106         }
107         if (authTypeList.size() == 1 && authTypeList[0] == AuthType::ALL) {
108             schedule_->StopSchedule();
109         } else {
110             schedule_->StopAuthList(authTypeList);
111         }
112     } else if (notice.event == NOTICE_EVENT_USER_NAVIGATION) {
113         schedule_->NaviPinAuth();
114     } else if (notice.event == NOTICE_EVENT_WIDGET_PARA_INVALID) {
115         schedule_->WidgetParaInvalid();
116     } else if (notice.event == NOTICE_EVENT_END) {
117         schedule_->StopAuthList(authTypeList);
118     } else if (notice.event == NOTICE_EVENT_RELOAD) {
119         if ((authTypeList.size() == 1 && authTypeList[0] == AuthType::ALL) || authTypeList.size() != 1) {
120             schedule_->WidgetParaInvalid();
121         } else {
122             schedule_->WidgetReload(notice.orientation, notice.needRotate, notice.alreadyLoad, authTypeList[0]);
123         }
124     } else if (notice.event == NOTICE_EVENT_AUTH_WIDGET_LOADED) {
125         WidgetLoad(notice.widgetContextId, authTypeList);
126     } else if (notice.event == NOTICE_EVENT_AUTH_WIDGET_RELEASED) {
127         WidgetRelease(notice.widgetContextId, authTypeList);
128     } else if (notice.event == NOTICE_EVENT_PROCESS_TERMINATE) {
129         ClearSchedule(notice.widgetContextId);
130     } else if (notice.event == NOTICE_EVENT_AUTH_SEND_TIP) {
131         schedule_->SendAuthTipInfo(authTypeList, notice.tipCode);
132     }
133 }
134 
SendCommand(const WidgetCommand & command)135 void WidgetClient::SendCommand(const WidgetCommand &command)
136 {
137     std::lock_guard<std::recursive_mutex> lock(mutex_);
138     if (widgetCallback_ == nullptr) {
139         IAM_LOGE("SendCommand widget callback is null");
140         return;
141     }
142     nlohmann::json root = command;
143     std::string cmdData = root.dump();
144     IAM_LOGD("SendCommand cmdData");
145     widgetCallback_->SendCommand(cmdData);
146 }
147 
ReportWidgetResult(int32_t result,AuthType authType,int32_t lockoutDuration,int32_t remainAttempts,bool skipLockedBiometricAuth)148 void WidgetClient::ReportWidgetResult(int32_t result, AuthType authType,
149     int32_t lockoutDuration, int32_t remainAttempts, bool skipLockedBiometricAuth)
150 {
151     std::lock_guard<std::recursive_mutex> lock(mutex_);
152     WidgetCommand::ExtraInfo extraInfo {
153         .callingBundleName = callingBundleName_,
154         .challenge = challenge_
155     };
156     // sendCommand of CMD_NOTIFY_AUTH_RESULT
157     WidgetCommand::Cmd cmd {
158         .event = CMD_NOTIFY_AUTH_RESULT,
159         .version = NOTICE_VERSION_STR,
160         .type = AuthType2Str(authType),
161         .result = result,
162         .lockoutDuration = lockoutDuration,
163         .remainAttempts = remainAttempts,
164         .extraInfo = extraInfo
165     };
166     if (authType == AuthType::FINGERPRINT && !sensorInfo_.empty()) {
167         cmd.sensorInfo = sensorInfo_;
168     }
169     WidgetCommand widgetCmd {
170         .widgetContextId = widgetContextId_,
171         .title = widgetParam_.title,
172         .windowModeType = WinModeType2Str(widgetParam_.windowMode),
173         .navigationButtonText = widgetParam_.navigationButtonText,
174         .cmdList = { cmd },
175         .skipLockedBiometricAuth = skipLockedBiometricAuth
176     };
177     for (auto &type : authTypeList_) {
178         widgetCmd.typeList.emplace_back(AuthType2Str(type));
179     }
180     if (!pinSubType_.empty()) {
181         widgetCmd.pinSubType = pinSubType_;
182     }
183     SendCommand(widgetCmd);
184 }
185 
ReportWidgetTip(int32_t tipType,AuthType authType,std::vector<uint8_t> tipInfo,bool skipLockedBiometricAuth)186 void WidgetClient::ReportWidgetTip(int32_t tipType, AuthType authType, std::vector<uint8_t> tipInfo,
187     bool skipLockedBiometricAuth)
188 {
189     // sendCommand of CMD_NOTIFY_AUTH_TIP
190     WidgetCommand::Cmd cmd {
191         .event = CMD_NOTIFY_AUTH_TIP,
192         .version = NOTICE_VERSION_STR,
193         .type = AuthType2Str(authType),
194         .tipType = tipType,
195         .tipInfo = tipInfo
196     };
197     std::lock_guard<std::recursive_mutex> lock(mutex_);
198     WidgetCommand widgetCmd {
199         .widgetContextId = widgetContextId_,
200         .cmdList = { cmd },
201         .skipLockedBiometricAuth = skipLockedBiometricAuth
202     };
203     SendCommand(widgetCmd);
204 }
205 
SetWidgetParam(const WidgetParamInner & param)206 void WidgetClient::SetWidgetParam(const WidgetParamInner &param)
207 {
208     std::lock_guard<std::recursive_mutex> lock(mutex_);
209     widgetParam_ = param;
210 }
211 
SetAuthTypeList(const std::vector<AuthType> & authTypeList)212 void WidgetClient::SetAuthTypeList(const std::vector<AuthType> &authTypeList)
213 {
214     std::lock_guard<std::recursive_mutex> lock(mutex_);
215     authTypeList_ = authTypeList;
216 }
217 
SetWidgetCallback(const sptr<IWidgetCallback> & callback)218 void WidgetClient::SetWidgetCallback(const sptr<IWidgetCallback> &callback)
219 {
220     std::lock_guard<std::recursive_mutex> lock(mutex_);
221     widgetCallback_ = callback;
222 }
223 
SetAuthTokenId(uint32_t tokenId)224 void WidgetClient::SetAuthTokenId(uint32_t tokenId)
225 {
226     std::lock_guard<std::recursive_mutex> lock(mutex_);
227     authTokenId_ = tokenId;
228     IAM_LOGI("WidgetClient SetAuthTokenId authTokenId: %{public}s", GET_MASKED_STRING(authTokenId_).c_str());
229 }
230 
GetAuthTokenId()231 uint32_t WidgetClient::GetAuthTokenId()
232 {
233     std::lock_guard<std::recursive_mutex> lock(mutex_);
234     return authTokenId_;
235 }
236 
Reset()237 void WidgetClient::Reset()
238 {
239     IAM_LOGI("WidgetClient Reset");
240     std::lock_guard<std::recursive_mutex> lock(mutex_);
241     widgetParam_.title.clear();
242     widgetParam_.navigationButtonText.clear();
243     widgetParam_.windowMode = WindowModeType::DIALOG_BOX;
244     widgetContextId_ = 0;
245     authTokenId_ = 0;
246     schedule_ = nullptr;
247     widgetCallback_ = nullptr;
248     pinSubType_.clear();
249     sensorInfo_.clear();
250 }
251 
ForceStopAuth()252 void WidgetClient::ForceStopAuth()
253 {
254     IAM_LOGI("stop auth process forcely by disconnect");
255     std::lock_guard<std::recursive_mutex> lock(mutex_);
256     if (schedule_ != nullptr) {
257         schedule_->StopSchedule();
258     }
259     ClearSchedule(widgetContextId_);
260 }
261 
SetPinSubType(const PinSubType & subType)262 void WidgetClient::SetPinSubType(const PinSubType &subType)
263 {
264     std::lock_guard<std::recursive_mutex> lock(mutex_);
265     pinSubType_ = PIN_SUB_TYPE_SIX;
266     switch (subType) {
267         case PinSubType::PIN_NUMBER:
268             pinSubType_ = PIN_SUB_TYPE_NUMBER;
269             break;
270         case PinSubType::PIN_MIXED:
271             pinSubType_ = PIN_SUB_TYPE_MIXED;
272             break;
273         case PinSubType::PIN_MAX:
274             pinSubType_ = PIN_SUB_TYPE_MAX;
275             break;
276         case PinSubType::PIN_FOUR:
277             pinSubType_ = PIN_SUB_TYPE_FOUR;
278             break;
279         case PinSubType::PIN_PATTERN:
280             pinSubType_ = PIN_SUB_TYPE_PATTERN;
281             break;
282         default:
283             break;
284     }
285 }
286 
SetSensorInfo(const std::string & info)287 void WidgetClient::SetSensorInfo(const std::string &info)
288 {
289     std::lock_guard<std::recursive_mutex> lock(mutex_);
290     sensorInfo_ = info;
291 }
292 
GetAuthTypeList(const WidgetNotice & notice,std::vector<AuthType> & authTypeList)293 bool WidgetClient::GetAuthTypeList(const WidgetNotice &notice, std::vector<AuthType> &authTypeList)
294 {
295     std::lock_guard<std::recursive_mutex> lock(mutex_);
296     if (authTypeList_.empty()) {
297         IAM_LOGE("inner auth type list is empty");
298         return false;
299     }
300     std::vector<AuthType> tempList = notice.AuthTypeList();
301     if (tempList.empty()) {
302         IAM_LOGE("auth type list is empty");
303         return false;
304     }
305     if (tempList.size() == 1 && tempList[0] == AuthType::ALL) {
306         if (notice.event != NOTICE_EVENT_CANCEL_AUTH && notice.event != NOTICE_EVENT_PROCESS_TERMINATE) {
307             IAM_LOGE("invalid type all case event type: %{public}s", notice.event.c_str());
308             return false;
309         }
310         authTypeList.emplace_back(AuthType::ALL);
311         return true;
312     }
313     for (auto &type : tempList) {
314         authTypeList.emplace_back(type);
315     }
316     if (authTypeList.size() == authTypeList_.size() && notice.event == NOTICE_EVENT_CANCEL_AUTH) {
317         authTypeList.clear();
318         authTypeList.emplace_back(AuthType::ALL);
319     }
320     return true;
321 }
322 
IsValidNoticeType(const WidgetNotice & notice)323 bool WidgetClient::IsValidNoticeType(const WidgetNotice &notice)
324 {
325     if (notice.event != NOTICE_EVENT_AUTH_READY &&
326         notice.event != NOTICE_EVENT_CANCEL_AUTH &&
327         notice.event != NOTICE_EVENT_USER_NAVIGATION &&
328         notice.event != NOTICE_EVENT_WIDGET_PARA_INVALID &&
329         notice.event != NOTICE_EVENT_RELOAD &&
330         notice.event != NOTICE_EVENT_END &&
331         notice.event != NOTICE_EVENT_AUTH_WIDGET_LOADED &&
332         notice.event != NOTICE_EVENT_AUTH_WIDGET_RELEASED &&
333         notice.event != NOTICE_EVENT_PROCESS_TERMINATE &&
334         notice.event != NOTICE_EVENT_AUTH_SEND_TIP) {
335         return false;
336     }
337     return true;
338 }
339 
SetChallenge(const std::vector<uint8_t> & challenge)340 void WidgetClient::SetChallenge(const std::vector<uint8_t> &challenge)
341 {
342     std::lock_guard<std::recursive_mutex> lock(mutex_);
343     challenge_ = challenge;
344 }
345 
SetCallingBundleName(const std::string & callingBundleName)346 void WidgetClient::SetCallingBundleName(const std::string &callingBundleName)
347 {
348     std::lock_guard<std::recursive_mutex> lock(mutex_);
349     callingBundleName_ = callingBundleName;
350 }
351 
InsertScheduleNode(uint64_t contextId,std::shared_ptr<WidgetScheduleNode> & scheduleNode)352 void WidgetClient::InsertScheduleNode(uint64_t contextId, std::shared_ptr<WidgetScheduleNode> &scheduleNode)
353 {
354     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
355     IF_FALSE_LOGE_AND_RETURN(scheduleNode != nullptr);
356     std::lock_guard<std::recursive_mutex> lock(mutex_);
357     scheduleMap_.insert(std::pair<uint64_t, std::shared_ptr<WidgetScheduleNode>>(contextId, scheduleNode));
358 }
359 
RemoveScheduleNode(uint64_t contextId)360 void WidgetClient::RemoveScheduleNode(uint64_t contextId)
361 {
362     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
363     std::lock_guard<std::recursive_mutex> lock(mutex_);
364     scheduleMap_.erase(contextId);
365 }
366 
GetScheduleNode(uint64_t contextId)367 std::shared_ptr<WidgetScheduleNode> WidgetClient::GetScheduleNode(uint64_t contextId)
368 {
369     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
370     std::lock_guard<std::recursive_mutex> lock(mutex_);
371     std::shared_ptr<WidgetScheduleNode> scheduleNode = nullptr;
372     auto iter = scheduleMap_.find(contextId);
373     if (iter != scheduleMap_.end()) {
374         scheduleNode = iter->second;
375         IAM_LOGI("success, contextId:%{public}hx", static_cast<uint16_t>(contextId));
376     }
377     return scheduleNode;
378 }
379 
ClearSchedule(uint64_t contextId)380 void WidgetClient::ClearSchedule(uint64_t contextId)
381 {
382     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
383     std::lock_guard<std::recursive_mutex> lock(mutex_);
384     auto schedule = GetScheduleNode(contextId);
385     if (schedule != nullptr) {
386         if (contextId == widgetContextId_) {
387             Reset();
388             if (!loadedAuthTypeList_.empty()) {
389                 schedule->SendAuthTipInfo(loadedAuthTypeList_, TIP_CODE_WIDGET_RELEASED);
390                 loadedAuthTypeList_.clear();
391             }
392         }
393         schedule->ClearSchedule();
394         RemoveScheduleNode(contextId);
395     }
396 }
397 
WidgetLoad(uint64_t contextId,std::vector<AuthType> & authTypeList)398 void WidgetClient::WidgetLoad(uint64_t contextId, std::vector<AuthType> &authTypeList)
399 {
400     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
401     std::lock_guard<std::recursive_mutex> lock(mutex_);
402     auto schedule = GetScheduleNode(contextId);
403     if (schedule != nullptr) {
404         if (contextId != widgetContextId_) {
405             IAM_LOGE("widgetContextId_:%{public}hx", static_cast<uint16_t>(widgetContextId_));
406             return;
407         }
408         schedule->SendAuthTipInfo(authTypeList, TIP_CODE_WIDGET_LOADED);
409         loadedAuthTypeList_ = authTypeList;
410     }
411 }
412 
WidgetRelease(uint64_t contextId,std::vector<AuthType> & authTypeList)413 void WidgetClient::WidgetRelease(uint64_t contextId, std::vector<AuthType> &authTypeList)
414 {
415     IAM_LOGI("start, contextId:%{public}hx", static_cast<uint16_t>(contextId));
416     std::lock_guard<std::recursive_mutex> lock(mutex_);
417     auto schedule = GetScheduleNode(contextId);
418     if (schedule != nullptr) {
419         schedule->SendAuthTipInfo(authTypeList, TIP_CODE_WIDGET_RELEASED);
420         if (contextId != widgetContextId_) {
421             IAM_LOGI("widgetContextId_:%{public}hx", static_cast<uint16_t>(widgetContextId_));
422             return;
423         }
424         loadedAuthTypeList_.clear();
425     }
426 }
427 } // namespace UserAuth
428 } // namespace UserIam
429 } // namespace OHOS
430