Coverage Report

Created: 2024-05-21 06:52

/src/curl_fuzzer/curl_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 2017 - 2022, Max Dymond, <cmeister2@gmail.com>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 ***************************************************************************/
22
23
#include <stdlib.h>
24
#include <signal.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <curl/curl.h>
28
#include "curl_fuzzer.h"
29
30
/**
31
 * Fuzzing entry point. This function is passed a buffer containing a test
32
 * case.  This test case should drive the CURL API into making a request.
33
 */
34
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
35
85.1k
{
36
85.1k
  int rc = 0;
37
85.1k
  int tlv_rc;
38
85.1k
  FUZZ_DATA fuzz;
39
85.1k
  TLV tlv;
40
41
  /* Ignore SIGPIPE errors. We'll handle the errors ourselves. */
42
85.1k
  signal(SIGPIPE, SIG_IGN);
43
44
  /* Have to set all fields to zero before getting to the terminate function */
45
85.1k
  memset(&fuzz, 0, sizeof(FUZZ_DATA));
46
47
85.1k
  if(size < sizeof(TLV_RAW)) {
48
    /* Not enough data for a single TLV - don't continue */
49
56
    goto EXIT_LABEL;
50
56
  }
51
52
  /* Try to initialize the fuzz data */
53
85.0k
  FTRY(fuzz_initialize_fuzz_data(&fuzz, data, size));
54
55
85.0k
  for(tlv_rc = fuzz_get_first_tlv(&fuzz, &tlv);
56
6.66M
      tlv_rc == 0;
57
6.58M
      tlv_rc = fuzz_get_next_tlv(&fuzz, &tlv)) {
58
59
    /* Have the TLV in hand. Parse the TLV. */
60
6.58M
    rc = fuzz_parse_tlv(&fuzz, &tlv);
61
62
6.58M
    if(rc != 0) {
63
      /* Failed to parse the TLV. Can't continue. */
64
3.75k
      goto EXIT_LABEL;
65
3.75k
    }
66
6.58M
  }
67
68
81.2k
  if(tlv_rc != TLV_RC_NO_MORE_TLVS) {
69
    /* A TLV call failed. Can't continue. */
70
1.32k
    goto EXIT_LABEL;
71
1.32k
  }
72
73
  /* Set up the standard easy options. */
74
79.9k
  FTRY(fuzz_set_easy_options(&fuzz));
75
76
  /**
77
   * Add in more curl options that have been accumulated over possibly
78
   * multiple TLVs.
79
   */
80
79.9k
  if(fuzz.header_list != NULL) {
81
6.48k
    curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
82
6.48k
  }
83
84
79.9k
  if(fuzz.mail_recipients_list != NULL) {
85
1.82k
    curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list);
86
1.82k
  }
87
88
79.9k
  if(fuzz.mime != NULL) {
89
5.57k
    curl_easy_setopt(fuzz.easy, CURLOPT_MIMEPOST, fuzz.mime);
90
5.57k
  }
91
92
79.9k
  if (fuzz.httppost != NULL) {
93
1.05k
    curl_easy_setopt(fuzz.easy, CURLOPT_HTTPPOST, fuzz.httppost);
94
1.05k
  }
95
96
  /* Run the transfer. */
97
79.9k
  fuzz_handle_transfer(&fuzz);
98
99
85.1k
EXIT_LABEL:
100
101
85.1k
  fuzz_terminate_fuzz_data(&fuzz);
102
103
  /* This function must always return 0. Non-zero codes are reserved. */
104
85.1k
  return 0;
105
79.9k
}
106
107
/**
108
 * Utility function to convert 4 bytes to a u32 predictably.
109
 */
110
uint32_t to_u32(const uint8_t b[4])
111
8.41M
{
112
8.41M
  uint32_t u;
113
8.41M
  u = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3];
114
8.41M
  return u;
115
8.41M
}
116
117
/**
118
 * Utility function to convert 2 bytes to a u16 predictably.
119
 */
120
uint16_t to_u16(const uint8_t b[2])
121
8.38M
{
122
8.38M
  uint16_t u;
123
8.38M
  u = (b[0] << 8) + b[1];
124
8.38M
  return u;
125
8.38M
}
126
127
/**
128
 * Initialize the local fuzz data structure.
129
 */
130
int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
131
                              const uint8_t *data,
132
                              size_t data_len)
133
85.0k
{
134
85.0k
  int rc = 0;
135
85.0k
  int ii;
136
137
  /* Initialize the fuzz data. */
138
85.0k
  memset(fuzz, 0, sizeof(FUZZ_DATA));
139
140
  /* Create an easy handle. This will have all of the settings configured on
141
     it. */
142
85.0k
  fuzz->easy = curl_easy_init();
143
85.0k
  FCHECK(fuzz->easy != NULL);
144
145
  /* Set up the state parser */
146
85.0k
  fuzz->state.data = data;
147
85.0k
  fuzz->state.data_len = data_len;
148
149
  /* Set up the state of the server sockets. */
150
255k
  for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
151
170k
    fuzz->sockman[ii].index = ii;
152
170k
    fuzz->sockman[ii].fd_state = FUZZ_SOCK_CLOSED;
153
170k
  }
154
155
  /* Check for verbose mode. */
156
85.0k
  fuzz->verbose = (getenv("FUZZ_VERBOSE") != NULL);
157
158
85.0k
  FCHECK(setenv("CURL_HSTS_HTTP", "1", 0) == 0);
159
85.0k
  FCHECK(setenv("CURL_ALTSVC_HTTP", "1", 0) == 0);
160
161
85.0k
EXIT_LABEL:
162
163
85.0k
  return rc;
164
85.0k
}
165
166
/**
167
 * Set standard options on the curl easy.
168
 */
169
int fuzz_set_easy_options(FUZZ_DATA *fuzz)
170
79.9k
{
171
79.9k
  int rc = 0;
172
79.9k
  unsigned long allowed_protocols;
173
174
  /* Set some standard options on the CURL easy handle. We need to override the
175
     socket function so that we create our own sockets to present to CURL. */
176
79.9k
  FTRY(curl_easy_setopt(fuzz->easy,
177
79.9k
                        CURLOPT_OPENSOCKETFUNCTION,
178
79.9k
                        fuzz_open_socket));
179
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_OPENSOCKETDATA, fuzz));
180
181
  /* In case something tries to set a socket option, intercept this. */
182
79.9k
  FTRY(curl_easy_setopt(fuzz->easy,
183
79.9k
                        CURLOPT_SOCKOPTFUNCTION,
184
79.9k
                        fuzz_sockopt_callback));
185
186
  /* Set the standard read function callback. */
187
79.9k
  FTRY(curl_easy_setopt(fuzz->easy,
188
79.9k
                        CURLOPT_READFUNCTION,
189
79.9k
                        fuzz_read_callback));
190
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz));
191
192
  /* Set the standard write function callback. */
193
79.9k
  FTRY(curl_easy_setopt(fuzz->easy,
194
79.9k
                        CURLOPT_WRITEFUNCTION,
195
79.9k
                        fuzz_write_callback));
196
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_WRITEDATA, fuzz));
197
198
  /* Set the writable cookie jar path so cookies are tested. */
199
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_COOKIEJAR, FUZZ_COOKIE_JAR_PATH));
200
201
  /* Set the RO cookie file path so cookies are tested. */
202
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_COOKIEFILE, FUZZ_RO_COOKIE_FILE_PATH));
203
204
  /* Set altsvc header cache filepath so that it can be fuzzed. */
205
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_ALTSVC, FUZZ_ALT_SVC_HEADER_CACHE_PATH));
206
207
  /* Set the hsts header cache filepath so that it can be fuzzed. */
208
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_HSTS, FUZZ_HSTS_HEADER_CACHE_PATH));
209
210
  /* Set the Certificate Revocation List file path so it can be fuzzed */
211
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_CRLFILE, FUZZ_CRL_FILE_PATH));
212
213
  /* Set the .netrc file path so it can be fuzzed */
214
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_NETRC_FILE, FUZZ_NETRC_FILE_PATH));
215
216
  /* Time out requests quickly. */
217
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_TIMEOUT_MS, 200L));
218
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_SERVER_RESPONSE_TIMEOUT, 1L));
219
220
  /* Can enable verbose mode by having the environment variable FUZZ_VERBOSE. */
221
79.9k
  if(fuzz->verbose) {
222
0
    FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 1L));
223
0
  }
224
225
  /* Force resolution of all addresses to a specific IP address. */
226
79.9k
  fuzz->connect_to_list = curl_slist_append(NULL, "::127.0.1.127:");
227
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_CONNECT_TO, fuzz->connect_to_list));
228
229
  /* Limit the protocols in use by this fuzzer. */
230
79.9k
  FTRY(fuzz_set_allowed_protocols(fuzz));
231
232
79.9k
EXIT_LABEL:
233
234
79.9k
  return rc;
235
79.9k
}
236
237
/**
238
 * Terminate the fuzz data structure, including freeing any allocated memory.
239
 */
240
void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
241
85.1k
{
242
85.1k
  int ii;
243
244
85.1k
  fuzz_free((void **)&fuzz->postfields);
245
246
255k
  for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
247
170k
    if(fuzz->sockman[ii].fd_state != FUZZ_SOCK_CLOSED) {
248
58.2k
      close(fuzz->sockman[ii].fd);
249
58.2k
      fuzz->sockman[ii].fd_state = FUZZ_SOCK_CLOSED;
250
58.2k
    }
251
170k
  }
252
253
85.1k
  if(fuzz->connect_to_list != NULL) {
254
79.9k
    curl_slist_free_all(fuzz->connect_to_list);
255
79.9k
    fuzz->connect_to_list = NULL;
256
79.9k
  }
257
258
85.1k
  if(fuzz->header_list != NULL) {
259
6.60k
    curl_slist_free_all(fuzz->header_list);
260
6.60k
    fuzz->header_list = NULL;
261
6.60k
  }
262
263
85.1k
  if(fuzz->mail_recipients_list != NULL) {
264
1.91k
    curl_slist_free_all(fuzz->mail_recipients_list);
265
1.91k
    fuzz->mail_recipients_list = NULL;
266
1.91k
  }
267
268
85.1k
  if(fuzz->mime != NULL) {
269
5.92k
    curl_mime_free(fuzz->mime);
270
5.92k
    fuzz->mime = NULL;
271
5.92k
  }
272
273
85.1k
  if(fuzz->easy != NULL) {
274
85.0k
    curl_easy_cleanup(fuzz->easy);
275
85.0k
    fuzz->easy = NULL;
276
85.0k
  }
277
278
  /* When you have passed the struct curl_httppost pointer to curl_easy_setopt
279
   * (using the CURLOPT_HTTPPOST option), you must not free the list until after
280
   *  you have called curl_easy_cleanup for the curl handle.
281
   *  https://curl.se/libcurl/c/curl_formadd.html */
282
85.1k
  if (fuzz->httppost != NULL) {
283
1.13k
    curl_formfree(fuzz->httppost);
284
1.13k
    fuzz->httppost = NULL;
285
1.13k
  }
286
287
  // free after httppost and last_post_part.
288
85.1k
  if (fuzz->post_body != NULL) {
289
1.13k
    fuzz_free((void **)&fuzz->post_body);
290
1.13k
  }
291
85.1k
}
292
293
/**
294
 * If a pointer has been allocated, free that pointer.
295
 */
296
void fuzz_free(void **ptr)
297
8.19M
{
298
8.19M
  if(*ptr != NULL) {
299
1.86M
    free(*ptr);
300
1.86M
    *ptr = NULL;
301
1.86M
  }
302
8.19M
}
303
304
/**
305
 * Function for handling the fuzz transfer, including sending responses to
306
 * requests.
307
 */
308
int fuzz_handle_transfer(FUZZ_DATA *fuzz)
309
79.9k
{
310
79.9k
  int rc = 0;
311
79.9k
  CURLM *multi_handle;
312
79.9k
  int still_running; /* keep number of running handles */
313
79.9k
  CURLMsg *msg; /* for picking up messages with the transfer status */
314
79.9k
  int msgs_left; /* how many messages are left */
315
79.9k
  int double_timeout = 0;
316
79.9k
  fd_set fdread;
317
79.9k
  fd_set fdwrite;
318
79.9k
  fd_set fdexcep;
319
79.9k
  struct timeval timeout;
320
79.9k
  int select_rc;
321
79.9k
  CURLMcode mc;
322
79.9k
  int maxfd = -1;
323
79.9k
  long curl_timeo = -1;
324
79.9k
  int ii;
325
79.9k
  FUZZ_SOCKET_MANAGER *sman[FUZZ_NUM_CONNECTIONS];
326
327
239k
  for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
328
159k
    sman[ii] = &fuzz->sockman[ii];
329
330
    /* Set up the starting index for responses. */
331
159k
    sman[ii]->response_index = 1;
332
159k
  }
333
334
  /* init a multi stack */
335
79.9k
  multi_handle = curl_multi_init();
336
337
  /* add the individual transfers */
338
79.9k
  curl_multi_add_handle(multi_handle, fuzz->easy);
339
340
  /* Do an initial process. This might end the transfer immediately. */
341
79.9k
  curl_multi_perform(multi_handle, &still_running);
342
79.9k
  FV_PRINTF(fuzz,
343
79.9k
            "FUZZ: Initial perform; still running? %d \n",
344
79.9k
            still_running);
345
346
36.8M
  while(still_running) {
347
    /* Reset the sets of file descriptors. */
348
36.7M
    FD_ZERO(&fdread);
349
36.7M
    FD_ZERO(&fdwrite);
350
36.7M
    FD_ZERO(&fdexcep);
351
352
    /* Set a timeout of 10ms. This is lower than recommended by the multi guide
353
       but we're not going to any remote servers, so everything should complete
354
       very quickly. */
355
36.7M
    timeout.tv_sec = 0;
356
36.7M
    timeout.tv_usec = 10000;
357
358
    /* get file descriptors from the transfers */
359
36.7M
    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
360
36.7M
    if(mc != CURLM_OK) {
361
0
      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
362
0
      rc = -1;
363
0
      break;
364
0
    }
365
366
110M
    for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
367
      /* Add the socket FD into the readable set if connected. */
368
73.5M
      if(sman[ii]->fd_state == FUZZ_SOCK_OPEN) {
369
7.11M
        FD_SET(sman[ii]->fd, &fdread);
370
371
        /* Work out the maximum FD between the cURL file descriptors and the
372
           server FD. */
373
7.11M
        maxfd = FUZZ_MAX(sman[ii]->fd, maxfd);
374
7.11M
      }
375
73.5M
    }
376
377
    /* Work out what file descriptors need work. */
378
36.7M
    rc = fuzz_select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
379
380
36.7M
    if(rc == -1) {
381
      /* Had an issue while selecting a file descriptor. Let's just exit. */
382
0
      FV_PRINTF(fuzz, "FUZZ: select failed, exiting \n");
383
0
      break;
384
0
    }
385
36.7M
    else if(rc == 0) {
386
1.76k
      FV_PRINTF(fuzz,
387
1.76k
                "FUZZ: Timed out; double timeout? %d \n",
388
1.76k
                double_timeout);
389
390
      /* Timed out. */
391
1.76k
      if(double_timeout == 1) {
392
        /* We don't expect multiple timeouts in a row. If there are double
393
           timeouts then exit. */
394
871
        break;
395
871
      }
396
897
      else {
397
        /* Set the timeout flag for the next time we select(). */
398
897
        double_timeout = 1;
399
897
      }
400
1.76k
    }
401
36.7M
    else {
402
      /* There's an active file descriptor. Reset the timeout flag. */
403
36.7M
      double_timeout = 0;
404
36.7M
    }
405
406
    /* Check to see if a server file descriptor is readable. If it is,
407
       then send the next response from the fuzzing data. */
408
110M
    for(ii = 0; ii < FUZZ_NUM_CONNECTIONS; ii++) {
409
73.5M
      if(sman[ii]->fd_state == FUZZ_SOCK_OPEN &&
410
73.5M
         FD_ISSET(sman[ii]->fd, &fdread)) {
411
36.8k
        rc = fuzz_send_next_response(fuzz, sman[ii]);
412
36.8k
        if(rc != 0) {
413
          /* Failed to send a response. Break out here. */
414
299
          break;
415
299
        }
416
36.8k
      }
417
73.5M
    }
418
419
36.7M
    curl_multi_perform(multi_handle, &still_running);
420
36.7M
  }
421
422
  /* Remove the easy handle from the multi stack. */
423
79.9k
  curl_multi_remove_handle(multi_handle, fuzz->easy);
424
425
  /* Clean up the multi handle - the top level function will handle the easy
426
     handle. */
427
79.9k
  curl_multi_cleanup(multi_handle);
428
429
79.9k
  return(rc);
430
79.9k
}
431
432
/**
433
 * Sends the next fuzzing response to the server file descriptor.
434
 */
435
int fuzz_send_next_response(FUZZ_DATA *fuzz, FUZZ_SOCKET_MANAGER *sman)
436
36.8k
{
437
36.8k
  int rc = 0;
438
36.8k
  ssize_t ret_in;
439
36.8k
  ssize_t ret_out;
440
36.8k
  char buffer[8192];
441
36.8k
  const uint8_t *data;
442
36.8k
  size_t data_len;
443
444
  /* Need to read all data sent by the client so the file descriptor becomes
445
     unreadable. Because the file descriptor is non-blocking we won't just
446
     hang here. */
447
87.6k
  do {
448
87.6k
    ret_in = read(sman->fd, buffer, sizeof(buffer));
449
87.6k
    if(fuzz->verbose && ret_in > 0) {
450
0
      printf("FUZZ[%d]: Received %zu bytes \n==>\n", sman->index, ret_in);
451
0
      fwrite(buffer, ret_in, 1, stdout);
452
0
      printf("\n<==\n");
453
0
    }
454
87.6k
  } while (ret_in > 0);
455
456
  /* Now send a response to the request that the client just made. */
457
36.8k
  FV_PRINTF(fuzz,
458
36.8k
            "FUZZ[%d]: Sending next response: %d \n",
459
36.8k
            sman->index,
460
36.8k
            sman->response_index);
461
36.8k
  data = sman->responses[sman->response_index].data;
462
36.8k
  data_len = sman->responses[sman->response_index].data_len;
463
464
36.8k
  if(data != NULL) {
465
36.8k
    if(write(sman->fd, data, data_len) != (ssize_t)data_len) {
466
      /* Failed to write the data back to the client. Prevent any further
467
         testing. */
468
299
      rc = -1;
469
299
    }
470
36.8k
  }
471
472
  /* Work out if there are any more responses. If not, then shut down the
473
     server. */
474
36.8k
  sman->response_index++;
475
476
36.8k
  if(sman->response_index >= TLV_MAX_NUM_RESPONSES ||
477
36.8k
     sman->responses[sman->response_index].data == NULL) {
478
21.4k
    FV_PRINTF(fuzz,
479
21.4k
              "FUZZ[%d]: Shutting down server socket: %d \n",
480
21.4k
              sman->index,
481
21.4k
              sman->fd);
482
21.4k
    shutdown(sman->fd, SHUT_WR);
483
21.4k
    sman->fd_state = FUZZ_SOCK_SHUTDOWN;
484
21.4k
  }
485
486
36.8k
  return(rc);
487
36.8k
}
488
489
/**
490
 * Wrapper for select() so profiling can track it.
491
 */
492
int fuzz_select(int nfds,
493
                fd_set *readfds,
494
                fd_set *writefds,
495
                fd_set *exceptfds,
496
36.7M
                struct timeval *timeout) {
497
36.7M
  return select(nfds, readfds, writefds, exceptfds, timeout);
498
36.7M
}
499
500
/**
501
 * Set allowed protocols based on the compile options.
502
 *
503
 * Note that it can only use ONE of the FUZZ_PROTOCOLS_* defines.a
504
 */
505
int fuzz_set_allowed_protocols(FUZZ_DATA *fuzz)
506
79.9k
{
507
79.9k
  int rc = 0;
508
79.9k
  const char *allowed_protocols = "";
509
510
#ifdef FUZZ_PROTOCOLS_ALL
511
  /* Do not allow telnet currently as it accepts input from stdin. */
512
  allowed_protocols =
513
    "dict,file,ftp,ftps,gopher,gophers,http,https,imap,imaps,"
514
    "mqtt,pop3,pop3s,"
515
    "rtsp,smb,smbs,smtp,smtps,tftp";
516
#endif
517
#ifdef FUZZ_PROTOCOLS_DICT
518
  allowed_protocols = "dict";
519
#endif
520
#ifdef FUZZ_PROTOCOLS_FILE
521
  allowed_protocols = "file";
522
#endif
523
#ifdef FUZZ_PROTOCOLS_FTP
524
  allowed_protocols = "ftp,ftps";
525
#endif
526
79.9k
#ifdef FUZZ_PROTOCOLS_GOPHER
527
79.9k
  allowed_protocols = "gopher,gophers";
528
79.9k
#endif
529
#ifdef FUZZ_PROTOCOLS_HTTP
530
  allowed_protocols = "http";
531
#endif
532
#ifdef FUZZ_PROTOCOLS_HTTPS
533
  allowed_protocols = "https";
534
#endif
535
#ifdef FUZZ_PROTOCOLS_IMAP
536
  allowed_protocols = "imap,imaps";
537
#endif
538
#ifdef FUZZ_PROTOCOLS_LDAP
539
  allowed_protocols = "ldap,ldaps";
540
#endif
541
#ifdef FUZZ_PROTOCOLS_MQTT
542
  allowed_protocols = "mqtt";
543
#endif
544
#ifdef FUZZ_PROTOCOLS_POP3
545
  allowed_protocols = "pop3,pop3s";
546
#endif
547
#ifdef FUZZ_PROTOCOLS_RTMP
548
  allowed_protocols = "rtmp,rtmpe,rtmps,rtmpt,rtmpte,rtmpts";
549
#endif
550
#ifdef FUZZ_PROTOCOLS_RTSP
551
  allowed_protocols = "rtsp";
552
#endif
553
#ifdef FUZZ_PROTOCOLS_SCP
554
  allowed_protocols = "scp";
555
#endif
556
#ifdef FUZZ_PROTOCOLS_SFTP
557
  allowed_protocols = "sftp";
558
#endif
559
#ifdef FUZZ_PROTOCOLS_SMB
560
  allowed_protocols = "smb,smbs";
561
#endif
562
#ifdef FUZZ_PROTOCOLS_SMTP
563
  allowed_protocols = "smtp,smtps";
564
#endif
565
#ifdef FUZZ_PROTOCOLS_TFTP
566
  allowed_protocols = "tftp";
567
#endif
568
#ifdef FUZZ_PROTOCOLS_WS
569
  allowed_protocols = "ws,wss";
570
#endif
571
572
79.9k
  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_PROTOCOLS_STR, allowed_protocols));
573
574
79.9k
EXIT_LABEL:
575
576
79.9k
  return rc;
577
79.9k
}