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 }