-const char jcc_rcs[] = "$Id: jcc.c,v 1.447 2016/09/27 22:48:28 ler762 Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.449 2016/12/24 16:00:49 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
#define sleep(N) DosSleep(((N) * 100))
#endif
+#ifdef FUZZ
+int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file);
+void show_fuzz_usage(const char *name);
+#endif
+
#ifdef MUTEX_LOCKS_AVAILABLE
/*
* XXX: Does the locking stuff really belong in this file?
do
{
- if (!data_is_available(csp->cfd, csp->config->socket_timeout))
+ if (
+#ifdef FUZZ
+ 0 == (csp->flags & CSP_FLAG_FUZZED_INPUT) &&
+#endif
+ !data_is_available(csp->cfd, csp->config->socket_timeout)
+ )
{
if (socket_is_still_alive(csp->cfd))
{
}
+#ifdef FUZZ
+/*********************************************************************
+ *
+ * Function : fuzz_chunked_transfer_encoding
+ *
+ * Description : Treat the fuzzed input as chunked transfer encoding
+ * to check and dechunk.
+ *
+ * Parameters :
+ * 1 : csp = Used to store the data.
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of dechunking
+ *
+ *********************************************************************/
+extern int fuzz_chunked_transfer_encoding(struct client_state *csp, char *fuzz_input_file)
+{
+ size_t length;
+ size_t size = (size_t)(csp->iob->eod - csp->iob->cur);
+ enum chunk_status status;
+
+ status = chunked_body_is_complete(csp->iob, &length);
+ if (CHUNK_STATUS_BODY_COMPLETE != status)
+ {
+ log_error(LOG_LEVEL_INFO, "Chunked body is incomplete or invalid");
+ }
+
+ return (JB_ERR_OK == remove_chunked_transfer_coding(csp->iob->cur, &size));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : fuzz_client_request
+ *
+ * Description : Try to get a client request from the fuzzed input.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : Result of fuzzing.
+ *
+ *********************************************************************/
+extern int fuzz_client_request(struct client_state *csp, char *fuzz_input_file)
+{
+ jb_err err;
+
+ csp->cfd = 0;
+ csp->ip_addr_str = "fuzzer";
+
+ if (strcmp(fuzz_input_file, "-") != 0)
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Fuzzed client requests can currenty only be read from stdin (-).");
+ }
+ err = receive_client_request(csp);
+ if (err != JB_ERR_OK)
+ {
+ return 1;
+ }
+ err = parse_client_request(csp);
+ if (err != JB_ERR_OK)
+ {
+ return 1;
+ }
+
+ return 0;
+
+}
+#endif /* def FUZZ */
+
+
#ifdef FEATURE_FORCE_LOAD
/*********************************************************************
*
}
+/*********************************************************************
+ *
+ * Function : send_http_request
+ *
+ * Description : Sends the HTTP headers from the client request
+ * and all the body data that has already been received.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 on success, anything else is na error.
+ *
+ *********************************************************************/
+static int send_http_request(struct client_state *csp)
+{
+ char *hdr;
+ int write_failure;
+
+ hdr = list_to_text(csp->headers);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
+ }
+ list_remove_all(csp->headers);
+
+ /*
+ * Write the client's (modified) header to the server
+ * (along with anything else that may be in the buffer)
+ */
+ write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
+ freez(hdr);
+
+ if (write_failure)
+ {
+ log_error(LOG_LEVEL_CONNECT, "Failed sending request headers to: %s: %E",
+ csp->http->hostport);
+ }
+ else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
+ && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
+ {
+ write_failure = 1;
+ log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
+ csp->http->hostport);
+ }
+
+ return write_failure;
+
+}
+
+
/*********************************************************************
*
* Function : handle_established_connection
csp->server_connection.timestamp = time(NULL);
}
+
/*********************************************************************
*
* Function : chat
static void chat(struct client_state *csp)
{
char buf[BUFFER_SIZE];
- char *hdr;
const struct forward_spec *fwd;
struct http_request *http;
/* Skeleton for HTTP response, if we should intercept the request */
}
else if (fwd->forward_host || (http->ssl == 0))
{
- int write_failure;
- hdr = list_to_text(csp->headers);
- if (hdr == NULL)
- {
- /* FIXME Should handle error properly */
- log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
- }
- list_remove_all(csp->headers);
-
- /*
- * Write the client's (modified) header to the server
- * (along with anything else that may be in the buffer)
- */
- write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
- freez(hdr);
-
- if (write_failure)
- {
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request headers to: %s: %E", http->hostport);
- }
- else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
- && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
- {
- write_failure = 1;
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request body to: %s: %E", http->hostport);
- }
-
- if (write_failure)
+ if (send_http_request(csp))
{
rsp = error_response(csp, "connect-failed");
if (rsp)
}
+#ifdef FUZZ
+/*********************************************************************
+ *
+ * Function : fuzz_server_response
+ *
+ * Description : Treat the input as a whole server response.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : fuzz_input_file = File to read the input from.
+ *
+ * Returns : 0
+ *
+ *********************************************************************/
+extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file)
+{
+ static struct forward_spec fwd; /* Zero'd due to being static */
+ csp->cfd = 0;
+
+ if (strcmp(fuzz_input_file, "-") == 0)
+ {
+ /* XXX: Doesn'T work yet. */
+ csp->server_connection.sfd = 0;
+ }
+ else
+ {
+ csp->server_connection.sfd = open(fuzz_input_file, O_RDONLY);
+ if (csp->server_connection.sfd == -1)
+ {
+ log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E",
+ fuzz_input_file);
+ }
+ }
+ csp->content_type |= CT_GIF;
+ csp->action->flags |= ACTION_DEANIMATE;
+ csp->action->string[ACTION_STRING_DEANIMATE] = "last";
+
+ csp->http->path = strdup_or_die("/");
+ csp->http->host = strdup_or_die("fuzz.example.org");
+ csp->http->hostport = strdup_or_die("fuzz.example.org:80");
+ /* Prevent client socket monitoring */
+ csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
+ csp->flags |= CSP_FLAG_CHUNKED;
+
+ csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
+ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
+
+ csp->content_type |= CT_DECLARED|CT_GIF;
+
+ csp->config->socket_timeout = 0;
+
+ cgi_init_error_messages();
+
+ handle_established_connection(csp, &fwd);
+
+ return 0;
+}
+#endif
+
+
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
/*********************************************************************
*
* Returns : No. ,-)
*
*********************************************************************/
-static void usage(const char *myname)
+static void usage(const char *name)
{
printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
"Usage: %s [--config-test] "
#if defined(unix)
"[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
#endif /* defined(unix) */
- "[--version] [configfile]\n"
- "Aborting\n", myname);
+ "[--version] [configfile]\n",
+ name);
+
+#ifdef FUZZ
+ show_fuzz_usage(name);
+#endif
+
+ printf("Aborting\n");
exit(2);
#endif /* def MUTEX_LOCKS_AVAILABLE */
}
-
/*********************************************************************
*
* Function : main
int do_chroot = 0;
char *pre_chroot_nslookup_to_load_resolver = NULL;
#endif
+#ifdef FUZZ
+ char *fuzz_input_type = NULL;
+ char *fuzz_input_file = NULL;
+#endif
Argc = argc;
Argv = argv;
{
do_config_test = 1;
}
-
+#ifdef FUZZ
+ else if (strcmp(argv[argc_pos], "--fuzz") == 0)
+ {
+ argc_pos++;
+ if (argc < argc_pos + 2) usage(argv[0]);
+ fuzz_input_type = argv[argc_pos];
+ argc_pos++;
+ fuzz_input_file = argv[argc_pos];
+ }
+ else if (strcmp(argv[argc_pos], "--stfu") == 0)
+ {
+ set_debug_level(LOG_LEVEL_STFU);
+ }
+#endif
else if (argc_pos + 1 != argc)
{
/*
# endif /* def _WIN_CONSOLE */
#endif /* def _WIN32 */
+#ifdef FUZZ
+ if (fuzz_input_type != NULL)
+ {
+ exit(process_fuzzed_input(fuzz_input_type, fuzz_input_file));
+ }
+#endif
+
if (do_config_test)
{
exit(NULL == load_config());