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