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