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