1 /*
2 * Copyright (c) 2023-2024 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 <cstring>
17 #include <map>
18 #include <securec.h>
19 #include <string>
20 #include <vector>
21
22 #define private public
23 #include "http_client.h"
24 #include "http_client_request.h"
25 #undef private
26 #include "http_request_options.h"
27 #include "netstack_log.h"
28 #include "secure_char.h"
29
30 namespace OHOS {
31 namespace NetStack {
32 namespace Http {
33 namespace {
34 using namespace OHOS::NetStack::HttpClient;
35 const uint8_t *g_baseFuzzData = nullptr;
36 size_t g_baseFuzzSize = 0;
37 size_t g_baseFuzzPos = 0;
38 constexpr size_t STR_LEN = 255;
39 constexpr int32_t TEST_PORT = 8888;
40 } // namespace
GetData()41 template <class T> T GetData()
42 {
43 T object{};
44 size_t objectSize = sizeof(object);
45 if (g_baseFuzzData == nullptr || g_baseFuzzSize <= g_baseFuzzPos || objectSize > g_baseFuzzSize - g_baseFuzzPos) {
46 return object;
47 }
48 if (memcpy_s(&object, objectSize, g_baseFuzzData + g_baseFuzzPos, objectSize)) {
49 return {};
50 }
51 g_baseFuzzPos += objectSize;
52 return object;
53 }
54
SetGlobalFuzzData(const uint8_t * data,size_t size)55 void SetGlobalFuzzData(const uint8_t *data, size_t size)
56 {
57 g_baseFuzzData = data;
58 g_baseFuzzSize = size;
59 g_baseFuzzPos = 0;
60 }
61
GetStringFromData(int strlen)62 std::string GetStringFromData(int strlen)
63 {
64 if (strlen < 1) {
65 return "";
66 }
67
68 char cstr[strlen];
69 cstr[strlen - 1] = '\0';
70 for (int i = 0; i < strlen - 1; i++) {
71 cstr[i] = GetData<char>();
72 }
73 std::string str(cstr);
74 return str;
75 }
76
SetCaPathFuzzTest(const uint8_t * data,size_t size)77 void SetCaPathFuzzTest(const uint8_t *data, size_t size)
78 {
79 if ((data == nullptr) || (size < 1)) {
80 return;
81 }
82 SetGlobalFuzzData(data, size);
83 std::string str = GetStringFromData(STR_LEN);
84
85 HttpRequestOptions requestOptions;
86 requestOptions.SetCaPath(str);
87 }
88
SetUrlFuzzTest(const uint8_t * data,size_t size)89 void SetUrlFuzzTest(const uint8_t *data, size_t size)
90 {
91 if ((data == nullptr) || (size < 1)) {
92 return;
93 }
94 SetGlobalFuzzData(data, size);
95 HttpRequestOptions requestOptions;
96 std::string str = GetStringFromData(STR_LEN);
97 requestOptions.SetUrl(str);
98 }
99
SetMethodFuzzTest(const uint8_t * data,size_t size)100 void SetMethodFuzzTest(const uint8_t *data, size_t size)
101 {
102 if ((data == nullptr) || (size < 1)) {
103 return;
104 }
105 SetGlobalFuzzData(data, size);
106 HttpRequestOptions requestOptions;
107 std::string str = GetStringFromData(STR_LEN);
108 requestOptions.SetMethod(str);
109 }
110
SetHeaderFuzzTest(const uint8_t * data,size_t size)111 void SetHeaderFuzzTest(const uint8_t *data, size_t size)
112 {
113 if ((data == nullptr) || (size < 1)) {
114 return;
115 }
116 SetGlobalFuzzData(data, size);
117 HttpRequestOptions requestOptions;
118 std::string str = GetStringFromData(STR_LEN);
119 requestOptions.SetHeader(str, str);
120 }
121
SetReadTimeoutFuzzTest(const uint8_t * data,size_t size)122 void SetReadTimeoutFuzzTest(const uint8_t *data, size_t size)
123 {
124 if ((data == nullptr) || (size < 1)) {
125 return;
126 }
127 SetGlobalFuzzData(data, size);
128 HttpRequestOptions requestOptions;
129 requestOptions.SetReadTimeout(size);
130 }
131
SetConnectTimeoutFuzzTest(const uint8_t * data,size_t size)132 void SetConnectTimeoutFuzzTest(const uint8_t *data, size_t size)
133 {
134 if ((data == nullptr) || (size < 1)) {
135 return;
136 }
137 SetGlobalFuzzData(data, size);
138 HttpRequestOptions requestOptions;
139 requestOptions.SetConnectTimeout(size);
140 }
141
SetUsingProtocolFuzzTest(const uint8_t * data,size_t size)142 void SetUsingProtocolFuzzTest(const uint8_t *data, size_t size)
143 {
144 if ((data == nullptr) || (size < 1)) {
145 return;
146 }
147 SetGlobalFuzzData(data, size);
148 HttpRequestOptions requestOptions;
149 }
150
SetHttpDataTypeFuzzTest(const uint8_t * data,size_t size)151 void SetHttpDataTypeFuzzTest(const uint8_t *data, size_t size)
152 {
153 if ((data == nullptr) || (size < 1)) {
154 return;
155 }
156 SetGlobalFuzzData(data, size);
157 HttpRequestOptions requestOptions;
158 std::string str = GetStringFromData(STR_LEN);
159 requestOptions.SetRequestTime(str);
160 }
161
SetUsingHttpProxyTypeFuzzTest(const uint8_t * data,size_t size)162 void SetUsingHttpProxyTypeFuzzTest(const uint8_t *data, size_t size)
163 {
164 if ((data == nullptr) || (size < 1)) {
165 return;
166 }
167 SetGlobalFuzzData(data, size);
168 HttpRequestOptions requestOptions;
169 requestOptions.SetUsingHttpProxyType(UsingHttpProxyType::USE_SPECIFIED);
170 }
171
SetSpecifiedHttpProxyFuzzTest(const uint8_t * data,size_t size)172 void SetSpecifiedHttpProxyFuzzTest(const uint8_t *data, size_t size)
173 {
174 if ((data == nullptr) || (size < 1)) {
175 return;
176 }
177 SetGlobalFuzzData(data, size);
178 HttpRequestOptions requestOptions;
179 std::string str = GetStringFromData(STR_LEN);
180 requestOptions.SetSpecifiedHttpProxy(str, size, str);
181 }
182
SetDnsServersFuzzTest(const uint8_t * data,size_t size)183 void SetDnsServersFuzzTest(const uint8_t *data, size_t size)
184 {
185 if ((data == nullptr) || (size < 1)) {
186 return;
187 }
188 SetGlobalFuzzData(data, size);
189 HttpRequestOptions requestOptions;
190 std::vector<std::string> dnsServers = { GetStringFromData(STR_LEN), GetStringFromData(STR_LEN),
191 GetStringFromData(STR_LEN) };
192 requestOptions.SetDnsServers(dnsServers);
193 }
194
SetDohUrlFuzzTest(const uint8_t * data,size_t size)195 void SetDohUrlFuzzTest(const uint8_t *data, size_t size)
196 {
197 if ((data == nullptr) || (size < 1)) {
198 return;
199 }
200 SetGlobalFuzzData(data, size);
201
202 HttpRequestOptions requestOptions;
203 std::string str = GetStringFromData(STR_LEN);
204 requestOptions.SetDohUrl(str);
205 }
206
SetRangeNumberFuzzTest(const uint8_t * data,size_t size)207 void SetRangeNumberFuzzTest(const uint8_t *data, size_t size)
208 {
209 if ((data == nullptr) || (size < 1)) {
210 return;
211 }
212 SetGlobalFuzzData(data, size);
213 HttpRequestOptions requestOptions;
214 requestOptions.SetRangeNumber(size, size);
215 }
216
SetClientCertFuzzTest(const uint8_t * data,size_t size)217 void SetClientCertFuzzTest(const uint8_t *data, size_t size)
218 {
219 if ((data == nullptr) || (size < 1)) {
220 return;
221 }
222 SetGlobalFuzzData(data, size);
223
224 HttpRequestOptions requestOptions;
225 std::string str = GetStringFromData(STR_LEN);
226 Secure::SecureChar pwd(str);
227 requestOptions.SetClientCert(str, str, str, pwd);
228 }
229
AddMultiFormDataFuzzTest(const uint8_t * data,size_t size)230 void AddMultiFormDataFuzzTest(const uint8_t *data, size_t size)
231 {
232 if ((data == nullptr) || (size < 1)) {
233 return;
234 }
235 SetGlobalFuzzData(data, size);
236 HttpRequestOptions requestOptions;
237 MultiFormData multiFormData;
238 std::string str = GetStringFromData(STR_LEN);
239 multiFormData.name = str;
240 multiFormData.data = str;
241 multiFormData.contentType = str;
242 multiFormData.remoteFileName = str;
243 multiFormData.filePath = str;
244 requestOptions.AddMultiFormData(multiFormData);
245 }
246
CreateHttpClientRequest()247 HttpClientRequest CreateHttpClientRequest()
248 {
249 HttpClientRequest httpReq;
250 std::string url = "https://www.baidu.com";
251 httpReq.SetURL(url);
252 return httpReq;
253 }
254
CreateHttpClientRequest(const uint8_t * data,size_t size)255 HttpClientRequest CreateHttpClientRequest(const uint8_t *data, size_t size)
256 {
257 g_baseFuzzData = data;
258 g_baseFuzzSize = size;
259 g_baseFuzzPos = 0;
260 HttpClientRequest httpReq;
261 std::string str = GetStringFromData(STR_LEN);
262 httpReq.SetURL(str);
263 return httpReq;
264 }
265
HttpSessionCreateTaskFuzzTest(const uint8_t * data,size_t size)266 void HttpSessionCreateTaskFuzzTest(const uint8_t *data, size_t size)
267 {
268 if ((data == nullptr) || (size < 1)) {
269 return;
270 }
271 HttpClientRequest httpReq = CreateHttpClientRequest();
272 auto testTask = HttpSession::GetInstance().CreateTask(httpReq);
273 testTask->Start();
274
275 httpReq = CreateHttpClientRequest(data, size);
276 testTask = HttpSession::GetInstance().CreateTask(httpReq);
277 testTask->Start();
278 }
279
HttpClientTaskGetHttpVersionFuzzTest(const uint8_t * data,size_t size)280 void HttpClientTaskGetHttpVersionFuzzTest(const uint8_t *data, size_t size)
281 {
282 if ((data == nullptr) || (size < 1)) {
283 return;
284 }
285
286 HttpClientRequest httpReq = CreateHttpClientRequest();
287 auto task = HttpSession::GetInstance().CreateTask(httpReq);
288 HttpClient::HttpProtocol ptcl = HttpClient::HttpProtocol::HTTP1_1;
289 HttpClientRequest request;
290 request.SetHttpProtocol(ptcl);
291 uint32_t timeout = GetData<uint32_t>();
292 request.SetTimeout(timeout);
293 std::string testData = GetStringFromData(STR_LEN);
294 std::string result = request.GetBody();
295 request.body_ = "";
296 request.SetCaPath(testData);
297 uint32_t priority = GetData<uint32_t>();
298 request.SetPriority(priority);
299 result = request.GetURL();
300 result = request.GetMethod();
301 uint32_t ret = request.GetTimeout();
302 ret = request.GetConnectTimeout();
303 ptcl = request.GetHttpProtocol();
304 HttpClient::HttpProxyType proType = request.GetHttpProxyType();
305 NETSTACK_LOGD("ptcl = %{private}d, proType = %{private}d", ptcl, proType);
306 result = request.GetCaPath();
307 ret = request.GetPriority();
308 HttpProxy proxy = request.GetHttpProxy();
309 request.SetRequestTime(testData);
310 result = request.GetRequestTime();
311 task->GetHttpVersion(ptcl);
312 }
313
HttpClientTaskSetHttpProtocolFuzzTest(const uint8_t * data,size_t size)314 void HttpClientTaskSetHttpProtocolFuzzTest(const uint8_t *data, size_t size)
315 {
316 if ((data == nullptr) || (size < 1)) {
317 return;
318 }
319
320 HttpClientRequest httpReq = CreateHttpClientRequest(data, size);
321 auto task = HttpSession::GetInstance().CreateTask(httpReq);
322 HttpClientRequest request;
323 HttpClient::HttpProtocol ptcl = HttpClient::HttpProtocol::HTTP1_1;
324 request.SetHttpProtocol(ptcl);
325 HttpProxy proxy = request.GetHttpProxy();
326 std::string testData = GetStringFromData(STR_LEN);
327 request.SetCaPath(testData);
328 request.SetRequestTime(testData);
329 std::string result = request.GetRequestTime();
330 result = request.GetBody();
331 request.body_ = "";
332 task->GetHttpVersion(ptcl);
333 result = request.GetURL();
334 result = request.GetMethod();
335 result = request.GetCaPath();
336 uint32_t timeout = GetData<uint32_t>();
337 request.SetTimeout(timeout);
338 uint32_t prio = GetData<uint32_t>();
339 request.SetPriority(prio);
340 uint32_t ret = request.GetTimeout();
341 ret = request.GetConnectTimeout();
342 ret = request.GetPriority();
343 ptcl = request.GetHttpProtocol();
344 HttpClient::HttpProxyType proType = request.GetHttpProxyType();
345 NETSTACK_LOGD("ptcl = %{private}d, proType = %{private}d", ptcl, proType);
346 }
347
HttpClientTaskSetOtherCurlOptionFuzzTest(const uint8_t * data,size_t size)348 void HttpClientTaskSetOtherCurlOptionFuzzTest(const uint8_t *data, size_t size)
349 {
350 if ((data == nullptr) || (size < 1)) {
351 return;
352 }
353
354 HttpClientRequest request;
355 std::string url = "http://www.httpbin.org/get";
356 request.SetURL(url);
357 request.SetHttpProxyType(NOT_USE);
358 HttpProxy testProxy;
359 testProxy.host = "192.168.147.60";
360 testProxy.exclusions = "www.httpbin.org";
361 testProxy.port = TEST_PORT;
362 testProxy.tunnel = false;
363 request.SetHttpProxy(testProxy);
364 auto task = HttpSession::GetInstance().CreateTask(request);
365 task->SetOtherCurlOption(task->curlHandle_);
366
367 request = CreateHttpClientRequest(data, size);
368 task = HttpSession::GetInstance().CreateTask(request);
369 task->SetOtherCurlOption(task->curlHandle_);
370 }
371
HttpClientTaskSetCurlOptionsFuzzTest(const uint8_t * data,size_t size)372 void HttpClientTaskSetCurlOptionsFuzzTest(const uint8_t *data, size_t size)
373 {
374 if ((data == nullptr) || (size < 1)) {
375 return;
376 }
377
378 HttpClientRequest httpReq;
379 std::string url = "http://www.httpbin.org/get";
380 httpReq.SetURL(url);
381 auto task = HttpSession::GetInstance().CreateTask(httpReq);
382 task->request_.SetMethod(HttpConstant::HTTP_METHOD_HEAD);
383 task->SetCurlOptions();
384
385 httpReq = CreateHttpClientRequest(data, size);
386 task = HttpSession::GetInstance().CreateTask(httpReq);
387 task->request_.SetMethod(HttpConstant::HTTP_METHOD_HEAD);
388 task->SetCurlOptions();
389 }
390
HttpClientTaskGetTypeFuzzTest(const uint8_t * data,size_t size)391 void HttpClientTaskGetTypeFuzzTest(const uint8_t *data, size_t size)
392 {
393 if ((data == nullptr) || (size < 1)) {
394 return;
395 }
396
397 HttpClientRequest httpReq = CreateHttpClientRequest();
398 auto task = HttpSession::GetInstance().CreateTask(httpReq);
399 TaskType type = task->GetType();
400 std::string result = task->GetFilePath();
401 int taskId = task->GetTaskId();
402 TaskStatus status = static_cast<TaskStatus>(size % 2);
403 task->SetStatus(status);
404 status = task->GetStatus();
405 NETSTACK_LOGD("type = %{private}d, result = %{private}s, taskId = %{private}d, status = %{private}d", type,
406 result.c_str(), taskId, status);
407 task->OnSuccess([task](const HttpClientRequest &request, const HttpClientResponse &response) {});
408 task->OnCancel([](const HttpClientRequest &request, const HttpClientResponse &response) {});
409 task->OnFail(
410 [](const HttpClientRequest &request, const HttpClientResponse &response, const HttpClientError &error) {});
411 task->OnDataReceive([](const HttpClientRequest &request, const uint8_t *data, size_t length) {});
412 task->OnProgress(
413 [](const HttpClientRequest &request, u_long dltotal, u_long dlnow, u_long ultotal, u_long ulnow) {});
414 task->OnDataReceive([](const HttpClientRequest &request, const uint8_t *data, size_t length) {});
415 httpReq = CreateHttpClientRequest(data, size);
416 task = HttpSession::GetInstance().CreateTask(httpReq);
417 type = task->GetType();
418 result = task->GetFilePath();
419 taskId = task->GetTaskId();
420 status = task->GetStatus();
421 task->SetStatus(status);
422 }
423 } // namespace Http
424 } // namespace NetStack
425 } // namespace OHOS
426
427 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)428 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
429 {
430 /* Run your code on data */
431 OHOS::NetStack::Http::SetCaPathFuzzTest(data, size);
432 OHOS::NetStack::Http::SetUrlFuzzTest(data, size);
433 OHOS::NetStack::Http::SetMethodFuzzTest(data, size);
434 OHOS::NetStack::Http::SetHeaderFuzzTest(data, size);
435 OHOS::NetStack::Http::SetReadTimeoutFuzzTest(data, size);
436 OHOS::NetStack::Http::SetConnectTimeoutFuzzTest(data, size);
437 OHOS::NetStack::Http::SetUsingProtocolFuzzTest(data, size);
438 OHOS::NetStack::Http::SetHttpDataTypeFuzzTest(data, size);
439 OHOS::NetStack::Http::SetUsingHttpProxyTypeFuzzTest(data, size);
440 OHOS::NetStack::Http::SetSpecifiedHttpProxyFuzzTest(data, size);
441 OHOS::NetStack::Http::SetDnsServersFuzzTest(data, size);
442 OHOS::NetStack::Http::SetDohUrlFuzzTest(data, size);
443 OHOS::NetStack::Http::SetRangeNumberFuzzTest(data, size);
444 OHOS::NetStack::Http::SetClientCertFuzzTest(data, size);
445 OHOS::NetStack::Http::AddMultiFormDataFuzzTest(data, size);
446 OHOS::NetStack::Http::HttpSessionCreateTaskFuzzTest(data, size);
447 OHOS::NetStack::Http::HttpClientTaskGetHttpVersionFuzzTest(data, size);
448 OHOS::NetStack::Http::HttpClientTaskSetHttpProtocolFuzzTest(data, size);
449 OHOS::NetStack::Http::HttpClientTaskSetOtherCurlOptionFuzzTest(data, size);
450 OHOS::NetStack::Http::HttpClientTaskSetCurlOptionsFuzzTest(data, size);
451 OHOS::NetStack::Http::HttpClientTaskGetTypeFuzzTest(data, size);
452 return 0;
453 }