• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "daemon.h"
16 #ifndef TEST_HASH
17 #include "hdc_hash_gen.h"
18 #endif
19 #include "../common/serial_struct.h"
20 #include <openssl/sha.h>
21 
22 namespace Hdc {
23 #ifdef USE_CONFIG_UV_THREADS
HdcDaemon(bool serverOrDaemonIn,size_t uvThreadSize)24 HdcDaemon::HdcDaemon(bool serverOrDaemonIn, size_t uvThreadSize)
25     : HdcSessionBase(serverOrDaemonIn, uvThreadSize)
26 #else
27 HdcDaemon::HdcDaemon(bool serverOrDaemonIn)
28     : HdcSessionBase(serverOrDaemonIn, -1)
29 #endif
30 {
31     clsTCPServ = nullptr;
32     clsUSBServ = nullptr;
33 #ifdef HDC_SUPPORT_UART
34     clsUARTServ = nullptr;
35 #endif
36     clsJdwp = nullptr;
37     enableSecure = false;
38 }
39 
~HdcDaemon()40 HdcDaemon::~HdcDaemon()
41 {
42     WRITE_LOG(LOG_DEBUG, "~HdcDaemon");
43 }
44 
ClearInstanceResource()45 void HdcDaemon::ClearInstanceResource()
46 {
47     TryStopInstance();
48     Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon");
49     if (clsTCPServ) {
50         delete (HdcDaemonTCP *)clsTCPServ;
51         clsTCPServ = nullptr;
52     }
53     if (clsUSBServ) {
54         delete (HdcDaemonUSB *)clsUSBServ;
55         clsUSBServ = nullptr;
56     }
57 #ifdef HDC_SUPPORT_UART
58     if (clsUARTServ) {
59         delete (HdcDaemonUART *)clsUARTServ;
60     }
61     clsUARTServ = nullptr;
62 #endif
63     if (clsJdwp) {
64         delete (HdcJdwp *)clsJdwp;
65         clsJdwp = nullptr;
66     }
67     WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish");
68 }
69 
TryStopInstance()70 void HdcDaemon::TryStopInstance()
71 {
72     ClearSessions();
73     if (clsTCPServ) {
74         WRITE_LOG(LOG_DEBUG, "Stop TCP");
75         ((HdcDaemonTCP *)clsTCPServ)->Stop();
76     }
77     if (clsUSBServ) {
78         WRITE_LOG(LOG_DEBUG, "Stop USB");
79         ((HdcDaemonUSB *)clsUSBServ)->Stop();
80     }
81 #ifdef HDC_SUPPORT_UART
82     if (clsUARTServ) {
83         WRITE_LOG(LOG_DEBUG, "Stop UART");
84         ((HdcDaemonUART *)clsUARTServ)->Stop();
85     }
86 #endif
87     ((HdcJdwp *)clsJdwp)->Stop();
88     // workaround temply remove MainLoop instance clear
89     ReMainLoopForInstanceClear();
90     WRITE_LOG(LOG_DEBUG, "Stop loopmain");
91 }
92 
93 #ifdef HDC_SUPPORT_UART
InitMod(bool bEnableTCP,bool bEnableUSB,bool bEnableUART)94 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, [[maybe_unused]] bool bEnableUART)
95 #else
96 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB)
97 #endif
98 {
99     WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");
100 #ifdef HDC_SUPPORT_UART
101     WRITE_LOG(LOG_DEBUG, "bEnableTCP:%d,bEnableUSB:%d", bEnableTCP, bEnableUSB);
102 #endif
103     if (bEnableTCP) {
104         // tcp
105         clsTCPServ = new(std::nothrow) HdcDaemonTCP(false, this);
106         if (clsTCPServ == nullptr) {
107             WRITE_LOG(LOG_FATAL, "InitMod new clsTCPServ failed");
108             return;
109         }
110         ((HdcDaemonTCP *)clsTCPServ)->Initial();
111     }
112     if (bEnableUSB) {
113         // usb
114         clsUSBServ = new(std::nothrow) HdcDaemonUSB(false, this);
115         if (clsUSBServ == nullptr) {
116             WRITE_LOG(LOG_FATAL, "InitMod new clsUSBServ failed");
117             return;
118         }
119         ((HdcDaemonUSB *)clsUSBServ)->Initial();
120     }
121 #ifdef HDC_SUPPORT_UART
122     WRITE_LOG(LOG_DEBUG, "bEnableUART:%d", bEnableUART);
123     if (bEnableUART) {
124         // UART
125         clsUARTServ = new(std::nothrow) HdcDaemonUART(*this);
126         if (clsUARTServ == nullptr) {
127             WRITE_LOG(LOG_FATAL, "InitMod new clsUARTServ failed");
128             return;
129         }
130         ((HdcDaemonUART *)clsUARTServ)->Initial();
131     }
132 #endif
133     clsJdwp = new(std::nothrow) HdcJdwp(&loopMain);
134     if (clsJdwp == nullptr) {
135         WRITE_LOG(LOG_FATAL, "InitMod new clsJdwp failed");
136         return;
137     }
138     ((HdcJdwp *)clsJdwp)->Initial();
139     // enable security
140     string secure;
141     SystemDepend::GetDevItem("ro.hdc.secure", secure);
142     enableSecure = (Base::Trim(secure) == "1");
143 }
144 
145 // clang-format off
RedirectToTask(HTaskInfo hTaskInfo,HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)146 bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
147                                const uint16_t command, uint8_t *payload, const int payloadSize)
148 {
149     bool ret = true;
150     hTaskInfo->ownerSessionClass = this;
151     switch (command) {
152         case CMD_UNITY_EXECUTE:
153         case CMD_UNITY_REMOUNT:
154         case CMD_UNITY_REBOOT:
155         case CMD_UNITY_RUNMODE:
156         case CMD_UNITY_HILOG:
157         case CMD_UNITY_ROOTRUN:
158         case CMD_UNITY_TERMINATE:
159         case CMD_UNITY_BUGREPORT_INIT:
160         case CMD_JDWP_LIST:
161         case CMD_JDWP_TRACK:
162             ret = TaskCommandDispatch<HdcDaemonUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
163             break;
164         case CMD_SHELL_INIT:
165         case CMD_SHELL_DATA:
166             ret = TaskCommandDispatch<HdcShell>(hTaskInfo, TYPE_SHELL, command, payload, payloadSize);
167             break;
168         case CMD_FILE_CHECK:
169         case CMD_FILE_DATA:
170         case CMD_FILE_FINISH:
171         case CMD_FILE_INIT:
172         case CMD_FILE_BEGIN:
173         case CMD_FILE_MODE:
174         case CMD_DIR_MODE:
175             ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
176             break;
177         // One-way function, so fewer options
178         case CMD_APP_CHECK:
179         case CMD_APP_DATA:
180         case CMD_APP_UNINSTALL:
181             ret = TaskCommandDispatch<HdcDaemonApp>(hTaskInfo, TASK_APP, command, payload, payloadSize);
182             break;
183         case CMD_FORWARD_INIT:
184         case CMD_FORWARD_CHECK:
185         case CMD_FORWARD_ACTIVE_MASTER:
186         case CMD_FORWARD_ACTIVE_SLAVE:
187         case CMD_FORWARD_DATA:
188         case CMD_FORWARD_FREE_CONTEXT:
189         case CMD_FORWARD_CHECK_RESULT:
190             ret = TaskCommandDispatch<HdcDaemonForward>(hTaskInfo, TASK_FORWARD, command, payload, payloadSize);
191             break;
192         default:
193         // ignore unknown command
194             break;
195     }
196     return ret;
197 }
198 // clang-format on
199 
HandDaemonAuth(HSession hSession,const uint32_t channelId,SessionHandShake & handshake)200 bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
201 {
202     bool ret = false;
203     switch (handshake.authType) {
204         case AUTH_NONE: {  // AUTH_NONE -> AUTH
205             hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH);
206             handshake.authType = AUTH_TOKEN;
207             handshake.buf = hSession->tokenRSA;
208             string bufString = SerialStruct::SerializeToString(handshake);
209             Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
210                  reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())),
211                  bufString.size());
212             ret = true;
213             break;
214         }
215         case AUTH_SIGNATURE: {
216             // When Host is first connected to the device, the signature authentication is inevitable, and the
217             // certificate verification must be triggered.
218             //
219             // When the certificate is verified, the client sends a public key to the device, triggered the system UI
220             // jump out dialog, and click the system, the system will store the Host public key certificate in the
221             // device locally, and the signature authentication will be correct when the subsequent connection is
222             // connected.
223             if (!HdcAuth::AuthVerify(reinterpret_cast<uint8_t *>(const_cast<char *>(hSession->tokenRSA.c_str())),
224                 reinterpret_cast<uint8_t *>(const_cast<char *>(handshake.buf.c_str())), handshake.buf.size())) {
225                 // Next auth
226                 handshake.authType = AUTH_TOKEN;
227                 handshake.buf = hSession->tokenRSA;
228                 string bufString = SerialStruct::SerializeToString(handshake);
229                 Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
230                      reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
231                 break;
232             }
233             ret = true;
234             break;
235         }
236         case AUTH_PUBLICKEY: {
237             ret = HdcAuth::PostUIConfirm(handshake.buf);
238             WRITE_LOG(LOG_DEBUG, "Auth host OK, postUIConfirm");
239             break;
240         }
241         default:
242             break;
243     }
244     return ret;
245 }
246 
DaemonSessionHandshake(HSession hSession,const uint32_t channelId,uint8_t * payload,int payloadSize)247 bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize)
248 {
249     // session handshake step2
250     string s = string(reinterpret_cast<char *>(payload), payloadSize);
251     SessionHandShake handshake;
252     string err;
253     SerialStruct::ParseFromString(handshake, s);
254 #ifdef HDC_DEBUG
255     WRITE_LOG(LOG_DEBUG, "session %s try to handshake", hSession->ToDebugString().c_str());
256 #endif
257     // banner to check is parse ok...
258     if (handshake.banner != HANDSHAKE_MESSAGE) {
259         hSession->availTailIndex = 0;
260         WRITE_LOG(LOG_FATAL, "Recv server-hello failed");
261         return false;
262     }
263     if (handshake.authType == AUTH_NONE) {
264         // daemon handshake 1st packet
265         uint32_t unOld = hSession->sessionId;
266         hSession->sessionId = handshake.sessionId;
267         hSession->connectKey = handshake.connectKey;
268         AdminSession(OP_UPDATE, unOld, hSession);
269 #ifdef HDC_SUPPORT_UART
270         if (hSession->connType == CONN_SERIAL and clsUARTServ!= nullptr) {
271             WRITE_LOG(LOG_DEBUG, " HdcDaemon::DaemonSessionHandshake %s",
272                       handshake.ToDebugString().c_str());
273             if (clsUARTServ != nullptr) {
274                 (static_cast<HdcDaemonUART *>(clsUARTServ))->OnNewHandshakeOK(hSession->sessionId);
275             }
276         } else
277 #endif // HDC_SUPPORT_UART
278         if (clsUSBServ != nullptr) {
279             (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId);
280         }
281 
282         handshake.sessionId = 0;
283         handshake.connectKey = "";
284     }
285     if (enableSecure && !HandDaemonAuth(hSession, channelId, handshake)) {
286         return false;
287     }
288     string version = Base::GetVersion() + HDC_MSG_HASH;
289 
290     WRITE_LOG(LOG_FATAL, "receive hs version = %s", handshake.version.c_str());
291 
292     if (!handshake.version.empty() && handshake.version != version) {
293         WRITE_LOG(LOG_FATAL, "DaemonSessionHandshake failed! version not match [%s] vs [%s]",
294             handshake.version.c_str(), version.c_str());
295 #ifdef HDC_CHECK_CHECK
296 	hSession->availTailIndex = 0;
297         handshake.banner = HANDSHAKE_FAILED;
298         string failedString = SerialStruct::SerializeToString(handshake);
299         Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)failedString.c_str(),
300              failedString.size());
301         return false;
302 #endif
303     }
304     if (handshake.version.empty()) {
305         handshake.version = Base::GetVersion();
306         WRITE_LOG(LOG_FATAL, "set version if check mode = %s", handshake.version.c_str());
307     }
308     // handshake auth OK.Can append the sending device information to HOST
309 #ifdef HDC_DEBUG
310     WRITE_LOG(LOG_INFO, "session %u handshakeOK send back CMD_KERNEL_HANDSHAKE", hSession->sessionId);
311 #endif
312     char hostName[BUF_SIZE_MEDIUM] = "";
313     size_t len = sizeof(hostName);
314     uv_os_gethostname(hostName, &len);
315     handshake.authType = AUTH_OK;
316     handshake.buf = hostName;
317     string bufString = SerialStruct::SerializeToString(handshake);
318     Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
319          reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
320     hSession->handshakeOK = true;
321     return true;
322 }
323 
FetchCommand(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)324 bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
325                              const int payloadSize)
326 {
327     bool ret = true;
328     if (!hSession->handshakeOK and command != CMD_KERNEL_HANDSHAKE) {
329         WRITE_LOG(LOG_WARN, "session %u wait CMD_KERNEL_HANDSHAKE , but got command %u",
330                   hSession->sessionId, command);
331         ret = false;
332         return ret;
333     }
334     if (command != CMD_UNITY_BUGREPORT_DATA &&
335         command != CMD_SHELL_DATA &&
336         command != CMD_FORWARD_DATA &&
337         command != CMD_FILE_DATA &&
338         command != CMD_APP_DATA) {
339         WRITE_LOG(LOG_DEBUG, "FetchCommand channelId:%u command:%u", channelId, command);
340     }
341     switch (command) {
342         case CMD_KERNEL_HANDSHAKE: {
343             // session handshake step2
344             ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize);
345             break;
346         }
347         case CMD_KERNEL_CHANNEL_CLOSE: {  // Daemon is only cleaning up the Channel task
348             ClearOwnTasks(hSession, channelId);
349             if (*payload != 0) {
350                 --(*payload);
351                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
352             }
353             ret = true;
354             break;
355         }
356         default:
357             ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize);
358             break;
359     }
360     return ret;
361 }
362 
RemoveInstanceTask(const uint8_t op,HTaskInfo hTask)363 bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
364 {
365     bool ret = true;
366 
367     if (!hTask->taskClass) {
368         return ret;
369     }
370 
371     switch (hTask->taskType) {
372         case TYPE_UNITY:
373             ret = DoTaskRemove<HdcDaemonUnity>(hTask, op);
374             break;
375         case TYPE_SHELL:
376             ret = DoTaskRemove<HdcShell>(hTask, op);
377             break;
378         case TASK_FILE:
379             ret = DoTaskRemove<HdcTransferBase>(hTask, op);
380             break;
381         case TASK_FORWARD:
382             ret = DoTaskRemove<HdcDaemonForward>(hTask, op);
383             break;
384         case TASK_APP:
385             ret = DoTaskRemove<HdcDaemonApp>(hTask, op);
386             break;
387         default:
388             ret = false;
389             break;
390     }
391     return ret;
392 }
393 
ServerCommand(const uint32_t sessionId,const uint32_t channelId,const uint16_t command,uint8_t * bufPtr,const int size)394 bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
395                               uint8_t *bufPtr, const int size)
396 {
397     return Send(sessionId, channelId, command, reinterpret_cast<uint8_t *>(bufPtr), size) > 0;
398 }
399 
JdwpNewFileDescriptor(const uint8_t * buf,const int bytesIO)400 void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO)
401 {
402     uint32_t pid = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 1));
403     uint32_t fd = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 5));  // 5 : fd offset
404     ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd);
405 }
406 
NotifyInstanceSessionFree(HSession hSession,bool freeOrClear)407 void HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
408 {
409     if (!freeOrClear) {
410         return;  // ignore step 1
411     }
412     if (clsUSBServ != nullptr) {
413         auto clsUsbModule = reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
414         clsUsbModule->OnSessionFreeFinally(hSession);
415     }
416 }
417 }  // namespace Hdc
418