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 30namespace OHOS { 31namespace NetStack { 32namespace Http { 33namespace { 34using namespace OHOS::NetStack::HttpClient; 35const uint8_t *g_baseFuzzData = nullptr; 36size_t g_baseFuzzSize = 0; 37size_t g_baseFuzzPos = 0; 38constexpr size_t STR_LEN = 255; 39constexpr int32_t TEST_PORT = 8888; 40} // namespace 41template <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 55void SetGlobalFuzzData(const uint8_t *data, size_t size) 56{ 57 g_baseFuzzData = data; 58 g_baseFuzzSize = size; 59 g_baseFuzzPos = 0; 60} 61 62std::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 77void 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 89void 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 100void 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 111void 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 122void 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 132void 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 142void 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 151void 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 162void 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 172void 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 183void 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 195void 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 207void 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 217void 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 230void 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 247HttpClientRequest CreateHttpClientRequest() 248{ 249 HttpClientRequest httpReq; 250 std::string url = "https://www.baidu.com"; 251 httpReq.SetURL(url); 252 return httpReq; 253} 254 255HttpClientRequest 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 266void 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 280void 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 314void 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 348void 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 372void 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 391void 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 */ 428extern "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}