receive_and_send_encrypted_post_data(): Loop until no data is left
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index 6963015..85c4182 100644 (file)
--- a/jcc.c
+++ b/jcc.c
 #include "project.h"
 #include "list.h"
 #include "jcc.h"
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
 #include "ssl.h"
 #endif
 #include "filters.h"
@@ -146,7 +146,7 @@ int g_terminate = 0;
 #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);
@@ -193,12 +193,10 @@ privoxy_mutex_t log_mutex;
 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;
@@ -447,7 +445,7 @@ static unsigned int get_write_delay(const struct client_state *csp)
  *                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.
@@ -483,8 +481,19 @@ static int client_protocol_is_unsupported(const struct client_state *csp, char *
       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;
    }
@@ -839,12 +848,24 @@ static void send_crunch_response(struct client_state *csp, struct http_response
 
       /* 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_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       if (client_use_ssl(csp))
       {
          if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl),
@@ -976,10 +997,10 @@ static void build_request_line(struct client_state *csp, const struct forward_sp
     * 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");
    }
 
    /*
@@ -998,7 +1019,7 @@ static void build_request_line(struct client_state *csp, const struct forward_sp
       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)
    {
@@ -1889,7 +1910,7 @@ static jb_err parse_client_request(struct client_state *csp)
 
 #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 */
@@ -2014,7 +2035,7 @@ static int send_http_request(struct client_state *csp)
 }
 
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
 /*********************************************************************
  *
  * Function    : receive_and_send_encrypted_post_data
@@ -2030,12 +2051,24 @@ static int send_http_request(struct client_state *csp)
  *********************************************************************/
 static jb_err 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;
@@ -2058,6 +2091,11 @@ static jb_err receive_and_send_encrypted_post_data(struct client_state *csp)
          {
             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;
+         }
       }
    }
 
@@ -2109,7 +2147,6 @@ static int send_https_request(struct client_state *csp)
          "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;
    }
 
@@ -2231,6 +2268,8 @@ static jb_err process_encrypted_request(struct client_state *csp)
    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;
@@ -2240,6 +2279,7 @@ static jb_err process_encrypted_request(struct client_state *csp)
    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;
@@ -2248,8 +2288,11 @@ static jb_err process_encrypted_request(struct client_state *csp)
 
    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;
    }
 
@@ -2303,6 +2346,8 @@ static jb_err process_encrypted_request(struct client_state *csp)
        * 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;
@@ -2352,6 +2397,8 @@ static jb_err process_encrypted_request(struct client_state *csp)
 
    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;
 
@@ -2391,19 +2438,12 @@ static void handle_established_connection(struct client_state *csp)
    long len = 0; /* for buffer sizes (and negative error codes) */
    int buffer_and_filter_content = 0;
    unsigned int write_delay;
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    int ret = 0;
    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_ENABLE_HTTPS_FILTER))
+   if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION))
    {
       /* Pass encrypted content without filtering. */
       use_ssl_tunnel = 1;
@@ -2514,114 +2554,62 @@ static void handle_established_connection(struct client_state *csp)
       }
 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
 
-#ifdef FEATURE_HTTPS_FILTERING
-      /*
-       * 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_FILTERING
-            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);
-#ifdef FEATURE_HTTPS_FILTERING
-            close_client_and_server_ssl_connections(csp);
+         mark_server_socket_tainted(csp);
+#ifdef FEATURE_HTTPS_INSPECTION
+         close_client_and_server_ssl_connections(csp);
 #endif
-            return;
-         }
+         return;
       }
-#ifdef FEATURE_HTTPS_FILTERING
-      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.
@@ -2692,39 +2680,14 @@ static void handle_established_connection(struct client_state *csp)
          assert(max_bytes_to_read <= csp->receive_buffer_size);
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
-#ifdef FEATURE_HTTPS_FILTERING
-         /*
-          * Reading data from standard or secured connection (HTTP/HTTPS)
-          */
+#ifdef FEATURE_HTTPS_INSPECTION
          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_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
          {
             len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read);
 
@@ -2757,9 +2720,6 @@ static void handle_established_connection(struct client_state *csp)
             {
                log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
-               close_client_and_server_ssl_connections(csp);
-#endif
                return;
             }
          }
@@ -2794,7 +2754,7 @@ static void handle_established_connection(struct client_state *csp)
             log_error(LOG_LEVEL_CONNECT,
                "The server still wants to talk, but the client hung up on us.");
             mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
             close_client_and_server_ssl_connections(csp);
 #endif
             return;
@@ -2802,7 +2762,7 @@ static void handle_established_connection(struct client_state *csp)
          }
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
          /*
           * Reading data from standard or secured connection (HTTP/HTTPS)
           */
@@ -2823,7 +2783,7 @@ static void handle_established_connection(struct client_state *csp)
             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
 
             if ((http->ssl && (csp->fwd == NULL))
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                && use_ssl_tunnel
 #endif
                 )
@@ -2849,7 +2809,7 @@ static void handle_established_connection(struct client_state *csp)
                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
                   "Unable to tell the client about the problem.");
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -2918,7 +2878,7 @@ static void handle_established_connection(struct client_state *csp)
          {
 
             if (server_body || (http->ssl
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                   && use_ssl_tunnel
 #endif
                ))
@@ -2968,7 +2928,7 @@ static void handle_established_connection(struct client_state *csp)
                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
                   }
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                   /*
                    * Sending data with standard or secured connection (HTTP/HTTPS)
                    */
@@ -2990,7 +2950,7 @@ static void handle_established_connection(struct client_state *csp)
                      }
                   }
                   else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                   {
                      if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
                       || write_socket_delayed(csp->cfd, ((p != NULL) ? p : csp->iob->cur),
@@ -3000,9 +2960,6 @@ static void handle_established_connection(struct client_state *csp)
                         freez(hdr);
                         freez(p);
                         mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
-                        close_client_and_server_ssl_connections(csp);
-#endif
                         return;
                      }
                   }
@@ -3035,7 +2992,7 @@ static void handle_established_connection(struct client_state *csp)
           * content-filtering.
           */
          if (server_body || (http->ssl
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                && use_ssl_tunnel
 #endif
             ))
@@ -3066,14 +3023,14 @@ static void handle_established_connection(struct client_state *csp)
                      rsp = cgi_error_memory();
                      send_crunch_response(csp, rsp);
                      mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                      close_client_and_server_ssl_connections(csp);
 #endif
                      return;
                   }
                   hdrlen = strlen(hdr);
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                   /*
                    * Sending data with standard or secured connection (HTTP/HTTPS)
                    */
@@ -3095,7 +3052,7 @@ static void handle_established_connection(struct client_state *csp)
                      }
                   }
                   else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                   {
                      if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay)
                       || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)
@@ -3106,9 +3063,6 @@ static void handle_established_connection(struct client_state *csp)
                            "Flush header and buffers to client failed: %E");
                         freez(hdr);
                         mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
-                        close_client_and_server_ssl_connections(csp);
-#endif
                         return;
                      }
                   }
@@ -3126,7 +3080,7 @@ static void handle_established_connection(struct client_state *csp)
             }
             else
             {
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                /*
                 * Sending data with standard or secured connection (HTTP/HTTPS)
                 */
@@ -3144,16 +3098,13 @@ static void handle_established_connection(struct client_state *csp)
                   }
                }
                else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                {
                   if (write_socket_delayed(csp->cfd, csp->receive_buffer,
                         (size_t)len, write_delay))
                   {
                      log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
                      mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
-                     close_client_and_server_ssl_connections(csp);
-#endif
                      return;
                   }
                }
@@ -3174,7 +3125,7 @@ static void handle_established_connection(struct client_state *csp)
                rsp = cgi_error_memory();
                send_crunch_response(csp, rsp);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3194,7 +3145,7 @@ static void handle_established_connection(struct client_state *csp)
                      "Applying the MS IIS5 hack didn't help.");
                   log_error(LOG_LEVEL_CLF,
                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                   /*
                    * Sending data with standard or secured connection (HTTP/HTTPS)
                    */
@@ -3205,14 +3156,14 @@ static void handle_established_connection(struct client_state *csp)
                         strlen(INVALID_SERVER_HEADERS_RESPONSE));
                   }
                   else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                   {
                      write_socket_delayed(csp->cfd,
                         INVALID_SERVER_HEADERS_RESPONSE,
                         strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
                   }
                   mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                   close_client_and_server_ssl_connections(csp);
 #endif
                   return;
@@ -3260,7 +3211,7 @@ static void handle_established_connection(struct client_state *csp)
                }
                free_http_request(http);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3288,7 +3239,7 @@ static void handle_established_connection(struct client_state *csp)
                   csp->headers->first->str);
                log_error(LOG_LEVEL_CLF,
                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                /*
                 * Sending data with standard or secured connection (HTTP/HTTPS)
                 */
@@ -3299,14 +3250,14 @@ static void handle_established_connection(struct client_state *csp)
                      strlen(INVALID_SERVER_HEADERS_RESPONSE));
                }
                else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                {
                   write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
                      strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
                }
                free_http_request(http);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3320,7 +3271,7 @@ static void handle_established_connection(struct client_state *csp)
             {
                log_error(LOG_LEVEL_CLF,
                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                /*
                 * Sending data with standard or secured connection (HTTP/HTTPS)
                 */
@@ -3338,7 +3289,7 @@ static void handle_established_connection(struct client_state *csp)
                }
                free_http_request(http);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3375,7 +3326,7 @@ static void handle_established_connection(struct client_state *csp)
                 */
                freez(hdr);
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3392,7 +3343,7 @@ static void handle_established_connection(struct client_state *csp)
                 * may be in the buffer). Use standard or secured
                 * connection.
                 */
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                if (client_use_ssl(csp))
                {
                   if ((ssl_send_data(&(csp->mbedtls_client_attr.ssl),
@@ -3408,14 +3359,14 @@ static void handle_established_connection(struct client_state *csp)
                       */
                      freez(hdr);
                      mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                      close_client_and_server_ssl_connections(csp);
 #endif
                      return;
                   }
                }
                else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                {
                   if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
                      || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0))
@@ -3428,9 +3379,6 @@ static void handle_established_connection(struct client_state *csp)
                       */
                      freez(hdr);
                      mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
-                     close_client_and_server_ssl_connections(csp);
-#endif
                      return;
                   }
                }
@@ -3453,7 +3401,7 @@ static void handle_established_connection(struct client_state *csp)
                   "Applying the MS IIS5 hack didn't help.");
                log_error(LOG_LEVEL_CLF,
                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                /*
                 * Sending data with standard or secured connection (HTTP/HTTPS)
                 */
@@ -3464,13 +3412,13 @@ static void handle_established_connection(struct client_state *csp)
                      strlen(INVALID_SERVER_HEADERS_RESPONSE));
                }
                else
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
                {
                   write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
                      strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
                }
                mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
                close_client_and_server_ssl_connections(csp);
 #endif
                return;
@@ -3479,12 +3427,12 @@ static void handle_established_connection(struct client_state *csp)
          continue;
       }
       mark_server_socket_tainted(csp);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       close_client_and_server_ssl_connections(csp);
 #endif
       return; /* huh? we should never get here */
    }
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    close_client_and_server_ssl_connections(csp);
 #endif
    if (csp->content_length == 0)
@@ -3507,9 +3455,19 @@ static void handle_established_connection(struct client_state *csp)
    }
 #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);
 }
 
@@ -3544,7 +3502,7 @@ static void chat(struct client_state *csp)
    struct http_request *http;
    /* Skeleton for HTTP response, if we should intercept the request */
    struct http_response *rsp;
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    int use_ssl_tunnel = 0;
 #endif
 
@@ -3568,12 +3526,12 @@ static void chat(struct client_state *csp)
       return;
    }
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    /*
     * Setting flags to use old solution with SSL tunnel and to disable
     * certificates verification.
     */
-   if (csp->http->ssl && !(csp->action->flags & ACTION_ENABLE_HTTPS_FILTER))
+   if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION))
    {
       use_ssl_tunnel = 1;
    }
@@ -3625,7 +3583,7 @@ static void chat(struct client_state *csp)
     *
     */
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    /*
     * Presetting SSL client and server flags
     */
@@ -3651,7 +3609,7 @@ static void chat(struct client_state *csp)
          csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
       csp->action->flags |= ACTION_BLOCK;
       http->ssl = 0;
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       http->client_ssl = 0;
       http->server_ssl = 0;
 #endif
@@ -3668,7 +3626,7 @@ static void chat(struct client_state *csp)
     * response later.
     */
    if (
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
        !client_use_ssl(csp) &&
 #endif
        crunch_response_triggered(csp, crunchers_all))
@@ -3680,8 +3638,17 @@ static void chat(struct client_state *csp)
    }
 
    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",
@@ -3725,7 +3692,7 @@ static void chat(struct client_state *csp)
          mark_connection_closed(&csp->server_connection);
       }
 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       if (http->ssl && !use_ssl_tunnel)
       {
          int ret;
@@ -3818,13 +3785,16 @@ static void chat(struct client_state *csp)
           * 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;
 
          return;
       }
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       /*
        * Creating TLS/SSL connections with destination server or parent
        * proxy. If forwarding is enabled, we must send client request to
@@ -3968,12 +3938,13 @@ static void chat(struct client_state *csp)
                   {
                      send_crunch_response(csp, rsp);
                   }
+                  close_client_and_server_ssl_connections(csp);
                   return;
                }
             }
          }
       }/* -END- if (http->ssl) */
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
 
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
       save_connection_destination(csp->server_connection.sfd,
@@ -3991,7 +3962,7 @@ static void chat(struct client_state *csp)
       assert(csp->headers->last == NULL);
    }
    else if (http->ssl == 0 || (fwd->forward_host
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
          && use_ssl_tunnel
 #endif
            ))
@@ -4012,7 +3983,7 @@ static void chat(struct client_state *csp)
        * Using old solution with SSL tunnel or new solution with SSL proxy
        */
       list_remove_all(csp->headers);
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       if (use_ssl_tunnel)
 #endif
       {
@@ -4027,7 +3998,7 @@ static void chat(struct client_state *csp)
             return;
          }
       }
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
       else
       {
          /*
@@ -4051,7 +4022,7 @@ static void chat(struct client_state *csp)
             return;
          }
       }
-#endif /* def FEATURE_HTTPS_FILTERING */
+#endif /* def FEATURE_HTTPS_INSPECTION */
       clear_iob(csp->client_iob);
    }/* -END- else ... if (http->ssl == 1) */
 
@@ -4590,17 +4561,10 @@ static void initialize_mutexes(void)
     * 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);
@@ -5637,7 +5601,7 @@ static void listen_loop(void)
 
    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
 
-#ifdef FEATURE_HTTPS_FILTERING
+#ifdef FEATURE_HTTPS_INSPECTION
    /* Clean up.  Aim: free all memory (no leaks) */
    if (rng_seeded == 1)
    {