/* # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const void *cur_data; static int cur_size = -1; static int server_fd = -1; static int client_fd = -1; static bool wrote = false; static void fail(const char *why) { perror(why); exit(1); } static curl_socket_t open_sock(void *ctx, curlsocktype purpose, struct curl_sockaddr *address) { if (cur_size == -1) fail("not fuzzing"); if (server_fd != -1 || client_fd != -1) fail("already connected"); int fds[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) fail("socketpair"); server_fd = fds[0]; client_fd = fds[1]; if (write(server_fd, cur_data, cur_size) != cur_size) fail("write"); if (shutdown(server_fd, SHUT_WR)) fail("shutdown"); return client_fd; } static int set_opt(void *ctx, curl_socket_t curlfd, curlsocktype purpose) { return CURL_SOCKOPT_ALREADY_CONNECTED; } static size_t write_callback(char *ptr, size_t size, size_t n, void *ctx) { return size * n; } static size_t read_callback(char *buf, size_t size, size_t n, void *ctx) { if (wrote || size * n == 0) return 0; wrote = true; buf[0] = 'a'; return 1; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { cur_data = Data; cur_size = Size; wrote = false; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, open_sock); curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, set_opt); #if defined(FUZZER_FTP) curl_easy_setopt(curl, CURLOPT_URL, "ftp://user@localhost/file.txt"); #elif defined(FUZZER_IMAP) curl_easy_setopt(curl, CURLOPT_USERNAME, "user"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret"); curl_easy_setopt(curl, CURLOPT_URL, "imap://localhost"); #elif defined(FUZZER_POP3) curl_easy_setopt(curl, CURLOPT_USERNAME, "user"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret"); curl_easy_setopt(curl, CURLOPT_URL, "pop3://localhost"); #elif defined(FUZZER_HTTP_UPLOAD) curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/"); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); #elif defined(FUZZER_HTTP2) curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/"); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 0L); #else curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/"); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); #endif curl_easy_perform(curl); curl_easy_cleanup(curl); close(server_fd); close(client_fd); server_fd = -1; client_fd = -1; cur_data = NULL; cur_size = -1; return 0; }