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 ¬ice, 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 ¶m)
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 ¬ice, 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 ¬ice)
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