Merge branch 'master' of ssh://git.privoxy.org:23/git/privoxy
authorLee <ler762@users.sourceforge.net>
Fri, 12 Mar 2021 11:53:16 +0000 (06:53 -0500)
committerLee <ler762@users.sourceforge.net>
Fri, 12 Mar 2021 11:53:16 +0000 (06:53 -0500)
1  2 
jcc.c

diff --combined jcc.c
--- 1/jcc.c
--- 2/jcc.c
+++ b/jcc.c
@@@ -995,12 -995,35 +995,35 @@@ static void build_request_line(struct c
      * Rebuild the request line.
      */
     freez(*request_line);
-    *request_line = strdup(http->gpc);
-    string_append(request_line, " ");
+ #ifdef FEATURE_HTTPS_INSPECTION
+    if (fwd != NULL && fwd->forward_host &&
+        fwd->type != FORWARD_WEBSERVER && client_use_ssl(csp))
+    {
+       *request_line = strdup("CONNECT ");
+    }
+    else
+ #endif
+    {
+       *request_line = strdup(http->gpc);
+       string_append(request_line, " ");
+    }
  
     if (fwd != NULL && fwd->forward_host && fwd->type != FORWARD_WEBSERVER)
     {
-       string_append(request_line, http->url);
+ #ifdef FEATURE_HTTPS_INSPECTION
+       if (client_use_ssl(csp))
+       {
+          char port_string[10];
+          string_append(request_line, http->host);
+          snprintf(port_string, sizeof(port_string), ":%d", http->port);
+          string_append(request_line, port_string);
+       }
+       else
+ #endif
+       {
+          string_append(request_line, http->url);
+       }
     }
     else
     {
@@@ -2972,6 -2995,7 +2995,7 @@@ static void continue_https_chat(struct 
           csp->cfd);
        return;
     }
+    csp->server_connection.request_sent = time(NULL);
     csp->server_connection.requests_sent_total++;
     handle_established_connection(csp);
     freez(csp->receive_buffer);
@@@ -3061,6 -3085,18 +3085,18 @@@ static void handle_established_connecti
  
     for (;;)
     {
+ #ifdef FEATURE_HTTPS_INSPECTION
+       if (server_use_ssl(csp) && is_ssl_pending(&(csp->ssl_server_attr)))
+       {
+          /*
+           * It's possible that the TLS library already consumed all the
+           * data the server intends to send. If that happens poll() and
+           * select() will no longer see the data as available so we have
+           * to skip the calls.
+           */
+          goto server_wants_to_talk;
+       }
+ #endif
  #ifndef HAVE_POLL
        FD_ZERO(&rfds);
  #ifdef FEATURE_CONNECTION_KEEP_ALIVE
        n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
  #endif /* def HAVE_POLL */
  
-       /*server or client not responding in timeout */
+       /* Server or client not responding in timeout */
        if (n == 0)
        {
           log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s",
        if (FD_ISSET(csp->server_connection.sfd, &rfds))
  #endif /* HAVE_POLL */
        {
+ #ifdef FEATURE_HTTPS_INSPECTION
+          server_wants_to_talk:
+ #endif
  #ifdef FEATURE_CONNECTION_KEEP_ALIVE
           /*
            * If we are buffering content, we don't want to eat up to
                                (const unsigned char *) ((p != NULL) ? p : csp->iob->cur),
                                csp->content_length, get_write_delay(csp)) < 0))
                       {
-                         log_error(LOG_LEVEL_ERROR, "write modified content to "
-                            "client over TLS/SSL failed");
+                         log_error(LOG_LEVEL_ERROR,
+                            "Failed to send the modified content to the client over TLS");
                          freez(hdr);
                          freez(p);
                          mark_server_socket_tainted(csp);
              }
  
              /*
-              * This is NOT the body, so
-              * Let's pretend the server just sent us a blank line.
+              * This is not the body, so let's pretend the server just sent
+              * us a blank line.
               */
              snprintf(csp->receive_buffer, csp->receive_buffer_size, "\r\n");
              len = (int)strlen(csp->receive_buffer);
                 return;
              }
  
+             /*
+              * Disable redirect checkers, so that they will be only run
+              * again if the user also enables them through tags.
+              *
+              * From a performance point of view it doesn't matter,
+              * but it prevents duplicated log messages.
+              */
+ #ifdef FEATURE_FAST_REDIRECTS
+             csp->action->flags &= ~ACTION_FAST_REDIRECTS;
+ #endif
+             csp->action->flags &= ~ACTION_REDIRECT;
              /*
               * We have now received the entire server header,
               * filter it and send the result to the client
@@@ -4119,9 -4170,6 +4170,6 @@@ static void chat(struct client_state *c
        return;
     }
  
-    /* decide how to route the HTTP request */
-    fwd = forward_url(csp, http);
  #ifdef FEATURE_HTTPS_INSPECTION
     /*
      * Setting flags to use old solution with SSL tunnel and to disable
  #endif
     }
  
-    freez(csp->headers->first->str);
-    build_request_line(csp, fwd, &csp->headers->first->str);
     /*
      * We have a request. Check if one of the crunchers wants it
      * unless the client wants to use TLS/SSL in which case we
        return;
     }
  
+ #ifdef FEATURE_HTTPS_INSPECTION
+    if (client_use_ssl(csp) && !use_ssl_tunnel)
+    {
+       int ret;
+       /*
+        * Creating a SSL proxy.
+        *
+        * By sending the CSUCCEED message we're lying to the client as
+        * the connection hasn't actually been established yet. We don't
+        * establish the connection until we have seen and parsed the
+        * encrypted client headers.
+        */
+       if (write_socket_delayed(csp->cfd, CSUCCEED,
+             strlen(CSUCCEED), get_write_delay(csp)) != 0)
+       {
+          log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed");
+          return;
+       }
+       ret = create_client_ssl_connection(csp);
+       if (ret != 0)
+       {
+          log_error(LOG_LEVEL_ERROR,
+             "Failed to open a secure connection with the client");
+          return;
+       }
+       if (JB_ERR_OK != process_encrypted_request(csp))
+       {
+          close_client_ssl_connection(csp);
+          return;
+       }
+       /*
+        * We have an encrypted request. Check if one of the crunchers now
+        * wants it (for example because the previously invisible path was
+        * required to match).
+        */
+       if (crunch_response_triggered(csp, crunchers_all))
+       {
+          /*
+           * Yes. The client got the crunch response and we're done here.
+           */
+          return;
+       }
+    }
+ #endif
+    /* decide how to route the HTTP request */
+    fwd = forward_url(csp, http);
+    freez(csp->headers->first->str);
+    build_request_line(csp, fwd, &csp->headers->first->str);
     log_applied_actions(csp->action);
     if (fwd->forward_host)
     {
           mark_connection_closed(&csp->server_connection);
        }
  #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
- #ifdef FEATURE_HTTPS_INSPECTION
-       if (client_use_ssl(csp) && !use_ssl_tunnel)
-       {
-          int ret;
-          /*
-           * Creating a SSL proxy.
-           *
-           * By sending the CSUCCEED message we're lying to the client as
-           * the connection hasn't actually been established yet. We don't
-           * establish the connection until we have seen and parsed the
-           * encrypted client headers.
-           */
-          if (write_socket_delayed(csp->cfd, CSUCCEED,
-                strlen(CSUCCEED), get_write_delay(csp)) != 0)
-          {
-             log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed");
-             return;
-          }
  
-          ret = create_client_ssl_connection(csp);
-          if (ret != 0)
-          {
-             log_error(LOG_LEVEL_ERROR,
-                "Failed to open a secure connection with the client");
-             return;
-          }
-          if (JB_ERR_OK != process_encrypted_request(csp))
-          {
-             close_client_ssl_connection(csp);
-             return;
-          }
-          /*
-           * We have an encrypted request. Check if one of the crunchers now
-           * wants it (for example because the previously invisible path was
-           * required to match).
-           */
-          if (crunch_response_triggered(csp, crunchers_all))
-          {
-             /*
-              * Yes. The client got the crunch response and we're done here.
-              */
-             return;
-          }
-       }
- #endif
        /*
         * Connecting to destination server
         */
@@@ -4834,6 -4886,22 +4886,22 @@@ static void serve(struct client_state *
  #endif
              close_socket(csp->server_connection.sfd);
              mark_connection_closed(&csp->server_connection);
+ #ifdef FEATURE_HTTPS_INSPECTION
+             if (continue_chatting && client_use_ssl(csp))
+             {
+                /*
+                 * Close the client socket as well as Privoxy currently
+                 * can't establish a new server connection when the client
+                 * socket is reused and would drop the connection in
+                 * continue_https_chat() anyway.
+                 */
+                continue_chatting = 0;
+                csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
+                log_error(LOG_LEVEL_CONNECT,
+                   "Client socket %d is no longer usable. "
+                   "The server socket has been closed.", csp->cfd);
+             }
+ #endif
           }
        }
  
@@@ -6065,7 -6133,7 +6133,7 @@@ static void listen_loop(void
           }
  #endif
  
 -#if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
 +#if defined(_WIN32) && !defined(SELECTED_ONE_OPTION)
  #define SELECTED_ONE_OPTION
           child_id = _beginthread(
              (void (*)(void *))serve,