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