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 &notice, 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 &param)
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 &notice, 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 &notice)
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