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/err.h>
24 #include <openssl/pem.h>
25 #include <fstream>
26 #include <unistd.h>
27 #include <sys/wait.h>
28 
29 namespace Hdc {
30 #ifdef USE_CONFIG_UV_THREADS
HdcDaemon(bool serverOrDaemonIn, size_t uvThreadSize)31 HdcDaemon::HdcDaemon(bool serverOrDaemonIn, size_t uvThreadSize)
32     : HdcSessionBase(serverOrDaemonIn, uvThreadSize)
33 #else
34 HdcDaemon::HdcDaemon(bool serverOrDaemonIn)
35     : HdcSessionBase(serverOrDaemonIn, -1)
36 #endif
37 {
38     clsTCPServ = nullptr;
39     clsUSBServ = nullptr;
40 #ifdef HDC_EMULATOR
41     clsBridgeServ = nullptr;
42 #endif
43 #ifdef HDC_SUPPORT_UART
44     clsUARTServ = nullptr;
45 #endif
46     clsJdwp = nullptr;
47     enableSecure = false;
48 }
49 
~HdcDaemon()50 HdcDaemon::~HdcDaemon()
51 {
52     WRITE_LOG(LOG_DEBUG, "~HdcDaemon");
53 }
54 
ClearInstanceResource()55 void HdcDaemon::ClearInstanceResource()
56 {
57     TryStopInstance();
58     Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon");
59     if (clsTCPServ) {
60         delete (HdcDaemonTCP *)clsTCPServ;
61         clsTCPServ = nullptr;
62     }
63     if (clsUSBServ) {
64         delete (HdcDaemonUSB *)clsUSBServ;
65         clsUSBServ = nullptr;
66     }
67 #ifdef HDC_EMULATOR
68     if (clsBridgeServ) {
69         delete (HdcDaemonBridge *)clsBridgeServ;
70     }
71 #endif
72 #ifdef HDC_SUPPORT_UART
73     if (clsUARTServ) {
74         delete (HdcDaemonUART *)clsUARTServ;
75     }
76     clsUARTServ = nullptr;
77 #endif
78     if (clsJdwp) {
79         delete (HdcJdwp *)clsJdwp;
80         clsJdwp = nullptr;
81     }
82     WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish");
83 }
84 
TryStopInstance()85 void HdcDaemon::TryStopInstance()
86 {
87     ClearSessions();
88     if (clsTCPServ) {
89         WRITE_LOG(LOG_DEBUG, "Stop TCP");
90         ((HdcDaemonTCP *)clsTCPServ)->Stop();
91     }
92     if (clsUSBServ) {
93         WRITE_LOG(LOG_DEBUG, "Stop USB");
94         ((HdcDaemonUSB *)clsUSBServ)->Stop();
95     }
96 #ifdef HDC_EMULATOR
97     if (clsBridgeServ) {
98         WRITE_LOG(LOG_DEBUG, "Stop Bridge");
99         ((HdcDaemonBridge *)clsBridgeServ)->Stop();
100     }
101 #endif
102 #ifdef HDC_SUPPORT_UART
103     if (clsUARTServ) {
104         WRITE_LOG(LOG_DEBUG, "Stop UART");
105         ((HdcDaemonUART *)clsUARTServ)->Stop();
106     }
107 #endif
108     ((HdcJdwp *)clsJdwp)->Stop();
109     // workaround temply remove MainLoop instance clear
110     ReMainLoopForInstanceClear();
111     WRITE_LOG(LOG_DEBUG, "Stop loopmain");
112 }
113 
114 #ifdef HDC_SUPPORT_UART
InitMod(bool bEnableTCP, bool bEnableUSB, [[maybe_unused]] bool bEnableUART)115 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, [[maybe_unused]] bool bEnableUART)
116 #else
117 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB)
118 #endif
119 {
120     WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");
121 #ifdef HDC_SUPPORT_UART
122     WRITE_LOG(LOG_DEBUG, "bEnableTCP:%d,bEnableUSB:%d", bEnableTCP, bEnableUSB);
123 #endif
124     if (bEnableTCP) {
125         // tcp
126         clsTCPServ = new(std::nothrow) HdcDaemonTCP(false, this);
127         if (clsTCPServ == nullptr) {
128             WRITE_LOG(LOG_FATAL, "InitMod new clsTCPServ failed");
129             return;
130         }
131         ((HdcDaemonTCP *)clsTCPServ)->Initial();
132     }
133     if (bEnableUSB) {
134         // usb
135         clsUSBServ = new(std::nothrow) HdcDaemonUSB(false, this);
136         if (clsUSBServ == nullptr) {
137             WRITE_LOG(LOG_FATAL, "InitMod new clsUSBServ failed");
138             return;
139         }
140         ((HdcDaemonUSB *)clsUSBServ)->Initial();
141     }
142 #ifdef HDC_SUPPORT_UART
143     WRITE_LOG(LOG_DEBUG, "bEnableUART:%d", bEnableUART);
144     if (bEnableUART) {
145         // UART
146         clsUARTServ = new(std::nothrow) HdcDaemonUART(*this);
147         if (clsUARTServ == nullptr) {
148             WRITE_LOG(LOG_FATAL, "InitMod new clsUARTServ failed");
149             return;
150         }
151         ((HdcDaemonUART *)clsUARTServ)->Initial();
152     }
153 #endif
154     clsJdwp = new(std::nothrow) HdcJdwp(&loopMain);
155     if (clsJdwp == nullptr) {
156         WRITE_LOG(LOG_FATAL, "InitMod new clsJdwp failed");
157         return;
158     }
159     ((HdcJdwp *)clsJdwp)->Initial();
160     // enable security
161     string secure;
162     SystemDepend::GetDevItem("const.hdc.secure", secure);
163     string authbypass;
164     SystemDepend::GetDevItem("persist.hdc.auth_bypass", authbypass);
165 #ifndef HDC_EMULATOR
166     enableSecure = ((Base::Trim(secure) == "1") && (Base::Trim(authbypass) != "1"));
167 #endif
168 }
169 
170 #ifdef HDC_EMULATOR
171 #ifdef HDC_SUPPORT_UART
InitMod(bool bEnableTCP, bool bEnableUSB, bool bEnableBridge, [[maybe_unused]] bool bEnableUART)172 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, bool bEnableBridge, [[maybe_unused]] bool bEnableUART)
173 {
174     InitMod(bEnableTCP, bEnableUSB, bEnableUART);
175 #else
176 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB, bool bEnableBridge)
177 {
178     InitMod(bEnableTCP, bEnableUSB);
179 #endif
180     if (bEnableBridge) {
181         clsBridgeServ = new(std::nothrow) HdcDaemonBridge(false, this);
182         if (clsBridgeServ == nullptr) {
183             WRITE_LOG(LOG_FATAL, "InitMod new clsBridgeServ failed");
184             return;
185         }
186         ((HdcDaemonBridge *)clsBridgeServ)->Initial();
187     }
188 }
189 #endif
190 
191 // clang-format off
192 bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
193                                const uint16_t command, uint8_t *payload, const int payloadSize)
194 {
195     StartTraceScope("HdcDaemon::RedirectToTask");
196     bool ret = true;
197     hTaskInfo->ownerSessionClass = this;
198     switch (command) {
199         case CMD_UNITY_EXECUTE:
200         case CMD_UNITY_REMOUNT:
201         case CMD_UNITY_REBOOT:
202         case CMD_UNITY_RUNMODE:
203         case CMD_UNITY_HILOG:
204         case CMD_UNITY_ROOTRUN:
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) - 1);
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, string pubkey)
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 
297     uint8_t sha256Result[SHA256_DIGEST_LENGTH] = { 0 };
298     if (SHA256(reinterpret_cast<const uint8_t *>(pubkey.c_str()), pubkey.length(), sha256Result) == nullptr) {
299         WRITE_LOG(LOG_FATAL, "sha256 pubkey failed");
300         return REFUSE;
301     }
302 
303     string hex = Base::Convert2HexStr(sha256Result, SHA256_DIGEST_LENGTH);
304     if (!SystemDepend::SetDevItem("persist.hdc.client.pubkey_sha256", hex.c_str())) {
305         WRITE_LOG(LOG_DEBUG, "Failed to set pubkey prop.");
306         return REFUSE;
307     }
308 
309     if (!ShowPermitDialog()) {
310         WRITE_LOG(LOG_FATAL, "show dialog failed, so refuse this connect.");
311         return REFUSE;
312     }
313 
314     string authResult;
315     if (!SystemDepend::GetDevItem("persist.hdc.daemon.auth_result", authResult)) {
316         WRITE_LOG(LOG_FATAL, "user refuse [%s] this developer [%s]", authResult.c_str(), hostname.c_str());
317         return REFUSE;
318     }
319     WRITE_LOG(LOG_FATAL, "user permit_result [%s] for this developer [%s]", authResult.c_str(), hostname.c_str());
320     string prifix = "auth_result:";
321     string result = authResult.substr(prifix.length());
322     if (result == "1") {
323         return ALLOWONCE;
324     }
325     if (result == "2") {
326         return ALLOWFORVER;
327     }
328     return REFUSE;
329 }
330 
331 bool HdcDaemon::GetHostPubkeyInfo(const string& buf, string& hostname, string& pubkey)
332 {
333     // "\f" asicc is 0x0C
334     char separator = '\x0C';
335 
336     hostname = buf.substr(0, buf.find(separator));
337     pubkey = buf.substr(buf.find(separator) + 1);
338     WRITE_LOG(LOG_INFO, "hostname is [%s], pubkey is [%s]", hostname.c_str(),
339         pubkey.substr(0, pubkey.size() / 2).c_str());
340 
341     return (!hostname.empty() && !pubkey.empty());
342 }
343 
344 void HdcDaemon::ClearKnownHosts()
345 {
346     char const *keyfile = "/data/service/el1/public/hdc/hdc_keys";
347 
348     if (!enableSecure || HandDaemonAuthBypass()) {
349         WRITE_LOG(LOG_INFO, "not enable secure, noneed clear keyfile");
350         return;
351     }
352 
353     string authcancel;
354     if (!SystemDepend::GetDevItem("persist.hdc.daemon.auth_cancel", authcancel)) {
355         WRITE_LOG(LOG_FATAL, "get param auth_cancel failed");
356         return;
357     }
358     if (authcancel != "true") {
359         WRITE_LOG(LOG_FATAL, "param auth_cancel is not true: %s", authcancel.c_str());
360         return;
361     }
362     if (!SystemDepend::SetDevItem("persist.hdc.daemon.auth_cancel", "false")) {
363         WRITE_LOG(LOG_FATAL, "set param auth_cancel failed");
364     }
365 
366     std::ofstream keyofs(keyfile, std::ios::out | std::ios::trunc);
367     if (!keyofs.is_open()) {
368         WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
369         return;
370     }
371 
372     keyofs.flush();
373     keyofs.close();
374 
375     WRITE_LOG(LOG_FATAL, "clear keyfile %s over", keyfile);
376 
377     return;
378 }
379 
380 void HdcDaemon::UpdateKnownHosts(const string& key)
381 {
382     char const *keyfile = "/data/service/el1/public/hdc/hdc_keys";
383 
384     std::ofstream keyofs(keyfile, std::ios::app);
385     if (!keyofs.is_open()) {
386         WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
387         return;
388     }
389 
390     string keytmp = key + "\n";
391     keyofs.write(keytmp.c_str(), keytmp.length());
392     keyofs.flush();
393     keyofs.close();
394 
395     WRITE_LOG(LOG_FATAL, "save new key [%s] into keyfile %s over", key.substr(0, key.size() / 2).c_str(), keyfile);
396 
397     return;
398 }
399 
400 bool HdcDaemon::AlreadyInKnownHosts(const string& key)
401 {
402     char const *keyfile = "/data/service/el1/public/hdc/hdc_keys";
403 
404     std::ifstream keyifs(keyfile);
405     if (!keyifs.is_open()) {
406         WRITE_LOG(LOG_FATAL, "open keyfile %s error", keyfile);
407         return false;
408     }
409 
410     std::string keys((std::istreambuf_iterator<char>(keyifs)), std::istreambuf_iterator<char>());
411     if (keys.find(key) != string::npos) {
412         keyifs.close();
413         return true;
414     }
415 
416     WRITE_LOG(LOG_FATAL, "key [%s] not in keyfile %s", key.substr(0, key.size() / 2).c_str(), keyfile);
417 
418     keyifs.close();
419     return false;
420 }
421 
422 bool HdcDaemon::HandDaemonAuthInit(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
423 {
424     hSession->tokenRSA = Base::GetSecureRandomString(SHA_DIGEST_LENGTH);
425     handshake.authType = AUTH_PUBLICKEY;
426     /*
427      * If we know client support RSA_3072_SHA512 in AUTH_NONE phase
428      * Then told client that the server also support RSA_3072_SHA512 auth
429      * Notice, before here is "handshake.buf = hSession->tokenRSA", but the server not use it
430     */
431     if (hSession->verifyType == AuthVerifyType::RSA_3072_SHA512) {
432         handshake.buf.clear();
433         Base::TlvAppend(handshake.buf, TAG_AUTH_TYPE, std::to_string(AuthVerifyType::RSA_3072_SHA512));
434         WRITE_LOG(LOG_INFO, "client support RSA_3072_SHA512 auth for %u session", hSession->sessionId);
435     }
436     string bufString = SerialStruct::SerializeToString(handshake);
437     Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
438             reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())),
439             bufString.size());
440 
441     InitSessionAuthInfo(hSession->sessionId, hSession->tokenRSA);
442     return true;
443 }
444 
445 bool HdcDaemon::HandDaemonAuthPubkey(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
446 {
447     bool ret = false;
448     string hostname, pubkey;
449 
450     do {
451         if (!GetHostPubkeyInfo(handshake.buf, hostname, pubkey)) {
452             WRITE_LOG(LOG_FATAL, "get pubkey failed for %u", hSession->sessionId);
453             break;
454         }
455         if (AlreadyInKnownHosts(pubkey)) {
456             ret = true;
457             break;
458         }
459 
460         string confirmmsg = "[E000002]:The device unauthorized.\r\n"\
461                              "This server's public key is not set.\r\n"\
462                              "Please check for a confirmation dialog on your device.\r\n"\
463                              "Otherwise try 'hdc kill' if that seems wrong.";
464         std::thread notifymsg([this, &handshake, channelId, sessionId = hSession->sessionId, &confirmmsg]() {
465             this->EchoHandshakeMsg(handshake, channelId, sessionId, confirmmsg);
466         });
467         notifymsg.detach();
468 
469         UserPermit permit = PostUIConfirm(hostname, pubkey);
470         if (permit == ALLOWONCE) {
471             WRITE_LOG(LOG_FATAL, "user allow onece for %u", hSession->sessionId);
472             ret = true;
473         } else if (permit == ALLOWFORVER) {
474             WRITE_LOG(LOG_FATAL, "user allow forever for %u", hSession->sessionId);
475             UpdateKnownHosts(pubkey);
476             ret = true;
477         } else {
478             WRITE_LOG(LOG_FATAL, "user refuse for %u", hSession->sessionId);
479             ret = false;
480         }
481     } while (0);
482 
483     if (ret) {
484         SendAuthSignMsg(handshake, channelId, hSession->sessionId, pubkey, hSession->tokenRSA);
485     } else {
486         string notifymsg = "[E000003]:The device unauthorized.\r\n"\
487                             "The user denied the access for the device.\r\n"\
488                              "Please execute 'hdc kill' and redo your command,\r\n"\
489                              "then check for a confirmation dialog on your device.";
490         EchoHandshakeMsg(handshake, channelId, hSession->sessionId, notifymsg);
491     }
492     return true;
493 }
494 
495 /*
496  * tokenSignBase64 is Base64 encode of the signing from server
497  * token is the source data same of server for signing
498  */
499 bool HdcDaemon::RsaSignVerify(HSession hSession, EVP_PKEY_CTX *ctx, const string &tokenSignBase64, const string &token)
500 {
501     unsigned char tokenSha512[SHA512_DIGEST_LENGTH];
502     try {
503         std::unique_ptr<unsigned char[]> tokenRsaSign = std::make_unique<unsigned char[]>(tokenSignBase64.length());
504         // Get the real token sign
505         int tokenRsaSignLen = EVP_DecodeBlock(tokenRsaSign.get(),
506             reinterpret_cast<const unsigned char *>(tokenSignBase64.c_str()), tokenSignBase64.length());
507         if (tokenRsaSignLen <= 0) {
508             WRITE_LOG(LOG_FATAL, "base64 decode token sign failed for session %u", hSession->sessionId);
509             return false;
510         }
511         SHA512(reinterpret_cast<const unsigned char *>(token.c_str()), token.size(), tokenSha512);
512         if (EVP_PKEY_verify(ctx, tokenRsaSign.get(), tokenRsaSignLen, tokenSha512, sizeof(tokenSha512)) < 0) {
513             WRITE_LOG(LOG_FATAL, "verify failed for session %u", hSession->sessionId);
514             return false;
515         }
516     } catch (std::exception &e) {
517         WRITE_LOG(LOG_FATAL, "sign verify failed for session %u with exception %s", hSession->sessionId, e.what());
518         return false;
519     }
520 
521     WRITE_LOG(LOG_FATAL, "sign verify success for session %u", hSession->sessionId);
522     return true;
523 }
524 
525 bool HdcDaemon::AuthVerifyRsaSign(HSession hSession, const string &tokenSign, const string &token, RSA *rsa)
526 {
527     EVP_PKEY *signKey = nullptr;
528     EVP_PKEY_CTX *ctx = nullptr;
529     bool signRet = false;
530 
531     signKey = EVP_PKEY_new();
532     if (signKey == nullptr) {
533         WRITE_LOG(LOG_FATAL, "EVP_PKEY_new failed");
534         return false;
535     }
536     do {
537         if (EVP_PKEY_set1_RSA(signKey, rsa) <= 0) {
538             WRITE_LOG(LOG_FATAL, "EVP_PKEY_new failed");
539             break;
540         }
541         // the length of vaild sign result for BASE64 can't bigger than  EVP_PKEY_size(signKey) * 2
542         if (tokenSign.size() > ((size_t)EVP_PKEY_size(signKey) * (size_t)2)) {
543             WRITE_LOG(LOG_FATAL, "invalid base64 sign size %zd for session %u", tokenSign.size(), hSession->sessionId);
544             break;
545         }
546         ctx = EVP_PKEY_CTX_new(signKey, nullptr);
547         if (ctx == nullptr) {
548             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
549             break;
550         }
551         if (EVP_PKEY_verify_init(ctx) <= 0) {
552             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_new failed");
553             break;
554         }
555         if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
556             EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_AUTO) <= 0) {
557             WRITE_LOG(LOG_FATAL, "set saltlen or padding failed");
558             break;
559         }
560         if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha512()) <= 0) {
561             WRITE_LOG(LOG_FATAL, "EVP_PKEY_CTX_set_signature_md failed");
562             break;
563         }
564         signRet = RsaSignVerify(hSession, ctx, tokenSign, token);
565     } while (0);
566 
567     if (ctx != nullptr) {
568         EVP_PKEY_CTX_free(ctx);
569     }
570     if (signKey != nullptr) {
571         EVP_PKEY_free(signKey);
572     }
573     return signRet;
574 }
575 
576 bool HdcDaemon::AuthVerify(HSession hSession, const string &encryptToken, const string &token, const string &pubkey)
577 {
578     BIO *bio = nullptr;
579     RSA *rsa = nullptr;
580     const unsigned char *pubkeyp = reinterpret_cast<const unsigned char *>(pubkey.c_str());
581     bool verifyResult = false;
582 
583     do {
584         bio = BIO_new(BIO_s_mem());
585         if (bio == nullptr) {
586             WRITE_LOG(LOG_FATAL, "bio failed for session %u", hSession->sessionId);
587             break;
588         }
589         int wbytes = BIO_write(bio, pubkeyp, pubkey.length());
590         if (wbytes <= 0) {
591             WRITE_LOG(LOG_FATAL, "bio write failed %d for session %u", wbytes, hSession->sessionId);
592             break;
593         }
594         rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr);
595         if (rsa == nullptr) {
596             WRITE_LOG(LOG_FATAL, "rsa failed for session %u", hSession->sessionId);
597             break;
598         }
599         if (hSession->verifyType == AuthVerifyType::RSA_3072_SHA512) {
600             verifyResult = AuthVerifyRsaSign(hSession, encryptToken, token, rsa);
601         } else {
602             verifyResult = AuthVerifyRsa(hSession, encryptToken, token, rsa);
603         }
604     } while (0);
605 
606     if (bio) {
607         BIO_free(bio);
608     }
609     if (rsa) {
610         RSA_free(rsa);
611     }
612 
613     return verifyResult;
614 }
615 
616 bool HdcDaemon::AuthVerifyRsa(HSession hSession, const string &encryptToken, const string &token, RSA *rsa)
617 {
618     const unsigned char *tokenp = reinterpret_cast<const unsigned char *>(encryptToken.c_str());
619     unsigned char tokenDecode[BUF_SIZE_DEFAULT] = { 0 };
620     unsigned char decryptToken[BUF_SIZE_DEFAULT] = { 0 };
621 
622     // for rsa encrypt, the length of encryptToken can't bigger than BUF_SIZE_DEFAULT
623     if (encryptToken.length() > BUF_SIZE_DEFAULT2) {
624         WRITE_LOG(LOG_FATAL, "invalid encryptToken, length is %zd", encryptToken.length());
625         return false;
626     }
627     int tbytes = EVP_DecodeBlock(tokenDecode, tokenp, encryptToken.length());
628     if (tbytes <= 0) {
629         WRITE_LOG(LOG_FATAL, "base64 decode pubkey failed");
630         return false;
631     }
632     int bytes = RSA_public_decrypt(tbytes, tokenDecode, decryptToken, rsa, RSA_PKCS1_PADDING);
633     if (bytes < 0) {
634         WRITE_LOG(LOG_FATAL, "decrypt failed(%lu) for session %u", ERR_get_error(), hSession->sessionId);
635         return false;
636     }
637     string sdecryptToken(reinterpret_cast<const char *>(decryptToken), bytes);
638     if (sdecryptToken != token) {
639         WRITE_LOG(LOG_FATAL, "auth failed for session %u)", hSession->sessionId);
640         return false;
641     }
642     return true;
643 }
644 
645 bool HdcDaemon::HandDaemonAuthSignature(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
646 {
647     // When Host is first connected to the device, the signature authentication is inevitable, and the
648     // certificate verification must be triggered.
649     //
650     // When the certificate is verified, the client sends a public key to the device, triggered the system UI
651     // jump out dialog, and click the system, the system will store the Host public key certificate in the
652     // device locally, and the signature authentication will be correct when the subsequent connection is
653     // connected.
654     string token = GetSessionAuthToken(hSession->sessionId);
655     string pubkey = GetSessionAuthPubkey(hSession->sessionId);
656     if (!AuthVerify(hSession, handshake.buf, token, pubkey)) {
657         WRITE_LOG(LOG_FATAL, "auth failed for session %u", hSession->sessionId);
658         // Next auth
659         EchoHandshakeMsg(handshake, channelId, hSession->sessionId, "[E000010]:Auth failed, cannt login the device.");
660         return true;
661     }
662 
663     WRITE_LOG(LOG_FATAL, "auth success for session %u", hSession->sessionId);
664 
665     UpdateSessionAuthOk(hSession->sessionId);
666     SendAuthOkMsg(handshake, channelId, hSession->sessionId);
667     return true;
668 }
669 
670 bool HdcDaemon::HandDaemonAuthBypass(void)
671 {
672     // persist.hdc.auth_bypass 1 is bypass orelse(0 or not set) not bypass
673     string authbypass;
674     SystemDepend::GetDevItem("persist.hdc.auth_bypass", authbypass);
675     return Base::Trim(authbypass) == "1";
676 }
677 
678 bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
679 {
680     if (!enableSecure) {
681         WRITE_LOG(LOG_INFO, "not enable secure, allow access for %u", hSession->sessionId);
682         UpdateSessionAuthOk(hSession->sessionId);
683         SendAuthOkMsg(handshake, channelId, hSession->sessionId);
684         return true;
685     } else if (HandDaemonAuthBypass()) {
686         WRITE_LOG(LOG_INFO, "auth bypass, allow access for %u", hSession->sessionId);
687         UpdateSessionAuthOk(hSession->sessionId);
688         SendAuthOkMsg(handshake, channelId, hSession->sessionId);
689         return true;
690     } else if (handshake.version < "Ver: 3.0.0b") {
691         WRITE_LOG(LOG_INFO, "session %u client version %s is too low %u authType %d",
692                     hSession->sessionId, handshake.version.c_str(), handshake.authType);
693         AuthRejectLowClient(handshake, channelId, hSession->sessionId);
694         return true;
695     } else if (GetSessionAuthStatus(hSession->sessionId) == AUTH_OK) {
696         WRITE_LOG(LOG_INFO, "session %u already auth ok", hSession->sessionId);
697         return true;
698     }
699 
700     if (handshake.authType == AUTH_NONE) {
701         return HandDaemonAuthInit(hSession, channelId, handshake);
702     } else if (handshake.authType == AUTH_PUBLICKEY) {
703         return HandDaemonAuthPubkey(hSession, channelId, handshake);
704     } else if (handshake.authType == AUTH_SIGNATURE) {
705         return HandDaemonAuthSignature(hSession, channelId, handshake);
706     } else {
707         WRITE_LOG(LOG_FATAL, "invalid auth state %d for session %u", handshake.authType, hSession->sessionId);
708         return false;
709     }
710 }
711 
712 /*
713  * For daemon, if server add new capability, we can parse it here
714  */
715 void HdcDaemon::GetServerCapability(HSession &hSession, SessionHandShake &handshake)
716 {
717     /*
718      * Check if server support RSA_3072_SHA512 for auth
719      * if the value not contain RSA_3072_SHA512, We treat it not support
720     */
721     std::map<string, string> tlvMap;
722     hSession->verifyType = AuthVerifyType::RSA_ENCRYPT;
723     if (!Base::TlvToStringMap(handshake.buf, tlvMap)) {
724         WRITE_LOG(LOG_INFO, "maybe old version client for %u session", hSession->sessionId);
725         return;
726     }
727     if (tlvMap.find(TAG_AUTH_TYPE) != tlvMap.end() &&
728         tlvMap[TAG_AUTH_TYPE] == std::to_string(AuthVerifyType::RSA_3072_SHA512)) {
729         hSession->verifyType = AuthVerifyType::RSA_3072_SHA512;
730     }
731     WRITE_LOG(LOG_INFO, "client auth type is %u for %u session", hSession->verifyType, hSession->sessionId);
732 }
733 
734 void HdcDaemon::DaemonSessionHandshakeInit(HSession &hSession, SessionHandShake &handshake)
735 {
736     // daemon handshake 1st packet
737     uint32_t unOld = hSession->sessionId;
738     hSession->sessionId = handshake.sessionId;
739     hSession->connectKey = handshake.connectKey;
740     hSession->handshakeOK = false;
741     AdminSession(OP_UPDATE, unOld, hSession);
742 #ifdef HDC_SUPPORT_UART
743     if (hSession->connType == CONN_SERIAL and clsUARTServ!= nullptr) {
744         WRITE_LOG(LOG_DEBUG, " HdcDaemon::DaemonSessionHandshake %s",
745                     handshake.ToDebugString().c_str());
746         if (clsUARTServ != nullptr) {
747             (static_cast<HdcDaemonUART *>(clsUARTServ))->OnNewHandshakeOK(hSession->sessionId);
748         }
749     } else
750 #endif // HDC_SUPPORT_UART
751     if (clsUSBServ != nullptr && hSession->connType == CONN_USB) {
752         (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId);
753     }
754 
755     handshake.sessionId = 0;
756     handshake.connectKey = "";
757     // Get server capability
758     GetServerCapability(hSession, handshake);
759 }
760 
761 bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize)
762 {
763     StartTraceScope("HdcDaemon::DaemonSessionHandshake");
764     // session handshake step2
765     string s = string(reinterpret_cast<char *>(payload), payloadSize);
766     SessionHandShake handshake;
767     string err;
768     SerialStruct::ParseFromString(handshake, s);
769 #ifdef HDC_DEBUG
770     WRITE_LOG(LOG_DEBUG, "session %s try to handshake", hSession->ToDebugString().c_str());
771 #endif
772     // banner to check is parse ok...
773     if (handshake.banner != HANDSHAKE_MESSAGE) {
774         hSession->availTailIndex = 0;
775         WRITE_LOG(LOG_FATAL, "Recv server-hello failed");
776         return false;
777     }
778     if (handshake.authType == AUTH_NONE) {
779         DaemonSessionHandshakeInit(hSession, handshake);
780     }
781     if (!HandDaemonAuth(hSession, channelId, handshake)) {
782         WRITE_LOG(LOG_FATAL, "auth failed");
783         return false;
784     }
785     string version = Base::GetVersion() + HDC_MSG_HASH;
786 
787     WRITE_LOG(LOG_DEBUG, "receive hs version = %s", handshake.version.c_str());
788 
789     if (!handshake.version.empty() && handshake.version != version) {
790         WRITE_LOG(LOG_FATAL, "DaemonSessionHandshake failed! version not match [%s] vs [%s]",
791             handshake.version.c_str(), version.c_str());
792 #ifdef HDC_CHECK_CHECK
793         hSession->availTailIndex = 0;
794         handshake.banner = HANDSHAKE_FAILED;
795         string failedString = SerialStruct::SerializeToString(handshake);
796         Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)failedString.c_str(),
797              failedString.size());
798         return false;
799 #endif
800     }
801     if (handshake.version.empty()) {
802         handshake.version = Base::GetVersion();
803         WRITE_LOG(LOG_FATAL, "set version if check mode = %s", handshake.version.c_str());
804     }
805     // handshake auth OK.Can append the sending device information to HOST
806 #ifdef HDC_DEBUG
807     WRITE_LOG(LOG_INFO, "session %u handshakeOK send back CMD_KERNEL_HANDSHAKE", hSession->sessionId);
808 #endif
809     hSession->handshakeOK = true;
810     return true;
811 }
812 
813 bool HdcDaemon::IsExpectedParam(const string& param, const string& expect)
814 {
815     string out;
816     SystemDepend::GetDevItem(param.c_str(), out);
817     return (out.empty() || out == expect); // default empty
818 }
819 
820 bool HdcDaemon::CheckControl(const uint16_t command)
821 {
822     bool ret = false; // default no debug
823     switch (command) { // this switch is match RedirectToTask function
824         case CMD_UNITY_EXECUTE:
825         case CMD_UNITY_REMOUNT:
826         case CMD_UNITY_REBOOT:
827         case CMD_UNITY_RUNMODE:
828         case CMD_UNITY_HILOG:
829         case CMD_UNITY_ROOTRUN:
830         case CMD_UNITY_BUGREPORT_INIT:
831         case CMD_JDWP_LIST:
832         case CMD_JDWP_TRACK:
833         case CMD_SHELL_INIT:
834         case CMD_SHELL_DATA: {
835             ret = IsExpectedParam("persist.hdc.control.shell", "true");
836             break;
837         }
838         case CMD_FILE_CHECK:
839         case CMD_FILE_DATA:
840         case CMD_FILE_FINISH:
841         case CMD_FILE_INIT:
842         case CMD_FILE_BEGIN:
843         case CMD_FILE_MODE:
844         case CMD_DIR_MODE:
845         case CMD_APP_CHECK:
846         case CMD_APP_DATA:
847         case CMD_APP_UNINSTALL: {
848             ret = IsExpectedParam("persist.hdc.control.file", "true");
849             break;
850         }
851         case CMD_FORWARD_INIT:
852         case CMD_FORWARD_CHECK:
853         case CMD_FORWARD_ACTIVE_MASTER:
854         case CMD_FORWARD_ACTIVE_SLAVE:
855         case CMD_FORWARD_DATA:
856         case CMD_FORWARD_FREE_CONTEXT:
857         case CMD_FORWARD_CHECK_RESULT: {
858             ret = IsExpectedParam("persist.hdc.control.fport", "true");
859             break;
860         }
861         default:
862             ret = true; // other ECHO_RAW and so on
863     }
864     return ret;
865 }
866 
867 bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
868                              const int payloadSize)
869 {
870     StartTraceScope("HdcDaemon::FetchCommand");
871     bool ret = true;
872     if (enableSecure && (GetSessionAuthStatus(hSession->sessionId) != AUTH_OK) &&
873         command != CMD_KERNEL_HANDSHAKE && command != CMD_KERNEL_CHANNEL_CLOSE) {
874         string authmsg = GetSessionAuthmsg(hSession->sessionId);
875         WRITE_LOG(LOG_WARN, "session %u auth failed: %s for command %u",
876                   hSession->sessionId, authmsg.c_str(), command);
877         if (!authmsg.empty()) {
878             LogMsg(hSession->sessionId, channelId, MSG_FAIL, authmsg.c_str());
879         }
880         uint8_t count = 1;
881         Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
882         return true;
883     }
884     if (command != CMD_UNITY_BUGREPORT_DATA &&
885         command != CMD_SHELL_DATA &&
886         command != CMD_FORWARD_DATA &&
887         command != CMD_FILE_DATA &&
888         command != CMD_APP_DATA) {
889         WRITE_LOG(LOG_DEBUG, "FetchCommand channelId:%u command:%u", channelId, command);
890     }
891     switch (command) {
892         case CMD_KERNEL_HANDSHAKE: {
893             // session handshake step2
894             ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize);
895             break;
896         }
897         case CMD_KERNEL_CHANNEL_CLOSE: {  // Daemon is only cleaning up the Channel task
898             ClearOwnTasks(hSession, channelId);
899             if (*payload != 0) {
900                 --(*payload);
901                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
902             }
903             ret = true;
904             break;
905         }
906         default:
907             ret = true;
908             if (CheckControl(command)) {
909                 ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize);
910             } else {
911                 LogMsg(hSession->sessionId, channelId, MSG_FAIL, "debugging is not allowed");
912                 uint8_t count = 1;
913                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
914             }
915             break;
916     }
917     return ret;
918 }
919 
920 bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
921 {
922     bool ret = true;
923 
924     if (!hTask->taskClass) {
925         WRITE_LOG(LOG_FATAL, "RemoveInstanceTask taskClass is null channelId:%u", hTask->channelId);
926         return ret;
927     }
928 
929     switch (hTask->taskType) {
930         case TYPE_UNITY:
931             ret = DoTaskRemove<HdcDaemonUnity>(hTask, op);
932             break;
933         case TYPE_SHELL:
934             ret = DoTaskRemove<HdcShell>(hTask, op);
935             break;
936         case TASK_FILE:
937             ret = DoTaskRemove<HdcTransferBase>(hTask, op);
938             break;
939         case TASK_FORWARD:
940             ret = DoTaskRemove<HdcDaemonForward>(hTask, op);
941             break;
942         case TASK_APP:
943             ret = DoTaskRemove<HdcDaemonApp>(hTask, op);
944             break;
945         default:
946             ret = false;
947             break;
948     }
949     return ret;
950 }
951 
952 bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
953                               uint8_t *bufPtr, const int size)
954 {
955     return Send(sessionId, channelId, command, reinterpret_cast<uint8_t *>(bufPtr), size) > 0;
956 }
957 
958 void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO)
959 {
960     uint8_t spcmd = *const_cast<uint8_t *>(buf);
961     if (spcmd == SP_JDWP_NEWFD) {
962         int cnt = sizeof(uint8_t) + sizeof(uint32_t) * 2;
963         if (bytesIO < cnt) {
964             WRITE_LOG(LOG_FATAL, "jdwp newfd data insufficient bytesIO:%d", bytesIO);
965             return;
966         }
967         uint32_t pid = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 1));
968         uint32_t fd = *reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 5));  // 5 : fd offset
969         ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd);
970     } else if (spcmd == SP_ARK_NEWFD) {
971         // SP_ARK_NEWFD | fd[1] | ark:pid@tid@Debugger
972         int cnt = sizeof(uint8_t) + sizeof(uint32_t);
973         if (bytesIO < cnt) {
974             WRITE_LOG(LOG_FATAL, "ark newfd data insufficient bytesIO:%d", bytesIO);
975             return;
976         }
977         int32_t fd = *reinterpret_cast<int32_t *>(const_cast<uint8_t *>(buf + 1));
978         std::string arkstr = std::string(
979             reinterpret_cast<char *>(const_cast<uint8_t *>(buf + 5)), bytesIO - 5);  // 5 : fd offset
980         WRITE_LOG(LOG_DEBUG, "JdwpNewFileDescriptor arkstr:%s fd:%d", arkstr.c_str(), fd);
981         ((HdcJdwp *)clsJdwp)->SendArkNewFD(arkstr, fd);
982     }
983 }
984 
985 void HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
986 {
987     if (!freeOrClear) {
988         WRITE_LOG(LOG_WARN, "NotifyInstanceSessionFree freeOrClear false");
989         return;  // ignore step 1
990     }
991     if (clsUSBServ != nullptr) {
992         auto clsUsbModule = reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
993         clsUsbModule->OnSessionFreeFinally(hSession);
994     }
995 }
996 
997 void HdcDaemon::InitSessionAuthInfo(uint32_t sessionid, string token)
998 {
999     HdcDaemonAuthInfo info = {
1000         AUTH_NONE,
1001         token,
1002         "",
1003         ""
1004     };
1005     mapAuthStatusMutex.lock();
1006     mapAuthStatus[sessionid] = info;
1007     mapAuthStatusMutex.unlock();
1008 }
1009 void HdcDaemon::UpdateSessionAuthOk(uint32_t sessionid)
1010 {
1011     HdcDaemonAuthInfo info;
1012     mapAuthStatusMutex.lock();
1013     info = mapAuthStatus[sessionid];
1014     info.authtype = AUTH_OK;
1015     info.token = "";
1016     info.pubkey = "";
1017     mapAuthStatus[sessionid] = info;
1018     mapAuthStatusMutex.unlock();
1019 }
1020 void HdcDaemon::UpdateSessionAuthPubkey(uint32_t sessionid, string pubkey)
1021 {
1022     HdcDaemonAuthInfo info;
1023     mapAuthStatusMutex.lock();
1024     info = mapAuthStatus[sessionid];
1025     info.authtype = AUTH_PUBLICKEY;
1026     info.pubkey = pubkey;
1027     mapAuthStatus[sessionid] = info;
1028     mapAuthStatusMutex.unlock();
1029 }
1030 void HdcDaemon::UpdateSessionAuthmsg(uint32_t sessionid, string authmsg)
1031 {
1032     HdcDaemonAuthInfo info;
1033     mapAuthStatusMutex.lock();
1034     info = mapAuthStatus[sessionid];
1035     info.authtype = AUTH_FAIL;
1036     info.authmsg = authmsg;
1037     mapAuthStatus[sessionid] = info;
1038     mapAuthStatusMutex.unlock();
1039 }
1040 void HdcDaemon::DeleteSessionAuthStatus(uint32_t sessionid)
1041 {
1042     mapAuthStatusMutex.lock();
1043     mapAuthStatus.erase(sessionid);
1044     mapAuthStatusMutex.unlock();
1045 }
1046 HdcSessionBase::AuthType HdcDaemon::GetSessionAuthStatus(uint32_t sessionid)
1047 {
1048     HdcDaemonAuthInfo info;
1049 
1050     mapAuthStatusMutex.lock();
1051     info = mapAuthStatus[sessionid];
1052     mapAuthStatusMutex.unlock();
1053 
1054     return info.authtype;
1055 }
1056 string HdcDaemon::GetSessionAuthToken(uint32_t sessionid)
1057 {
1058     HdcDaemonAuthInfo info;
1059 
1060     mapAuthStatusMutex.lock();
1061     info = mapAuthStatus[sessionid];
1062     mapAuthStatusMutex.unlock();
1063 
1064     return info.token;
1065 }
1066 string HdcDaemon::GetSessionAuthPubkey(uint32_t sessionid)
1067 {
1068     HdcDaemonAuthInfo info;
1069 
1070     mapAuthStatusMutex.lock();
1071     info = mapAuthStatus[sessionid];
1072     mapAuthStatusMutex.unlock();
1073 
1074     return info.pubkey;
1075 }
1076 string HdcDaemon::GetSessionAuthmsg(uint32_t sessionid)
1077 {
1078     HdcDaemonAuthInfo info;
1079 
1080     mapAuthStatusMutex.lock();
1081     info = mapAuthStatus[sessionid];
1082     mapAuthStatusMutex.unlock();
1083 
1084     return info.authmsg;
1085 }
1086 void HdcDaemon::SendAuthOkMsg(SessionHandShake &handshake, uint32_t channelid,
1087                               uint32_t sessionid, string msg, string daemonAuthResult)
1088 {
1089     char hostname[BUF_SIZE_MEDIUM] = { 0 };
1090     if (gethostname(hostname, BUF_SIZE_MEDIUM) != 0) {
1091         WRITE_LOG(LOG_FATAL, "get hostname failed %s", strerror(errno));
1092     }
1093     if (handshake.version < "Ver: 3.0.0b") {
1094         if (msg.empty()) {
1095             msg = hostname;
1096         }
1097         handshake.buf = msg;
1098     } else {
1099         string emgmsg;
1100         Base::TlvAppend(emgmsg, TAG_EMGMSG, msg);
1101         Base::TlvAppend(emgmsg, TAG_DEVNAME, hostname);
1102         Base::TlvAppend(emgmsg, TAG_DAEOMN_AUTHSTATUS, daemonAuthResult);
1103         handshake.buf = emgmsg;
1104     }
1105 
1106     handshake.authType = AUTH_OK;
1107     string bufString = SerialStruct::SerializeToString(handshake);
1108     Send(sessionid, channelid, CMD_KERNEL_HANDSHAKE,
1109             reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
1110     uint8_t count = 1;
1111     Send(sessionid, channelid, CMD_KERNEL_CHANNEL_CLOSE, &count, 1);
1112 }
1113 void HdcDaemon::SendAuthSignMsg(SessionHandShake &handshake,
1114         uint32_t channelId, uint32_t sessionid, string pubkey, string token)
1115 {
1116     UpdateSessionAuthPubkey(sessionid, pubkey);
1117     handshake.authType = AUTH_SIGNATURE;
1118     handshake.buf = token;
1119     string bufString = SerialStruct::SerializeToString(handshake);
1120     Send(sessionid, channelId, CMD_KERNEL_HANDSHAKE,
1121             reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
1122 }
1123 void HdcDaemon::EchoHandshakeMsg(SessionHandShake &handshake, uint32_t channelid, uint32_t sessionid, string msg)
1124 {
1125     SendAuthOkMsg(handshake, channelid, sessionid, msg, DAEOMN_UNAUTHORIZED);
1126     LogMsg(sessionid, channelid, MSG_FAIL, msg.c_str());
1127     UpdateSessionAuthmsg(sessionid, msg);
1128 }
1129 void HdcDaemon::AuthRejectLowClient(SessionHandShake &handshake, uint32_t channelid, uint32_t sessionid)
1130 {
1131     string msg = "[E000001]:The sdk hdc.exe version is too low, please upgrade to the latest version.";
1132     EchoHandshakeMsg(handshake, channelid, sessionid, msg);
1133 }
1134 }  // namespace Hdc
1135