#if !defined(_WIN32) && !defined(__OS2__)
static void sig_handler(int the_signal);
#endif
-static int client_protocol_is_unsupported(const struct client_state *csp, char *req);
+static int client_protocol_is_unsupported(struct client_state *csp, char *req);
static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
static jb_err get_server_headers(struct client_state *csp);
static const char *crunch_reason(const struct http_response *rsp);
privoxy_mutex_t log_init_mutex;
privoxy_mutex_t connection_reuse_mutex;
-#ifdef LIMIT_MUTEX_NUMBER
-privoxy_mutex_t certificates_mutexes[32];
-#else
-privoxy_mutex_t certificates_mutexes[65536];
-#endif /* LIMIT_MUTEX_NUMBER */
+#ifdef FEATURE_HTTPS_INSPECTION
+privoxy_mutex_t certificate_mutex;
privoxy_mutex_t rng_mutex;
+#endif
#ifdef FEATURE_EXTERNAL_FILTERS
privoxy_mutex_t external_filter_mutex;
* FALSE if the request doesn't look invalid.
*
*********************************************************************/
-static int client_protocol_is_unsupported(const struct client_state *csp, char *req)
+static int client_protocol_is_unsupported(struct client_state *csp, char *req)
{
/*
* If it's a FTP or gopher request, we don't support it.
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
freez(req);
- write_socket_delayed(csp->cfd, response, strlen(response),
- get_write_delay(csp));
+
+#ifdef FEATURE_HTTPS_INSPECTION
+ if (client_use_ssl(csp))
+ {
+ ssl_send_data(&(csp->mbedtls_client_attr.ssl),
+ (const unsigned char *)response, strlen(response));
+ }
+ else
+#endif
+ {
+ write_socket_delayed(csp->cfd, response, strlen(response),
+ get_write_delay(csp));
+ }
return TRUE;
}
/* Log that the request was crunched and why. */
log_applied_actions(csp->action);
- log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
- log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u",
- csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
-
+#ifdef FEATURE_HTTPS_INSPECTION
+ if (client_use_ssl(csp))
+ {
+ log_error(LOG_LEVEL_CRUNCH, "%s: https://%s%s", crunch_reason(rsp),
+ http->hostport, http->path);
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" %s %llu",
+ csp->ip_addr_str, http->gpc, http->hostport, http->path,
+ http->version, status_code, rsp->content_length);
+ }
+ else
+#endif
+ {
+ log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u",
+ csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
+ }
/* Write the answer to the client */
#ifdef FEATURE_HTTPS_INSPECTION
if (client_use_ssl(csp))
* if +downgrade action applies.
*/
if ((csp->action->flags & ACTION_DOWNGRADE)
- && (!strcmpic(http->ver, "HTTP/1.1")))
+ && (!strcmpic(http->version, "HTTP/1.1")))
{
- freez(http->ver);
- http->ver = strdup_or_die("HTTP/1.0");
+ freez(http->version);
+ http->version = strdup_or_die("HTTP/1.0");
}
/*
string_append(request_line, http->path);
}
string_append(request_line, " ");
- string_append(request_line, http->ver);
+ string_append(request_line, http->version);
if (*request_line == NULL)
{
if (strcmp(fuzz_input_file, "-") != 0)
{
log_error(LOG_LEVEL_FATAL,
- "Fuzzed client requests can currenty only be read from stdin (-).");
+ "Fuzzed client requests can currently only be read from stdin (-).");
}
err = receive_client_request(csp);
if (err != JB_ERR_OK)
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
- && (!strcmpic(csp->http->ver, "HTTP/1.1"))
+ && (!strcmpic(csp->http->version, "HTTP/1.1"))
&& (csp->http->ssl == 0))
{
/* Assume persistence until further notice */
* Returns : 0 on success, anything else is an error.
*
*********************************************************************/
-static jb_err receive_and_send_encrypted_post_data(struct client_state *csp)
+static int receive_and_send_encrypted_post_data(struct client_state *csp)
{
- unsigned char buf[BUFFER_SIZE];
- int len;
+ int content_length_known = csp->expected_client_content_length != 0;
- while (is_ssl_pending(&(csp->mbedtls_client_attr.ssl)))
+ while (is_ssl_pending(&(csp->mbedtls_client_attr.ssl))
+ || (content_length_known && csp->expected_client_content_length != 0))
{
- len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl), buf, sizeof(buf));
+ unsigned char buf[BUFFER_SIZE];
+ int len;
+ int max_bytes_to_read = sizeof(buf);
+
+ if (content_length_known && csp->expected_client_content_length < sizeof(buf))
+ {
+ max_bytes_to_read = (int)csp->expected_client_content_length;
+ }
+ log_error(LOG_LEVEL_CONNECT,
+ "Waiting for up to %d bytes of POST data from the client.",
+ max_bytes_to_read);
+ len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl), buf,
+ (unsigned)max_bytes_to_read);
if (len == -1)
{
return 1;
/* XXX: Does this actually happen? */
break;
}
- log_error(LOG_LEVEL_HEADER, "Forwarding %d bytes of encrypted POST data",
+ log_error(LOG_LEVEL_CONNECT, "Forwarding %d bytes of encrypted POST data",
len);
len = ssl_send_data(&(csp->mbedtls_server_attr.ssl), buf, (size_t)len);
if (len == -1)
{
csp->expected_client_content_length -= (unsigned)len;
}
+ if (csp->expected_client_content_length == 0)
+ {
+ log_error(LOG_LEVEL_HEADER, "Forwarded the last %d bytes", len);
+ break;
+ }
}
}
"Failed sending encrypted request headers to: %s: %E",
csp->http->hostport);
mark_server_socket_tainted(csp);
- close_client_and_server_ssl_connections(csp);
return 1;
}
if (err != JB_ERR_OK)
{
/* XXX: Also used for JB_ERR_MEMORY */
+ log_error(LOG_LEVEL_ERROR, "Failed to receive encrypted request: %s",
+ jb_err_to_string(err));
ssl_send_data(&(csp->mbedtls_client_attr.ssl),
(const unsigned char *)CHEADER, strlen(CHEADER));
return err;
request_line = get_header(csp->client_iob);
if (request_line == NULL)
{
+ log_error(LOG_LEVEL_ERROR, "Failed to get the encrypted request line");
ssl_send_data(&(csp->mbedtls_client_attr.ssl),
(const unsigned char *)CHEADER, strlen(CHEADER));
return JB_ERR_PARSE;
if (client_protocol_is_unsupported(csp, request_line))
{
- ssl_send_data(&(csp->mbedtls_client_attr.ssl),
- (const unsigned char *)CHEADER, strlen(CHEADER));
+ /*
+ * If the protocol is unsupported we're done here.
+ * client_protocol_is_unsupported() took care of sending
+ * the error response and logging the error message.
+ */
return JB_ERR_PARSE;
}
* Our attempts to get the request destination
* elsewhere failed.
*/
+ log_error(LOG_LEVEL_ERROR,
+ "Failed to get the encrypted request destination");
ssl_send_data(&(csp->mbedtls_client_attr.ssl),
(const unsigned char *)CHEADER, strlen(CHEADER));
return JB_ERR_PARSE;
log_error(LOG_LEVEL_HEADER, "Encrypted request processed");
log_applied_actions(csp->action);
+ log_error(LOG_LEVEL_GPC, "https://%s%s", csp->http->hostport,
+ csp->http->path);
return err;
int use_ssl_tunnel = 0;
csp->dont_verify_certificate = 0;
- /*
- * Preset flags informing if SSL connections with server or client
- * are opened or closed
- */
- csp->ssl_with_server_is_opened = 0;
- csp->ssl_with_client_is_opened = 0;
-
if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION))
{
/* Pass encrypted content without filtering. */
}
#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
-#ifdef FEATURE_HTTPS_INSPECTION
- /*
- * Test if some data from client or destination server are pending
- * on TLS/SSL. We must work with them preferably. TLS/SSL data can
- * be pending because of maximal fragment size.
- */
- int read_ssl_server = 0;
- int read_ssl_client = 0;
-
- if (client_use_ssl(csp))
- {
- read_ssl_client = is_ssl_pending(&(csp->mbedtls_client_attr.ssl)) != 0;
- }
-
- if (server_use_ssl(csp))
+#ifdef HAVE_POLL
+ poll_fds[0].fd = csp->cfd;
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ if (!watch_client_socket)
{
- read_ssl_server = is_ssl_pending(&(csp->mbedtls_server_attr.ssl)) != 0;
+ /*
+ * Ignore incoming data, but still watch out
+ * for disconnects etc. These flags are always
+ * implied anyway but explicitly setting them
+ * doesn't hurt.
+ */
+ poll_fds[0].events = POLLERR|POLLHUP;
}
-
- if (!read_ssl_server && !read_ssl_client)
+ else
#endif
{
-#ifdef HAVE_POLL
- poll_fds[0].fd = csp->cfd;
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
- if (!watch_client_socket)
- {
- /*
- * Ignore incoming data, but still watch out
- * for disconnects etc. These flags are always
- * implied anyway but explicitly setting them
- * doesn't hurt.
- */
- poll_fds[0].events = POLLERR|POLLHUP;
- }
- else
-#endif
- {
- poll_fds[0].events = POLLIN;
- }
- poll_fds[1].fd = csp->server_connection.sfd;
- poll_fds[1].events = POLLIN;
- n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
+ poll_fds[0].events = POLLIN;
+ }
+ poll_fds[1].fd = csp->server_connection.sfd;
+ poll_fds[1].events = POLLIN;
+ n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
#else
- timeout.tv_sec = csp->config->socket_timeout;
- timeout.tv_usec = 0;
- n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
+ timeout.tv_sec = csp->config->socket_timeout;
+ timeout.tv_usec = 0;
+ n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
#endif /* def HAVE_POLL */
- /*server or client not responding in timeout */
- if (n == 0)
+ /*server or client not responding in timeout */
+ if (n == 0)
+ {
+ log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s",
+ csp->config->socket_timeout, http->url);
+ if ((byte_count == 0) && (http->ssl == 0))
{
- log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s",
- csp->config->socket_timeout, http->url);
- if ((byte_count == 0) && (http->ssl == 0))
- {
- send_crunch_response(csp, error_response(csp, "connection-timeout"));
- }
- mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
- return;
+ send_crunch_response(csp, error_response(csp, "connection-timeout"));
}
- else if (n < 0)
- {
-#ifdef HAVE_POLL
- log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
-#else
- log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
-#endif
- mark_server_socket_tainted(csp);
+ mark_server_socket_tainted(csp);
#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
+ close_client_and_server_ssl_connections(csp);
#endif
- return;
- }
+ return;
}
-#ifdef FEATURE_HTTPS_INSPECTION
- else
+ else if (n < 0)
{
- /* set FD if some data are pending on TLS/SSL connections */
-#ifndef HAVE_POLL
- FD_ZERO(&rfds);
-#endif
- if (read_ssl_client)
- {
#ifdef HAVE_POLL
- poll_fds[0].fd = csp->cfd;
- poll_fds[0].events = POLLIN;
+ log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
#else
- FD_SET(csp->cfd, &rfds);
+ log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
#endif
- n++;
- }
-
- if (read_ssl_server)
- {
-#ifdef HAVE_POLL
- poll_fds[1].fd = csp->server_connection.sfd;
- poll_fds[1].events = POLLIN;
-#else
- FD_SET(csp->server_connection.sfd, &rfds);
+ mark_server_socket_tainted(csp);
+#ifdef FEATURE_HTTPS_INSPECTION
+ close_client_and_server_ssl_connections(csp);
#endif
- n++;
- }
+ return;
}
-#endif
+
/*
* This is the body of the browser's request,
* just read and write it.
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
#ifdef FEATURE_HTTPS_INSPECTION
- /*
- * Reading data from standard or secured connection (HTTP/HTTPS)
- */
if (client_use_ssl(csp))
{
- /*
- * Receiving HTTP request from client over TLS/SSL and sending
- * it to server over TLS/SSL.
- */
- len = ssl_recv_data(&(csp->mbedtls_client_attr.ssl),
- (unsigned char *)csp->receive_buffer, (size_t)max_bytes_to_read);
-
- if (len <= 0)
- {
- mark_server_socket_tainted(csp);
- break;
- }
-
- ret = ssl_send_data(&(csp->mbedtls_server_attr.ssl),
- (const unsigned char *)csp->receive_buffer, (size_t)len);
-
- if (ret < 0)
- {
- log_error(LOG_LEVEL_ERROR,
- "Send request over TLS/SSL to: %s failed", http->host);
- mark_server_socket_tainted(csp);
- close_client_and_server_ssl_connections(csp);
- return;
- }
+ log_error(LOG_LEVEL_CONNECT, "Breaking with TLS/SSL.");
+ break;
}
else
#endif /* def FEATURE_HTTPS_INSPECTION */
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
return;
}
}
freez(hdr);
freez(p);
mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
return;
}
}
"Flush header and buffers to client failed: %E");
freez(hdr);
mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
return;
}
}
{
log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
return;
}
}
*/
freez(hdr);
mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_INSPECTION
- close_client_and_server_ssl_connections(csp);
-#endif
return;
}
}
}
#endif
- log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
- csp->ip_addr_str, http->ocmd, csp->content_length);
-
+#ifdef FEATURE_HTTPS_INSPECTION
+ if (client_use_ssl(csp))
+ {
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" 200 %llu",
+ csp->ip_addr_str, http->gpc, http->hostport, http->path,
+ http->version, csp->content_length);
+ }
+ else
+#endif
+ {
+ log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
+ csp->ip_addr_str, http->ocmd, csp->content_length);
+ }
csp->server_connection.timestamp = time(NULL);
}
}
log_applied_actions(csp->action);
- log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
-
+#ifdef FEATURE_HTTPS_INSPECTION
+ /*
+ * Log the request unless we're https inspecting
+ * in which case we don't have the path yet and
+ * will log the request later.
+ */
+ if (!client_use_ssl(csp))
+#endif
+ {
+ log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
+ }
if (fwd->forward_host)
{
log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
int ret;
/*
* Creating an SSL proxy. If forwarding is disabled, we must send
- * CSUCCEED mesage to client. Then TLS/SSL connection with client
+ * CSUCCEED message to client. Then TLS/SSL connection with client
* is created.
*/
* client body in the buffer (if there is one) and to
* continue parsing the bytes that follow.
*/
+#ifdef FEATURE_HTTPS_INSPECTION
+ close_client_ssl_connection(csp);
+#endif
drain_and_close_socket(csp->cfd);
csp->cfd = JB_INVALID_SOCKET;
{
send_crunch_response(csp, rsp);
}
+ close_client_and_server_ssl_connections(csp);
return;
}
}
* Prepare global mutex semaphores
*/
-#ifdef LIMIT_MUTEX_NUMBER
- int i = 0;
- for (i = 0; i < 32; i++)
-#else
- int i = 0;
- for (i = 0; i < 65536; i++)
-#endif /* LIMIT_MUTEX_NUMBER */
- {
- privoxy_mutex_init(&(certificates_mutexes[i]));
- }
+#ifdef FEATURE_HTTPS_INSPECTION
+ privoxy_mutex_init(&certificate_mutex);
privoxy_mutex_init(&rng_mutex);
+#endif
privoxy_mutex_init(&log_mutex);
privoxy_mutex_init(&log_init_mutex);