1 /*
2  * Copyright (c) 2023 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 #ifndef FIRMWARE_ICHECK_H
17 #define FIRMWARE_ICHECK_H
18 
19 #include <arpa/inet.h>
20 #include <sys/socket.h>
21 #include <unistd.h>
22 #include <vector>
23 
24 #include "cJSON.h"
25 #include "nlohmann/json.hpp"
26 #include "openssl/err.h"
27 #include "openssl/ssl.h"
28 #include "parameter.h"
29 #include "parameters.h"
30 
31 #include "anonymous_utils.h"
32 #include "firmware_check_analyze_utils.h"
33 #include "firmware_common.h"
34 #include "firmware_component.h"
35 #include "firmware_constant.h"
36 #include "device_adapter.h"
37 #include "firmware_update_helper.h"
38 #include "network_response.h"
39 #include "search_status.h"
40 #include "update_service_util.h"
41 
42 constexpr int32_t PORT_NUMBER = 5022;
43 constexpr int32_t JSON_MAX_SIZE = 4096;
44 #ifndef UPDATER_UT
45 constexpr int32_t TIMEOUT_FOR_CONNECT = 10;
46 #else
47 constexpr int32_t TIMEOUT_FOR_CONNECT = 1;
48 #endif
49 
50 namespace OHOS {
51 namespace UpdateEngine {
52 const std::string DEFAULT_SERVER_IP = "127.0.0.1";
53 const std::string PARAM_NAME_FOR_SEARCH = "update.serverip.search";
54 using CheckCallback = std::function<void(CheckStatus status, const Duration &duration,
55     const std::vector<FirmwareComponent> &firmwareCheckResultList, const CheckAndAuthInfo &checkAndAuthInfo)>;
56 
57 using cJSONPtr = std::unique_ptr<cJSON, decltype(&cJSON_Delete)>;
58 struct FirmwareCheckCallback {
59     CheckCallback callback;
60 };
61 
62 class FirmwareICheck {
63 public:
FirmwareICheck(const RequestType requestType)64     explicit FirmwareICheck(const RequestType requestType)
65     {
66         requestType_ = requestType;
67     }
68     virtual ~FirmwareICheck() = default;
69 
DoAction(FirmwareCheckCallback checkCallback)70     void DoAction(FirmwareCheckCallback checkCallback)
71     {
72         FIRMWARE_LOGI("FirmwareCheck::DoAction");
73         if (checkCallback.callback == nullptr) {
74             FIRMWARE_LOGE("FirmwareICheck DoAction callback is null");
75             return;
76         }
77         int32_t engineSocket = socket(AF_INET, SOCK_STREAM, 0);
78         ENGINE_CHECK(engineSocket >= 0,
79             checkCallback.callback(CheckStatus::CHECK_FAIL, duration_, checkResultList_, checkAndAuthInfo_);
80             return, "socket error !");
81 
82         std::string serverIp = OHOS::system::GetParameter(PARAM_NAME_FOR_SEARCH, DEFAULT_SERVER_IP);
83         FIRMWARE_LOGI("CheckNewVersion serverIp: %s ", serverIp.c_str());
84         sockaddr_in engineSin {};
85         engineSin.sin_family = AF_INET;
86         engineSin.sin_port = htons(PORT_NUMBER);
87         int32_t ret = inet_pton(AF_INET, serverIp.c_str(), &engineSin.sin_addr);
88         ENGINE_CHECK(ret > 0, close(engineSocket);
89             checkCallback.callback(CheckStatus::CHECK_FAIL, duration_, checkResultList_, checkAndAuthInfo_);
90             return, "socket error");
91 
92         struct timeval tv = {TIMEOUT_FOR_CONNECT, 0};
93         setsockopt(engineSocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));
94         ret = connect(engineSocket, reinterpret_cast<sockaddr *>(&engineSin), sizeof(engineSin));
95         ENGINE_CHECK(ret == 0,
96             close(engineSocket);
97             checkCallback.callback(CheckStatus::CHECK_FAIL, duration_, checkResultList_, checkAndAuthInfo_);
98             return, "connect error");
99         NetworkResponse response {};
100         ret = ReadDataFromSSL(engineSocket, response);
101         ENGINE_CHECK(ret == 0,
102             close(engineSocket);
103             checkCallback.callback(CheckStatus::CHECK_FAIL, duration_, checkResultList_, checkAndAuthInfo_);
104             return, "SSL ReadData error");
105         close(engineSocket);
106         CheckStatus checkStatus;
107         if (response.status != static_cast<int64_t>(HttpConstant::SUCCESS) || response.content.empty()) {
108             checkStatus = CheckStatus::CHECK_FAIL;
109         } else {
110             nlohmann::json root = nlohmann::json::parse(response.content, nullptr, false);
111             if (!root.is_discarded()) {
112                 FIRMWARE_LONG_LOGI("FirmwareCheck response: %{public}s", root.dump().c_str());
113             }
114             FirmwareCheckAnalyzeUtils().DoAnalyze(response.content, checkResultList_, duration_, checkAndAuthInfo_);
115             checkStatus = CheckStatus::CHECK_SUCCESS;
116         }
117         checkCallback.callback(checkStatus, duration_, checkResultList_, checkAndAuthInfo_);
118     }
119 
120 private:
ParseJsonFile(const std::vector<char> & buffer,NetworkResponse & response)121     int32_t ParseJsonFile(const std::vector<char> &buffer, NetworkResponse &response)
122     {
123         response.content.assign(buffer.begin(), buffer.end());
124         response.status = static_cast<int64_t>(HttpConstant::SUCCESS);
125         cJSONPtr root(cJSON_Parse(buffer.data()), cJSON_Delete);
126         ENGINE_CHECK(root != nullptr, return -1, "Error get root");
127         cJSON *item = cJSON_GetObjectItem(root.get(), "searchStatus");
128         ENGINE_CHECK(root != nullptr, return -1, "Error get searchStatus");
129         if (!cJSON_IsNumber(item)) {
130             FIRMWARE_LOGE("Error json parse");
131             return -1;
132         }
133         return CAST_INT(static_cast<SearchStatus>(item->valueint));
134     }
135 
ReadDataFromSSL(int32_t engineSocket,NetworkResponse & response)136     int32_t ReadDataFromSSL(int32_t engineSocket, NetworkResponse &response)
137     {
138         SearchStatus result = SearchStatus::SERVER_BUSY;
139         std::string errMsg = "Couldn't connect to server";
140         std::vector<char> buffer(JSON_MAX_SIZE);
141 
142         SSL_library_init();
143         OpenSSL_add_all_algorithms();
144         SSL_load_error_strings();
145         SSL_CTX *sslCtx = SSL_CTX_new(SSLv23_client_method());
146         ENGINE_CHECK(sslCtx != nullptr, return -1, "sslCtx is nullptr");
147         SSL *ssl = SSL_new(sslCtx);
148         ENGINE_CHECK(ssl != nullptr,
149             SSL_CTX_free(sslCtx);
150             return -1,
151             "ssl is nullptr");
152         SSL_set_fd(ssl, engineSocket);
153         int32_t ret = SSL_connect(ssl);
154         if (ret != -1) {
155             int32_t len = SSL_read(ssl, buffer.data(), JSON_MAX_SIZE);
156             if (len > 0 && ParseJsonFile(buffer, response) == 0) {
157                 result = SearchStatus::HAS_NEW_VERSION;
158                 errMsg = "";
159             } else {
160                 result = SearchStatus::SYSTEM_ERROR;
161                 errMsg = "Couldn't read data";
162             }
163         } else {
164             result = SearchStatus::SYSTEM_ERROR;
165             errMsg = "Couldn't connect to server";
166         }
167         SSL_shutdown(ssl);
168         SSL_free(ssl);
169         SSL_CTX_free(sslCtx);
170         FIRMWARE_LOGI("ReadDataFromSSL errMsg: %s, result: %d", errMsg.c_str(), result);
171         return result == SearchStatus::HAS_NEW_VERSION ? 0 : -1;
172     }
173 
174     RequestType requestType_ = RequestType::CHECK;
175     Duration duration_;
176     CheckAndAuthInfo checkAndAuthInfo_;
177     std::vector<FirmwareComponent> checkResultList_;
178 };
179 } // namespace UpdateEngine
180 } // namespace OHOS
181 #endif // FIRMWARE_ICHECK_H