• 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 
17 #include <openssl/sha.h>
18 #include "daemon_updater.h"
19 #include "flashd_define.h"
20 #include "serial_struct.h"
21 
22 namespace Hdc {
HdcDaemon(bool serverOrDaemonIn)23 HdcDaemon::HdcDaemon(bool serverOrDaemonIn)
24     : HdcSessionBase(serverOrDaemonIn)
25 {
26     clsTCPServ = nullptr;
27     clsUSBServ = nullptr;
28     clsJdwp = nullptr;
29     enableSecure = false;
30 }
31 
~HdcDaemon()32 HdcDaemon::~HdcDaemon()
33 {
34     WRITE_LOG(LOG_DEBUG, "~HdcDaemon");
35 }
36 
ClearInstanceResource()37 void HdcDaemon::ClearInstanceResource()
38 {
39     TryStopInstance();
40     Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon");
41     if (clsTCPServ) {
42         delete reinterpret_cast<HdcDaemonTCP *>(clsTCPServ);
43         clsTCPServ = nullptr;
44     }
45     if (clsUSBServ) {
46         delete reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
47         clsUSBServ = nullptr;
48     }
49     if (clsJdwp) {
50         delete reinterpret_cast<HdcJdwp *>(clsJdwp);
51         clsJdwp = nullptr;
52     }
53     WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish");
54 }
55 
TryStopInstance()56 void HdcDaemon::TryStopInstance()
57 {
58     ClearSessions();
59     if (clsTCPServ) {
60         WRITE_LOG(LOG_DEBUG, "Stop TCP");
61         (reinterpret_cast<HdcDaemonTCP *>(clsTCPServ))->Stop();
62     }
63     if (clsUSBServ) {
64         WRITE_LOG(LOG_DEBUG, "Stop USB");
65         (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->Stop();
66     }
67     (reinterpret_cast<HdcJdwp *>(clsJdwp))->Stop();
68     // workaround temply remove MainLoop instance clear
69     ReMainLoopForInstanceClear();
70     WRITE_LOG(LOG_DEBUG, "Stop loopmain");
71 }
72 
InitMod(bool bEnableTCP,bool bEnableUSB)73 void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB)
74 {
75     WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");
76     if (bEnableTCP) {
77         // tcp
78         clsTCPServ = new HdcDaemonTCP(false, this);
79         (reinterpret_cast<HdcDaemonTCP *>(clsTCPServ))->Initial();
80     }
81     if (bEnableUSB) {
82         // usb
83         clsUSBServ = new HdcDaemonUSB(false, this);
84         (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->Initial();
85     }
86 
87     clsJdwp = new HdcJdwp(&loopMain);
88     (reinterpret_cast<HdcJdwp *>(clsJdwp))->Initial();
89 
90     // enable security
91     string secure;
92     SystemDepend::GetDevItem("ro.hdc.secure", secure);
93     enableSecure = (Base::Trim(secure) == "1");
94 }
95 
96 // clang-format off
RedirectToTask(HTaskInfo hTaskInfo,HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)97 bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
98     const uint16_t command, uint8_t *payload, const int payloadSize)
99 {
100     bool ret = true;
101     hTaskInfo->ownerSessionClass = this;
102     WRITE_LOG(LOG_DEBUG, "RedirectToTask command %d", command);
103     switch (command) {
104         case CMD_UNITY_EXECUTE:
105         case CMD_UNITY_REMOUNT:
106         case CMD_UNITY_REBOOT:
107         case CMD_UNITY_RUNMODE:
108         case CMD_UNITY_HILOG:
109         case CMD_UNITY_ROOTRUN:
110         case CMD_UNITY_TERMINATE:
111         case CMD_UNITY_BUGREPORT_INIT:
112         case CMD_JDWP_LIST:
113         case CMD_JDWP_TRACK:
114             ret = TaskCommandDispatch<HdcDaemonUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
115             break;
116         case CMD_SHELL_INIT:
117         case CMD_SHELL_DATA:
118             ret = TaskCommandDispatch<HdcShell>(hTaskInfo, TYPE_SHELL, command, payload, payloadSize);
119             break;
120         case CMD_FILE_CHECK:
121         case CMD_FILE_DATA:
122         case CMD_FILE_FINISH:
123         case CMD_FILE_INIT:
124         case CMD_FILE_BEGIN:
125             ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
126             break;
127         // One-way function, so fewer options
128         case CMD_UPDATER_UPDATE_INIT:
129         case CMD_UPDATER_FLASH_INIT:
130         case CMD_UPDATER_CHECK:
131         case CMD_UPDATER_BEGIN:
132         case CMD_UPDATER_DATA:
133         case CMD_UPDATER_FINISH:
134         case CMD_UPDATER_ERASE:
135         case CMD_UPDATER_FORMAT:
136         case CMD_UPDATER_PROGRESS:
137             ret = TaskCommandDispatch<DaemonUpdater>(hTaskInfo, TASK_UPDATER, command, payload, payloadSize);
138             break;
139         default:
140             break;
141     }
142     return ret;
143 }
144 
HandDaemonAuth(HSession hSession,const uint32_t channelId,SessionHandShake & handshake)145 bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
146 {
147     bool ret = false;
148     switch (handshake.authType) {
149         case AUTH_NONE: {  // AUTH_NONE -> AUTH
150             hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH);
151             handshake.authType = AUTH_TOKEN;
152             handshake.buf = hSession->tokenRSA;
153             string bufString = SerialStruct::SerializeToString(handshake);
154             Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
155                 reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
156             ret = true;
157             break;
158         }
159         case AUTH_SIGNATURE: {
160             // When Host is first connected to the device, the signature authentication is inevitable, and the
161             // certificate verification must be triggered.
162             //
163             // When the certificate is verified, the client sends a public key to the device, triggered the system UI
164             // jump out dialog, and click the system, the system will store the Host public key certificate in the
165             // device locally, and the signature authentication will be correct when the subsequent connection is
166             // connected.
167             if (!HdcAuth::AuthVerify(reinterpret_cast<uint8_t *>(const_cast<char *>(hSession->tokenRSA.c_str())),
168                 reinterpret_cast<uint8_t *>(const_cast<char *>(handshake.buf.c_str())), handshake.buf.size())) {
169                 // Next auth
170                 handshake.authType = AUTH_TOKEN;
171                 handshake.buf = hSession->tokenRSA;
172                 string bufString = SerialStruct::SerializeToString(handshake);
173                 Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
174                     reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
175                 break;
176             }
177             ret = true;
178             break;
179         }
180         case AUTH_PUBLICKEY: {
181             ret = HdcAuth::PostUIConfirm(handshake.buf);
182             WRITE_LOG(LOG_DEBUG, "Auth host OK, postUIConfirm");
183             break;
184         }
185         default:
186             break;
187     }
188     return ret;
189 }
190 
DaemonSessionHandshake(HSession hSession,const uint32_t channelId,uint8_t * payload,int payloadSize)191 bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize)
192 {
193     // session handshake step2
194     string s = string(reinterpret_cast<char *>(payload), payloadSize);
195     SessionHandShake handshake;
196     string err;
197     SerialStruct::ParseFromString(handshake, s);
198     // banner to check is parse ok...
199     if (handshake.banner != HANDSHAKE_MESSAGE) {
200         hSession->availTailIndex = 0;
201         WRITE_LOG(LOG_FATAL, "Recv server-hello failed");
202         return false;
203     }
204     if (handshake.authType == AUTH_NONE) {
205         // daemon handshake 1st packet
206         uint32_t unOld = hSession->sessionId;
207         hSession->sessionId = handshake.sessionId;
208         hSession->connectKey = handshake.connectKey;
209         AdminSession(OP_UPDATE, unOld, hSession);
210         if (clsUSBServ != nullptr) {
211             (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId);
212         }
213 
214         handshake.sessionId = 0;
215         handshake.connectKey = "";
216     }
217     if (enableSecure && !HandDaemonAuth(hSession, channelId, handshake)) {
218         return false;
219     }
220     // handshake auth OK.Can append the sending device information to HOST
221     char hostName[BUF_SIZE_MEDIUM] = "";
222     size_t len = sizeof(hostName);
223     uv_os_gethostname(hostName, &len);
224     handshake.authType = AUTH_OK;
225     handshake.buf = hostName;
226     string bufString = SerialStruct::SerializeToString(handshake);
227     Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE,
228         reinterpret_cast<uint8_t *>(const_cast<char *>(bufString.c_str())), bufString.size());
229     hSession->handshakeOK = true;
230     return true;
231 }
232 
FetchCommand(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,int payloadSize)233 bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
234                              int payloadSize)
235 {
236     WRITE_LOG(LOG_DEBUG, "FetchCommand command %d", command);
237     bool ret = true;
238     if (!hSession->handshakeOK && command != CMD_KERNEL_HANDSHAKE) {
239         ret = false;
240         return ret;
241     }
242     switch (command) {
243         case CMD_KERNEL_HANDSHAKE: {
244             // session handshake step2
245             ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize);
246             break;
247         }
248         case CMD_KERNEL_CHANNEL_CLOSE: {  // Daemon is only cleaning up the Channel task
249             ClearOwnTasks(hSession, channelId);
250             if (*payload != 0) {
251                 --(*payload);
252                 Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
253             }
254             ret = true;
255             break;
256         }
257         default:
258             ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize);
259             break;
260     }
261     return ret;
262 }
263 
RemoveInstanceTask(const uint8_t op,HTaskInfo hTask)264 bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
265 {
266     bool ret = true;
267     switch (hTask->taskType) {
268         case TYPE_UNITY:
269             ret = DoTaskRemove<HdcDaemonUnity>(hTask, op);
270             break;
271         case TYPE_SHELL:
272             ret = DoTaskRemove<HdcShell>(hTask, op);
273             break;
274         case TASK_FILE:
275             ret = DoTaskRemove<HdcTransferBase>(hTask, op);
276             break;
277         case TASK_FORWARD:
278             ret = DoTaskRemove<HdcDaemonForward>(hTask, op);
279             break;
280         case TASK_APP:
281             ret = DoTaskRemove<HdcDaemonApp>(hTask, op);
282             break;
283         case TASK_UPDATER:
284             ret = DoTaskRemove<DaemonUpdater>(hTask, op);
285             break;
286         default:
287             ret = false;
288             break;
289     }
290     return ret;
291 }
292 
ServerCommand(const uint32_t sessionId,const uint32_t channelId,const uint16_t command,uint8_t * bufPtr,const int size)293 bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
294                               uint8_t *bufPtr, const int size)
295 {
296     return Send(sessionId, channelId, command, bufPtr, size) > 0;
297 }
298 
JdwpNewFileDescriptor(const uint8_t * buf,const int bytesIO)299 void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO)
300 {
301     uint32_t pid = *(reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 1)));
302     uint32_t fd = *(reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(buf + 5)));  // 5 : fd offset
303     (reinterpret_cast<HdcJdwp *>(clsJdwp))->SendJdwpNewFD(pid, fd);
304 };
305 
NotifyInstanceSessionFree(HSession hSession,bool freeOrClear)306 void HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
307 {
308     if (!freeOrClear) {
309         return;  // ignore step 1
310     }
311     if (clsUSBServ != nullptr) {
312         auto clsUsbModule = reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
313         clsUsbModule->OnSessionFreeFinally(hSession);
314     }
315 }
316 }  // namespace Hdc
317