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 "widget_callback_interface.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(const std::shared_ptr<WidgetScheduleNode> & schedule)48 void WidgetClient::SetWidgetSchedule(const std::shared_ptr<WidgetScheduleNode> &schedule)
49 {
50 IF_FALSE_LOGE_AND_RETURN(schedule != nullptr);
51 schedule_ = schedule;
52 }
53
OnNotice(NoticeType type,const std::string & eventData)54 ResultCode WidgetClient::OnNotice(NoticeType type, const std::string &eventData)
55 {
56 // handle notice from widget
57 if (type != WIDGET_NOTICE) {
58 IAM_LOGE("Invalid notice type");
59 return ResultCode::INVALID_PARAMETERS;
60 }
61 if (eventData.empty()) {
62 IAM_LOGE("Invalid notice event data");
63 return ResultCode::INVALID_PARAMETERS;
64 }
65 IAM_LOGI("recv notice eventData: %{public}s", eventData.c_str());
66 auto root = nlohmann::json::parse(eventData.c_str(), nullptr, false);
67 if (root.is_null() || root.is_discarded()) {
68 IAM_LOGE("OnNotice eventData is not json format");
69 return ResultCode::INVALID_PARAMETERS;
70 }
71 WidgetNotice notice = root.get<WidgetNotice>();
72 if (notice.widgetContextId == 0) {
73 IAM_LOGE("Invalid widget context id");
74 return ResultCode::INVALID_PARAMETERS;
75 }
76 if (!IsValidNoticeType(notice)) {
77 IAM_LOGE("Not support notice event");
78 return ResultCode::INVALID_PARAMETERS;
79 }
80 if (schedule_ == nullptr) {
81 IAM_LOGE("Invalid schedule node, report auth false");
82 return ResultCode::GENERAL_ERROR;
83 }
84 std::vector<AuthType> authTypeList = {};
85 if (!GetAuthTypeList(notice, authTypeList)) {
86 IAM_LOGE("Invalid auth type list");
87 return ResultCode::INVALID_PARAMETERS;
88 }
89 ProcessNotice(notice, authTypeList);
90 return ResultCode::SUCCESS;
91 }
92
ProcessNotice(const WidgetNotice & notice,std::vector<AuthType> & authTypeList)93 void WidgetClient::ProcessNotice(const WidgetNotice ¬ice, std::vector<AuthType> &authTypeList)
94 {
95 if (notice.event == NOTICE_EVENT_AUTH_READY) {
96 schedule_->StartAuthList(authTypeList, notice.endAfterFirstFail, notice.authIntent);
97 } else if (notice.event == NOTICE_EVENT_CANCEL_AUTH) {
98 if (authTypeList.size() == 1 && authTypeList[0] == AuthType::ALL) {
99 schedule_->StopSchedule();
100 } else {
101 schedule_->StopAuthList(authTypeList);
102 }
103 } else if (notice.event == NOTICE_EVENT_USER_NAVIGATION) {
104 schedule_->NaviPinAuth();
105 } else if (notice.event == NOTICE_EVENT_WIDGET_PARA_INVALID) {
106 schedule_->WidgetParaInvalid();
107 } else if (notice.event == NOTICE_EVENT_END) {
108 schedule_->StopAuthList(authTypeList);
109 } else if (notice.event == NOTICE_EVENT_RELOAD) {
110 if ((authTypeList.size() == 1 && authTypeList[0] == AuthType::ALL) || authTypeList.size() != 1) {
111 schedule_->WidgetParaInvalid();
112 } else {
113 schedule_->WidgetReload(notice.orientation, notice.needRotate, notice.alreadyLoad, authTypeList[0]);
114 }
115 }
116 }
117
SendCommand(const WidgetCommand & command)118 void WidgetClient::SendCommand(const WidgetCommand &command)
119 {
120 if (widgetCallback_ == nullptr) {
121 IAM_LOGE("SendCommand widget callback is null");
122 return;
123 }
124 nlohmann::json root = command;
125 std::string cmdData = root.dump();
126 IAM_LOGI("SendCommand cmdData");
127 widgetCallback_->SendCommand(cmdData);
128 }
129
ReportWidgetResult(int32_t result,AuthType authType,int32_t lockoutDuration,int32_t remainAttempts)130 void WidgetClient::ReportWidgetResult(int32_t result, AuthType authType,
131 int32_t lockoutDuration, int32_t remainAttempts)
132 {
133 WidgetCommand::ExtraInfo extraInfo {
134 .callingBundleName = callingBundleName_,
135 .challenge = challenge_
136 };
137 // sendCommand of CMD_NOTIFY_AUTH_RESULT
138 WidgetCommand::Cmd cmd {
139 .event = CMD_NOTIFY_AUTH_RESULT,
140 .version = NOTICE_VERSION_STR,
141 .type = AuthType2Str(authType),
142 .result = result,
143 .lockoutDuration = lockoutDuration,
144 .remainAttempts = remainAttempts,
145 .extraInfo = extraInfo
146 };
147 if (authType == AuthType::FINGERPRINT && !sensorInfo_.empty()) {
148 cmd.sensorInfo = sensorInfo_;
149 }
150 WidgetCommand widgetCmd {
151 .widgetContextId = widgetContextId_,
152 .title = widgetParam_.title,
153 .windowModeType = WinModeType2Str(widgetParam_.windowMode),
154 .navigationButtonText = widgetParam_.navigationButtonText,
155 .cmdList = { cmd }
156 };
157 for (auto &type : authTypeList_) {
158 widgetCmd.typeList.emplace_back(AuthType2Str(type));
159 }
160 if (!pinSubType_.empty()) {
161 widgetCmd.pinSubType = pinSubType_;
162 }
163 SendCommand(widgetCmd);
164 }
165
ReportWidgetTip(int32_t tipType,AuthType authType,std::vector<uint8_t> tipInfo)166 void WidgetClient::ReportWidgetTip(int32_t tipType, AuthType authType, std::vector<uint8_t> tipInfo)
167 {
168 // sendCommand of CMD_NOTIFY_AUTH_TIP
169 WidgetCommand::Cmd cmd {
170 .event = CMD_NOTIFY_AUTH_TIP,
171 .version = NOTICE_VERSION_STR,
172 .type = AuthType2Str(authType),
173 .tipType = tipType,
174 .tipInfo = tipInfo
175 };
176 WidgetCommand widgetCmd {
177 .widgetContextId = widgetContextId_,
178 .cmdList = { cmd }
179 };
180 SendCommand(widgetCmd);
181 }
182
SetWidgetContextId(uint64_t contextId)183 void WidgetClient::SetWidgetContextId(uint64_t contextId)
184 {
185 widgetContextId_ = contextId;
186 }
187
SetWidgetParam(const WidgetParam & param)188 void WidgetClient::SetWidgetParam(const WidgetParam ¶m)
189 {
190 widgetParam_ = param;
191 }
192
SetAuthTypeList(const std::vector<AuthType> & authTypeList)193 void WidgetClient::SetAuthTypeList(const std::vector<AuthType> &authTypeList)
194 {
195 authTypeList_ = authTypeList;
196 }
197
SetWidgetCallback(const sptr<WidgetCallbackInterface> & callback)198 void WidgetClient::SetWidgetCallback(const sptr<WidgetCallbackInterface> &callback)
199 {
200 widgetCallback_ = callback;
201 }
202
SetAuthTokenId(uint32_t tokenId)203 void WidgetClient::SetAuthTokenId(uint32_t tokenId)
204 {
205 authTokenId_ = tokenId;
206 IAM_LOGI("WidgetClient SetAuthTokenId authTokenId: %{public}s", GET_MASKED_STRING(authTokenId_).c_str());
207 }
208
GetAuthTokenId() const209 uint32_t WidgetClient::GetAuthTokenId() const
210 {
211 return authTokenId_;
212 }
213
Reset()214 void WidgetClient::Reset()
215 {
216 IAM_LOGI("WidgetClient Reset");
217 widgetParam_.title.clear();
218 widgetParam_.navigationButtonText.clear();
219 widgetParam_.windowMode = WindowModeType::DIALOG_BOX;
220 widgetContextId_ = 0;
221 authTokenId_ = 0;
222 schedule_ = nullptr;
223 widgetCallback_ = nullptr;
224 pinSubType_.clear();
225 sensorInfo_.clear();
226 }
227
ForceStopAuth()228 void WidgetClient::ForceStopAuth()
229 {
230 IAM_LOGE("Stop Auth process forcely by disconnect");
231 if (widgetContextId_ != 0) {
232 IAM_LOGE("widget context id hasn't been reset");
233 UserIam::UserAuth::ReportSystemFault(Common::GetNowTimeString(), "AuthWidget");
234 }
235 if (schedule_ != nullptr) {
236 schedule_->StopSchedule();
237 }
238 }
239
SetPinSubType(const PinSubType & subType)240 void WidgetClient::SetPinSubType(const PinSubType &subType)
241 {
242 pinSubType_ = PIN_SUB_TYPE_SIX;
243 switch (subType) {
244 case PinSubType::PIN_NUMBER:
245 pinSubType_ = PIN_SUB_TYPE_NUMBER;
246 break;
247 case PinSubType::PIN_MIXED:
248 pinSubType_ = PIN_SUB_TYPE_MIXED;
249 break;
250 case PinSubType::PIN_MAX:
251 pinSubType_ = PIN_SUB_TYPE_MAX;
252 break;
253 case PinSubType::PIN_FOUR:
254 pinSubType_ = PIN_SUB_TYPE_FOUR;
255 break;
256 case PinSubType::PIN_PATTERN:
257 pinSubType_ = PIN_SUB_TYPE_PATTERN;
258 break;
259 default:
260 break;
261 }
262 }
263
SetSensorInfo(const std::string & info)264 void WidgetClient::SetSensorInfo(const std::string &info)
265 {
266 sensorInfo_ = info;
267 }
268
GetAuthTypeList(const WidgetNotice & notice,std::vector<AuthType> & authTypeList)269 bool WidgetClient::GetAuthTypeList(const WidgetNotice ¬ice, std::vector<AuthType> &authTypeList)
270 {
271 if (authTypeList_.empty()) {
272 IAM_LOGE("inner auth type list is empty");
273 return false;
274 }
275 std::vector<AuthType> tempList = notice.AuthTypeList();
276 if (tempList.empty()) {
277 IAM_LOGE("auth type list is empty");
278 return false;
279 }
280 if (tempList.size() == 1 && tempList[0] == AuthType::ALL) {
281 if (notice.event != NOTICE_EVENT_CANCEL_AUTH) {
282 IAM_LOGE("invalid type all case event type: %{public}s", notice.event.c_str());
283 return false;
284 }
285 authTypeList.emplace_back(AuthType::ALL);
286 return true;
287 }
288 for (auto &type : tempList) {
289 if (std::find(authTypeList_.begin(), authTypeList_.end(), type) == authTypeList_.end()) {
290 IAM_LOGE("invalid auth type: %{public}d", type);
291 return false;
292 }
293 authTypeList.emplace_back(type);
294 }
295 if (authTypeList.size() == authTypeList_.size() && notice.event == NOTICE_EVENT_CANCEL_AUTH) {
296 authTypeList.clear();
297 authTypeList.emplace_back(AuthType::ALL);
298 }
299 return true;
300 }
301
IsValidNoticeType(const WidgetNotice & notice)302 bool WidgetClient::IsValidNoticeType(const WidgetNotice ¬ice)
303 {
304 if (notice.event != NOTICE_EVENT_AUTH_READY &&
305 notice.event != NOTICE_EVENT_CANCEL_AUTH &&
306 notice.event != NOTICE_EVENT_USER_NAVIGATION &&
307 notice.event != NOTICE_EVENT_WIDGET_PARA_INVALID &&
308 notice.event != NOTICE_EVENT_RELOAD &&
309 notice.event != NOTICE_EVENT_END) {
310 return false;
311 }
312 return true;
313 }
314
SetChallenge(const std::vector<uint8_t> & challenge)315 void WidgetClient::SetChallenge(const std::vector<uint8_t> &challenge)
316 {
317 challenge_ = challenge;
318 }
319
SetCallingBundleName(const std::string & callingBundleName)320 void WidgetClient::SetCallingBundleName(const std::string &callingBundleName)
321 {
322 callingBundleName_ = callingBundleName;
323 }
324 } // namespace UserAuth
325 } // namespace UserIam
326 } // namespace OHOS