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_context.h"
17
18 #include "iam_check.h"
19 #include "iam_logger.h"
20 #include "iam_para2str.h"
21 #include "iam_ptr.h"
22
23 #include "device_manager_util.h"
24 #include "relative_timer.h"
25 #include "remote_msg_util.h"
26 #include "resource_node_utils.h"
27 #include "thread_handler.h"
28 #include "thread_handler_manager.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 SETUP_CONNECTION_TIME_OUT_MS = 3 * 60 * 1000; // 3min
37 }
38 class RemoteAuthContextMessageCallback : public ConnectionListener, public NoCopyable {
39 public:
RemoteAuthContextMessageCallback(std::weak_ptr<BaseContext> callbackWeakBase, RemoteAuthContext *callback)40 RemoteAuthContextMessageCallback(std::weak_ptr<BaseContext> callbackWeakBase, RemoteAuthContext *callback)
41 : callbackWeakBase_(callbackWeakBase),
42 callback_(callback),
43 threadHandler_(ThreadHandler::GetSingleThreadInstance())
44 {
45 }
46
47 ~RemoteAuthContextMessageCallback() = default;
48
49 void OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
50 const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply) override
51 {
52 IF_FALSE_LOGE_AND_RETURN(request != nullptr);
53 IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
54
55 IAM_LOGI("connectionName: %{public}s, srcEndPoint: %{public}s", connectionName.c_str(), srcEndPoint.c_str());
56 }
57
58 void OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus) override
59 {
60 IAM_LOGI("connectionName: %{public}s, connectStatus %{public}d", connectionName.c_str(), connectStatus);
61
62 IF_FALSE_LOGE_AND_RETURN(threadHandler_ != nullptr);
63 threadHandler_->PostTask(
64 [connectionName, connectStatus, callbackWeakBase = callbackWeakBase_, callback = callback_, this]() {
65 IAM_LOGI("OnConnectStatus process begin");
66 auto callbackSharedBase = callbackWeakBase.lock();
67 IF_FALSE_LOGE_AND_RETURN(callbackSharedBase != nullptr);
68
69 IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
70 callback->OnConnectStatus(connectionName, connectStatus);
71 IAM_LOGI("OnConnectStatus process success");
72 });
73 IAM_LOGI("task posted");
74 }
75
76 private:
77 std::weak_ptr<BaseContext> callbackWeakBase_;
78 RemoteAuthContext *callback_ = nullptr;
79 std::shared_ptr<ThreadHandler> threadHandler_ = nullptr;
80 };
81
RemoteAuthContext(uint64_t contextId, std::shared_ptr<Authentication> auth, RemoteAuthContextParam ¶m, std::shared_ptr<ContextCallback> callback)82 RemoteAuthContext::RemoteAuthContext(uint64_t contextId, std::shared_ptr<Authentication> auth,
83 RemoteAuthContextParam ¶m, std::shared_ptr<ContextCallback> callback)
84 : SimpleAuthContext("RemoteAuthContext", contextId, auth, callback),
85 authType_(param.authType),
86 connectionName_(param.connectionName),
87 collectorNetworkId_(param.collectorNetworkId),
88 executorInfoMsg_(param.executorInfoMsg)
89 {
90 endPointName_ = REMOTE_AUTH_CONTEXT_ENDPOINT_NAME;
91 needSetupConnection_ = (executorInfoMsg_.size() == 0);
92 if (needSetupConnection_) {
93 ThreadHandlerManager::GetInstance().CreateThreadHandler(connectionName_);
94 }
95 }
96
~RemoteAuthContext()97 RemoteAuthContext::~RemoteAuthContext()
98 {
99 std::lock_guard<std::recursive_mutex> lock(mutex_);
100 if (cancelTimerId_.has_value()) {
101 RelativeTimer::GetInstance().Unregister(cancelTimerId_.value());
102 }
103 RemoteConnectionManager::GetInstance().UnregisterConnectionListener(connectionName_, endPointName_);
104 if (needSetupConnection_) {
105 RemoteConnectionManager::GetInstance().CloseConnection(connectionName_);
106 ThreadHandlerManager::GetInstance().DestroyThreadHandler(connectionName_);
107 }
108 IAM_LOGI("%{public}s destroy", GetDescription());
109 }
110
GetContextType() const111 ContextType RemoteAuthContext::GetContextType() const
112 {
113 return REMOTE_AUTH_CONTEXT;
114 }
115
SetExecutorInfoMsg(std::vector<uint8_t> msg)116 void RemoteAuthContext::SetExecutorInfoMsg(std::vector<uint8_t> msg)
117 {
118 std::lock_guard<std::recursive_mutex> lock(mutex_);
119
120 executorInfoMsg_ = msg;
121 IAM_LOGI("%{public}s executorInfoMsg_ size is %{public}zu", GetDescription(), executorInfoMsg_.size());
122 }
123
OnStart()124 bool RemoteAuthContext::OnStart()
125 {
126 std::lock_guard<std::recursive_mutex> lock(mutex_);
127 IAM_LOGI("%{public}s start", GetDescription());
128
129 cancelTimerId_ = RelativeTimer::GetInstance().Register(
130 [weakThis = weak_from_this(), this]() {
131 auto sharedThis = weakThis.lock();
132 IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
133 OnTimeOut();
134 },
135 SETUP_CONNECTION_TIME_OUT_MS);
136
137 if (needSetupConnection_) {
138 IAM_LOGI("%{public}s SetupConnection", GetDescription());
139 return SetupConnection();
140 }
141
142 IAM_LOGI("%{public}s StartAuth", GetDescription());
143 return StartAuth();
144 }
145
StartAuth()146 bool RemoteAuthContext::StartAuth()
147 {
148 std::lock_guard<std::recursive_mutex> lock(mutex_);
149 IAM_LOGI("%{public}s start remote auth", GetDescription());
150
151 IF_FALSE_LOGE_AND_RETURN_VAL(executorInfoMsg_.size() > 0, false);
152
153 std::vector<ExecutorInfo> executorInfos;
154 bool decodeRet = RemoteMsgUtil::DecodeQueryExecutorInfoReply(Attributes(executorInfoMsg_), executorInfos);
155 IF_FALSE_LOGE_AND_RETURN_VAL(decodeRet, false);
156 IF_FALSE_LOGE_AND_RETURN_VAL(executorInfos.size() > 0, false);
157
158 remoteExecutorProxy_ = Common::MakeShared<RemoteExecutorProxy>(connectionName_, executorInfos[0]);
159 IF_FALSE_LOGE_AND_RETURN_VAL(remoteExecutorProxy_ != nullptr, false);
160
161 ResultCode startExecutorRet = remoteExecutorProxy_->Start();
162 IF_FALSE_LOGE_AND_RETURN_VAL(startExecutorRet == SUCCESS, false);
163
164 std::string collectorUdid;
165 bool getCollectorUdidRet = DeviceManagerUtil::GetInstance().GetUdidByNetworkId(collectorNetworkId_, collectorUdid);
166 IF_FALSE_LOGE_AND_RETURN_VAL(getCollectorUdidRet, false);
167
168 IF_FALSE_LOGE_AND_RETURN_VAL(callback_ != nullptr, false);
169 callback_->SetTraceRemoteUdid(collectorUdid);
170 callback_->SetTraceIsRemoteAuth(true);
171 std::string localUdid;
172 IF_FALSE_LOGE_AND_RETURN_VAL(DeviceManagerUtil::GetInstance().GetLocalDeviceUdid(localUdid), false);
173 callback_->SetTraceLocalUdid(localUdid);
174 callback_->SetTraceConnectionName(connectionName_);
175 IF_FALSE_LOGE_AND_RETURN_VAL(auth_ != nullptr, false);
176 auth_->SetCollectorUdid(collectorUdid);
177
178 bool startAuthRet = SimpleAuthContext::OnStart();
179 IF_FALSE_LOGE_AND_RETURN_VAL(startAuthRet, false);
180 IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_.size() == 1, false);
181 IF_FALSE_LOGE_AND_RETURN_VAL(scheduleList_[0] != nullptr, false);
182
183 IAM_LOGI("%{public}s start remote auth success, connectionName:%{public}s, scheduleId:%{public}s",
184 GetDescription(), connectionName_.c_str(), GET_MASKED_STRING(scheduleList_[0]->GetScheduleId()).c_str());
185 return true;
186 }
187
StartAuthDelayed()188 void RemoteAuthContext::StartAuthDelayed()
189 {
190 std::lock_guard<std::recursive_mutex> lock(mutex_);
191 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
192 IAM_LOGI("%{public}s start", GetDescription());
193
194 bool ret = StartAuth();
195 if (!ret) {
196 IAM_LOGE("%{public}s StartAuth failed, latest error %{public}d", GetDescription(), GetLatestError());
197 Attributes attr;
198 callback_->SetTraceAuthFinishReason("RemoteAuthContext StartAuthDelayed fail");
199 callback_->OnResult(GetLatestError(), attr);
200 return;
201 }
202 IAM_LOGI("%{public}s success", GetDescription());
203 }
204
SendQueryExecutorInfoMsg()205 bool RemoteAuthContext::SendQueryExecutorInfoMsg()
206 {
207 std::lock_guard<std::recursive_mutex> lock(mutex_);
208 IAM_LOGI("%{public}s start", GetDescription());
209
210 std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>();
211 IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, false);
212
213 bool setMsgTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, QUERY_EXECUTOR_INFO);
214 IF_FALSE_LOGE_AND_RETURN_VAL(setMsgTypeRet, false);
215
216 std::vector<int32_t> authTypes = { authType_ };
217 bool setAuthTypesRet = request->SetInt32ArrayValue(Attributes::ATTR_AUTH_TYPES, authTypes);
218 IF_FALSE_LOGE_AND_RETURN_VAL(setAuthTypesRet, false);
219
220 bool setExecutorRoleRet = request->SetInt32Value(Attributes::ATTR_EXECUTOR_ROLE, COLLECTOR);
221 IF_FALSE_LOGE_AND_RETURN_VAL(setExecutorRoleRet, false);
222
223 std::string localUdid;
224 bool getLocalUdidRet = DeviceManagerUtil::GetInstance().GetLocalDeviceUdid(localUdid);
225 IF_FALSE_LOGE_AND_RETURN_VAL(getLocalUdidRet, false);
226
227 MsgCallback msgCallback = [weakThis = weak_from_this(), this](const std::shared_ptr<Attributes> &reply) {
228 IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
229
230 auto sharedThis = weakThis.lock();
231 IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
232
233 int32_t resultCode;
234 bool getResultCodeRet = reply->GetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
235 IF_FALSE_LOGE_AND_RETURN(getResultCodeRet);
236
237 if (resultCode != SUCCESS) {
238 IAM_LOGE("%{public}s query executor info failed", GetDescription());
239 Attributes attr;
240 callback_->SetTraceAuthFinishReason("RemoteAuthContext SendQueryExecutorInfoMsg QUERY_EXECUTOR_INFO fail");
241 callback_->OnResult(GENERAL_ERROR, attr);
242 return;
243 }
244
245 SetExecutorInfoMsg(reply->Serialize());
246
247 auto handler = ThreadHandler::GetSingleThreadInstance();
248 IF_FALSE_LOGE_AND_RETURN(handler != nullptr);
249 handler->PostTask([weakThis = weak_from_this(), this]() {
250 auto sharedThis = weakThis.lock();
251 IF_FALSE_LOGE_AND_RETURN(sharedThis != nullptr);
252 StartAuthDelayed();
253 });
254 IAM_LOGI("%{public}s query executor info success", GetDescription());
255 };
256
257 ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
258 REMOTE_SERVICE_ENDPOINT_NAME, request, msgCallback);
259 IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == SUCCESS, false);
260
261 IAM_LOGI("%{public}s success", GetDescription());
262 return true;
263 }
264
SetupConnection()265 bool RemoteAuthContext::SetupConnection()
266 {
267 std::lock_guard<std::recursive_mutex> lock(mutex_);
268 IAM_LOGI("%{public}s start", GetDescription());
269
270 std::shared_ptr<RemoteAuthContextMessageCallback> callback =
271 Common::MakeShared<RemoteAuthContextMessageCallback>(shared_from_this(), this);
272 IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, false);
273
274 ResultCode registerResult =
275 RemoteConnectionManager::GetInstance().RegisterConnectionListener(connectionName_, endPointName_, callback);
276 IF_FALSE_LOGE_AND_RETURN_VAL(registerResult == SUCCESS, false);
277
278 ResultCode connectResult =
279 RemoteConnectionManager::GetInstance().OpenConnection(connectionName_, collectorNetworkId_, GetTokenId());
280 IF_FALSE_LOGE_AND_RETURN_VAL(connectResult == SUCCESS, false);
281
282 IAM_LOGI("%{public}s success", GetDescription());
283 return true;
284 }
285
OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus)286 void RemoteAuthContext::OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus)
287 {
288 std::lock_guard<std::recursive_mutex> lock(mutex_);
289
290 IF_FALSE_LOGE_AND_RETURN(connectionName_ == connectionName);
291 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
292
293 Attributes attr;
294 if (connectStatus == ConnectStatus::DISCONNECTED) {
295 IAM_LOGI("%{public}s connection is disconnected", GetDescription());
296 callback_->SetTraceAuthFinishReason("RemoteAuthContext OnConnectStatus disconnected");
297 callback_->OnResult(ResultCode::GENERAL_ERROR, attr);
298 return;
299 } else {
300 IAM_LOGI("%{public}s connection is connected", GetDescription());
301 bool sendMsgRet = SendQueryExecutorInfoMsg();
302 if (!sendMsgRet) {
303 IAM_LOGE("%{public}s SendQueryExecutorInfoMsg failed", GetDescription());
304 callback_->SetTraceAuthFinishReason("RemoteAuthContext OnConnectStatus send message fail");
305 callback_->OnResult(GENERAL_ERROR, attr);
306 return;
307 }
308 IAM_LOGI("%{public}s connection is connected processed", GetDescription());
309 }
310 }
311
OnTimeOut()312 void RemoteAuthContext::OnTimeOut()
313 {
314 IAM_LOGI("%{public}s timeout", GetDescription());
315 IF_FALSE_LOGE_AND_RETURN(callback_ != nullptr);
316
317 Attributes attr;
318 callback_->SetTraceAuthFinishReason("RemoteAuthContext OnTimeOut");
319 callback_->OnResult(TIMEOUT, attr);
320 }
321 } // namespace UserAuth
322 } // namespace UserIam
323 } // namespace OHOS
324