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