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
16 #include "update_service.h"
17
18 #include <arpa/inet.h>
19 #include <cerrno>
20 #include <cstdlib>
21 #include <cstring>
22 #include <fstream>
23 #include <iomanip>
24 #include <iostream>
25 #include <unistd.h>
26 #include <sys/reboot.h>
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <vector>
32
33 #include "cJSON.h"
34 #include "iservice_registry.h"
35 #include "libxml/parser.h"
36 #include "libxml/tree.h"
37 #include "misc_info/misc_info.h"
38 #include "openssl/err.h"
39 #include "openssl/ssl.h"
40 #include "package/package.h"
41 #include "parameters.h"
42 #include "progress_thread.h"
43 #include "securec.h"
44 #include "system_ability_definition.h"
45 #include "update_helper.h"
46 #include "updaterkits/updaterkits.h"
47 #include "utils.h"
48
49 namespace OHOS {
50 namespace update_engine {
51 REGISTER_SYSTEM_ABILITY_BY_ID(UpdateService, UPDATE_DISTRIBUTED_SERVICE_ID, true)
52
53 constexpr int32_t PORT_NUMBER = 5022;
54 constexpr int32_t JSON_MAX_SIZE = 4096;
55 const mode_t MKDIR_MODE = 0777;
56
57 const std::string MISC_FILE = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
58 const std::string BASE_PATH = "/data/updater";
59 #ifndef UPDATER_UT
60 const std::string SIGNING_CERT_NAME = "/data/update_sa/signing_cert.crt";
61 #else
62 const std::string SIGNING_CERT_NAME = "/data/updater/src/signing_cert.crt";
63 #endif
64 const std::string PARAM_NAME_FOR_VERSION = "hw_sc.build.os.version";
65 const std::string DEFAULT_VERSION = "2.2.0";
66 const std::string PARAM_NAME_FOR_SEARCH = "update.serverip.search";
67 const std::string PARAM_NAME_FOR_DOWNLOAD = "update.serverip.download";
68 const std::string DEFAULT_SERVER_IP = "127.0.0.1";
69
UpdateService(int32_t systemAbilityId,bool runOnCreate)70 UpdateService::UpdateService(int32_t systemAbilityId, bool runOnCreate)
71 : SystemAbility(systemAbilityId, runOnCreate)
72 {
73 InitVersionInfo(versionInfo_);
74 }
75
~UpdateService()76 UpdateService::~UpdateService()
77 {
78 ENGINE_LOGE("UpdateServerTest free %p", this);
79 if (downloadThread_ != nullptr) {
80 downloadThread_->StopDownload();
81 delete downloadThread_;
82 downloadThread_ = nullptr;
83 }
84 }
85
RegisterUpdateCallback(const UpdateContext & ctx,const sptr<IUpdateCallback> & updateCallback)86 int32_t UpdateService::RegisterUpdateCallback(const UpdateContext &ctx,
87 const sptr<IUpdateCallback> &updateCallback)
88 {
89 ENGINE_CHECK(updateCallback != nullptr, return -1, "Invalid callback");
90 updateCallback_ = updateCallback;
91 updateContext_.upgradeDevId = ctx.upgradeDevId;
92 updateContext_.controlDevId = ctx.controlDevId;
93 updateContext_.upgradeApp = ctx.upgradeApp;
94 updateContext_.type = ctx.type;
95 updateContext_.upgradeFile = ctx.upgradeFile;
96 return 0;
97 }
98
UnregisterUpdateCallback()99 int32_t UpdateService::UnregisterUpdateCallback()
100 {
101 updateCallback_ = nullptr;
102 return 0;
103 }
104
GetNewVersion(VersionInfo & versionInfo)105 int32_t UpdateService::GetNewVersion(VersionInfo &versionInfo)
106 {
107 InitVersionInfo(versionInfo);
108 return 0;
109 }
110
GetUpgradeStatus(UpgradeInfo & info)111 int32_t UpdateService::GetUpgradeStatus(UpgradeInfo &info)
112 {
113 info.status = upgradeStatus_;
114 return 0;
115 }
116
SetUpdatePolicy(const UpdatePolicy & policy)117 int32_t UpdateService::SetUpdatePolicy(const UpdatePolicy &policy)
118 {
119 return UpdateHelper::CopyUpdatePolicy(policy, policy_);
120 }
121
GetUpdatePolicy(UpdatePolicy & policy)122 int32_t UpdateService::GetUpdatePolicy(UpdatePolicy &policy)
123 {
124 return UpdateHelper::CopyUpdatePolicy(policy_, policy);
125 }
126
CheckNewVersion()127 int32_t UpdateService::CheckNewVersion()
128 {
129 upgradeStatus_ = UPDATE_STATE_CHECK_VERSION_ON;
130 int32_t engineSocket = socket(AF_INET, SOCK_STREAM, 0);
131 ENGINE_CHECK(engineSocket >= 0, SearchCallback("socket error !", SERVER_BUSY); return 1, "socket error !");
132
133 std::string serverIp = OHOS::system::GetParameter(PARAM_NAME_FOR_SEARCH, DEFAULT_SERVER_IP);
134 ENGINE_LOGI("CheckNewVersion serverIp: %s ", serverIp.c_str());
135
136 sockaddr_in engineSin {};
137 engineSin.sin_family = AF_INET;
138 engineSin.sin_port = htons(PORT_NUMBER);
139 int32_t ret = inet_pton(AF_INET, serverIp.c_str(), &engineSin.sin_addr);
140 ENGINE_CHECK(ret > 0, close(engineSocket); SearchCallback("Invalid ip!", SERVER_BUSY); return 1, "socket error");
141
142 struct timeval tv = {TIMEOUT_FOR_CONNECT, 0};
143 setsockopt(engineSocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
144 ret = connect(engineSocket, reinterpret_cast<sockaddr*>(&engineSin), sizeof(engineSin));
145 ENGINE_CHECK(ret == 0,
146 #ifndef UPDATER_UT
147 SearchCallback("Connect error !", SERVER_BUSY);
148 close(engineSocket);
149 #else
150 versionInfo_.result[0].verifyInfo = "updater/test.txt";
151 SearchCallback("update service test connect error !", HAS_NEW_VERSION);
152 close(engineSocket);
153 #endif
154 return 1, "connect error");
155 ReadDataFromSSL(engineSocket);
156 return 0;
157 }
158
DownloadVersion()159 int32_t UpdateService::DownloadVersion()
160 {
161 if (access(BASE_PATH.c_str(), 0) == -1) {
162 mkdir(BASE_PATH.c_str(), MKDIR_MODE);
163 }
164
165 Progress progress0 = {0, UPDATE_STATE_DOWNLOAD_ON, ""};
166 ENGINE_CHECK(upgradeStatus_ >= UPDATE_STATE_CHECK_VERSION_SUCCESS,
167 progress0.status = UPDATE_STATE_DOWNLOAD_FAIL;
168 progress0.endReason = "Invalid status";
169 DownloadCallback("", progress0); return -1, "Invalid status %d", upgradeStatus_);
170
171 ENGINE_CHECK(!versionInfo_.result[0].verifyInfo.empty(),
172 progress0.status = UPDATE_STATE_DOWNLOAD_FAIL;
173 progress0.endReason = "Invalid verify info";
174 DownloadCallback("", progress0); return -1, "Invalid verify info");
175 std::string downloadFileName = BASE_PATH + "/" + versionInfo_.result[0].verifyInfo;
176 size_t localFileLength = DownloadThread::GetLocalFileLength(downloadFileName);
177 ENGINE_LOGI("Download %zu %s", localFileLength, downloadFileName.c_str());
178 if (localFileLength == versionInfo_.result[0].size && versionInfo_.result[0].size != 0) {
179 progress0.percent = DOWNLOAD_FINISH_PERCENT;
180 progress0.status = UPDATE_STATE_DOWNLOAD_SUCCESS;
181 DownloadCallback(downloadFileName, progress0);
182 return 0;
183 }
184
185 upgradeStatus_ = UPDATE_STATE_DOWNLOAD_ON;
186 if (downloadThread_ == nullptr) {
187 downloadThread_ = new DownloadThread([&](const std::string &fileName, const Progress &progress) -> int {
188 DownloadCallback(fileName, progress);
189 return 0;
190 });
191 ENGINE_CHECK(downloadThread_ != nullptr,
192 progress0.status = UPDATE_STATE_DOWNLOAD_FAIL;
193 progress0.endReason = "Failed to start thread";
194 DownloadCallback(downloadFileName, progress0); return -1, "Failed to start thread");
195 }
196 return downloadThread_->StartDownload(downloadFileName, GetDownloadServerUrl());
197 }
198
DoUpdate()199 int32_t UpdateService::DoUpdate()
200 {
201 Progress progress;
202 progress.percent = 1;
203 progress.status = UPDATE_STATE_INSTALL_ON;
204 ENGINE_CHECK(upgradeStatus_ >= UPDATE_STATE_DOWNLOAD_SUCCESS,
205 progress.endReason = "Invalid status";
206 progress.status = UPDATE_STATE_INSTALL_FAIL;
207 UpgradeCallback(progress);
208 return -1, "Invalid status %d", upgradeStatus_);
209
210 progress.status = UPDATE_STATE_INSTALL_SUCCESS;
211 bool ret = RebootAndInstallUpgradePackage(MISC_FILE, updateContext_.upgradeFile);
212 ENGINE_CHECK(ret, return -1, "UpdateService::DoUpdate SetParameter failed");
213 progress.percent = DOWNLOAD_FINISH_PERCENT;
214 UpgradeCallback(progress);
215 return 0;
216 }
217
SearchCallback(const std::string & msg,SearchStatus status)218 void UpdateService::SearchCallback(const std::string &msg, SearchStatus status)
219 {
220 ENGINE_LOGI("SearchCallback %s ", msg.c_str());
221 versionInfo_.status = status;
222 versionInfo_.errMsg = msg;
223 if (status == HAS_NEW_VERSION || status == NO_NEW_VERSION) {
224 upgradeStatus_ = UPDATE_STATE_CHECK_VERSION_SUCCESS;
225
226 // Compare the downloaded version with the local version.
227 std::string loadVersion = OHOS::system::GetParameter(PARAM_NAME_FOR_VERSION, DEFAULT_VERSION);
228 int32_t ret = UpdateHelper::CompareVersion(versionInfo_.result[0].versionCode, loadVersion);
229 if (ret <= 0) {
230 versionInfo_.status = NO_NEW_VERSION;
231 }
232 } else {
233 upgradeStatus_ = UPDATE_STATE_CHECK_VERSION_FAIL;
234 }
235 if (updateCallback_ != nullptr) {
236 updateCallback_->OnCheckVersionDone(versionInfo_);
237 }
238 }
239
DownloadCallback(const std::string & fileName,const Progress & progress)240 void UpdateService::DownloadCallback(const std::string &fileName, const Progress &progress)
241 {
242 Progress downloadProgress {};
243 upgradeStatus_ = UPDATE_STATE_DOWNLOAD_ON;
244 if (progress.status == UPDATE_STATE_DOWNLOAD_FAIL ||
245 progress.status == UPDATE_STATE_DOWNLOAD_SUCCESS) {
246 upgradeStatus_ = progress.status;
247 }
248 downloadProgress.percent = progress.percent;
249 downloadProgress.status = progress.status;
250 downloadProgress.endReason = progress.endReason;
251
252 #ifdef UPDATER_UT
253 upgradeStatus_ = UPDATE_STATE_DOWNLOAD_SUCCESS;
254 #endif
255 ENGINE_LOGI("DownloadCallback status %d %d", progress.status, progress.percent);
256 if (upgradeStatus_ == UPDATE_STATE_DOWNLOAD_SUCCESS) {
257 ENGINE_LOGI("DownloadCallback fileName %s %s", fileName.c_str(), updateContext_.upgradeFile.c_str());
258 if (rename(fileName.c_str(), updateContext_.upgradeFile.c_str())) {
259 ENGINE_LOGE("Rename file fail %s", fileName.c_str());
260 remove(updateContext_.upgradeFile.c_str());
261 downloadProgress.status = UPDATE_STATE_DOWNLOAD_FAIL;
262 } else if (!VerifyDownloadPkg(updateContext_.upgradeFile, downloadProgress)) {
263 // If the verification fails, delete the corresponding package.
264 remove(updateContext_.upgradeFile.c_str());
265 downloadProgress.status = UPDATE_STATE_VERIFY_FAIL;
266 }
267 }
268
269 if (updateCallback_ != nullptr) {
270 updateCallback_->OnDownloadProgress(downloadProgress);
271 }
272 }
273
UpgradeCallback(const Progress & progress)274 void UpdateService::UpgradeCallback(const Progress &progress)
275 {
276 upgradeStatus_ = progress.status;
277 ENGINE_LOGE("UpgradeCallback status %d %d", progress.status, progress.percent);
278 if (updateCallback_ != nullptr) {
279 updateCallback_->OnUpgradeProgress(progress);
280 }
281 }
282
ReadDataFromSSL(int32_t engineSocket)283 void UpdateService::ReadDataFromSSL(int32_t engineSocket)
284 {
285 SearchStatus result = SERVER_BUSY;
286 std::string errMsg = "Couldn't connect to server";
287 std::vector<char> buffer(JSON_MAX_SIZE);
288
289 SSL_library_init();
290 OpenSSL_add_all_algorithms();
291 SSL_load_error_strings();
292 SSL_CTX* sslCtx = SSL_CTX_new(SSLv23_client_method());
293 ENGINE_CHECK(sslCtx != nullptr, return, "sslCtx is nullptr");
294 SSL *ssl = SSL_new(sslCtx);
295 ENGINE_CHECK(ssl != nullptr, SSL_CTX_free(sslCtx); return, "ssl is nullptr");
296 SSL_set_fd(ssl, engineSocket);
297 int32_t ret = SSL_connect(ssl);
298 if (ret != -1) {
299 int32_t len = SSL_read(ssl, buffer.data(), JSON_MAX_SIZE);
300 if (len > 0 && ParseJsonFile(buffer, versionInfo_, downloadUrl_) == 0) {
301 result = HAS_NEW_VERSION;
302 errMsg = "";
303 } else {
304 result = SYSTEM_ERROR;
305 errMsg = "Couldn't read data";
306 }
307 } else {
308 result = SYSTEM_ERROR;
309 errMsg = "Couldn't connect to server";
310 }
311 SSL_shutdown(ssl);
312 SSL_free(ssl);
313 close(engineSocket);
314 SSL_CTX_free(sslCtx);
315
316 SearchCallback(errMsg, result);
317 return;
318 }
319
ParseJsonFile(const std::vector<char> & buffer,VersionInfo & info,std::string & url)320 int32_t UpdateService::ParseJsonFile(const std::vector<char> &buffer, VersionInfo &info, std::string &url)
321 {
322 ENGINE_CHECK(buffer.size() > 0, return -1, "JsonFile length must > 0");
323 cJSON *root = cJSON_Parse(buffer.data());
324 ENGINE_CHECK(root != nullptr, return -1, "Error get root");
325
326 cJSON *item = cJSON_GetObjectItem(root, "searchStatus");
327 ENGINE_CHECK(item != nullptr, cJSON_Delete(root); return -1, "Error get searchStatus");
328 info.status = static_cast<SearchStatus>(item->valueint);
329
330 item = cJSON_GetObjectItem(root, "errMsg");
331 ENGINE_CHECK(item != nullptr, cJSON_Delete(root); return -1, "Error get errMsg");
332 info.errMsg = item->valuestring;
333
334 cJSON *results = cJSON_GetObjectItem(root, "checkResults");
335 ENGINE_CHECK(results != nullptr, cJSON_Delete(root); return -1, "Error get checkResults");
336 int32_t ret = ReadCheckVersionResult(results, info, url);
337 ENGINE_CHECK(ret == 0, cJSON_Delete(root); return -1, "Error get checkResults");
338
339 cJSON *descriptInfo = cJSON_GetObjectItem(root, "descriptInfo");
340 ENGINE_CHECK(descriptInfo != nullptr, cJSON_Delete(root); return -1, "Error get descriptInfo");
341 ret = ReadCheckVersiondescriptInfo(descriptInfo, info);
342 ENGINE_CHECK(ret == 0, cJSON_Delete(root); return -1, "Error get descriptInfo");
343
344 cJSON_Delete(root);
345 if (info.status == HAS_NEW_VERSION) {
346 ENGINE_CHECK(!info.result[0].verifyInfo.empty() &&
347 !info.result[0].versionName.empty() &&
348 info.result[0].size > 0, return -1, "Error get descriptInfo");
349 }
350 return 0;
351 }
352
ReadCheckVersionResult(const cJSON * results,VersionInfo & info,std::string & url)353 int32_t UpdateService::ReadCheckVersionResult(const cJSON* results, VersionInfo &info, std::string &url)
354 {
355 size_t number = cJSON_GetArraySize(results);
356 for (size_t i = 0; i < number && i < sizeof(info.result) / sizeof(info.result[0]); i++) {
357 cJSON *result = cJSON_GetArrayItem(results, i);
358 ENGINE_CHECK(result != nullptr, return -1, "Error get result");
359
360 cJSON *item = cJSON_GetObjectItem(result, "versionName");
361 ENGINE_CHECK(item != nullptr, return -1, "Error get versionName");
362 info.result[i].versionName = item->valuestring;
363
364 item = cJSON_GetObjectItem(result, "versionCode");
365 ENGINE_CHECK(item != nullptr, return -1, "Error get versionCode");
366 info.result[i].versionCode = item->valuestring;
367
368 item = cJSON_GetObjectItem(result, "verifyInfo");
369 ENGINE_CHECK(item != nullptr, return -1, "Error get verifyInfo");
370 info.result[i].verifyInfo = item->valuestring;
371
372 item = cJSON_GetObjectItem(result, "size");
373 ENGINE_CHECK(item != nullptr, return -1, "Error get size");
374 info.result[i].size = item->valueint;
375
376 item = cJSON_GetObjectItem(result, "packageType");
377 ENGINE_CHECK(item != nullptr, return -1, "Error get packageType");
378 info.result[i].packageType = (PackageType)(item->valueint);
379
380 item = cJSON_GetObjectItem(result, "url");
381 ENGINE_CHECK(item != nullptr, return -1, "Error get url");
382 url = item->valuestring;
383
384 item = cJSON_GetObjectItem(result, "descriptPackageId");
385 ENGINE_CHECK(item != nullptr, return -1, "Error get descriptPackageId");
386 info.result[i].descriptPackageId = item->valuestring;
387 }
388 return 0;
389 }
390
ReadCheckVersiondescriptInfo(const cJSON * descriptInfo,VersionInfo & info)391 int32_t UpdateService::ReadCheckVersiondescriptInfo(const cJSON *descriptInfo, VersionInfo &info)
392 {
393 size_t number = cJSON_GetArraySize(descriptInfo);
394 for (size_t i = 0; i < number && i < sizeof(info.result) / sizeof(info.result[0]); i++) {
395 cJSON* descript = cJSON_GetArrayItem(descriptInfo, i);
396 ENGINE_CHECK(descript != nullptr, return -1, "Error get descriptInfo");
397
398 cJSON *item = cJSON_GetObjectItem(descript, "descriptPackageId");
399 if (item != nullptr) {
400 info.descriptInfo[i].descriptPackageId = item->valuestring;
401 }
402 item = cJSON_GetObjectItem(descript, "content");
403 if (item != nullptr) {
404 info.descriptInfo[i].content = item->valuestring;
405 ENGINE_LOGI(" descriptInfo content %s", info.descriptInfo[i].content.c_str());
406 }
407 }
408 return 0;
409 }
410
VerifyDownloadPkg(const std::string & pkgName,Progress & progress)411 bool UpdateService::VerifyDownloadPkg(const std::string &pkgName, Progress &progress)
412 {
413 // Compare the downloaded version with the local version. Only update is supported.
414 std::string loadVersion = OHOS::system::GetParameter(PARAM_NAME_FOR_VERSION, DEFAULT_VERSION);
415 int32_t ret = UpdateHelper::CompareVersion(versionInfo_.result[0].versionCode, loadVersion);
416 if (ret <= 0) {
417 progress.endReason = "Update package version earlier than the local version";
418 ENGINE_LOGE("Version compare Failed local '%s' server '%s'",
419 loadVersion.c_str(), versionInfo_.result[0].versionCode.c_str());
420 return false;
421 }
422 ENGINE_LOGI("versionInfo_.result[0].verifyInfo %s ", versionInfo_.result[0].verifyInfo.c_str());
423 std::vector<uint8_t> digest = UpdateHelper::HexToDegist(versionInfo_.result[0].verifyInfo);
424 ret = VerifyPackage(pkgName.c_str(),
425 SIGNING_CERT_NAME.c_str(), versionInfo_.result[0].versionCode.c_str(), digest.data(), digest.size());
426 if (ret != 0) {
427 progress.endReason = "Upgrade package verify Failed";
428 ENGINE_LOGE("Package %s verification Failed", pkgName.c_str());
429 return false;
430 }
431 ENGINE_LOGE("Package verify success");
432 return true;
433 }
434
GetDownloadServerUrl() const435 std::string UpdateService::GetDownloadServerUrl() const
436 {
437 return downloadUrl_;
438 }
439
Cancel(int32_t service)440 int32_t UpdateService::Cancel(int32_t service)
441 {
442 ENGINE_LOGI("Cancel %d", service);
443 if (downloadThread_ != nullptr && service == DOWNLOAD) {
444 downloadThread_->StopDownload();
445 }
446 return 0;
447 }
448
RebootAndClean(const std::string & miscFile,const std::string & cmd)449 int32_t UpdateService::RebootAndClean(const std::string &miscFile, const std::string &cmd)
450 {
451 #ifndef UPDATER_UT
452 return RebootAndCleanUserData(miscFile, cmd) ? 0 : -1;
453 #else
454 return 0;
455 #endif
456 }
457
RebootAndInstall(const std::string & miscFile,const std::string & packageName)458 int32_t UpdateService::RebootAndInstall(const std::string &miscFile, const std::string &packageName)
459 {
460 #ifndef UPDATER_UT
461 return RebootAndInstallUpgradePackage(miscFile, packageName) ? 0 : -1;
462 #else
463 return 0;
464 #endif
465 }
466
InitVersionInfo(VersionInfo & versionInfo) const467 void UpdateService::InitVersionInfo(VersionInfo &versionInfo) const
468 {
469 versionInfo.status = HAS_NEW_VERSION;
470 std::string versionName = OHOS::system::GetParameter(PARAM_NAME_FOR_VERSION, DEFAULT_VERSION);
471 if (versionName.empty()) {
472 versionInfo.status = SYSTEM_ERROR;
473 versionInfo.errMsg = "Can not get local version";
474 }
475
476 for (size_t i = 0; i < sizeof(versionInfo.result) / sizeof(versionInfo.result[0]); i++) {
477 versionInfo.result[i].size = 0;
478 versionInfo.result[i].packageType = PACKAGE_TYPE_NORMAL;
479 versionInfo.result[i].versionName = versionName;
480 versionInfo.result[i].versionCode = "";
481 versionInfo.result[i].verifyInfo = "";
482 versionInfo.result[i].descriptPackageId = "";
483 }
484 for (size_t i = 0; i < sizeof(versionInfo.descriptInfo) / sizeof(versionInfo.descriptInfo[0]); i++) {
485 versionInfo.descriptInfo[i].content = "";
486 versionInfo.descriptInfo[i].descriptPackageId = "";
487 }
488 }
489
OnStart()490 void UpdateService::OnStart()
491 {
492 ENGINE_LOGI("UpdaterService OnStart");
493 bool res = Publish(this);
494 if (res == false) {
495 ENGINE_LOGI("UpdaterService OnStart failed");
496 }
497 return;
498 }
499
OnStop()500 void UpdateService::OnStop()
501 {
502 ENGINE_LOGI("UpdaterService OnStop");
503 }
504 }
505 } // namespace OHOS
506