1 /*
2 * Copyright (c) 2024 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 "remote_auth_invoker_context.h"
17
18 #include "device_manager_util.h"
19 #include "hdi_wrapper.h"
20 #include "iam_check.h"
21 #include "iam_logger.h"
22 #include "iam_para2str.h"
23 #include "iam_ptr.h"
24 #include "relative_timer.h"
25 #include "remote_connect_manager.h"
26 #include "thread_handler.h"
27 #include "thread_handler_manager.h"
28 #include "user_auth_hdi.h"
29
30 #define LOG_TAG "USER_AUTH_SA"
31
32 namespace OHOS {
33 namespace UserIam {
34 namespace UserAuth {
35 namespace {
36 constexpr uint32_t TIME_OUT_MS = 3 * 60 * 1000; // 3min
37 }
38 class RemoteAuthInvokerContextMessageCallback : public ConnectionListener, public NoCopyable {
39 public:
RemoteAuthInvokerContextMessageCallback(std::weak_ptr<BaseContext> callbackWeakBase,RemoteAuthInvokerContext * callback)40 explicit RemoteAuthInvokerContextMessageCallback(std::weak_ptr<BaseContext> callbackWeakBase,
41 RemoteAuthInvokerContext *callback)
42 : callbackWeakBase_(callbackWeakBase),
43 callback_(callback),
44 threadHandler_(ThreadHandler::GetSingleThreadInstance())
45 {
46 }
47
48 ~RemoteAuthInvokerContextMessageCallback() = default;
49
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)50 void OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
51 const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply) override
52 {
53 IF_FALSE_LOGE_AND_RETURN(request != nullptr);
54 IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
55
56 IAM_LOGI("connectionName: %{public}s, srcEndPoint: %{public}s", connectionName.c_str(), srcEndPoint.c_str());
57
58 std::shared_ptr<BaseContext> callbackSharedBase = callbackWeakBase_.lock();
59 IF_FALSE_LOGE_AND_RETURN(callbackSharedBase != nullptr);
60
61 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
62 callback_->OnMessage(connectionName, srcEndPoint, request, reply);
63 }
64
OnConnectStatus(const std::string & connectionName,ConnectStatus connectStatus)65 void OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus) override
66 {
67 IAM_LOGI("connectionName: %{public}s, connectStatus %{public}d", connectionName.c_str(), connectStatus);
68
69 IF_FALSE_LOGE_AND_RETURN(threadHandler_ != nullptr);
70 threadHandler_->PostTask(
71 [connectionName, connectStatus, callbackWeakBase = callbackWeakBase_, callback = callback_, this]() {
72 IAM_LOGI("OnConnectStatus process begin");
73 auto callbackSharedBase = callbackWeakBase.lock();
74 IF_FALSE_LOGE_AND_RETURN(callbackSharedBase != nullptr);
75
76 IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
77 callback->OnConnectStatus(connectionName, connectStatus);
78 IAM_LOGI("OnConnectStatus process success");
79 });
80 IAM_LOGI("task posted");
81 }
82
83 private:
84 std::weak_ptr<BaseContext> callbackWeakBase_;
85 RemoteAuthInvokerContext *callback_;
86 std::shared_ptr<ThreadHandler> threadHandler_ = nullptr;
87 };
88
RemoteAuthInvokerContext(uint64_t contextId,AuthParamInner authParam,RemoteAuthInvokerContextParam param,std::shared_ptr<ContextCallback> callback)89 RemoteAuthInvokerContext::RemoteAuthInvokerContext(uint64_t contextId, AuthParamInner authParam,
90 RemoteAuthInvokerContextParam param, std::shared_ptr<ContextCallback> callback)
91 : BaseContext("RemoteAuthInvokerContext", contextId, callback),
92 authParam_(authParam),
93 connectionName_(param.connectionName),
94 verifierNetworkId_(param.verifierNetworkId),
95 collectorNetworkId_(param.collectorNetworkId),
96 tokenId_(param.tokenId),
97 collectorTokenId_(param.collectorTokenId),
98 callerName_(param.callerName),
99 callerType_(param.callerType),
100 callback_(callback)
101 {
102 endPointName_ = REMOTE_AUTH_INVOKER_CONTEXT_ENDPOINT_NAME;
103 ThreadHandlerManager::GetInstance().CreateThreadHandler(connectionName_);
104 }
105
~RemoteAuthInvokerContext()106 RemoteAuthInvokerContext::~RemoteAuthInvokerContext()
107 {
108 std::lock_guard<std::recursive_mutex> lock(mutex_);
109 if (cancelTimerId_.has_value()) {
110 RelativeTimer::GetInstance().Unregister(cancelTimerId_.value());
111 }
112 RemoteConnectionManager::GetInstance().UnregisterConnectionListener(connectionName_, endPointName_);
113 RemoteConnectionManager::GetInstance().CloseConnection(connectionName_);
114 ThreadHandlerManager::GetInstance().DestroyThreadHandler(connectionName_);
115 IAM_LOGI("%{public}s destroy", GetDescription());
116 }
117
GetContextType() const118 ContextType RemoteAuthInvokerContext::GetContextType() const
119 {
120 return ContextType::REMOTE_AUTH_INVOKER_CONTEXT;
121 }
122
GetTokenId() const123 uint32_t RemoteAuthInvokerContext::GetTokenId() const
124 {
125 return tokenId_;
126 }
127
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)128 void RemoteAuthInvokerContext::OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
129 const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply)
130 {
131 std::lock_guard<std::recursive_mutex> lock(mutex_);
132
133 int32_t msgType;
134 IF_FALSE_LOGE_AND_RETURN(request->GetInt32Value(Attributes::ATTR_MSG_TYPE, msgType));
135
136 int32_t resultCode = ResultCode::GENERAL_ERROR;
137 switch (msgType) {
138 case SEND_REMOTE_AUTH_TIP:
139 resultCode = ProcAuthTipMsg(*request);
140 break;
141 case SEND_REMOTE_AUTH_RESULT:
142 resultCode = ProcAuthResultMsg(*request);
143 break;
144 default:
145 IAM_LOGE("%{public}s invalid msgType:%{public}d", GetDescription(), msgType);
146 break;
147 }
148
149 IF_FALSE_LOGE_AND_RETURN(resultCode == ResultCode::SUCCESS);
150 IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
151 bool setResultCodeRet = reply->SetInt32Value(Attributes::ATTR_RESULT_CODE, ResultCode::SUCCESS);
152 IF_FALSE_LOGE_AND_RETURN(setResultCodeRet);
153 }
154
OnConnectStatus(const std::string & connectionName,ConnectStatus connectStatus)155 void RemoteAuthInvokerContext::OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus)
156 {
157 std::lock_guard<std::recursive_mutex> lock(mutex_);
158 IAM_LOGI("%{public}s start", GetDescription());
159 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
160
161 Attributes attr;
162 if (connectStatus == ConnectStatus::DISCONNECTED) {
163 IAM_LOGI("%{public}s connection is disconnected", GetDescription());
164 callback_->OnResult(ResultCode::GENERAL_ERROR, attr);
165 return;
166 } else {
167 IAM_LOGI("%{public}s connection is connected", GetDescription());
168 bool sendRequestRet = SendRequest();
169 if (!sendRequestRet) {
170 IAM_LOGE("%{public}s SendRequest failed", GetDescription());
171 callback_->OnResult(GENERAL_ERROR, attr);
172 return;
173 }
174 IAM_LOGI("%{public}s connection is connected processed", GetDescription());
175 }
176 }
177
SetVerifierContextId(uint64_t contextId)178 void RemoteAuthInvokerContext::SetVerifierContextId(uint64_t contextId)
179 {
180 std::lock_guard<std::recursive_mutex> lock(mutex_);
181 verifierContextId_ = contextId;
182 IAM_LOGI("%{public}s set verifierContextId %{public}s success", GetDescription(),
183 GET_MASKED_STRING(contextId).c_str());
184 }
185
OnStart()186 bool RemoteAuthInvokerContext::OnStart()
187 {
188 std::lock_guard<std::recursive_mutex> lock(mutex_);
189 IAM_LOGI("%{public}s start", GetDescription());
190
191 cancelTimerId_ = RelativeTimer::GetInstance().Register(
192 [weakThis = weak_from_this(), this]() {
193 auto sharedThis = weakThis.lock();
194 IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
195 OnTimeOut();
196 },
197 TIME_OUT_MS);
198
199 bool getUdidRet = DeviceManagerUtil::GetInstance().GetUdidByNetworkId(verifierNetworkId_, verifierUdid_);
200 IF_FALSE_LOGE_AND_RETURN_VAL(getUdidRet, false);
201
202 endPointName_ = REMOTE_AUTH_INVOKER_CONTEXT_ENDPOINT_NAME;
203
204 std::shared_ptr<RemoteAuthInvokerContextMessageCallback> callback =
205 Common::MakeShared<RemoteAuthInvokerContextMessageCallback>(shared_from_this(), this);
206 IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, false);
207
208 ResultCode registerResult =
209 RemoteConnectionManager::GetInstance().RegisterConnectionListener(connectionName_, endPointName_, callback);
210 IF_FALSE_LOGE_AND_RETURN_VAL(registerResult == SUCCESS, false);
211
212 ResultCode connectResult =
213 RemoteConnectionManager::GetInstance().OpenConnection(connectionName_, verifierNetworkId_, GetTokenId());
214 IF_FALSE_LOGE_AND_RETURN_VAL(connectResult == SUCCESS, false);
215
216 IAM_LOGI("%{public}s success", GetDescription());
217 return true;
218 }
219
SendRequest()220 bool RemoteAuthInvokerContext::SendRequest()
221 {
222 std::lock_guard<std::recursive_mutex> lock(mutex_);
223 IAM_LOGI("%{public}s start", GetDescription());
224
225 request_ = Common::MakeShared<Attributes>();
226 IF_FALSE_LOGE_AND_RETURN_VAL(request_ != nullptr, false);
227
228 bool setMsgTypeRet = request_->SetInt32Value(Attributes::ATTR_MSG_TYPE, START_REMOTE_AUTH);
229 IF_FALSE_LOGE_AND_RETURN_VAL(setMsgTypeRet, false);
230
231 std::vector<int32_t> authTypes = { static_cast<int32_t>(authParam_.authType) };
232 bool getExecutorInfoRet = RemoteMsgUtil::GetQueryExecutorInfoReply(authTypes, COLLECTOR, verifierUdid_, *request_);
233 IF_FALSE_LOGE_AND_RETURN_VAL(getExecutorInfoRet, false);
234
235 bool encodeAuthParamRet = RemoteMsgUtil::EncodeAuthParam(authParam_, *request_);
236 IF_FALSE_LOGE_AND_RETURN_VAL(encodeAuthParamRet, false);
237
238 bool setTokenIdRet = request_->SetUint32Value(Attributes::ATTR_COLLECTOR_TOKEN_ID, collectorTokenId_);
239 IF_FALSE_LOGE_AND_RETURN_VAL(setTokenIdRet, false);
240
241 bool setCallerNameRet = request_->SetStringValue(Attributes::ATTR_CALLER_NAME, callerName_);
242 IF_FALSE_LOGE_AND_RETURN_VAL(setCallerNameRet, false);
243
244 bool setCallerTypeRet = request_->SetInt32Value(Attributes::ATTR_CALLER_TYPE, callerType_);
245 IF_FALSE_LOGE_AND_RETURN_VAL(setCallerTypeRet, false);
246
247 bool setCollectorNetworkIdRet =
248 request_->SetStringValue(Attributes::ATTR_COLLECTOR_NETWORK_ID, collectorNetworkId_);
249 IF_FALSE_LOGE_AND_RETURN_VAL(setCollectorNetworkIdRet, false);
250
251 MsgCallback msgCallback = [weakThis = weak_from_this(), this](const std::shared_ptr<Attributes> &reply) {
252 IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
253
254 auto sharedThis = weakThis.lock();
255 IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
256
257 int32_t resultCode;
258 bool getResultCodeRet = reply->GetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
259 IF_FALSE_LOGE_AND_RETURN(getResultCodeRet);
260
261 if (resultCode != ResultCode::SUCCESS) {
262 IAM_LOGE("%{public}s start remote auth failed %{public}d", GetDescription(), resultCode);
263 Attributes attr;
264 callback_->OnResult(resultCode, attr);
265 return;
266 }
267
268 uint64_t contextId;
269 bool getContextIdRet = reply->GetUint64Value(Attributes::ATTR_CONTEXT_ID, contextId);
270 IF_FALSE_LOGE_AND_RETURN(getContextIdRet);
271
272 this->SetVerifierContextId(contextId);
273 IAM_LOGI("%{public}s start remote auth success %{public}d", GetDescription(), resultCode);
274 };
275 IF_FALSE_LOGE_AND_RETURN_VAL(request_ != nullptr, false);
276 ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
277 REMOTE_SERVICE_ENDPOINT_NAME, request_, msgCallback);
278 IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == SUCCESS, false);
279
280 IAM_LOGI("%{public}s success", GetDescription());
281 return true;
282 }
283
OnResult(int32_t resultCode,const std::shared_ptr<Attributes> & scheduleResultAttr)284 void RemoteAuthInvokerContext::OnResult(int32_t resultCode, const std::shared_ptr<Attributes> &scheduleResultAttr)
285 {
286 IAM_LOGE("%{public}s this method is not supported", GetDescription());
287 }
288
OnStop()289 bool RemoteAuthInvokerContext::OnStop()
290 {
291 std::lock_guard<std::recursive_mutex> lock(mutex_);
292 IAM_LOGI("%{public}s canceled", GetDescription());
293 Attributes attr;
294 callback_->OnResult(ResultCode::CANCELED, attr);
295 // other module is canceled by disconnecting the connection
296
297 IAM_LOGI("%{public}s success", GetDescription());
298 return true;
299 }
300
ProcAuthTipMsg(Attributes & message)301 int32_t RemoteAuthInvokerContext::ProcAuthTipMsg(Attributes &message)
302 {
303 std::lock_guard<std::recursive_mutex> lock(mutex_);
304 IAM_LOGI("%{public}s start", GetDescription());
305
306 int32_t destRole;
307 bool getDestRoleRet = message.GetInt32Value(Attributes::ATTR_DEST_ROLE, destRole);
308 IF_FALSE_LOGE_AND_RETURN_VAL(getDestRoleRet, ResultCode::GENERAL_ERROR);
309
310 int32_t tipInfo;
311 bool getAcquireInfoRet = message.GetInt32Value(Attributes::ATTR_TIP_INFO, tipInfo);
312 IF_FALSE_LOGE_AND_RETURN_VAL(getAcquireInfoRet, ResultCode::GENERAL_ERROR);
313
314 IF_FALSE_LOGE_AND_RETURN_VAL(callback_ != nullptr, ResultCode::GENERAL_ERROR);
315 callback_->OnAcquireInfo(static_cast<ExecutorRole>(destRole), tipInfo, message.Serialize());
316
317 IAM_LOGI("%{public}s success", GetDescription());
318 return ResultCode::SUCCESS;
319 }
320
ProcAuthResultMsgInner(Attributes & message,int32_t & resultCode,Attributes & attr)321 int32_t RemoteAuthInvokerContext::ProcAuthResultMsgInner(Attributes &message, int32_t &resultCode, Attributes &attr)
322 {
323 resultCode = GENERAL_ERROR;
324 bool getResultCodeRet = message.GetInt32Value(Attributes::ATTR_RESULT, resultCode);
325 IF_FALSE_LOGE_AND_RETURN_VAL(getResultCodeRet, ResultCode::GENERAL_ERROR);
326
327 std::vector<uint8_t> remoteAuthResult;
328 bool getRemoteAuthResultRet = message.GetUint8ArrayValue(Attributes::ATTR_SIGNED_AUTH_RESULT, remoteAuthResult);
329 if (getRemoteAuthResultRet) {
330 auto hdi = HdiWrapper::GetHdiInstance();
331 IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, ResultCode::GENERAL_ERROR);
332 HdiAuthResultInfo authResultInfo;
333 int32_t hdiRet = hdi->GetAuthResultFromMessage(verifierUdid_, remoteAuthResult, authResultInfo);
334 IF_FALSE_LOGE_AND_RETURN_VAL(hdiRet == SUCCESS, ResultCode::GENERAL_ERROR);
335
336 resultCode = authResultInfo.result;
337 if (resultCode == ResultCode::FAIL || resultCode == ResultCode::LOCKED || resultCode == ResultCode::SUCCESS) {
338 bool setLockOutDurationRet =
339 attr.SetInt32Value(Attributes::ATTR_LOCKOUT_DURATION, authResultInfo.lockoutDuration);
340 IF_FALSE_LOGE_AND_RETURN_VAL(setLockOutDurationRet, ResultCode::GENERAL_ERROR);
341 bool setRemainAttemptsRet =
342 attr.SetInt32Value(Attributes::ATTR_REMAIN_ATTEMPTS, authResultInfo.remainAttempts);
343 IF_FALSE_LOGE_AND_RETURN_VAL(setRemainAttemptsRet, ResultCode::GENERAL_ERROR);
344 }
345 if (resultCode == ResultCode::SUCCESS) {
346 bool setTokenRet = attr.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, authResultInfo.token);
347 IF_FALSE_LOGE_AND_RETURN_VAL(setTokenRet, ResultCode::GENERAL_ERROR);
348 bool setUserId = attr.SetInt32Value(Attributes::ATTR_USER_ID, authResultInfo.userId);
349 IF_FALSE_LOGE_AND_RETURN_VAL(setUserId, ResultCode::GENERAL_ERROR);
350 }
351 IAM_LOGI("%{public}s parsed auth result: %{public}d, lockout duration %{public}d, "
352 "remain attempts %{public}d, token size %{public}zu, user id %{public}d",
353 GetDescription(), resultCode, authResultInfo.lockoutDuration, authResultInfo.remainAttempts,
354 authResultInfo.token.size(), authResultInfo.userId);
355 } else if (resultCode == ResultCode::SUCCESS) {
356 IAM_LOGE("%{public}s remote auth result is empty, set result GENERAL_ERROR", GetDescription());
357 resultCode = ResultCode::GENERAL_ERROR;
358 }
359
360 IAM_LOGI("%{public}s result code %{public}d", GetDescription(), resultCode);
361 bool setResultCodeRet = attr.SetInt32Value(Attributes::ATTR_RESULT, resultCode);
362 IF_FALSE_LOGE_AND_RETURN_VAL(setResultCodeRet, ResultCode::GENERAL_ERROR);
363
364 return ResultCode::SUCCESS;
365 }
366
ProcAuthResultMsg(Attributes & message)367 int32_t RemoteAuthInvokerContext::ProcAuthResultMsg(Attributes &message)
368 {
369 std::lock_guard<std::recursive_mutex> lock(mutex_);
370 IAM_LOGI("%{public}s start", GetDescription());
371
372 int32_t authResultCode = GENERAL_ERROR;
373 Attributes attr;
374
375 int32_t ret = ProcAuthResultMsgInner(message, authResultCode, attr);
376
377 callback_->OnResult(authResultCode, attr);
378
379 IAM_LOGI("%{public}s success", GetDescription());
380 return ret;
381 }
382
OnTimeOut()383 void RemoteAuthInvokerContext::OnTimeOut()
384 {
385 IAM_LOGI("%{public}s timeout", GetDescription());
386 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
387
388 Attributes attr;
389 callback_->OnResult(TIMEOUT, attr);
390 }
391 } // namespace UserAuth
392 } // namespace UserIam
393 } // namespace OHOS