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