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_executor_stub.h"
17 
18 #include "iam_check.h"
19 #include "schedule_node.h"
20 
21 #include "context_factory.h"
22 #include "context_pool.h"
23 #include "device_manager_util.h"
24 #include "hdi_wrapper.h"
25 #include "iam_logger.h"
26 #include "iam_para2str.h"
27 #include "iam_ptr.h"
28 #include "remote_auth_service.h"
29 #include "remote_msg_util.h"
30 #include "resource_node_pool.h"
31 #include "schedule_resource_node_listener.h"
32 #include "thread_handler.h"
33 
34 #define LOG_TAG "USER_AUTH_SA"
35 
36 namespace OHOS {
37 namespace UserIam {
38 namespace UserAuth {
39 class RemoteExecutorStubScheduleNode : public ScheduleNode,
40                                        public std::enable_shared_from_this<ScheduleNode>,
41                                        public NoCopyable {
42 public:
RemoteExecutorStubScheduleNode(HdiScheduleInfo & scheduleInfo,std::weak_ptr<RemoteExecutorStub> callback,std::weak_ptr<ResourceNode> collectorExecutor)43     RemoteExecutorStubScheduleNode(HdiScheduleInfo &scheduleInfo, std::weak_ptr<RemoteExecutorStub> callback,
44         std::weak_ptr<ResourceNode> collectorExecutor)
45         : scheduleId_(scheduleInfo.scheduleId),
46           callback_(callback),
47           collectorExecutor_(collectorExecutor)
48     {
49     }
50 
~RemoteExecutorStubScheduleNode()51     ~RemoteExecutorStubScheduleNode()
52     {
53         if (resourceNodePoolListener_ != nullptr) {
54             ResourceNodePool::Instance().DeregisterResourceNodePoolListener(resourceNodePoolListener_);
55         }
56     }
57 
GetScheduleId() const58     uint64_t GetScheduleId() const override
59     {
60         return scheduleId_;
61     }
62 
GetContextId() const63     uint64_t GetContextId() const override
64     {
65         return 0;
66     }
67 
GetAuthType() const68     AuthType GetAuthType() const override
69     {
70         return AuthType::ALL;
71     }
72 
GetExecutorMatcher() const73     uint64_t GetExecutorMatcher() const override
74     {
75         return 0;
76     }
GetScheduleMode() const77     ScheduleMode GetScheduleMode() const override
78     {
79         return ScheduleMode::AUTH;
80     }
GetCollectorExecutor() const81     std::weak_ptr<ResourceNode> GetCollectorExecutor() const override
82     {
83         return collectorExecutor_;
84     }
GetVerifyExecutor() const85     std::weak_ptr<ResourceNode> GetVerifyExecutor() const override
86     {
87         static std::weak_ptr<ResourceNode> nullNode;
88         return nullNode;
89     }
GetTemplateIdList() const90     std::optional<std::vector<uint64_t>> GetTemplateIdList() const override
91     {
92         return std::nullopt;
93     }
GetCurrentScheduleState() const94     State GetCurrentScheduleState() const override
95     {
96         return State::S_INIT;
97     }
GetScheduleCallback()98     std::shared_ptr<ScheduleNodeCallback> GetScheduleCallback() override
99     {
100         return nullptr;
101     }
GetAuthIntent() const102     int32_t GetAuthIntent() const override
103     {
104         return 0;
105     }
ClearScheduleCallback()106     void ClearScheduleCallback() override
107     {
108         return;
109     }
StartSchedule()110     bool StartSchedule() override
111     {
112         std::lock_guard<std::recursive_mutex> lock(mutex_);
113         resourceNodePoolListener_ = Common::MakeShared<ScheduleResourceNodeListener>(weak_from_this());
114         IF_FALSE_LOGE_AND_RETURN_VAL(resourceNodePoolListener_ != nullptr, false);
115         bool registerRet = ResourceNodePool::Instance().RegisterResourceNodePoolListener(resourceNodePoolListener_);
116         IF_FALSE_LOGE_AND_RETURN_VAL(registerRet, false);
117         return true;
118     }
StopSchedule()119     bool StopSchedule() override
120     {
121         return true;
122     }
StopSchedule(ResultCode errorCode)123     bool StopSchedule(ResultCode errorCode) override
124     {
125         std::lock_guard<std::recursive_mutex> lock(mutex_);
126         IAM_LOGI("stop schedule errorCode %{public}d", errorCode);
127         auto finalResult = Common::MakeShared<Attributes>();
128         IF_FALSE_LOGE_AND_RETURN_VAL(finalResult != nullptr, false);
129         bool setResultCodeRet = finalResult->SetInt32Value(Attributes::ATTR_RESULT_CODE, errorCode);
130         IF_FALSE_LOGE_AND_RETURN_VAL(setResultCodeRet, false);
131 
132         return ContinueSchedule(errorCode, finalResult);
133     }
SendMessage(ExecutorRole dstRole,const std::vector<uint8_t> & msg)134     bool SendMessage(ExecutorRole dstRole, const std::vector<uint8_t> &msg) override
135     {
136         std::lock_guard<std::recursive_mutex> lock(mutex_);
137         auto callback = callback_.lock();
138         IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, GENERAL_ERROR);
139         int32_t ret = callback->OnMessage(dstRole, msg);
140         return ret == ResultCode::SUCCESS;
141     }
ContinueSchedule(ResultCode resultCode,const std::shared_ptr<Attributes> & finalResult)142     bool ContinueSchedule(ResultCode resultCode, const std::shared_ptr<Attributes> &finalResult) override
143     {
144         std::lock_guard<std::recursive_mutex> lock(mutex_);
145         auto callback = callback_.lock();
146         IF_FALSE_LOGE_AND_RETURN_VAL(callback != nullptr, GENERAL_ERROR);
147         int32_t ret = callback->ContinueSchedule(resultCode, finalResult);
148         return ret == ResultCode::SUCCESS;
149     }
150 
151 private:
152     std::recursive_mutex mutex_;
153     uint64_t scheduleId_;
154     std::weak_ptr<RemoteExecutorStub> callback_;
155     std::weak_ptr<ResourceNode> collectorExecutor_;
156     std::shared_ptr<ResourceNodePool::ResourceNodePoolListener> resourceNodePoolListener_ {nullptr};
157 };
158 
159 class RemoteExecutorStubMessageCallback : public ConnectionListener, public NoCopyable {
160 public:
RemoteExecutorStubMessageCallback(uint64_t scheduleId,std::weak_ptr<RemoteExecutorStub> callback)161     explicit RemoteExecutorStubMessageCallback(uint64_t scheduleId, std::weak_ptr<RemoteExecutorStub> callback)
162         : scheduleId_(scheduleId),
163           callback_(callback),
164           threadHandler_(ThreadHandler::GetSingleThreadInstance())
165     {
166     }
167     ~RemoteExecutorStubMessageCallback() = default;
168 
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)169     void OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
170         const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply) override
171     {
172         IF_FALSE_LOGE_AND_RETURN(request != nullptr);
173         IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
174 
175         IAM_LOGI("connectionName: %{public}s, srcEndPoint: %{public}s", connectionName.c_str(), srcEndPoint.c_str());
176 
177         auto callback = callback_.lock();
178         IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
179         callback->OnMessage(connectionName, srcEndPoint, request, reply);
180     }
181 
OnConnectStatus(const std::string & connectionName,ConnectStatus connectStatus)182     void OnConnectStatus(const std::string &connectionName, ConnectStatus connectStatus) override
183     {
184         IAM_LOGI("connectionName: %{public}s, connectStatus %{public}d, scheduleId "
185                  "%{public}s",
186             connectionName.c_str(), connectStatus, GET_MASKED_STRING(scheduleId_).c_str());
187 
188         IF_FALSE_LOGE_AND_RETURN(connectStatus == ConnectStatus::DISCONNECTED);
189 
190         IF_FALSE_LOGE_AND_RETURN(threadHandler_ != nullptr);
191 
192         threadHandler_->PostTask([scheduleId = scheduleId_]() {
193             IAM_LOGI("OnConnectStatus process begin, scheduleId %{public}s", GET_MASKED_STRING(scheduleId).c_str());
194 
195             auto request = Common::MakeShared<Attributes>();
196             IF_FALSE_LOGE_AND_RETURN(request != nullptr);
197             bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
198             IF_FALSE_LOGE_AND_RETURN(setScheduleIdRet);
199 
200             auto reply = Common::MakeShared<Attributes>();
201             IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
202             RemoteAuthService::GetInstance().ProcEndExecuteRequest(request, reply);
203             IAM_LOGI("OnConnectStatus process success, scheduleId %{public}s", GET_MASKED_STRING(scheduleId).c_str());
204         });
205 
206         IAM_LOGI("task posted");
207     }
208 
209 private:
210     uint64_t scheduleId_;
211     std::weak_ptr<RemoteExecutorStub> callback_;
212     std::shared_ptr<ThreadHandler> threadHandler_ = nullptr;
213 };
214 
RemoteExecutorStub()215 RemoteExecutorStub::RemoteExecutorStub() : endPointName_(EXECUTOR_STUB_ENDPOINT_NAME)
216 {
217 }
218 
~RemoteExecutorStub()219 RemoteExecutorStub::~RemoteExecutorStub()
220 {
221     std::lock_guard<std::recursive_mutex> lock(mutex_);
222     if (connectionCallback_ != nullptr) {
223         RemoteConnectionManager::GetInstance().UnregisterConnectionListener(connectionName_, endPointName_);
224     }
225     if (contextId_.has_value()) {
226         ContextPool::Instance().Delete(contextId_.value());
227     }
228     IAM_LOGI("ConnectionName %{public}s RemoteExecutorStub destructed", connectionName_.c_str());
229 }
230 
ProcBeginExecuteRequest(Attributes & attr)231 int32_t RemoteExecutorStub::ProcBeginExecuteRequest(Attributes &attr)
232 {
233     std::lock_guard<std::recursive_mutex> lock(mutex_);
234     IAM_LOGI("start");
235 
236     uint64_t scheduleId;
237     bool getScheduleIdRet = attr.GetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
238     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleIdRet, GENERAL_ERROR);
239     IAM_LOGI("scheduleId %{public}s begin execute", GET_MASKED_STRING(scheduleId).c_str());
240 
241     connectionCallback_ = Common::MakeShared<RemoteExecutorStubMessageCallback>(scheduleId, shared_from_this());
242     IF_FALSE_LOGE_AND_RETURN_VAL(connectionCallback_ != nullptr, GENERAL_ERROR);
243 
244     bool getConnectionName = attr.GetStringValue(Attributes::ATTR_CONNECTION_NAME, connectionName_);
245     IF_FALSE_LOGE_AND_RETURN_VAL(getConnectionName, GENERAL_ERROR);
246 
247     ResultCode registerResult = RemoteConnectionManager::GetInstance().RegisterConnectionListener(connectionName_,
248         endPointName_, connectionCallback_);
249     IF_FALSE_LOGE_AND_RETURN_VAL(registerResult == SUCCESS, GENERAL_ERROR);
250 
251     std::string srcUdid;
252     bool getSrcUdidRet = attr.GetStringValue(Attributes::ATTR_MSG_SRC_UDID, srcUdid);
253     IF_FALSE_LOGE_AND_RETURN_VAL(getSrcUdidRet, GENERAL_ERROR);
254 
255     std::vector<uint8_t> scheduleData;
256     bool getScheduleDataRet = attr.GetUint8ArrayValue(Attributes::ATTR_SCHEDULE_DATA, scheduleData);
257     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleDataRet, GENERAL_ERROR);
258 
259     HdiScheduleInfo scheduleInfo;
260     auto hdi = HdiWrapper::GetHdiInstance();
261     IF_FALSE_LOGE_AND_RETURN_VAL(hdi != nullptr, GENERAL_ERROR);
262 
263     int32_t ret = hdi->GetLocalScheduleFromMessage(srcUdid, scheduleData, scheduleInfo);
264     IF_FALSE_LOGE_AND_RETURN_VAL(ret == SUCCESS, GENERAL_ERROR);
265     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleInfo.executorIndexes.size() == 1, GENERAL_ERROR);
266     IF_FALSE_LOGE_AND_RETURN_VAL(scheduleInfo.executorMessages.size() == 1, GENERAL_ERROR);
267 
268     executorIndex_ = scheduleInfo.executorIndexes[0];
269     std::weak_ptr<ResourceNode> weakNode = ResourceNodePool::Instance().Select(executorIndex_);
270     std::shared_ptr<ResourceNode> node = weakNode.lock();
271     IF_FALSE_LOGE_AND_RETURN_VAL(node != nullptr, GENERAL_ERROR);
272 
273     remoteScheduleNode_ = Common::MakeShared<RemoteExecutorStubScheduleNode>(scheduleInfo, weak_from_this(), node);
274     IF_FALSE_LOGE_AND_RETURN_VAL(remoteScheduleNode_ != nullptr, GENERAL_ERROR);
275 
276     bool startScheduleRet = remoteScheduleNode_->StartSchedule();
277     IF_FALSE_LOGE_AND_RETURN_VAL(startScheduleRet, GENERAL_ERROR);
278 
279     auto context = ContextFactory::CreateScheduleHolderContext(remoteScheduleNode_);
280     IF_FALSE_LOGE_AND_RETURN_VAL(context != nullptr, GENERAL_ERROR);
281 
282     bool addContextRet = ContextPool::Instance().Insert(context);
283     IF_FALSE_LOGE_AND_RETURN_VAL(addContextRet, GENERAL_ERROR);
284     contextId_ = context->GetContextId();
285 
286     bool setExtraInfo = attr.SetUint8ArrayValue(Attributes::ATTR_EXTRA_INFO, scheduleInfo.executorMessages[0]);
287     IF_FALSE_LOGE_AND_RETURN_VAL(setExtraInfo, GENERAL_ERROR);
288 
289     std::vector<uint8_t> publicKey;
290     node->BeginExecute(scheduleInfo.scheduleId, publicKey, attr);
291 
292     IAM_LOGI("ConnectionName %{public}s scheduleId %{public}s begin execute success", connectionName_.c_str(),
293         GET_MASKED_STRING(scheduleId).c_str());
294     return ResultCode::SUCCESS;
295 }
296 
OnMessage(const std::string & connectionName,const std::string & srcEndPoint,const std::shared_ptr<Attributes> & request,std::shared_ptr<Attributes> & reply)297 void RemoteExecutorStub::OnMessage(const std::string &connectionName, const std::string &srcEndPoint,
298     const std::shared_ptr<Attributes> &request, std::shared_ptr<Attributes> &reply)
299 {
300     std::lock_guard<std::recursive_mutex> lock(mutex_);
301     IAM_LOGI("start");
302     IF_FALSE_LOGE_AND_RETURN(request != nullptr);
303     IF_FALSE_LOGE_AND_RETURN(reply != nullptr);
304 
305     int32_t msgType;
306     bool getMsgTypeRet = request->GetInt32Value(Attributes::ATTR_MSG_TYPE, msgType);
307     IF_FALSE_LOGE_AND_RETURN(getMsgTypeRet);
308 
309     int32_t resultCode = ResultCode::GENERAL_ERROR;
310     switch (msgType) {
311         case MessageType::SEND_DATA_TO_EXECUTOR:
312             resultCode = ProcSendDataMsg(*request);
313             break;
314         default:
315             IAM_LOGE("unsupported message type: %{public}d", msgType);
316             break;
317     }
318 
319     IF_FALSE_LOGE_AND_RETURN(resultCode == ResultCode::SUCCESS);
320     bool setResultCodeRet = reply->SetInt32Value(Attributes::ATTR_RESULT_CODE, ResultCode::SUCCESS);
321     IF_FALSE_LOGE_AND_RETURN(setResultCodeRet);
322 
323     IAM_LOGI("success");
324 }
325 
OnMessage(ExecutorRole dstRole,const std::vector<uint8_t> & msg)326 int32_t RemoteExecutorStub::OnMessage(ExecutorRole dstRole, const std::vector<uint8_t> &msg)
327 {
328     std::lock_guard<std::recursive_mutex> lock(mutex_);
329     IF_FALSE_LOGE_AND_RETURN_VAL(remoteScheduleNode_ != nullptr, GENERAL_ERROR);
330 
331     IAM_LOGI("start, scheduleId %{public}s", GET_MASKED_STRING(remoteScheduleNode_->GetScheduleId()).c_str());
332 
333     std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>(msg);
334     IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, GENERAL_ERROR);
335 
336     bool setMsgTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, MessageType::EXECUTOR_SEND_DATA);
337     IF_FALSE_LOGE_AND_RETURN_VAL(setMsgTypeRet, GENERAL_ERROR);
338 
339     bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, remoteScheduleNode_->GetScheduleId());
340     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleIdRet, GENERAL_ERROR);
341 
342     bool setDestRoleRet = request->SetInt32Value(Attributes::ATTR_DEST_ROLE, dstRole);
343     IF_FALSE_LOGE_AND_RETURN_VAL(setDestRoleRet, GENERAL_ERROR);
344 
345     MsgCallback msgCallback = [](const std::shared_ptr<Attributes> &) { IAM_LOGI("message sent"); };
346 
347     ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
348         EXECUTOR_PROXY_ENDPOINT_NAME, request, msgCallback);
349     IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == ResultCode::SUCCESS, GENERAL_ERROR);
350 
351     IAM_LOGI("success, ConnectionName %{public}s scheduleId %{public}s", connectionName_.c_str(),
352         GET_MASKED_STRING(remoteScheduleNode_->GetScheduleId()).c_str());
353     return SUCCESS;
354 }
355 
ContinueSchedule(ResultCode resultCode,const std::shared_ptr<Attributes> & finalResult)356 int32_t RemoteExecutorStub::ContinueSchedule(ResultCode resultCode, const std::shared_ptr<Attributes> &finalResult)
357 {
358     std::lock_guard<std::recursive_mutex> lock(mutex_);
359     IAM_LOGI("start");
360 
361     IF_FALSE_LOGE_AND_RETURN_VAL(finalResult != nullptr, GENERAL_ERROR);
362     IF_FALSE_LOGE_AND_RETURN_VAL(remoteScheduleNode_ != nullptr, GENERAL_ERROR);
363     IAM_LOGI("ConnectionName %{public}s scheduleId %{public}s continue schedule", connectionName_.c_str(),
364         GET_MASKED_STRING(remoteScheduleNode_->GetScheduleId()).c_str());
365 
366     std::shared_ptr<Attributes> request = Common::MakeShared<Attributes>(finalResult->Serialize());
367     IF_FALSE_LOGE_AND_RETURN_VAL(request != nullptr, GENERAL_ERROR);
368 
369     bool setMsgTypeRet = request->SetInt32Value(Attributes::ATTR_MSG_TYPE, MessageType::EXECUTOR_FINISH);
370     IF_FALSE_LOGE_AND_RETURN_VAL(setMsgTypeRet, GENERAL_ERROR);
371 
372     bool setScheduleIdRet = request->SetUint64Value(Attributes::ATTR_SCHEDULE_ID, remoteScheduleNode_->GetScheduleId());
373     IF_FALSE_LOGE_AND_RETURN_VAL(setScheduleIdRet, GENERAL_ERROR);
374 
375     bool setResultCodeRet = request->SetInt32Value(Attributes::ATTR_RESULT_CODE, resultCode);
376     IF_FALSE_LOGE_AND_RETURN_VAL(setResultCodeRet, GENERAL_ERROR);
377 
378     MsgCallback msgCallback = [](const std::shared_ptr<Attributes> &) { IAM_LOGI("message sent"); };
379 
380     ResultCode sendMsgRet = RemoteConnectionManager::GetInstance().SendMessage(connectionName_, endPointName_,
381         EXECUTOR_PROXY_ENDPOINT_NAME, request, msgCallback);
382     IF_FALSE_LOGE_AND_RETURN_VAL(sendMsgRet == ResultCode::SUCCESS, GENERAL_ERROR);
383 
384     IAM_LOGI("ConnectionName %{public}s scheduleId %{public}s continue schedule "
385              "success",
386         connectionName_.c_str(), GET_MASKED_STRING(remoteScheduleNode_->GetScheduleId()).c_str());
387     return SUCCESS;
388 }
389 
ProcSendDataMsg(Attributes & attr)390 int32_t RemoteExecutorStub::ProcSendDataMsg(Attributes &attr)
391 {
392     std::lock_guard<std::recursive_mutex> lock(mutex_);
393     IAM_LOGI("start");
394 
395     uint64_t scheduleId;
396     bool getScheduleIdRet = attr.GetUint64Value(Attributes::ATTR_SCHEDULE_ID, scheduleId);
397     IF_FALSE_LOGE_AND_RETURN_VAL(getScheduleIdRet, GENERAL_ERROR);
398     IAM_LOGI("ConnectionName %{public}s scheduleId %{public}s proc send data", connectionName_.c_str(),
399         GET_MASKED_STRING(scheduleId).c_str());
400 
401     std::weak_ptr<ResourceNode> weakNode = ResourceNodePool::Instance().Select(executorIndex_);
402     std::shared_ptr<ResourceNode> node = weakNode.lock();
403     IF_FALSE_LOGE_AND_RETURN_VAL(node != nullptr, GENERAL_ERROR);
404 
405     int32_t ret = node->SendData(scheduleId, attr);
406     IF_FALSE_LOGE_AND_RETURN_VAL(ret == ResultCode::SUCCESS, GENERAL_ERROR);
407 
408     IAM_LOGI("ConnectionName %{public}s scheduleId %{public}s proc send data success", connectionName_.c_str(),
409         GET_MASKED_STRING(scheduleId).c_str());
410     return ret;
411 }
412 
413 } // namespace UserAuth
414 } // namespace UserIam
415 } // namespace OHOS