• 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 "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