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 "serial_struct.h"
20 #include <openssl/sha.h>
21 #include <openssl/bio.h>
22 #include <openssl/evp.h>
23 #include <openssl/pem.h>
24 #include <fstream>
25 #include <unistd.h>
26 #include <sys/wait.h>
27
28 namespace Hdc {
29 #ifdef USE_CONFIG_UV_THREADS
HdcDaemon(bool serverOrDaemonIn,size_t uvThreadSize)30 HdcDaemon::HdcDaemon(bool serverOrDaemonIn, size_t uvThreadSize)
31 : HdcSessionBase(serverOrDaemonIn, uvThreadSize)
32 #else
33 HdcDaemon::HdcDaemon(bool serverOrDaemonIn)
34 : HdcSessionBase(serverOrDaemonIn, -1)
35 #endif
36 {
37 clsTCPServ = nullptr;
38 clsUSBServ = nullptr;
39 #ifdef HDC_EMULATOR
40 clsBridgeServ = nullptr;
41 #endif
42 #ifdef HDC_SUPPORT_UART
43 clsUARTServ = nullptr;
44 #endif
45 clsJdwp = nullptr;
46 enableSecure = false;
47 }
48
~HdcDaemon()49 HdcDaemon::~HdcDaemon()
50 {
51 WRITE_LOG(LOG_DEBUG, "~HdcDaemon");
52 }
53
ClearInstanceResource()54 void HdcDaemon::ClearInstanceResource()
55 {
56 TryStopInstance();
57 Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon");
58 if (clsTCPServ) {
59 delete (HdcDaemonTCP *)clsTCPServ;
60 clsTCPServ = nullptr;
61 }
62 if (clsUSBServ) {
63 delete (HdcDaemonUSB *)clsUSBServ;
64 clsUSBServ = nullptr;
65 }
66 #ifdef HDC_EMULATOR
67 if (clsBridgeServ) {
68 delete (HdcDaemonBridge *)clsBridgeServ;
69 }
70 #endif
71 #ifdef HDC_SUPPORT_UART
72 if (clsUARTServ) {
73 delete (HdcDaemonUART *)clsUARTServ;
74 }
75 clsUARTServ = nullptr;
76 #endif
77 if (clsJdwp) {
78 delete (HdcJdwp *)clsJdwp;
79 clsJdwp = nullptr;
80 }
81 WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish");
82 }
83
TryStopInstance()84 void HdcDaemon::TryStopInstance()
85 {
86 ClearSessions();
87 if (clsTCPServ) {
88 WRITE_LOG(LOG_DEBUG, "Stop TCP");
89 ((HdcDaemonTCP *)clsTCPServ)->Stop();
90 }
91 if (clsUSBServ) {
92 WRITE_LOG(LOG_DEBUG, "Stop USB");
93 ((HdcDaemonUSB *)clsUSBServ)->Stop();
94 }
95 #ifdef HDC_EMULATOR
96 if (clsBridgeServ) {
97 WRITE_LOG(LOG_DEBUG, "Stop Bridge");
98 ((HdcDaemonBridge *)clsBridgeServ)->Stop();
99 }
100 #endif
101 #ifdef HDC_SUPPORT_UART
102 if (clsUARTServ) {
103 WRITE_LOG(LOG_DEBUG, "Stop UART");
104 ((HdcDaemonUART *)clsUARTServ)->Stop();
105 }
106 #endif
107 ((HdcJdwp *)clsJdwp)->Stop();
108 // workaround temply remove MainLoop instance clear
109 ReMainLoopForInstanceClear();
110 WRITE_LOG(LOG_DEBUG, "Stop loopmain");
111 }
112
113 #ifdef HDC_SUPPORT_UART
InitMod(bool bEnableTCP,bool bEnableUSB,bool bEnableUART)114 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, [[maybe_unused]] bool bEnableUART)
115 #else
116 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB)
117 #endif
118 {
119 WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");
120 #ifdef HDC_SUPPORT_UART
121 WRITE_LOG(LOG_DEBUG, "bEnableTCP:%d,bEnableUSB:%d", bEnableTCP, bEnableUSB);
122 #endif
123 if (bEnableTCP) {
124 // tcp
125 clsTCPServ = new(std::nothrow) HdcDaemonTCP(false, this);
126 if (clsTCPServ == nullptr) {
127 WRITE_LOG(LOG_FATAL, "InitMod new clsTCPServ failed");
128 return;
129 }
130 ((HdcDaemonTCP *)clsTCPServ)->Initial();
131 }
132 if (bEnableUSB) {
133 // usb
134 clsUSBServ = new(std::nothrow) HdcDaemonUSB(false, this);
135 if (clsUSBServ == nullptr) {
136 WRITE_LOG(LOG_FATAL, "InitMod new clsUSBServ failed");
137 return;
138 }
139 ((HdcDaemonUSB *)clsUSBServ)->Initial();
140 }
141 #ifdef HDC_SUPPORT_UART
142 WRITE_LOG(LOG_DEBUG, "bEnableUART:%d", bEnableUART);
143 if (bEnableUART) {
144 // UART
145 clsUARTServ = new(std::nothrow) HdcDaemonUART(*this);
146 if (clsUARTServ == nullptr) {
147 WRITE_LOG(LOG_FATAL, "InitMod new clsUARTServ failed");
148 return;
149 }
150 ((HdcDaemonUART *)clsUARTServ)->Initial();
151 }
152 #endif
153 clsJdwp = new(std::nothrow) HdcJdwp(&loopMain);
154 if (clsJdwp == nullptr) {
155 WRITE_LOG(LOG_FATAL, "InitMod new clsJdwp failed");
156 return;
157 }
158 ((HdcJdwp *)clsJdwp)->Initial();
159 // enable security
160 string secure;
161 SystemDepend::GetDevItem("const.hdc.secure", secure);
162 string authbypass;
163 SystemDepend::GetDevItem("persist.hdc.auth_bypass", authbypass);
164 #ifndef HDC_EMULATOR
165 enableSecure = ((Base::Trim(secure) == "1") && (Base::Trim(authbypass) != "1"));
166 #endif
167 }
168
169 #ifdef HDC_EMULATOR
170 #ifdef HDC_SUPPORT_UART
InitMod(bool bEnableTCP,bool bEnableUSB,bool bEnableBridge,bool bEnableUART)171 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, bool bEnableBridge, [[maybe_unused]] bool bEnableUART)
172 {
173 InitMod(bEnableTCP, bEnableUSB, bEnableUART);
174 #else
175 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, bool bEnableBridge)
176 {
177 InitMod(bEnableTCP, bEnableUSB);
178 #endif
179 if (bEnableBridge) {
180 clsBridgeServ = new(std::nothrow) HdcDaemonBridge(false, this);
181 if (clsBridgeServ == nullptr) {
182 WRITE_LOG(LOG_FATAL, "InitMod new clsBridgeServ failed");
183 return;
184 }
185 ((HdcDaemonBridge *)clsBridgeServ)->Initial();
186 }
187 }
188 #endif
189
190 // clang-format off
191 bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
192 const uint16_t command, uint8_t *payload, const int payloadSize)
193 {
194 StartTraceScope("HdcDaemon::RedirectToTask");
195 bool ret = true;
196 hTaskInfo->ownerSessionClass = this;
197 switch (command) {
198 case CMD_UNITY_EXECUTE:
199 case CMD_UNITY_REMOUNT:
200 case CMD_UNITY_REBOOT:
201 case CMD_UNITY_RUNMODE:
202 case CMD_UNITY_HILOG:
203 case CMD_UNITY_ROOTRUN:
204 case CMD_UNITY_TERMINATE:
205 case CMD_UNITY_BUGREPORT_INIT:
206 case CMD_JDWP_LIST:
207 case CMD_JDWP_TRACK:
208 ret = TaskCommandDispatch<HdcDaemonUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
209 break;
210 case CMD_SHELL_INIT:
211 case CMD_SHELL_DATA:
212 ret = TaskCommandDispatch<HdcShell>(hTaskInfo, TYPE_SHELL, command, payload, payloadSize);
213 break;
214 case CMD_FILE_CHECK:
215 case CMD_FILE_DATA:
216 case CMD_FILE_FINISH:
217 case CMD_FILE_INIT:
218 case CMD_FILE_BEGIN:
219 case CMD_FILE_MODE:
220 case CMD_DIR_MODE:
221 ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
222 break;
223 // One-way function, so fewer options
224 case CMD_APP_CHECK:
225 case CMD_APP_DATA:
226 case CMD_APP_UNINSTALL:
227 ret = TaskCommandDispatch<HdcDaemonApp>(hTaskInfo, TASK_APP, command, payload, payloadSize);
228 break;
229 case CMD_FORWARD_INIT:
230 case CMD_FORWARD_CHECK:
231 case CMD_FORWARD_ACTIVE_MASTER:
232 case CMD_FORWARD_ACTIVE_SLAVE:
233 case CMD_FORWARD_DATA:
234 case CMD_FORWARD_FREE_CONTEXT:
235 case CMD_FORWARD_CHECK_RESULT:
236 ret = TaskCommandDispatch<HdcDaemonForward>(hTaskInfo, TASK_FORWARD, command, payload, payloadSize);
237 break;
238 default:
239 // ignore unknown command
240 break;
241 }
242 return ret;
243 }
244 // clang-format on
245
246 bool HdcDaemon::ShowPermitDialog()
247 {
248 pid_t pid;
249 int fds[2];
250 pipe(fds);
251
252 if ((pid = fork()) == -1) {
253 WRITE_LOG(LOG_FATAL, "fork failed %s", strerror(errno));
254 return false;
255 }
256 if (pid == 0) {
257 Base::DeInitProcess();
258 // close the child read channel
259 close(fds[0]);
260 // redirect the child write channel
261 dup2(fds[1], STDOUT_FILENO);
262 dup2(fds[1], STDERR_FILENO);
263
264 setsid();
265 setpgid(pid, pid);
266
267 int ret = execl("/system/bin/hdcd_user_permit", "hdcd_user_permit", NULL);
268 // if execl failed need return false
269 WRITE_LOG(LOG_FATAL, "start user_permit failed %d: %s", ret, strerror(errno));
270 return false;
271 } else {
272 Base::CloseFd(fds[1]);
273 waitpid(pid, nullptr, 0);
274 char buf[1024] = { 0 };
275 int nbytes = read(fds[0], buf, sizeof(buf));
276 WRITE_LOG(LOG_FATAL, "user_permit put %d bytes: %s", nbytes, buf);
277 close(fds[0]);
278 }
279
280 return true;
281 }
282
283 UserPermit HdcDaemon::PostUIConfirm(string hostname)
284 {
285 // clear result first
286 if (!SystemDepend::SetDevItem("persist.hdc.daemon.auth_result", "auth_result_none")) {
287 WRITE_LOG(LOG_FATAL, "debug auth result failed, so refuse this connect");
288 return REFUSE;
289 }
290
291 // then write para for setting
292 if (!SystemDepend::SetDevItem("persist.hdc.client.hostname", hostname.c_str())) {
293 WRITE_LOG(LOG_FATAL, "set param(%s) failed", hostname.c_str());
294 return REFUSE;
295 }
296 if (!ShowPermitDialog()) {
297 WRITE_LOG(LOG_FATAL, "show dialog failed, so refuse this connect.");
298 return REFUSE;
299 }
300
301 string authResult;
302 if (!SystemDepend::GetDevItem("persist.hdc.daemon.auth_result", authResult)) {
303 WRITE_LOG(LOG_FATAL, "user refuse [%s] this developer [%s]", authResult.c_str(), hostname.c_str());
304 return REFUSE;
305 }
306 WRITE_LOG(LOG_FATAL, "user permit_result [%s] for this developer [%s]", authResult.c_str(), hostname.c_str());
307 string prifix = "auth_result:";
308 string result = authResult.substr(prifix.length());
309 if (result == "1") {
310 return ALLOWONCE;
311 }
312 if (result == "2") {
313 return ALLOWFORVER;
314 }
315 return REFUSE;
316 }
317
318 bool HdcDaemon::GetHostPubkeyInfo(const string& buf, string& hostname, string& pubkey)
319 {
320 // "\f" asicc is 0x0C
321 char separator = '\x0C';
322
323 hostname = buf.substr(0, buf.find(separator));
324 pubkey = buf.substr(buf.find(separator) + 1);
325 WRITE_LOG(LOG_INFO, "hostname is [%s], pubkey is [%s]", hostname.c_str(), pubkey.c_str());
326
327 return (!hostname.empty() && !pubkey.empty());
328 }
329
330 void HdcDaemon::ClearKnownHosts()
331 {
332 char const *keyfile = "/data/service/el0/hdc/hdc_keys";
333
334 if (!enableSecure || HandDaemonAuthBypass()) {
335 WRITE_LOG(LOG_INFO, "not enable secure, noneed clear keyfile");
336 return;
337 }
338
339 string authcancel;
340 if (!SystemDepend::GetDevItem("persist.hdc.daemon.auth_cancel", authcancel)) {
341 WRITE_LOG(LOG_FATAL, "get param auth_cancel failed");
342 return;
343 }
344 if (authcancel != "true") {
345 WRITE_LOG(LOG_FATAL, "param auth_cancel is not true: %s", authcancel.c_str());
346 return;
347 }
348 if (!SystemDepend::SetDevItem("persist.hdc.daemon.auth_cancel", "false")) {
349 WRITE_LOG(LOG_FATAL, "set param auth_cancel failed");
350 }
351
352 std::ofstream keyofs(keyfile, std::ios::out | std::ios::trunc);
353 if (!keyofs.is_open()) {
354 WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
355 return;
356 }
357
358 keyofs.flush();
359 keyofs.close();
360
361 WRITE_LOG(LOG_FATAL, "clear keyfile %s over", keyfile);
362
363 return;
364 }
365
366 void HdcDaemon::UpdateKnownHosts(const string& key)
367 {
368 char const *keyfile = "/data/service/el0/hdc/hdc_keys";
369
370 std::ofstream keyofs(keyfile, std::ios::app);
371 if (!keyofs.is_open()) {
372 WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
373 return;
374 }
375
376 string keytmp = key + "\n";
377 keyofs.write(keytmp.c_str(), keytmp.length());
378 keyofs.flush();
379 keyofs.close();
380
381 WRITE_LOG(LOG_FATAL, "save new key [%s] into keyfile %s over", key.c_str(), keyfile);
382
383 return;
384 }
385
386 bool HdcDaemon::AlreadyInKnownHosts(const string& key)
387 {
388 char const *keyfile = "/data/service/el0/hdc/hdc_keys";
389
390 std::ifstream keyifs(keyfile);
391 if (!keyifs.is_open()) {
392 WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
393 return false;
394 }
395
396 std::string keys((std::istreambuf_iterator<char>(keyifs)), std::istreambuf_iterator<char>());
397 if (keys.find(key) != string::npos) {
398 keyifs.close();
399 return true;
400 }
401
402 WRITE_LOG(LOG_FATAL, "key [%s] not in keyfile %s", key.c_str(), keyfile);
403
404 keyifs.close();
405 return false;
406 }
407
408 bool HdcDaemon::HandDaemonAuthInit(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
409 {
410 hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH);
411 handshake.authType = AUTH_PUBLICKEY;
412 handshake.buf = hSession->tokenRSA;
413 string bufString = SerialStruct::SerializeToString(handshake);
414 Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
415 reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())),
416 bufString.size());
417
418 InitSessionAuthInfo(hSession->sessionId, hSession->tokenRSA);
419 return true;
420 }
421
422 bool HdcDaemon::HandDaemonAuthPubkey(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
423 {
424 bool ret = false;
425 string hostname, pubkey;
426
427 do {
428 if (!GetHostPubkeyInfo(handshake.buf, hostname, pubkey)) {
429 WRITE_LOG(LOG_FATAL, "get pubkey failed for %u", hSession->sessionId);
430 break;
431 }
432 if (AlreadyInKnownHosts(pubkey)) {
433 ret = true;
434 break;
435 }
436
437 string confirmmsg = "[E000002]:The device unauthorized.\n"\
438 "This server's public key is not set.\n"\
439 "Please check for a confirmation dialog on your device.\n"\
440 "Otherwise try 'hdc kill' if that seems wrong.";
441 std::thread notifymsg(&HdcDaemon::EchoHandshakeMsg, this,
442 std::ref(handshake), channelId, hSession->sessionId, confirmmsg);
443 notifymsg.detach();
444
445 UserPermit permit = PostUIConfirm(hostname);
446 if (permit == ALLOWONCE) {
447 WRITE_LOG(LOG_FATAL, "user allow onece for %u", hSession->sessionId);
448 ret = true;
449 } else if (permit == ALLOWFORVER) {
450 WRITE_LOG(LOG_FATAL, "user allow forever for %u", hSession->sessionId);
451 UpdateKnownHosts(pubkey);
452 ret = true;
453 } else {
454 WRITE_LOG(LOG_FATAL, "user refuse for %u", hSession->sessionId);
455 ret = false;
456 }
457 } while (0);
458
459 if (ret) {
460 SendAuthSignMsg(handshake, channelId, hSession->sessionId, pubkey, hSession->tokenRSA);
461 } else {
462 string notifymsg = "[E000003]:The device unauthorized.\n"\
463 "The user denied the access for the device.\n"\
464 "Please execute 'hdc kill' and redo your command, "\
465 "then check for a confirmation dialog on your device.";
466 EchoHandshakeMsg(handshake, channelId, hSession->sessionId, notifymsg);
467 }
468 return true;
469 }
470
471 bool HdcDaemon::AuthVerify(HSession hSession, string encryptToken)
472 {
473 string token = GetSessionAuthToken(hSession->sessionId);
474 string pubkey = GetSessionAuthPubkey(hSession->sessionId);
475 const unsigned char *pubkeyp = reinterpret_cast<const unsigned char *>(pubkey.c_str());
476 const unsigned char *tokenp = reinterpret_cast<const unsigned char *>(encryptToken.c_str());
477 unsigned char tokenDecode[1024] = { 0 };
478 BIO *bio = nullptr;
479 RSA *rsa = nullptr;
480 bool verifyret = false;
481
482 do {
483 int tbytes = EVP_DecodeBlock(tokenDecode, tokenp, token.length());
484 if (tbytes <= 0) {
485 WRITE_LOG(LOG_FATAL, "base64 decode pubkey failed");
486 break;
487 }
488
489 bio = BIO_new(BIO_s_mem());
490 if (bio == nullptr) {
491 WRITE_LOG(LOG_FATAL, "bio failed for session %u", hSession->sessionId);
492 break;
493 }
494 int wbytes = BIO_write(bio, pubkeyp, pubkey.length());
495 if (wbytes <= 0) {
496 WRITE_LOG(LOG_FATAL, "bio write failed %d for session %u", wbytes, hSession->sessionId);
497 break;
498 }
499 rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr);
500 if (rsa == nullptr) {
501 WRITE_LOG(LOG_FATAL, "rsa failed for session %u", hSession->sessionId);
502 break;
503 }
504 int ret = RSA_verify(NID_sha256, reinterpret_cast<const unsigned char *>(token.c_str()),
505 20, tokenDecode, encryptToken.size(), rsa);
506
507 verifyret = (ret == 1);
508 } while (0);
509
510 if (bio) {
511 BIO_free(bio);
512 }
513 if (rsa) {
514 RSA_free(rsa);
515 }
516
517 if (verifyret) {
518 WRITE_LOG(LOG_FATAL, "auth success for session %u", hSession->sessionId);
519 } else {
520 WRITE_LOG(LOG_FATAL, "auth fail for session %u", hSession->sessionId);
521 }
522 return true;
523 }
524
525 bool HdcDaemon::HandDaemonAuthSignature(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
526 {
527 // When Host is first connected to the device, the signature authentication is inevitable, and the
528 // certificate verification must be triggered.
529 //
530 // When the certificate is verified, the client sends a public key to the device, triggered the system UI
531 // jump out dialog, and click the system, the system will store the Host public key certificate in the
532 // device locally, and the signature authentication will be correct when the subsequent connection is
533 // connected.
534 if (!AuthVerify(hSession, handshake.buf)) {
535 WRITE_LOG(LOG_FATAL, "auth failed for %u", hSession->sessionId);
536 // Next auth
537 EchoHandshakeMsg(handshake, channelId, hSession->sessionId, "[E000010]:Auth failed, cannt login the device.");
538 return false;
539 }
540
541 UpdateSessionAuthOk(hSession->sessionId);
542 SendAuthOkMsg(handshake, channelId, hSession->sessionId);
543 return true;
544 }
545
546 bool HdcDaemon::HandDaemonAuthBypass(void)
547 {
548 // persist.hdc.auth_bypass 1 is bypass orelse(0 or not set) not bypass
549 string authbypass;
550 SystemDepend::GetDevItem("persist.hdc.auth_bypass", authbypass);
551 return Base::Trim(authbypass) == "1";
552 }
553
554 bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
555 {
556 if (!enableSecure) {
557 WRITE_LOG(LOG_INFO, "not enable secure, allow access for %u", hSession->sessionId);
558 UpdateSessionAuthOk(hSession->sessionId);
559 SendAuthOkMsg(handshake, channelId, hSession->sessionId);
560 return true;
561 } else if (HandDaemonAuthBypass()) {
562 WRITE_LOG(LOG_INFO, "auth bypass, allow access for %u", hSession->sessionId);
563 UpdateSessionAuthOk(hSession->sessionId);
564 SendAuthOkMsg(handshake, channelId, hSession->sessionId);
565 return true;
566 } else if (handshake.version < "Ver: 3.0.0b") {
567 WRITE_LOG(LOG_INFO, "session %u client version %s is too low %u authType %d",
568 hSession->sessionId, handshake.version.c_str(), handshake.authType);
569 AuthRejectLowClient(handshake, channelId, hSession->sessionId);
570 return true;
571 } else if (GetSessionAuthStatus(hSession->sessionId) == AUTH_OK) {
572 WRITE_LOG(LOG_INFO, "session %u already auth ok", hSession->sessionId);
573 return true;
574 }
575
576 if (handshake.authType == AUTH_NONE) {
577 return HandDaemonAuthInit(hSession, channelId, handshake);
578 } else if (handshake.authType == AUTH_PUBLICKEY) {
579 return HandDaemonAuthPubkey(hSession, channelId, handshake);
580 } else if (handshake.authType == AUTH_SIGNATURE) {
581 return HandDaemonAuthSignature(hSession, channelId, handshake);
582 } else {
583 WRITE_LOG(LOG_FATAL, "invalid auth state %d for session %u", handshake.authType, hSession->sessionId);
584 return false;
585 }
586 }
587
588 void HdcDaemon::DaemonSessionHandshakeInit(HSession &hSession, SessionHandShake &handshake)
589 {
590 // daemon handshake 1st packet
591 uint32_t unOld = hSession->sessionId;
592 hSession->sessionId = handshake.sessionId;
593 hSession->connectKey = handshake.connectKey;
594 hSession->handshakeOK = false;
595 AdminSession(OP_UPDATE, unOld, hSession);
596 #ifdef HDC_SUPPORT_UART
597 if (hSession->connType == CONN_SERIAL and clsUARTServ!= nullptr) {
598 WRITE_LOG(LOG_DEBUG, " HdcDaemon::DaemonSessionHandshake %s",
599 handshake.ToDebugString().c_str());
600 if (clsUARTServ != nullptr) {
601 (static_cast<HdcDaemonUART *>(clsUARTServ))->OnNewHandshakeOK(hSession->sessionId);
602 }
603 } else
604 #endif // HDC_SUPPORT_UART
605 if (clsUSBServ != nullptr) {
606 (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId);
607 }
608
609 handshake.sessionId = 0;
610 handshake.connectKey = "";
611 }
612
613 bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize)
614 {
615 StartTraceScope("HdcDaemon::DaemonSessionHandshake");
616 // session handshake step2
617 string s = string(reinterpret_cast<char *>(payload), payloadSize);
618 SessionHandShake handshake;
619 string err;
620 SerialStruct::ParseFromString(handshake, s);
621 #ifdef HDC_DEBUG
622 WRITE_LOG(LOG_DEBUG, "session %s try to handshake", hSession->ToDebugString().c_str());
623 #endif
624 // banner to check is parse ok...
625 if (handshake.banner != HANDSHAKE_MESSAGE) {
626 hSession->availTailIndex = 0;
627 WRITE_LOG(LOG_FATAL, "Recv server-hello failed");
628 return false;
629 }
630 if (handshake.authType == AUTH_NONE) {
631 DaemonSessionHandshakeInit(hSession, handshake);
632 }
633 if (!HandDaemonAuth(hSession, channelId, handshake)) {
634 WRITE_LOG(LOG_FATAL, "auth failed");
635 return false;
636 }
637 string version = Base::GetVersion() + HDC_MSG_HASH;
638
639 WRITE_LOG(LOG_DEBUG, "receive hs version = %s", handshake.version.c_str());
640
641 if (!handshake.version.empty() && handshake.version != version) {
642 WRITE_LOG(LOG_FATAL, "DaemonSessionHandshake failed! version not match [%s] vs [%s]",
643 handshake.version.c_str(), version.c_str());
644 #ifdef HDC_CHECK_CHECK
645 hSession->availTailIndex = 0;
646 handshake.banner = HANDSHAKE_FAILED;
647 string failedString = SerialStruct::SerializeToString(handshake);
648 Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)failedString.c_str(),
649 failedString.size());
650 return false;
651 #endif
652 }
653 if (handshake.version.empty()) {
654 handshake.version = Base::GetVersion();
655 WRITE_LOG(LOG_FATAL, "set version if check mode = %s", handshake.version.c_str());
656 }
657 // handshake auth OK.Can append the sending device information to HOST
658 #ifdef HDC_DEBUG
659 WRITE_LOG(LOG_INFO, "session %u handshakeOK send back CMD_KERNEL_HANDSHAKE", hSession->sessionId);
660 #endif
661 hSession->handshakeOK = true;
662 return true;
663 }
664
665 bool HdcDaemon::IsExpectedParam(const string& param, const string& expect)
666 {
667 string out;
668 SystemDepend::GetDevItem(param.c_str(), out);
669 return (out.empty() || out == expect); // default empty
670 }
671
672 bool HdcDaemon::CheckControl(const uint16_t command)
673 {
674 bool ret = false; // default no debug
675 switch (command) { // this switch is match RedirectToTask function
676 case CMD_UNITY_EXECUTE:
677 case CMD_UNITY_REMOUNT:
678 case CMD_UNITY_REBOOT:
679 case CMD_UNITY_RUNMODE:
680 case CMD_UNITY_HILOG:
681 case CMD_UNITY_ROOTRUN:
682 case CMD_UNITY_TERMINATE:
683 case CMD_UNITY_BUGREPORT_INIT:
684 case CMD_JDWP_LIST:
685 case CMD_JDWP_TRACK:
686 case CMD_SHELL_INIT:
687 case CMD_SHELL_DATA: {
688 ret = IsExpectedParam("persist.hdc.control.shell", "true");
689 break;
690 }
691 case CMD_FILE_CHECK:
692 case CMD_FILE_DATA:
693 case CMD_FILE_FINISH:
694 case CMD_FILE_INIT:
695 case CMD_FILE_BEGIN:
696 case CMD_FILE_MODE:
697 case CMD_DIR_MODE:
698 case CMD_APP_CHECK:
699 case CMD_APP_DATA:
700 case CMD_APP_UNINSTALL: {
701 ret = IsExpectedParam("persist.hdc.control.file", "true");
702 break;
703 }
704 case CMD_FORWARD_INIT:
705 case CMD_FORWARD_CHECK:
706 case CMD_FORWARD_ACTIVE_MASTER:
707 case CMD_FORWARD_ACTIVE_SLAVE:
708 case CMD_FORWARD_DATA:
709 case CMD_FORWARD_FREE_CONTEXT:
710 case CMD_FORWARD_CHECK_RESULT: {
711 ret = IsExpectedParam("persist.hdc.control.fport", "true");
712 break;
713 }
714 default:
715 ret = true; // other ECHO_RAW and so on
716 }
717 return ret;
718 }
719
720 bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
721 const int payloadSize)
722 {
723 StartTraceScope("HdcDaemon::FetchCommand");
724 bool ret = true;
725 if (enableSecure && (GetSessionAuthStatus(hSession->sessionId) != AUTH_OK) &&
726 command != CMD_KERNEL_HANDSHAKE && command != CMD_KERNEL_CHANNEL_CLOSE) {
727 string authmsg = GetSessionAuthmsg(hSession->sessionId);
728 WRITE_LOG(LOG_WARN, "session %u auth failed: %s for command %u",
729 hSession->sessionId, authmsg.c_str(), command);
730 if (!authmsg.empty()) {
731 LogMsg(hSession->sessionId, channelId, MSG_FAIL, authmsg.c_str());
732 }
733 uint8_t count = 1;
734 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
735 return true;
736 }
737 if (command != CMD_UNITY_BUGREPORT_DATA &&
738 command != CMD_SHELL_DATA &&
739 command != CMD_FORWARD_DATA &&
740 command != CMD_FILE_DATA &&
741 command != CMD_APP_DATA) {
742 WRITE_LOG(LOG_DEBUG, "FetchCommand channelId:%u command:%u", channelId, command);
743 }
744 switch (command) {
745 case CMD_KERNEL_HANDSHAKE: {
746 // session handshake step2
747 ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize);
748 break;
749 }
750 case CMD_KERNEL_CHANNEL_CLOSE: { // Daemon is only cleaning up the Channel task
751 ClearOwnTasks(hSession, channelId);
752 if (*payload != 0) {
753 --(*payload);
754 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
755 }
756 ret = true;
757 break;
758 }
759 default:
760 ret = true;
761 if (CheckControl(command)) {
762 ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize);
763 } else {
764 LogMsg(hSession->sessionId, channelId, MSG_FAIL, "debugging is not allowed");
765 uint8_t count = 1;
766 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
767 }
768 break;
769 }
770 return ret;
771 }
772
773 bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
774 {
775 bool ret = true;
776
777 if (!hTask->taskClass) {
778 return ret;
779 }
780
781 switch (hTask->taskType) {
782 case TYPE_UNITY:
783 ret = DoTaskRemove<HdcDaemonUnity>(hTask, op);
784 break;
785 case TYPE_SHELL:
786 ret = DoTaskRemove<HdcShell>(hTask, op);
787 break;
788 case TASK_FILE:
789 ret = DoTaskRemove<HdcTransferBase>(hTask, op);
790 break;
791 case TASK_FORWARD:
792 ret = DoTaskRemove<HdcDaemonForward>(hTask, op);
793 break;
794 case TASK_APP:
795 ret = DoTaskRemove<HdcDaemonApp>(hTask, op);
796 break;
797 default:
798 ret = false;
799 break;
800 }
801 return ret;
802 }
803
804 bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
805 uint8_t *bufPtr, const int size)
806 {
807 return Send(sessionId, channelId, command, reinterpret_cast<uint8_t *>(bufPtr), size) > 0;
808 }
809
810 void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO)
811 {
812 uint8_t spcmd = *const_cast<uint8_t *>(buf);
813 if (spcmd == SP_JDWP_NEWFD) {
814 int cnt = sizeof(uint8_t) + sizeof(uint32_t) * 2;
815 if (bytesIO < cnt) {
816 WRITE_LOG(LOG_FATAL, "jdwp newfd data insufficient bytesIO:%d", bytesIO);
817 return;
818 }
819 uint32_t pid = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 1));
820 uint32_t fd = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 5)); // 5 : fd offset
821 ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd);
822 } else if (spcmd == SP_ARK_NEWFD) {
823 // SP_ARK_NEWFD | fd[1] | ark:pid@tid@Debugger
824 int cnt = sizeof(uint8_t) + sizeof(uint32_t);
825 if (bytesIO < cnt) {
826 WRITE_LOG(LOG_FATAL, "ark newfd data insufficient bytesIO:%d", bytesIO);
827 return;
828 }
829 int32_t fd = *reinterpret_cast<int32_t *>(const_cast<uint8_t *>(buf + 1));
830 std::string arkstr = std::string(
831 reinterpret_cast<char *>(const_cast<uint8_t *>(buf + 5)), bytesIO - 5); // 5 : fd offset
832 WRITE_LOG(LOG_DEBUG, "JdwpNewFileDescriptor arkstr:%s fd:%d", arkstr.c_str(), fd);
833 ((HdcJdwp *)clsJdwp)->SendArkNewFD(arkstr, fd);
834 }
835 }
836
837 void HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
838 {
839 if (!freeOrClear) {
840 WRITE_LOG(LOG_WARN, "NotifyInstanceSessionFree freeOrClear false");
841 return; // ignore step 1
842 }
843 if (clsUSBServ != nullptr) {
844 auto clsUsbModule = reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
845 clsUsbModule->OnSessionFreeFinally(hSession);
846 }
847 }
848
849 void HdcDaemon::InitSessionAuthInfo(uint32_t sessionid, string token)
850 {
851 HdcDaemonAuthInfo info = {
852 AUTH_NONE,
853 token
854 };
855 mapAuthStatusMutex.lock();
856 mapAuthStatus[sessionid] = info;
857 mapAuthStatusMutex.unlock();
858 }
859 void HdcDaemon::UpdateSessionAuthOk(uint32_t sessionid)
860 {
861 HdcDaemonAuthInfo info;
862 mapAuthStatusMutex.lock();
863 info = mapAuthStatus[sessionid];
864 info.authtype = AUTH_OK;
865 info.token = "";
866 info.pubkey = "";
867 mapAuthStatus[sessionid] = info;
868 mapAuthStatusMutex.unlock();
869 }
870 void HdcDaemon::UpdateSessionAuthPubkey(uint32_t sessionid, string pubkey)
871 {
872 HdcDaemonAuthInfo info;
873 mapAuthStatusMutex.lock();
874 info = mapAuthStatus[sessionid];
875 info.authtype = AUTH_PUBLICKEY;
876 info.pubkey = pubkey;
877 mapAuthStatus[sessionid] = info;
878 mapAuthStatusMutex.unlock();
879 }
880 void HdcDaemon::UpdateSessionAuthmsg(uint32_t sessionid, string authmsg)
881 {
882 HdcDaemonAuthInfo info;
883 mapAuthStatusMutex.lock();
884 info = mapAuthStatus[sessionid];
885 info.authtype = AUTH_FAIL;
886 info.authmsg = authmsg;
887 mapAuthStatus[sessionid] = info;
888 mapAuthStatusMutex.unlock();
889 }
890 void HdcDaemon::DeleteSessionAuthStatus(uint32_t sessionid)
891 {
892 mapAuthStatusMutex.lock();
893 mapAuthStatus.erase(sessionid);
894 mapAuthStatusMutex.unlock();
895 }
896 HdcSessionBase::AuthType HdcDaemon::GetSessionAuthStatus(uint32_t sessionid)
897 {
898 HdcDaemonAuthInfo info;
899
900 mapAuthStatusMutex.lock();
901 info = mapAuthStatus[sessionid];
902 mapAuthStatusMutex.unlock();
903
904 return info.authtype;
905 }
906 string HdcDaemon::GetSessionAuthToken(uint32_t sessionid)
907 {
908 HdcDaemonAuthInfo info;
909
910 mapAuthStatusMutex.lock();
911 info = mapAuthStatus[sessionid];
912 mapAuthStatusMutex.unlock();
913
914 return info.token;
915 }
916 string HdcDaemon::GetSessionAuthPubkey(uint32_t sessionid)
917 {
918 HdcDaemonAuthInfo info;
919
920 mapAuthStatusMutex.lock();
921 info = mapAuthStatus[sessionid];
922 mapAuthStatusMutex.unlock();
923
924 return info.pubkey;
925 }
926 string HdcDaemon::GetSessionAuthmsg(uint32_t sessionid)
927 {
928 HdcDaemonAuthInfo info;
929
930 mapAuthStatusMutex.lock();
931 info = mapAuthStatus[sessionid];
932 mapAuthStatusMutex.unlock();
933
934 return info.authmsg;
935 }
936 void HdcDaemon::SendAuthOkMsg(SessionHandShake &handshake, uint32_t channelid,
937 uint32_t sessionid, string msg, string daemonAuthResult)
938 {
939 char hostname[BUF_SIZE_MEDIUM] = { 0 };
940 if (gethostname(hostname, BUF_SIZE_MEDIUM) != 0) {
941 WRITE_LOG(LOG_FATAL, "get hostname failed %s", strerror(errno));
942 }
943 if (handshake.version < "Ver: 3.0.0b") {
944 if (msg.empty()) {
945 msg = hostname;
946 }
947 handshake.buf = msg;
948 } else {
949 string emgmsg;
950 Base::TlvAppend(emgmsg, TAG_EMGMSG, msg);
951 Base::TlvAppend(emgmsg, TAG_DEVNAME, hostname);
952 Base::TlvAppend(emgmsg, TAG_DAEOMN_AUTHSTATUS, daemonAuthResult);
953 handshake.buf = emgmsg;
954 }
955
956 handshake.authType = AUTH_OK;
957 string bufString = SerialStruct::SerializeToString(handshake);
958 Send(sessionid, channelid, CMD_KERNEL_HANDSHAKE,
959 reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
960 uint8_t count = 1;
961 Send(sessionid, channelid, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
962 }
963 void HdcDaemon::SendAuthSignMsg(SessionHandShake &handshake,
964 uint32_t channelId, uint32_t sessionid, string pubkey, string token)
965 {
966 UpdateSessionAuthPubkey(sessionid, pubkey);
967 handshake.authType = AUTH_SIGNATURE;
968 handshake.buf = token;
969 string bufString = SerialStruct::SerializeToString(handshake);
970 Send(sessionid, channelId, CMD_KERNEL_HANDSHAKE,
971 reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
972 }
973 void HdcDaemon::EchoHandshakeMsg(SessionHandShake &handshake, uint32_t channelid, uint32_t sessionid, string msg)
974 {
975 SendAuthOkMsg(handshake, channelid, sessionid, msg, DAEOMN_UNAUTHORIZED);
976 LogMsg(sessionid, channelid, MSG_FAIL, msg.c_str());
977 UpdateSessionAuthmsg(sessionid, msg);
978 }
979 void HdcDaemon::AuthRejectLowClient(SessionHandShake &handshake, uint32_t channelid, uint32_t sessionid)
980 {
981 string msg = "[E000001]:The sdk hdc.exe version is too low, please upgrade to the latest version.";
982 EchoHandshakeMsg(handshake, channelid, sessionid, msg);
983 }
984 } // namespace Hdc
985