LCOV - code coverage report
Current view: top level - fuzz - jcc.c (source / functions) Hit Total Coverage
Test: trace.lcov_info_final Lines: 1189 1742 68.3 %
Date: 2021-02-22 04:51:02 Functions: 43 52 82.7 %

          Line data    Source code
       1             : /*********************************************************************
       2             :  *
       3             :  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
       4             :  *
       5             :  * Purpose     :  Main file.  Contains main() method, main loop, and
       6             :  *                the main connection-handling function.
       7             :  *
       8             :  * Copyright   :  Written by and Copyright (C) 2001-2021 the
       9             :  *                Privoxy team. https://www.privoxy.org/
      10             :  *
      11             :  *                Based on the Internet Junkbuster originally written
      12             :  *                by and Copyright (C) 1997 Anonymous Coders and
      13             :  *                Junkbusters Corporation.  http://www.junkbusters.com
      14             :  *
      15             :  *                This program is free software; you can redistribute it
      16             :  *                and/or modify it under the terms of the GNU General
      17             :  *                Public License as published by the Free Software
      18             :  *                Foundation; either version 2 of the License, or (at
      19             :  *                your option) any later version.
      20             :  *
      21             :  *                This program is distributed in the hope that it will
      22             :  *                be useful, but WITHOUT ANY WARRANTY; without even the
      23             :  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
      24             :  *                PARTICULAR PURPOSE.  See the GNU General Public
      25             :  *                License for more details.
      26             :  *
      27             :  *                The GNU General Public License should be included with
      28             :  *                this file.  If not, you can view it at
      29             :  *                http://www.gnu.org/copyleft/gpl.html
      30             :  *                or write to the Free Software Foundation, Inc., 59
      31             :  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
      32             :  *
      33             :  *********************************************************************/
      34             : 
      35             : 
      36             : #include "config.h"
      37             : 
      38             : #include <stdio.h>
      39             : #include <sys/types.h>
      40             : #include <stdlib.h>
      41             : #include <string.h>
      42             : #include <signal.h>
      43             : #include <fcntl.h>
      44             : #include <errno.h>
      45             : #include <assert.h>
      46             : 
      47             : #ifdef _WIN32
      48             : # ifndef FEATURE_PTHREAD
      49             : #  ifndef STRICT
      50             : #   define STRICT
      51             : #  endif
      52             : #  include <winsock2.h>
      53             : #  include <windows.h>
      54             : #  include <process.h>
      55             : # endif /* ndef FEATURE_PTHREAD */
      56             : 
      57             : # include "win32.h"
      58             : # ifndef _WIN_CONSOLE
      59             : #  include "w32log.h"
      60             : # endif /* ndef _WIN_CONSOLE */
      61             : # include "w32svrapi.h"
      62             : 
      63             : #else /* ifndef _WIN32 */
      64             : 
      65             : # include <unistd.h>
      66             : # include <sys/wait.h>
      67             : # include <sys/time.h>
      68             : # include <sys/stat.h>
      69             : # include <sys/ioctl.h>
      70             : 
      71             : #ifdef sun
      72             : #include <sys/termios.h>
      73             : #endif /* sun */
      74             : 
      75             : #ifdef unix
      76             : #include <pwd.h>
      77             : #include <grp.h>
      78             : #endif
      79             : 
      80             : # include <signal.h>
      81             : 
      82             : # ifdef __BEOS__
      83             : #  include <socket.h>  /* BeOS has select() for sockets only. */
      84             : #  include <OS.h>      /* declarations for threads and stuff. */
      85             : # endif
      86             : 
      87             : #ifdef HAVE_POLL
      88             : #ifdef __GLIBC__
      89             : #include <sys/poll.h>
      90             : #else
      91             : #include <poll.h>
      92             : #endif /* def __GLIBC__ */
      93             : #else
      94             : # ifndef FD_ZERO
      95             : #  include <select.h>
      96             : # endif
      97             : #warning poll() appears to be unavailable. Your platform will become unsupported in the future.
      98             : #endif /* HAVE_POLL */
      99             : 
     100             : #endif
     101             : 
     102             : #include "project.h"
     103             : #include "list.h"
     104             : #include "jcc.h"
     105             : #ifdef FEATURE_HTTPS_INSPECTION
     106             : #include "ssl.h"
     107             : #endif
     108             : #include "filters.h"
     109             : #include "loaders.h"
     110             : #include "parsers.h"
     111             : #include "miscutil.h"
     112             : #include "errlog.h"
     113             : #include "jbsockets.h"
     114             : #include "gateway.h"
     115             : #include "actions.h"
     116             : #include "cgi.h"
     117             : #include "loadcfg.h"
     118             : #include "urlmatch.h"
     119             : #ifdef FEATURE_CLIENT_TAGS
     120             : #include "client-tags.h"
     121             : #endif
     122             : 
     123             : int daemon_mode = 1;
     124             : struct client_states clients[1];
     125             : struct file_list     files[1];
     126             : 
     127             : #ifdef FEATURE_STATISTICS
     128             : int urls_read     = 0;     /* total nr of urls read inc rejected */
     129             : int urls_rejected = 0;     /* total nr of urls rejected */
     130             : #endif /* def FEATURE_STATISTICS */
     131             : 
     132             : #ifdef FEATURE_GRACEFUL_TERMINATION
     133             : int g_terminate = 0;
     134             : #endif
     135             : 
     136             : #if !defined(_WIN32)
     137             : static void sig_handler(int the_signal);
     138             : #endif
     139             : static int client_protocol_is_unsupported(struct client_state *csp, char *req);
     140             : static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
     141             : static jb_err get_server_headers(struct client_state *csp);
     142             : static const char *crunch_reason(const struct http_response *rsp);
     143             : static void send_crunch_response(struct client_state *csp, struct http_response *rsp);
     144             : static char *get_request_line(struct client_state *csp);
     145             : static jb_err receive_client_request(struct client_state *csp);
     146             : static jb_err parse_client_request(struct client_state *csp);
     147             : static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line);
     148             : static jb_err change_request_destination(struct client_state *csp);
     149             : static void handle_established_connection(struct client_state *csp);
     150             : static void chat(struct client_state *csp);
     151             : static void serve(struct client_state *csp);
     152             : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
     153             : static void usage(const char *myname);
     154             : #endif
     155             : static void initialize_mutexes(void);
     156             : static jb_socket bind_port_helper(const char *haddr, int hport, int backlog);
     157             : static void bind_ports_helper(struct configuration_spec *config, jb_socket sockets[]);
     158             : static void close_ports_helper(jb_socket sockets[]);
     159             : static void listen_loop(void);
     160             : static void serve(struct client_state *csp);
     161             : 
     162             : #ifdef __BEOS__
     163             : static int32 server_thread(void *data);
     164             : #endif /* def __BEOS__ */
     165             : 
     166             : #ifdef _WIN32
     167             : #define sleep(N)  Sleep(((N) * 1000))
     168             : #endif
     169             : 
     170             : #ifdef FUZZ
     171             : int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file);
     172             : void show_fuzz_usage(const char *name);
     173             : #endif
     174             : 
     175             : #ifdef MUTEX_LOCKS_AVAILABLE
     176             : /*
     177             :  * XXX: Does the locking stuff really belong in this file?
     178             :  */
     179             : privoxy_mutex_t log_mutex;
     180             : privoxy_mutex_t log_init_mutex;
     181             : privoxy_mutex_t connection_reuse_mutex;
     182             : 
     183             : #ifdef FEATURE_HTTPS_INSPECTION
     184             : privoxy_mutex_t certificate_mutex;
     185             : privoxy_mutex_t ssl_init_mutex;
     186             : #endif
     187             : 
     188             : #ifdef FEATURE_EXTERNAL_FILTERS
     189             : privoxy_mutex_t external_filter_mutex;
     190             : #endif
     191             : #ifdef FEATURE_CLIENT_TAGS
     192             : privoxy_mutex_t client_tags_mutex;
     193             : #endif
     194             : #ifdef FEATURE_EXTENDED_STATISTICS
     195             : privoxy_mutex_t filter_statistics_mutex;
     196             : privoxy_mutex_t block_statistics_mutex;
     197             : #endif
     198             : 
     199             : #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
     200             : privoxy_mutex_t resolver_mutex;
     201             : #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
     202             : 
     203             : #ifndef HAVE_GMTIME_R
     204             : privoxy_mutex_t gmtime_mutex;
     205             : #endif /* ndef HAVE_GMTIME_R */
     206             : 
     207             : #ifndef HAVE_LOCALTIME_R
     208             : privoxy_mutex_t localtime_mutex;
     209             : #endif /* ndef HAVE_GMTIME_R */
     210             : 
     211             : #if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
     212             : privoxy_mutex_t rand_mutex;
     213             : #endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
     214             : 
     215             : #endif /* def MUTEX_LOCKS_AVAILABLE */
     216             : 
     217             : #if defined(unix)
     218             : const char *basedir = NULL;
     219             : const char *pidfile = NULL;
     220             : static int received_hup_signal = 0;
     221             : #endif /* defined unix */
     222             : 
     223             : /* HTTP snipplets. */
     224             : static const char CSUCCEED[] =
     225             :    "HTTP/1.1 200 Connection established\r\n\r\n";
     226             : 
     227             : static const char CHEADER[] =
     228             :    "HTTP/1.1 400 Invalid header received from client\r\n"
     229             :    "Content-Type: text/plain\r\n"
     230             :    "Connection: close\r\n\r\n"
     231             :    "Invalid header received from client.\r\n";
     232             : 
     233             : static const char FTP_RESPONSE[] =
     234             :    "HTTP/1.1 400 Invalid request received from client\r\n"
     235             :    "Content-Type: text/plain\r\n"
     236             :    "Connection: close\r\n\r\n"
     237             :    "Invalid request. Privoxy doesn't support FTP.\r\n";
     238             : 
     239             : static const char GOPHER_RESPONSE[] =
     240             :    "HTTP/1.1 400 Invalid request received from client\r\n"
     241             :    "Content-Type: text/plain\r\n"
     242             :    "Connection: close\r\n\r\n"
     243             :    "Invalid request. Privoxy doesn't support gopher.\r\n";
     244             : 
     245             : /* XXX: should be a template */
     246             : static const char MISSING_DESTINATION_RESPONSE[] =
     247             :    "HTTP/1.1 400 Bad request received from client\r\n"
     248             :    "Content-Type: text/plain\r\n"
     249             :    "Connection: close\r\n\r\n"
     250             :    "Bad request. Privoxy was unable to extract the destination.\r\n";
     251             : 
     252             : /* XXX: should be a template */
     253             : static const char INVALID_SERVER_HEADERS_RESPONSE[] =
     254             :    "HTTP/1.1 502 Server or forwarder response invalid\r\n"
     255             :    "Content-Type: text/plain\r\n"
     256             :    "Connection: close\r\n\r\n"
     257             :    "Bad response. The server or forwarder response doesn't look like HTTP.\r\n";
     258             : 
     259             : /* XXX: should be a template */
     260             : static const char MESSED_UP_REQUEST_RESPONSE[] =
     261             :    "HTTP/1.1 400 Malformed request after rewriting\r\n"
     262             :    "Content-Type: text/plain\r\n"
     263             :    "Connection: close\r\n\r\n"
     264             :    "Bad request. Messed up with header filters.\r\n";
     265             : 
     266             : static const char TOO_MANY_CONNECTIONS_RESPONSE[] =
     267             :    "HTTP/1.1 503 Too many open connections\r\n"
     268             :    "Content-Type: text/plain\r\n"
     269             :    "Connection: close\r\n\r\n"
     270             :    "Maximum number of open connections reached.\r\n";
     271             : 
     272             : static const char CLIENT_CONNECTION_TIMEOUT_RESPONSE[] =
     273             :    "HTTP/1.1 504 Connection timeout\r\n"
     274             :    "Content-Type: text/plain\r\n"
     275             :    "Connection: close\r\n\r\n"
     276             :    "The connection timed out because the client request didn't arrive in time.\r\n";
     277             : 
     278             : static const char CLIENT_BODY_PARSE_ERROR_RESPONSE[] =
     279             :    "HTTP/1.1 400 Failed reading client body\r\n"
     280             :    "Content-Type: text/plain\r\n"
     281             :    "Connection: close\r\n\r\n"
     282             :    "Failed parsing or buffering the chunk-encoded client body.\r\n";
     283             : 
     284             : static const char UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE[] =
     285             :    "HTTP/1.1 417 Expecting too much\r\n"
     286             :    "Content-Type: text/plain\r\n"
     287             :    "Connection: close\r\n\r\n"
     288             :    "Privoxy detected an unsupported Expect header value.\r\n";
     289             : 
     290             : /* A function to crunch a response */
     291             : typedef struct http_response *(*crunch_func_ptr)(struct client_state *);
     292             : 
     293             : /* Crunch function flags */
     294             : #define CF_NO_FLAGS        0
     295             : /* Cruncher applies to forced requests as well */
     296             : #define CF_IGNORE_FORCE    1
     297             : /* Crunched requests are counted for the block statistics */
     298             : #define CF_COUNT_AS_REJECT 2
     299             : 
     300             : /* A crunch function and its flags */
     301             : struct cruncher
     302             : {
     303             :    const crunch_func_ptr cruncher;
     304             :    const int flags;
     305             : };
     306             : 
     307             : static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]);
     308             : 
     309             : /* Complete list of cruncher functions */
     310             : static const struct cruncher crunchers_all[] = {
     311             :    { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE},
     312             :    { block_url,       CF_COUNT_AS_REJECT },
     313             : #ifdef FEATURE_TRUST
     314             :    { trust_url,       CF_COUNT_AS_REJECT },
     315             : #endif /* def FEATURE_TRUST */
     316             :    { redirect_url,    CF_NO_FLAGS  },
     317             :    { dispatch_cgi,    CF_IGNORE_FORCE},
     318             :    { NULL,            0 }
     319             : };
     320             : 
     321             : /* Light version, used after tags are applied */
     322             : static const struct cruncher crunchers_light[] = {
     323             :    { block_url,       CF_COUNT_AS_REJECT },
     324             :    { redirect_url,    CF_NO_FLAGS },
     325             :    { NULL,            0 }
     326             : };
     327             : 
     328             : 
     329             : /*
     330             :  * XXX: Don't we really mean
     331             :  *
     332             :  * #if defined(unix)
     333             :  *
     334             :  * here?
     335             :  */
     336             : #if !defined(_WIN32)
     337             : /*********************************************************************
     338             :  *
     339             :  * Function    :  sig_handler
     340             :  *
     341             :  * Description :  Signal handler for different signals.
     342             :  *                Exit gracefully on TERM and INT
     343             :  *                or set a flag that will cause the errlog
     344             :  *                to be reopened by the main thread on HUP.
     345             :  *
     346             :  * Parameters  :
     347             :  *          1  :  the_signal = the signal cause this function to call
     348             :  *
     349             :  * Returns     :  -
     350             :  *
     351             :  *********************************************************************/
     352           0 : static void sig_handler(int the_signal)
     353             : {
     354           0 :    switch(the_signal)
     355             :    {
     356           0 :       case SIGTERM:
     357             :       case SIGINT:
     358           0 :          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
     359             : #if defined(unix)
     360           0 :          if (pidfile)
     361             :          {
     362           0 :             unlink(pidfile);
     363             :          }
     364             : #endif /* unix */
     365           0 :          exit(the_signal);
     366             :          break;
     367             : 
     368           0 :       case SIGHUP:
     369             : #if defined(unix)
     370           0 :          received_hup_signal = 1;
     371             : #endif
     372           0 :          break;
     373             : 
     374           0 :       default:
     375             :          /*
     376             :           * We shouldn't be here, unless we catch signals
     377             :           * in main() that we can't handle here!
     378             :           */
     379           0 :          log_error(LOG_LEVEL_FATAL,
     380             :             "sig_handler: exiting on unexpected signal %d", the_signal);
     381             :    }
     382           0 :    return;
     383             : 
     384             : }
     385             : #endif
     386             : 
     387             : 
     388             : /*********************************************************************
     389             :  *
     390             :  * Function    :  get_write_delay
     391             :  *
     392             :  * Description :  Parse the delay-response parameter.
     393             :  *
     394             :  * Parameters  :
     395             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     396             :  *
     397             :  * Returns     :  Number of milliseconds to delay writes.
     398             :  *
     399             :  *********************************************************************/
     400       60883 : static unsigned int get_write_delay(const struct client_state *csp)
     401             : {
     402             :    unsigned int delay;
     403             :    char *endptr;
     404             :    char *newval;
     405             : 
     406       60883 :    if ((csp->action->flags & ACTION_DELAY_RESPONSE) == 0)
     407             :    {
     408       60883 :       return 0;
     409             :    }
     410           0 :    newval = csp->action->string[ACTION_STRING_DELAY_RESPONSE];
     411             : 
     412           0 :    delay = (unsigned)strtol(newval, &endptr, 0);
     413           0 :    if (*endptr != '\0')
     414             :    {
     415           0 :       log_error(LOG_LEVEL_FATAL,
     416             :          "Invalid delay-response{} parameter: '%s'", newval);
     417             :    }
     418             : 
     419           0 :    return delay;
     420             : 
     421             : }
     422             : 
     423             : 
     424             : /*********************************************************************
     425             :  *
     426             :  * Function    :  client_protocol_is_unsupported
     427             :  *
     428             :  * Description :  Checks if the client used a known unsupported
     429             :  *                protocol and deals with it by sending an error
     430             :  *                response.
     431             :  *
     432             :  * Parameters  :
     433             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     434             :  *          2  :  req = the first request line send by the client
     435             :  *
     436             :  * Returns     :  TRUE if an error response has been generated, or
     437             :  *                FALSE if the request doesn't look invalid.
     438             :  *
     439             :  *********************************************************************/
     440       34220 : static int client_protocol_is_unsupported(struct client_state *csp, char *req)
     441             : {
     442             :    /*
     443             :     * If it's a FTP or gopher request, we don't support it.
     444             :     *
     445             :     * These checks are better than nothing, but they might
     446             :     * not work in all configurations and some clients might
     447             :     * have problems digesting the answer.
     448             :     *
     449             :     * They should, however, never cause more problems than
     450             :     * Privoxy's old behaviour (returning the misleading HTML
     451             :     * error message:
     452             :     *
     453             :     * "Could not resolve http://(ftp|gopher)://example.org").
     454             :     */
     455       34220 :    if (!strncmpic(req, "GET ftp://", 10) || !strncmpic(req, "GET gopher://", 13))
     456             :    {
     457           3 :       const char *response = NULL;
     458           3 :       const char *protocol = NULL;
     459             : 
     460           3 :       if (!strncmpic(req, "GET ftp://", 10))
     461             :       {
     462           2 :          response = FTP_RESPONSE;
     463           2 :          protocol = "FTP";
     464             :       }
     465             :       else
     466             :       {
     467           1 :          response = GOPHER_RESPONSE;
     468           1 :          protocol = "GOPHER";
     469             :       }
     470           3 :       log_error(LOG_LEVEL_ERROR,
     471             :          "%s tried to use Privoxy as %s proxy: %s",
     472             :          csp->ip_addr_str, protocol, req);
     473           3 :       log_error(LOG_LEVEL_CLF,
     474             :          "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
     475           3 :       freez(req);
     476             : 
     477             : #ifdef FEATURE_HTTPS_INSPECTION
     478           3 :       if (client_use_ssl(csp))
     479             :       {
     480           1 :          ssl_send_data_delayed(&(csp->ssl_client_attr),
     481             :             (const unsigned char *)response, strlen(response),
     482             :             get_write_delay(csp));
     483             :       }
     484             :       else
     485             : #endif
     486             :       {
     487           2 :          write_socket_delayed(csp->cfd, response, strlen(response),
     488             :             get_write_delay(csp));
     489             :       }
     490             : 
     491           3 :       return TRUE;
     492             :    }
     493             : 
     494       34217 :    return FALSE;
     495             : }
     496             : 
     497             : 
     498             : /*********************************************************************
     499             :  *
     500             :  * Function    :  client_has_unsupported_expectations
     501             :  *
     502             :  * Description :  Checks if the client used an unsupported expectation
     503             :  *                in which case an error message is delivered.
     504             :  *
     505             :  * Parameters  :
     506             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     507             :  *
     508             :  * Returns     :  TRUE if an error response has been generated, or
     509             :  *                FALSE if the request doesn't look invalid.
     510             :  *
     511             :  *********************************************************************/
     512       31138 : static int client_has_unsupported_expectations(const struct client_state *csp)
     513             : {
     514       31138 :    if ((csp->flags & CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION))
     515             :    {
     516          20 :       log_error(LOG_LEVEL_ERROR,
     517             :          "Rejecting request from client %s with unsupported Expect header value",
     518             :          csp->ip_addr_str);
     519          20 :       log_error(LOG_LEVEL_CLF,
     520             :          "%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd);
     521          20 :       write_socket_delayed(csp->cfd,
     522             :          UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE,
     523             :          strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE),
     524             :          get_write_delay(csp));
     525             : 
     526          20 :       return TRUE;
     527             :    }
     528             : 
     529       31118 :    return FALSE;
     530             : 
     531             : }
     532             : 
     533             : 
     534             : /*********************************************************************
     535             :  *
     536             :  * Function    :  get_request_destination_elsewhere
     537             :  *
     538             :  * Description :  If the client's request was redirected into
     539             :  *                Privoxy without the client's knowledge,
     540             :  *                the request line lacks the destination host.
     541             :  *
     542             :  *                This function tries to get it elsewhere,
     543             :  *                provided accept-intercepted-requests is enabled.
     544             :  *
     545             :  *                "Elsewhere" currently only means "Host: header",
     546             :  *                but in the future we may ask the redirecting
     547             :  *                packet filter to look the destination up.
     548             :  *
     549             :  *                If the destination stays unknown, an error
     550             :  *                response is send to the client and headers
     551             :  *                are freed so that chat() can return directly.
     552             :  *
     553             :  * Parameters  :
     554             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     555             :  *          2  :  headers = a header list
     556             :  *
     557             :  * Returns     :  JB_ERR_OK if the destination is now known, or
     558             :  *                JB_ERR_PARSE if it isn't.
     559             :  *
     560             :  *********************************************************************/
     561       15190 : static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
     562             : {
     563       15190 :    if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
     564             :    {
     565           0 :       log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
     566             :          " Privoxy isn't configured to accept intercepted requests.",
     567             :          csp->ip_addr_str, csp->http->cmd);
     568             :       /* XXX: Use correct size */
     569           0 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
     570             :          csp->ip_addr_str, csp->http->cmd);
     571             : 
     572           0 :       write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
     573             :          get_write_delay(csp));
     574           0 :       destroy_list(headers);
     575             : 
     576           0 :       return JB_ERR_PARSE;
     577             :    }
     578       15190 :    else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http))
     579             :    {
     580             :       /* Split the domain we just got for pattern matching */
     581       15170 :       init_domain_components(csp->http);
     582             : 
     583       15170 :       return JB_ERR_OK;
     584             :    }
     585             :    else
     586             :    {
     587             :       /* We can't work without destination. Go spread the news.*/
     588             : 
     589             :       /* XXX: Use correct size */
     590          20 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
     591             :          csp->ip_addr_str, csp->http->cmd);
     592          20 :       log_error(LOG_LEVEL_ERROR,
     593             :          "Privoxy was unable to get the destination for %s's request: %s",
     594             :          csp->ip_addr_str, csp->http->cmd);
     595             : 
     596          20 :       write_socket_delayed(csp->cfd, MISSING_DESTINATION_RESPONSE,
     597             :          strlen(MISSING_DESTINATION_RESPONSE), get_write_delay(csp));
     598          20 :       destroy_list(headers);
     599             : 
     600          20 :       return JB_ERR_PARSE;
     601             :    }
     602             :    /*
     603             :     * TODO: If available, use PF's ioctl DIOCNATLOOK as last resort
     604             :     * to get the destination IP address, use it as host directly
     605             :     * or do a reverse DNS lookup first.
     606             :     */
     607             : }
     608             : 
     609             : 
     610             : /*********************************************************************
     611             :  *
     612             :  * Function    :  get_server_headers
     613             :  *
     614             :  * Description :  Parses server headers in iob and fills them
     615             :  *                into csp->headers so that they can later be
     616             :  *                handled by sed().
     617             :  *
     618             :  * Parameters  :
     619             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     620             :  *
     621             :  * Returns     :  JB_ERR_OK if everything went fine, or
     622             :  *                JB_ERR_PARSE if the headers were incomplete.
     623             :  *
     624             :  *********************************************************************/
     625       10831 : static jb_err get_server_headers(struct client_state *csp)
     626             : {
     627       10831 :    int continue_hack_in_da_house = 0;
     628             :    char * header;
     629             : 
     630      100233 :    while (((header = get_header(csp->iob)) != NULL) || continue_hack_in_da_house)
     631             :    {
     632       94044 :       if (header == NULL)
     633             :       {
     634             :          /*
     635             :           * continue hack in da house. Ignore the ending of
     636             :           * this head and continue enlisting header lines.
     637             :           * The reason is described below.
     638             :           */
     639          81 :          enlist(csp->headers, "");
     640          81 :          continue_hack_in_da_house = 0;
     641          81 :          continue;
     642             :       }
     643       93963 :       else if (0 == strncmpic(header, "HTTP/1.1 100", 12))
     644             :       {
     645             :          /*
     646             :           * It's a bodyless continue response, don't
     647             :           * stop header parsing after reaching its end.
     648             :           *
     649             :           * As a result Privoxy will concatenate the
     650             :           * next response's head and parse and deliver
     651             :           * the headers as if they belonged to one request.
     652             :           *
     653             :           * The client will separate them because of the
     654             :           * empty line between them.
     655             :           *
     656             :           * XXX: What we're doing here is clearly against
     657             :           * the intended purpose of the continue header,
     658             :           * and under some conditions (HTTP/1.0 client request)
     659             :           * it's a standard violation.
     660             :           *
     661             :           * Anyway, "sort of against the spec" is preferable
     662             :           * to "always getting confused by Continue responses"
     663             :           * (Privoxy's behaviour before this hack was added)
     664             :           */
     665          86 :          log_error(LOG_LEVEL_HEADER, "Continue hack in da house.");
     666          86 :          continue_hack_in_da_house = 1;
     667             :       }
     668       93877 :       else if (*header == '\0')
     669             :       {
     670             :          /*
     671             :           * If the header is empty, but the Continue hack
     672             :           * isn't active, we can assume that we reached the
     673             :           * end of the buffer before we hit the end of the
     674             :           * head.
     675             :           *
     676             :           * Inform the caller an let it decide how to handle it.
     677             :           */
     678        4642 :          return JB_ERR_PARSE;
     679             :       }
     680             : 
     681       89321 :       if (JB_ERR_MEMORY == enlist(csp->headers, header))
     682             :       {
     683             :          /*
     684             :           * XXX: Should we quit the request and return a
     685             :           * out of memory error page instead?
     686             :           */
     687           0 :          log_error(LOG_LEVEL_ERROR,
     688             :             "Out of memory while enlisting server headers. %s lost.",
     689             :             header);
     690             :       }
     691       89321 :       freez(header);
     692             :    }
     693             : 
     694        6189 :    return JB_ERR_OK;
     695             : }
     696             : 
     697             : 
     698             : /*********************************************************************
     699             :  *
     700             :  * Function    :  crunch_reason
     701             :  *
     702             :  * Description :  Translates the crunch reason code into a string.
     703             :  *
     704             :  * Parameters  :
     705             :  *          1  :  rsp = a http_response
     706             :  *
     707             :  * Returns     :  A string with the crunch reason or an error description.
     708             :  *
     709             :  *********************************************************************/
     710       26436 : static const char *crunch_reason(const struct http_response *rsp)
     711             : {
     712       26436 :    char * reason = NULL;
     713             : 
     714       26436 :    assert(rsp != NULL);
     715       26436 :    if (rsp == NULL)
     716             :    {
     717           0 :       return "Internal error while searching for crunch reason";
     718             :    }
     719             : 
     720       26436 :    switch (rsp->crunch_reason)
     721             :    {
     722         928 :       case UNSUPPORTED:
     723         928 :          reason = "Unsupported HTTP feature";
     724         928 :          break;
     725        2309 :       case BLOCKED:
     726        2309 :          reason = "Blocked";
     727        2309 :          break;
     728           0 :       case UNTRUSTED:
     729           0 :          reason = "Untrusted";
     730           0 :          break;
     731         872 :       case REDIRECTED:
     732         872 :          reason = "Redirected";
     733         872 :          break;
     734       22219 :       case CGI_CALL:
     735       22219 :          reason = "CGI Call";
     736       22219 :          break;
     737           0 :       case NO_SUCH_DOMAIN:
     738           0 :          reason = "DNS failure";
     739           0 :          break;
     740           0 :       case FORWARDING_FAILED:
     741           0 :          reason = "Forwarding failed";
     742           0 :          break;
     743          41 :       case CONNECT_FAILED:
     744          41 :          reason = "Connection failure";
     745          41 :          break;
     746           0 :       case OUT_OF_MEMORY:
     747           0 :          reason = "Out of memory (may mask other reasons)";
     748           0 :          break;
     749           0 :       case CONNECTION_TIMEOUT:
     750           0 :          reason = "Connection timeout";
     751           0 :          break;
     752          67 :       case NO_SERVER_DATA:
     753          67 :          reason = "No server data received";
     754          67 :          break;
     755           0 :       default:
     756           0 :          reason = "No reason recorded";
     757           0 :          break;
     758             :    }
     759             : 
     760       26436 :    return reason;
     761             : }
     762             : 
     763             : 
     764             : /*********************************************************************
     765             :  *
     766             :  * Function    :  log_applied_actions
     767             :  *
     768             :  * Description :  Logs the applied actions if LOG_LEVEL_ACTIONS is
     769             :  *                enabled.
     770             :  *
     771             :  * Parameters  :
     772             :  *          1  :  actions = Current action spec to log
     773             :  *
     774             :  * Returns     :  Nothing.
     775             :  *
     776             :  *********************************************************************/
     777       35226 : static void log_applied_actions(const struct current_action_spec *actions)
     778             : {
     779             :    /*
     780             :     * The conversion to text requires lots of memory allocations so
     781             :     * we only do the conversion if the user is actually interested.
     782             :     */
     783       35226 :    if (debug_level_is_enabled(LOG_LEVEL_ACTIONS))
     784             :    {
     785       35226 :       char *actions_as_text = actions_to_line_of_text(actions);
     786       35226 :       log_error(LOG_LEVEL_ACTIONS, "%s", actions_as_text);
     787       35226 :       freez(actions_as_text);
     788             :    }
     789       35226 : }
     790             : 
     791             : 
     792             : /*********************************************************************
     793             :  *
     794             :  * Function    :  send_crunch_response
     795             :  *
     796             :  * Description :  Delivers already prepared response for
     797             :  *                intercepted requests, logs the interception
     798             :  *                and frees the response.
     799             :  *
     800             :  * Parameters  :
     801             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     802             :  *          2  :  rsp = Fully prepared response. Will be freed on exit.
     803             :  *
     804             :  * Returns     :  Nothing.
     805             :  *
     806             :  *********************************************************************/
     807       26436 : static void send_crunch_response(struct client_state *csp, struct http_response *rsp)
     808             : {
     809       26436 :       const struct http_request *http = csp->http;
     810             :       char status_code[4];
     811             : 
     812       26436 :       assert(rsp != NULL);
     813       26436 :       assert(rsp->head != NULL);
     814             : 
     815       26436 :       if (rsp == NULL)
     816             :       {
     817           0 :          log_error(LOG_LEVEL_FATAL, "NULL response in send_crunch_response.");
     818             :       }
     819             : 
     820             :       /*
     821             :        * Extract the status code from the actual head
     822             :        * that will be send to the client. It is the only
     823             :        * way to get it right for all requests, including
     824             :        * the fixed ones for out-of-memory problems.
     825             :        *
     826             :        * A head starts like this: 'HTTP/1.1 200...'
     827             :        *                           0123456789|11
     828             :        *                                     10
     829             :        */
     830       26436 :       status_code[0] = rsp->head[9];
     831       26436 :       status_code[1] = rsp->head[10];
     832       26436 :       status_code[2] = rsp->head[11];
     833       26436 :       status_code[3] = '\0';
     834             : 
     835             :       /* Log that the request was crunched and why. */
     836       26436 :       log_applied_actions(csp->action);
     837             : #ifdef FEATURE_HTTPS_INSPECTION
     838       26436 :       if (client_use_ssl(csp))
     839             :       {
     840        1903 :          log_error(LOG_LEVEL_CRUNCH, "%s: https://%s%s", crunch_reason(rsp),
     841             :             http->hostport, http->path);
     842        1903 :          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" %s %lu",
     843             :             csp->ip_addr_str, http->gpc, http->hostport, http->path,
     844             :             http->version, status_code, rsp->content_length);
     845             :       }
     846             :       else
     847             : #endif
     848             :       {
     849       24533 :          log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
     850       24533 :          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %lu",
     851             :             csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
     852             :       }
     853             :       /* Write the answer to the client */
     854             : #ifdef FEATURE_HTTPS_INSPECTION
     855       26436 :       if (client_use_ssl(csp))
     856             :       {
     857        1903 :          if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
     858        1903 :                 (const unsigned char *)rsp->head, rsp->head_length,
     859             :                 get_write_delay(csp)) < 0)
     860        1903 :           || (ssl_send_data_delayed(&(csp->ssl_client_attr),
     861        1903 :                 (const unsigned char *)rsp->body, rsp->content_length,
     862             :                 get_write_delay(csp)) < 0))
     863             :          {
     864             :             /* There is nothing we can do about it. */
     865           0 :             log_error(LOG_LEVEL_CONNECT, "Couldn't deliver the error message "
     866             :                "for https://%s%s through client socket %d using TLS/SSL",
     867             :                http->hostport, http->url, csp->cfd);
     868             :          }
     869             :       }
     870             :       else
     871             : #endif
     872             :       {
     873       24533 :          if (write_socket_delayed(csp->cfd, rsp->head, rsp->head_length,
     874             :                 get_write_delay(csp))
     875       24533 :           || write_socket_delayed(csp->cfd, rsp->body, rsp->content_length,
     876             :                 get_write_delay(csp)))
     877             :          {
     878             :             /* There is nothing we can do about it. */
     879           0 :             log_error(LOG_LEVEL_CONNECT,
     880             :                "Couldn't deliver the error message for %s through client socket %d: %E",
     881             :                http->url, csp->cfd);
     882             :          }
     883             :       }
     884             : 
     885             :       /* Clean up and return */
     886             : //      if (cgi_error_memory() != rsp)
     887       26436 : if(!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING))
     888             :       {
     889       26436 :          free_http_response(rsp);
     890             :       }
     891       52872 :       return;
     892             : }
     893             : 
     894             : 
     895             : /*********************************************************************
     896             :  *
     897             :  * Function    :  crunch_response_triggered
     898             :  *
     899             :  * Description :  Checks if the request has to be crunched,
     900             :  *                and delivers the crunch response if necessary.
     901             :  *
     902             :  * Parameters  :
     903             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     904             :  *          2  :  crunchers = list of cruncher functions to run
     905             :  *
     906             :  * Returns     :  TRUE if the request was answered with a crunch response
     907             :  *                FALSE otherwise.
     908             :  *
     909             :  *********************************************************************/
     910       38895 : static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[])
     911             : {
     912       38895 :    struct http_response *rsp = NULL;
     913             :    const struct cruncher *c;
     914             : 
     915             :    /*
     916             :     * If CGI request crunching is disabled,
     917             :     * check the CGI dispatcher out of order to
     918             :     * prevent unintentional blocks or redirects.
     919             :     */
     920       38895 :    if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING)
     921       38895 :        && (NULL != (rsp = dispatch_cgi(csp))))
     922             :    {
     923             :       /* Deliver, log and free the interception response. */
     924       22219 :       send_crunch_response(csp, rsp);
     925       22219 :       csp->flags |= CSP_FLAG_CRUNCHED;
     926       22219 :       return TRUE;
     927             :    }
     928             : 
     929       66484 :    for (c = crunchers; c->cruncher != NULL; c++)
     930             :    {
     931             :       /*
     932             :        * Check the cruncher if either Privoxy is toggled
     933             :        * on and the request isn't forced, or if the cruncher
     934             :        * applies to forced requests as well.
     935             :        */
     936       53917 :       if (((csp->flags & CSP_FLAG_TOGGLED_ON) &&
     937       53917 :           !(csp->flags & CSP_FLAG_FORCED)) ||
     938        4202 :           (c->flags & CF_IGNORE_FORCE))
     939             :       {
     940       50959 :          rsp = c->cruncher(csp);
     941       50959 :          if (NULL != rsp)
     942             :          {
     943             :             /* Deliver, log and free the interception response. */
     944        4109 :             send_crunch_response(csp, rsp);
     945        4109 :             csp->flags |= CSP_FLAG_CRUNCHED;
     946             : #ifdef FEATURE_STATISTICS
     947        4109 :             if (c->flags & CF_COUNT_AS_REJECT)
     948             :             {
     949        3237 :                csp->flags |= CSP_FLAG_REJECTED;
     950             :             }
     951             : #endif /* def FEATURE_STATISTICS */
     952             : 
     953        4109 :             return TRUE;
     954             :          }
     955             :       }
     956             :    }
     957             : 
     958       12567 :    return FALSE;
     959             : }
     960             : 
     961             : 
     962             : /*********************************************************************
     963             :  *
     964             :  * Function    :  build_request_line
     965             :  *
     966             :  * Description :  Builds the HTTP request line.
     967             :  *
     968             :  *                If a HTTP forwarder is used it expects the whole URL,
     969             :  *                web servers only get the path.
     970             :  *
     971             :  * Parameters  :
     972             :  *          1  :  csp = Current client state (buffers, headers, etc...)
     973             :  *          2  :  fwd = The forwarding spec used for the request.
     974             :  *                      Can be NULL.
     975             :  *          3  :  request_line = The old request line which will be replaced.
     976             :  *
     977             :  * Returns     :  Nothing. Terminates in case of memory problems.
     978             :  *
     979             :  *********************************************************************/
     980       31169 : static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line)
     981             : {
     982       31169 :    struct http_request *http = csp->http;
     983             : 
     984             :    /*
     985             :     * Downgrade http version from 1.1 to 1.0
     986             :     * if +downgrade action applies.
     987             :     */
     988       31169 :    if ((csp->action->flags & ACTION_DOWNGRADE)
     989         278 :      && (!strcmpic(http->version, "HTTP/1.1")))
     990             :    {
     991         180 :       freez(http->version);
     992         180 :       http->version = strdup_or_die("HTTP/1.0");
     993             :    }
     994             : 
     995             :    /*
     996             :     * Rebuild the request line.
     997             :     */
     998       31169 :    freez(*request_line);
     999       31169 :    *request_line = strdup(http->gpc);
    1000       31169 :    string_append(request_line, " ");
    1001             : 
    1002       31169 :    if (fwd != NULL && fwd->forward_host && fwd->type != FORWARD_WEBSERVER)
    1003             :    {
    1004           0 :       string_append(request_line, http->url);
    1005             :    }
    1006             :    else
    1007             :    {
    1008       31169 :       string_append(request_line, http->path);
    1009             :    }
    1010       31169 :    string_append(request_line, " ");
    1011       31169 :    string_append(request_line, http->version);
    1012             : 
    1013       31169 :    if (*request_line == NULL)
    1014             :    {
    1015           0 :       log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
    1016             :    }
    1017       31169 :    log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line);
    1018       31169 : }
    1019             : 
    1020             : 
    1021             : /*********************************************************************
    1022             :  *
    1023             :  * Function    :  change_request_destination
    1024             :  *
    1025             :  * Description :  Parse a (rewritten) request line and regenerate
    1026             :  *                the http request data.
    1027             :  *
    1028             :  * Parameters  :
    1029             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1030             :  *
    1031             :  * Returns     :  Forwards the parse_http_request() return code.
    1032             :  *                Terminates in case of memory problems.
    1033             :  *
    1034             :  *********************************************************************/
    1035          52 : static jb_err change_request_destination(struct client_state *csp)
    1036             : {
    1037          52 :    struct http_request *http = csp->http;
    1038             :    jb_err err;
    1039             : 
    1040          52 :    log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s",
    1041          52 :       csp->headers->first->str);
    1042          52 :    free_http_request(http);
    1043          52 :    err = parse_http_request(csp->headers->first->str, http);
    1044          52 :    if (JB_ERR_OK != err)
    1045             :    {
    1046           1 :       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
    1047             :          jb_err_to_string(err));
    1048             :    }
    1049          52 :    if (http->ssl && strcmpic(csp->http->gpc, "CONNECT"))
    1050             :    {
    1051             :       /*
    1052             :        * A client header filter changed the request URL from
    1053             :        * http:// to https:// which we currently don't support.
    1054             :        */
    1055           1 :       log_error(LOG_LEVEL_ERROR, "Changing the request destination from http "
    1056             :          "to https behind the client's back currently isn't supported.");
    1057           1 :       return JB_ERR_PARSE;
    1058             :    }
    1059             : 
    1060          51 :    return err;
    1061             : }
    1062             : 
    1063             : 
    1064             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    1065             : /*********************************************************************
    1066             :  *
    1067             :  * Function    :  server_response_is_complete
    1068             :  *
    1069             :  * Description :  Determines whether we should stop reading
    1070             :  *                from the server socket.
    1071             :  *
    1072             :  * Parameters  :
    1073             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1074             :  *          2  :  content_length = Length of content received so far.
    1075             :  *
    1076             :  * Returns     :  TRUE if the response is complete,
    1077             :  *                FALSE otherwise.
    1078             :  *
    1079             :  *********************************************************************/
    1080        9497 : static int server_response_is_complete(struct client_state *csp,
    1081             :    unsigned long long content_length)
    1082             : {
    1083        9497 :    int content_length_known = !!(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET);
    1084             : 
    1085        9497 :    if (!strcmpic(csp->http->gpc, "HEAD"))
    1086             :    {
    1087             :       /*
    1088             :        * "HEAD" implies no body, we are thus expecting
    1089             :        * no content. XXX: incomplete "list" of methods?
    1090             :        */
    1091         183 :       csp->expected_content_length = 0;
    1092         183 :       content_length_known = TRUE;
    1093         183 :       csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
    1094             :    }
    1095             : 
    1096        9497 :    if (csp->http->status == 204 || csp->http->status == 304)
    1097             :    {
    1098             :       /*
    1099             :        * Expect no body. XXX: incomplete "list" of status codes?
    1100             :        */
    1101        2923 :       csp->expected_content_length = 0;
    1102        2923 :       content_length_known = TRUE;
    1103        2923 :       csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
    1104             :    }
    1105             : 
    1106       12366 :    return (content_length_known && ((0 == csp->expected_content_length)
    1107        2869 :             || (csp->expected_content_length <= content_length)));
    1108             : }
    1109             : 
    1110             : 
    1111             : #ifdef FEATURE_CONNECTION_SHARING
    1112             : /*********************************************************************
    1113             :  *
    1114             :  * Function    :  wait_for_alive_connections
    1115             :  *
    1116             :  * Description :  Waits for alive connections to timeout.
    1117             :  *
    1118             :  * Parameters  :  N/A
    1119             :  *
    1120             :  * Returns     :  N/A
    1121             :  *
    1122             :  *********************************************************************/
    1123           0 : static void wait_for_alive_connections(void)
    1124             : {
    1125           0 :    int connections_alive = close_unusable_connections();
    1126             : 
    1127           0 :    while (0 < connections_alive)
    1128             :    {
    1129           0 :       log_error(LOG_LEVEL_CONNECT,
    1130             :          "Waiting for %d connections to timeout.",
    1131             :          connections_alive);
    1132           0 :       sleep(60);
    1133           0 :       connections_alive = close_unusable_connections();
    1134             :    }
    1135             : 
    1136           0 :    log_error(LOG_LEVEL_CONNECT, "No connections to wait for left.");
    1137             : 
    1138           0 : }
    1139             : #endif /* def FEATURE_CONNECTION_SHARING */
    1140             : 
    1141             : 
    1142             : /*********************************************************************
    1143             :  *
    1144             :  * Function    :  save_connection_destination
    1145             :  *
    1146             :  * Description :  Remembers a connection for reuse later on.
    1147             :  *
    1148             :  * Parameters  :
    1149             :  *          1  :  sfd  = Open socket to remember.
    1150             :  *          2  :  http = The destination for the connection.
    1151             :  *          3  :  fwd  = The forwarder settings used.
    1152             :  *          4  :  server_connection  = storage.
    1153             :  *
    1154             :  * Returns     : void
    1155             :  *
    1156             :  *********************************************************************/
    1157        6474 : void save_connection_destination(jb_socket sfd,
    1158             :                                  const struct http_request *http,
    1159             :                                  const struct forward_spec *fwd,
    1160             :                                  struct reusable_connection *server_connection)
    1161             : {
    1162        6474 :    assert(sfd != JB_INVALID_SOCKET);
    1163        6474 :    assert(NULL != http->host);
    1164             : 
    1165        6474 :    server_connection->sfd = sfd;
    1166        6474 :    server_connection->host = strdup_or_die(http->host);
    1167        6474 :    server_connection->port = http->port;
    1168             : 
    1169        6474 :    assert(NULL != fwd);
    1170        6474 :    assert(server_connection->gateway_host == NULL);
    1171        6474 :    assert(server_connection->gateway_port == 0);
    1172        6474 :    assert(server_connection->forwarder_type == 0);
    1173        6474 :    assert(server_connection->forward_host == NULL);
    1174        6474 :    assert(server_connection->forward_port == 0);
    1175             : 
    1176        6474 :    server_connection->forwarder_type = fwd->type;
    1177        6474 :    if (NULL != fwd->gateway_host)
    1178             :    {
    1179           0 :       server_connection->gateway_host = strdup_or_die(fwd->gateway_host);
    1180             :    }
    1181             :    else
    1182             :    {
    1183        6474 :       server_connection->gateway_host = NULL;
    1184             :    }
    1185        6474 :    server_connection->gateway_port = fwd->gateway_port;
    1186        6474 :    if (NULL != fwd->auth_username)
    1187             :    {
    1188           0 :       server_connection->auth_username = strdup_or_die(fwd->auth_username);
    1189             :    }
    1190             :    else
    1191             :    {
    1192        6474 :       server_connection->auth_username = NULL;
    1193             :    }
    1194        6474 :    if (NULL != fwd->auth_password)
    1195             :    {
    1196           0 :       server_connection->auth_password = strdup_or_die(fwd->auth_password);
    1197             :    }
    1198             :    else
    1199             :    {
    1200        6474 :       server_connection->auth_password = NULL;
    1201             :    }
    1202             : 
    1203        6474 :    if (NULL != fwd->forward_host)
    1204             :    {
    1205           0 :       server_connection->forward_host = strdup_or_die(fwd->forward_host);
    1206             :    }
    1207             :    else
    1208             :    {
    1209        6474 :       server_connection->forward_host = NULL;
    1210             :    }
    1211        6474 :    server_connection->forward_port = fwd->forward_port;
    1212        6474 : }
    1213             : #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
    1214             : 
    1215             : 
    1216             : /*********************************************************************
    1217             :  *
    1218             :  * Function    : verify_request_length
    1219             :  *
    1220             :  * Description : Checks if we already got the whole client requests
    1221             :  *               and sets CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ if
    1222             :  *               we do.
    1223             :  *
    1224             :  *               Data that doesn't belong to the current request is
    1225             :  *               either thrown away to let the client retry on a clean
    1226             :  *               socket, or stashed to be dealt with after the current
    1227             :  *               request is served.
    1228             :  *
    1229             :  * Parameters  :
    1230             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1231             :  *
    1232             :  * Returns     :  void
    1233             :  *
    1234             :  *********************************************************************/
    1235       30671 : static void verify_request_length(struct client_state *csp)
    1236             : {
    1237       30671 :    unsigned long long buffered_request_bytes =
    1238       30671 :       (unsigned long long)(csp->client_iob->eod - csp->client_iob->cur);
    1239             : 
    1240       30671 :    if ((csp->expected_client_content_length != 0)
    1241        1194 :       && (buffered_request_bytes != 0))
    1242             :    {
    1243        1158 :       if (csp->expected_client_content_length >= buffered_request_bytes)
    1244             :       {
    1245        1126 :          csp->expected_client_content_length -= buffered_request_bytes;
    1246        1126 :          log_error(LOG_LEVEL_CONNECT, "Reduced expected bytes to %llu "
    1247             :             "to account for the %llu ones we already got.",
    1248             :             csp->expected_client_content_length, buffered_request_bytes);
    1249             :       }
    1250             :       else
    1251             :       {
    1252          32 :          assert(csp->client_iob->eod > csp->client_iob->cur + csp->expected_client_content_length);
    1253          32 :          csp->client_iob->eod = csp->client_iob->cur + csp->expected_client_content_length;
    1254          32 :          log_error(LOG_LEVEL_CONNECT, "Reducing expected bytes to 0. "
    1255             :             "Marking the server socket tainted after throwing %llu bytes away.",
    1256          32 :             buffered_request_bytes - csp->expected_client_content_length);
    1257          32 :          csp->expected_client_content_length = 0;
    1258          32 :          csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    1259             :       }
    1260             : 
    1261        1158 :       if (csp->expected_client_content_length == 0)
    1262             :       {
    1263        1107 :          csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
    1264             :       }
    1265             :    }
    1266             : 
    1267       30671 :    if (!(csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)
    1268       29564 :       && ((csp->client_iob->cur < csp->client_iob->eod)
    1269       17111 :          || (csp->expected_client_content_length != 0)))
    1270             :    {
    1271       12489 :       if (strcmpic(csp->http->gpc, "GET")
    1272        2357 :          && strcmpic(csp->http->gpc, "HEAD")
    1273        2128 :          && strcmpic(csp->http->gpc, "TRACE")
    1274        1567 :          && strcmpic(csp->http->gpc, "OPTIONS")
    1275        1280 :          && strcmpic(csp->http->gpc, "DELETE"))
    1276             :       {
    1277             :          /* XXX: this is an incomplete hack */
    1278        1271 :          csp->flags &= ~CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
    1279        1271 :          log_error(LOG_LEVEL_CONNECT, "There better be a request body.");
    1280             :       }
    1281             :       else
    1282             :       {
    1283       11218 :          csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
    1284             : 
    1285       11218 :          if ((csp->config->feature_flags & RUNTIME_FEATURE_TOLERATE_PIPELINING) == 0)
    1286             :          {
    1287           0 :             csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    1288           0 :             log_error(LOG_LEVEL_CONNECT,
    1289             :                "Possible pipeline attempt detected. The connection will not "
    1290             :                "be kept alive and we will only serve the first request.");
    1291             :             /* Nuke the pipelined requests from orbit, just to be sure. */
    1292           0 :             clear_iob(csp->client_iob);
    1293             :          }
    1294             :          else
    1295             :          {
    1296             :             /*
    1297             :              * Keep the pipelined data around for now, we'll deal with
    1298             :              * it once we're done serving the current request.
    1299             :              */
    1300       11218 :             csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
    1301       11218 :             assert(csp->client_iob->eod >= csp->client_iob->cur);
    1302       11218 :             log_error(LOG_LEVEL_CONNECT, "Complete client request followed by "
    1303             :                "%d bytes of pipelined data received.",
    1304       11218 :                (int)(csp->client_iob->eod - csp->client_iob->cur));
    1305             :          }
    1306             :       }
    1307             :    }
    1308             :    else
    1309             :    {
    1310       18182 :       csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
    1311       18182 :       log_error(LOG_LEVEL_CONNECT, "Complete client request received.");
    1312             :    }
    1313       30671 : }
    1314             : 
    1315             : 
    1316             : /*********************************************************************
    1317             :  *
    1318             :  * Function    :  mark_server_socket_tainted
    1319             :  *
    1320             :  * Description :  Makes sure we don't reuse a server socket
    1321             :  *                (if we didn't read everything the server sent
    1322             :  *                us reusing the socket would lead to garbage).
    1323             :  *
    1324             :  * Parameters  :
    1325             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1326             :  *
    1327             :  * Returns     :  void.
    1328             :  *
    1329             :  *********************************************************************/
    1330         932 : static void mark_server_socket_tainted(struct client_state *csp)
    1331             : {
    1332             :    /*
    1333             :     * For consistency we always mark the server socket
    1334             :     * tainted, however, to reduce the log noise we only
    1335             :     * emit a log message if the server socket could have
    1336             :     * actually been reused.
    1337             :     */
    1338         932 :    if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
    1339         172 :       && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
    1340             :    {
    1341         172 :       log_error(LOG_LEVEL_CONNECT,
    1342             :          "Marking the server socket %d tainted.",
    1343             :          csp->server_connection.sfd);
    1344             :    }
    1345         932 :    csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    1346         932 : }
    1347             : 
    1348             : /*********************************************************************
    1349             :  *
    1350             :  * Function    :  get_request_line
    1351             :  *
    1352             :  * Description : Read the client request line.
    1353             :  *
    1354             :  * Parameters  :
    1355             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1356             :  *
    1357             :  * Returns     :  Pointer to request line or NULL in case of errors.
    1358             :  *
    1359             :  *********************************************************************/
    1360       32220 : static char *get_request_line(struct client_state *csp)
    1361             : {
    1362             :    char buf[BUFFER_SIZE];
    1363       32220 :    char *request_line = NULL;
    1364             :    int len;
    1365             : 
    1366       32220 :    memset(buf, 0, sizeof(buf));
    1367             : 
    1368       32220 :    if ((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
    1369             :    {
    1370             :       /*
    1371             :        * If there are multiple pipelined requests waiting,
    1372             :        * the flag will be set again once the next request
    1373             :        * has been parsed.
    1374             :        */
    1375       10571 :       csp->flags &= ~CSP_FLAG_PIPELINED_REQUEST_WAITING;
    1376             : 
    1377       10571 :       request_line = get_header(csp->client_iob);
    1378       10571 :       if ((NULL != request_line) && ('\0' != *request_line))
    1379             :       {
    1380        9836 :          return request_line;
    1381             :       }
    1382             :       else
    1383             :       {
    1384         735 :          log_error(LOG_LEVEL_CONNECT, "No complete request line "
    1385             :             "received yet. Continuing reading from %d.", csp->cfd);
    1386             :       }
    1387             :    }
    1388             : 
    1389             :    do
    1390             :    {
    1391       23923 :       if (
    1392             : #ifdef FUZZ
    1393       44379 :           0 == (csp->flags & CSP_FLAG_FUZZED_INPUT) &&
    1394             : #endif
    1395       20456 :           !data_is_available(csp->cfd, csp->config->socket_timeout)
    1396             :           )
    1397             :       {
    1398         134 :          if (socket_is_still_alive(csp->cfd))
    1399             :          {
    1400           0 :             log_error(LOG_LEVEL_CONNECT,
    1401             :                "No request line on socket %d received in time. Timeout: %d.",
    1402           0 :                csp->cfd, csp->config->socket_timeout);
    1403           0 :             write_socket_delayed(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
    1404             :                strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE),
    1405             :                get_write_delay(csp));
    1406             :          }
    1407             :          else
    1408             :          {
    1409         134 :             log_error(LOG_LEVEL_CONNECT,
    1410             :                "The client side of the connection on socket %d got "
    1411             :                "closed without sending a complete request line.", csp->cfd);
    1412             :          }
    1413         134 :          return NULL;
    1414             :       }
    1415             : 
    1416       23789 :       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
    1417             : 
    1418       23789 :       if (len <= 0) return NULL;
    1419             : 
    1420             :       /*
    1421             :        * If there is no memory left for buffering the
    1422             :        * request, there is nothing we can do but hang up
    1423             :        */
    1424       23756 :       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
    1425             :       {
    1426           0 :          return NULL;
    1427             :       }
    1428             : 
    1429       23756 :       request_line = get_header(csp->client_iob);
    1430             : 
    1431       23756 :    } while ((NULL != request_line) && ('\0' == *request_line));
    1432             : 
    1433       22217 :    return request_line;
    1434             : 
    1435             : }
    1436             : 
    1437             : enum chunk_status
    1438             : {
    1439             :    CHUNK_STATUS_MISSING_DATA,
    1440             :    CHUNK_STATUS_BODY_COMPLETE,
    1441             :    CHUNK_STATUS_PARSE_ERROR
    1442             : };
    1443             : 
    1444             : 
    1445             : /*********************************************************************
    1446             :  *
    1447             :  * Function    :  chunked_body_is_complete
    1448             :  *
    1449             :  * Description :  Figures out whether or not a chunked body is complete.
    1450             :  *
    1451             :  *                Currently it always starts at the beginning of the
    1452             :  *                buffer which is somewhat wasteful and prevents Privoxy
    1453             :  *                from starting to forward the correctly parsed chunks
    1454             :  *                as soon as theoretically possible.
    1455             :  *
    1456             :  *                Should be modified to work with a common buffer,
    1457             :  *                and allow the caller to skip already parsed chunks.
    1458             :  *
    1459             :  *                This would allow the function to be used for unbuffered
    1460             :  *                response bodies as well.
    1461             :  *
    1462             :  * Parameters  :
    1463             :  *          1  :  iob = Buffer with the body to check.
    1464             :  *          2  :  length = Length of complete body
    1465             :  *
    1466             :  * Returns     :  Enum with the result of the check.
    1467             :  *
    1468             :  *********************************************************************/
    1469         677 : static enum chunk_status chunked_body_is_complete(struct iob *iob, size_t *length)
    1470             : {
    1471             :    unsigned int chunksize;
    1472         677 :    char *p = iob->cur;
    1473             : 
    1474             :    do
    1475             :    {
    1476             :       /*
    1477             :        * We need at least a single digit, followed by "\r\n",
    1478             :        * followed by an unknown amount of data, followed by "\r\n".
    1479             :        */
    1480         893 :       if (p + 5 > iob->eod)
    1481             :       {
    1482          17 :          return CHUNK_STATUS_MISSING_DATA;
    1483             :       }
    1484         876 :       if (sscanf(p, "%x", &chunksize) != 1)
    1485             :       {
    1486           2 :          return CHUNK_STATUS_PARSE_ERROR;
    1487             :       }
    1488             : 
    1489             :       /*
    1490             :        * We want at least a single digit, followed by "\r\n",
    1491             :        * followed by the specified amount of data, followed by "\r\n".
    1492             :        */
    1493         874 :       if (p + chunksize + 5 > iob->eod)
    1494             :       {
    1495         510 :          return CHUNK_STATUS_MISSING_DATA;
    1496             :       }
    1497             : 
    1498             :       /* Skip chunk-size. */
    1499         364 :       p = strstr(p, "\r\n");
    1500         364 :       if (NULL == p)
    1501             :       {
    1502           2 :          return CHUNK_STATUS_PARSE_ERROR;
    1503             :       }
    1504             :       /* Move beyond the chunkdata. */
    1505         362 :       p += 2 + chunksize;
    1506             : 
    1507             :       /* Make sure we're still within the buffer and have two bytes left */
    1508         362 :       if (p + 2 > iob->eod)
    1509             :       {
    1510          85 :          return CHUNK_STATUS_MISSING_DATA;
    1511             :       }
    1512             : 
    1513             :       /* There should be another "\r\n" to skip */
    1514         277 :       if (memcmp(p, "\r\n", 2))
    1515             :       {
    1516          14 :          return CHUNK_STATUS_PARSE_ERROR;
    1517             :       }
    1518         263 :       p += 2;
    1519         263 :    } while (chunksize > 0U);
    1520             : 
    1521          47 :    *length = (size_t)(p - iob->cur);
    1522          47 :    assert(*length <= (size_t)(iob->eod - iob->cur));
    1523          47 :    assert(p <= iob->eod);
    1524             : 
    1525          47 :    return CHUNK_STATUS_BODY_COMPLETE;
    1526             : 
    1527             : }
    1528             : 
    1529             : 
    1530             : /*********************************************************************
    1531             :  *
    1532             :  * Function    : receive_chunked_client_request_body
    1533             :  *
    1534             :  * Description : Read the chunk-encoded client request body.
    1535             :  *               Failures are dealt with.
    1536             :  *
    1537             :  * Parameters  :
    1538             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1539             :  *
    1540             :  * Returns     :  JB_ERR_OK or JB_ERR_PARSE
    1541             :  *
    1542             :  *********************************************************************/
    1543          81 : static jb_err receive_chunked_client_request_body(struct client_state *csp)
    1544             : {
    1545             :    size_t body_length;
    1546             :    enum chunk_status status;
    1547             : 
    1548         758 :    while (CHUNK_STATUS_MISSING_DATA ==
    1549         677 :       (status = chunked_body_is_complete(csp->client_iob, &body_length)))
    1550             :    {
    1551             :       char buf[BUFFER_SIZE];
    1552             :       int len;
    1553             : 
    1554         612 :       if (!data_is_available(csp->cfd, csp->config->socket_timeout))
    1555             :       {
    1556          15 :          log_error(LOG_LEVEL_ERROR,
    1557             :             "Timeout while waiting for the client body.");
    1558          16 :          break;
    1559             :       }
    1560         597 :       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
    1561         597 :       if (len <= 0)
    1562             :       {
    1563           1 :          log_error(LOG_LEVEL_ERROR,
    1564             :             "Reading the client body failed: %E");
    1565           1 :          break;
    1566             :       }
    1567         596 :       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
    1568             :       {
    1569           0 :          break;
    1570             :       }
    1571             :    }
    1572          81 :    if (status != CHUNK_STATUS_BODY_COMPLETE)
    1573             :    {
    1574          34 :       write_socket_delayed(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE,
    1575             :          strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE), get_write_delay(csp));
    1576          34 :       log_error(LOG_LEVEL_CLF,
    1577             :          "%s - - [%T] \"Failed reading chunked client body\" 400 0", csp->ip_addr_str);
    1578          34 :       return JB_ERR_PARSE;
    1579             :    }
    1580          47 :    log_error(LOG_LEVEL_CONNECT,
    1581             :       "Chunked client body completely read. Length: %lu", body_length);
    1582          47 :    csp->expected_client_content_length = body_length;
    1583             : 
    1584          47 :    return JB_ERR_OK;
    1585             : 
    1586             : }
    1587             : 
    1588             : 
    1589             : #ifdef FUZZ
    1590             : /*********************************************************************
    1591             :  *
    1592             :  * Function    :  fuzz_chunked_transfer_encoding
    1593             :  *
    1594             :  * Description :  Treat the fuzzed input as chunked transfer encoding
    1595             :  *                to check and dechunk.
    1596             :  *
    1597             :  * Parameters  :
    1598             :  *          1  :  csp      = Used to store the data.
    1599             :  *          2  :  fuzz_input_file = File to read the input from.
    1600             :  *
    1601             :  * Returns     : Result of dechunking
    1602             :  *
    1603             :  *********************************************************************/
    1604           0 : extern int fuzz_chunked_transfer_encoding(struct client_state *csp, char *fuzz_input_file)
    1605             : {
    1606             :    size_t length;
    1607           0 :    size_t size = (size_t)(csp->iob->eod - csp->iob->cur);
    1608             :    enum chunk_status status;
    1609             : 
    1610           0 :    status = chunked_body_is_complete(csp->iob, &length);
    1611           0 :    if (CHUNK_STATUS_BODY_COMPLETE != status)
    1612             :    {
    1613           0 :       log_error(LOG_LEVEL_INFO, "Chunked body is incomplete or invalid");
    1614             :    }
    1615             : 
    1616           0 :    return (JB_ERR_OK == remove_chunked_transfer_coding(csp->iob->cur, &size));
    1617             : 
    1618             : }
    1619             : 
    1620             : 
    1621             : /*********************************************************************
    1622             :  *
    1623             :  * Function    : fuzz_client_request
    1624             :  *
    1625             :  * Description : Try to get a client request from the fuzzed input.
    1626             :  *
    1627             :  * Parameters  :
    1628             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1629             :  *          2  :  fuzz_input_file = File to read the input from.
    1630             :  *
    1631             :  * Returns     :  Result of fuzzing.
    1632             :  *
    1633             :  *********************************************************************/
    1634        3098 : extern int fuzz_client_request(struct client_state *csp, char *fuzz_input_file)
    1635             : {
    1636             : 
    1637             :        jb_err err;
    1638             : 
    1639        3098 :        csp->cfd = 0; //stdin
    1640        3098 :                  csp->ip_addr_str = "255.255.255.255";
    1641        3098 :        if (strcmp(fuzz_input_file, "-") != 0)
    1642             :        {
    1643           0 :                log_error(LOG_LEVEL_FATAL,
    1644             :                "Fuzzed client requests can currently only be read from stdin (-).");
    1645             :        }
    1646        3098 :         csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
    1647             : 
    1648        3098 :        serve(csp);
    1649             : //   free_csp_resources(csp); //static...
    1650        3098 :        return 0;
    1651             : 
    1652             : }
    1653             : #endif  /* def FUZZ */
    1654             : 
    1655             : 
    1656             : #ifdef FEATURE_FORCE_LOAD
    1657             : /*********************************************************************
    1658             :  *
    1659             :  * Function    :  force_required
    1660             :  *
    1661             :  * Description : Checks a request line to see if it contains
    1662             :  *               the FORCE_PREFIX. If it does, it is removed
    1663             :  *               unless enforcing requests has beend disabled.
    1664             :  *
    1665             :  * Parameters  :
    1666             :  *          1  :  request_line = HTTP request line
    1667             :  *
    1668             :  * Returns     :  TRUE if force is required, FALSE otherwise.
    1669             :  *
    1670             :  *********************************************************************/
    1671       34217 : static int force_required(const struct client_state *csp, char *request_line)
    1672             : {
    1673             :    char *p;
    1674             : 
    1675       34217 :    p = strstr(request_line, "http://");
    1676       34217 :    if (p != NULL)
    1677             :    {
    1678             :       /* Skip protocol */
    1679       15978 :       p += strlen("http://");
    1680             :    }
    1681             :    else
    1682             :    {
    1683             :       /* Intercepted request usually don't specify the protocol. */
    1684       18239 :       p = request_line;
    1685             :    }
    1686             : 
    1687             :    /* Go to the beginning of the path */
    1688       34217 :    p = strstr(p, "/");
    1689       34217 :    if (p == NULL)
    1690             :    {
    1691             :       /*
    1692             :        * If the path is missing the request line is invalid and we
    1693             :        * are done here. The client-visible rejection happens later on.
    1694             :        */
    1695          95 :       return 0;
    1696             :    }
    1697             : 
    1698       34122 :    if (0 == strncmpic(p, FORCE_PREFIX, strlen(FORCE_PREFIX) - 1))
    1699             :    {
    1700         902 :       if (!(csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS))
    1701             :       {
    1702             :          /* XXX: Should clean more carefully */
    1703         902 :          strclean(request_line, FORCE_PREFIX);
    1704         902 :          log_error(LOG_LEVEL_FORCE,
    1705             :             "Enforcing request: \"%s\".", request_line);
    1706             : 
    1707         902 :          return 1;
    1708             :       }
    1709           0 :       log_error(LOG_LEVEL_FORCE,
    1710             :          "Ignored force prefix in request: \"%s\".", request_line);
    1711             :    }
    1712             : 
    1713       33220 :    return 0;
    1714             : 
    1715             : }
    1716             : #endif /* def FEATURE_FORCE_LOAD */
    1717             : 
    1718             : 
    1719             : /*********************************************************************
    1720             :  *
    1721             :  * Function    :  receive_client_request
    1722             :  *
    1723             :  * Description : Read the client's request (more precisely the
    1724             :  *               client headers) and answer it if necessary.
    1725             :  *
    1726             :  * Parameters  :
    1727             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1728             :  *
    1729             :  * Returns     :  JB_ERR_OK, JB_ERR_PARSE or JB_ERR_MEMORY
    1730             :  *
    1731             :  *********************************************************************/
    1732       32220 : static jb_err receive_client_request(struct client_state *csp)
    1733             : {
    1734             :    char buf[BUFFER_SIZE];
    1735             :    char *p;
    1736       32220 :    char *req = NULL;
    1737             :    struct http_request *http;
    1738             :    int len;
    1739             :    jb_err err;
    1740             : 
    1741             :    /* Temporary copy of the client's headers before they get enlisted in csp->headers */
    1742             :    struct list header_list;
    1743       32220 :    struct list *headers = &header_list;
    1744             : 
    1745             :    /* We don't care if the arriving data is a valid HTTP request or not. */
    1746       32220 :    csp->requests_received_total++;
    1747             : 
    1748       32220 :    http = csp->http;
    1749             : 
    1750       32220 :    memset(buf, 0, sizeof(buf));
    1751             : 
    1752       32220 :    req = get_request_line(csp);
    1753       32220 :    if (req == NULL)
    1754             :    {
    1755         173 :       mark_server_socket_tainted(csp);
    1756         173 :       return JB_ERR_PARSE;
    1757             :    }
    1758       32047 :    assert(*req != '\0');
    1759             : 
    1760       32047 :    if (client_protocol_is_unsupported(csp, req))
    1761             :    {
    1762           2 :       return JB_ERR_PARSE;
    1763             :    }
    1764             : 
    1765             : #ifdef FEATURE_FORCE_LOAD
    1766       32045 :    if (force_required(csp, req))
    1767             :    {
    1768         892 :       csp->flags |= CSP_FLAG_FORCED;
    1769             :    }
    1770             : #endif /* def FEATURE_FORCE_LOAD */
    1771             : 
    1772       32045 :    err = parse_http_request(req, http);
    1773       32045 :    freez(req);
    1774       32045 :    if (JB_ERR_OK != err)
    1775             :    {
    1776         435 :       write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
    1777             :          get_write_delay(csp));
    1778             :       /* XXX: Use correct size */
    1779         435 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
    1780         435 :       log_error(LOG_LEVEL_ERROR,
    1781             :          "Couldn't parse request line received from %s: %s",
    1782             :          csp->ip_addr_str, jb_err_to_string(err));
    1783             : 
    1784         435 :       free_http_request(http);
    1785         435 :       return JB_ERR_PARSE;
    1786             :    }
    1787             : 
    1788             :    /* grab the rest of the client's headers */
    1789       31610 :    init_list(headers);
    1790             :    for (;;)
    1791             :    {
    1792      338406 :       p = get_header(csp->client_iob);
    1793             : 
    1794      338406 :       if (p == NULL)
    1795             :       {
    1796             :          /* There are no additional headers to read. */
    1797       31197 :          break;
    1798             :       }
    1799             : 
    1800      307209 :       if (*p == '\0')
    1801             :       {
    1802             :          /*
    1803             :           * We didn't receive a complete header
    1804             :           * line yet, get the rest of it.
    1805             :           */
    1806        9272 :          if (!data_is_available(csp->cfd, csp->config->socket_timeout))
    1807             :          {
    1808         402 :             log_error(LOG_LEVEL_ERROR,
    1809             :                "Stopped grabbing the client headers.");
    1810         402 :             destroy_list(headers);
    1811         402 :             return JB_ERR_PARSE;
    1812             :          }
    1813             : 
    1814        8870 :          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
    1815        8870 :          if (len <= 0)
    1816             :          {
    1817          11 :             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
    1818          11 :             destroy_list(headers);
    1819          11 :             return JB_ERR_PARSE;
    1820             :          }
    1821             : 
    1822        8859 :          if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
    1823             :          {
    1824             :             /*
    1825             :              * If there is no memory left for buffering the
    1826             :              * request, there is nothing we can do but hang up
    1827             :              */
    1828           0 :             destroy_list(headers);
    1829           0 :             return JB_ERR_MEMORY;
    1830             :          }
    1831             :       }
    1832             :       else
    1833             :       {
    1834      297937 :          if (!strncmpic(p, "Transfer-Encoding:", 18))
    1835             :          {
    1836             :             /*
    1837             :              * XXX: should be called through sed()
    1838             :              *      but currently can't.
    1839             :              */
    1840         784 :             client_transfer_encoding(csp, &p);
    1841             :          }
    1842             :          /*
    1843             :           * We were able to read a complete
    1844             :           * header and can finally enlist it.
    1845             :           */
    1846      297937 :          enlist(headers, p);
    1847      297937 :          freez(p);
    1848             :       }
    1849             :    }
    1850             : 
    1851       31197 :    if (http->host == NULL)
    1852             :    {
    1853             :       /*
    1854             :        * If we still don't know the request destination,
    1855             :        * the request is invalid or the client uses
    1856             :        * Privoxy without its knowledge.
    1857             :        */
    1858       15190 :       if (JB_ERR_OK != get_request_destination_elsewhere(csp, headers))
    1859             :       {
    1860             :          /*
    1861             :           * Our attempts to get the request destination
    1862             :           * elsewhere failed or Privoxy is configured
    1863             :           * to only accept proxy requests.
    1864             :           *
    1865             :           * An error response has already been sent
    1866             :           * and we're done here.
    1867             :           */
    1868          20 :          return JB_ERR_PARSE;
    1869             :       }
    1870             :    }
    1871             : 
    1872             : #ifdef FEATURE_CLIENT_TAGS
    1873             :    /* XXX: If the headers were enlisted sooner, passing csp would do. */
    1874       31177 :    set_client_address(csp, headers);
    1875       31177 :    get_tag_list_for_client(csp->client_tags, csp->client_address);
    1876             : #endif
    1877             : 
    1878             :    /*
    1879             :     * Determine the actions for this URL
    1880             :     */
    1881             : #ifdef FEATURE_TOGGLE
    1882       31177 :    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
    1883             :    {
    1884             :       /* Most compatible set of actions (i.e. none) */
    1885        1100 :       init_current_action(csp->action);
    1886             :    }
    1887             :    else
    1888             : #endif /* ndef FEATURE_TOGGLE */
    1889             :    {
    1890       30077 :       get_url_actions(csp, http);
    1891             :    }
    1892             : 
    1893       31177 :    enlist(csp->headers, http->cmd);
    1894             : 
    1895             :    /* Append the previously read headers */
    1896       31177 :    err = list_append_list_unique(csp->headers, headers);
    1897       31177 :    destroy_list(headers);
    1898             : 
    1899       31177 :    return err;
    1900             : 
    1901             : }
    1902             : 
    1903             : 
    1904             : /*********************************************************************
    1905             :  *
    1906             :  * Function    : parse_client_request
    1907             :  *
    1908             :  * Description : Parses the client's request and decides what to do
    1909             :  *               with it.
    1910             :  *
    1911             :  *               Note that since we're not using select() we could get
    1912             :  *               blocked here if a client connected, then didn't say
    1913             :  *               anything!
    1914             :  *
    1915             :  * Parameters  :
    1916             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    1917             :  *
    1918             :  * Returns     :  JB_ERR_OK or JB_ERR_PARSE
    1919             :  *
    1920             :  *********************************************************************/
    1921       31177 : static jb_err parse_client_request(struct client_state *csp)
    1922             : {
    1923       31177 :    struct http_request *http = csp->http;
    1924             :    jb_err err;
    1925             : 
    1926             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    1927       31177 :    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
    1928       31177 :     && (!strcmpic(csp->http->version, "HTTP/1.1"))
    1929       27525 :     && (csp->http->ssl == 0))
    1930             :    {
    1931             :       /* Assume persistence until further notice */
    1932       27096 :       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    1933             :    }
    1934             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    1935             : 
    1936       31177 :    if (csp->http->ssl == 0)
    1937             :    {
    1938             :       /*
    1939             :        * This whole block belongs to chat() but currently
    1940             :        * has to be executed before sed().
    1941             :        */
    1942       30705 :       if (csp->flags & CSP_FLAG_CHUNKED_CLIENT_BODY)
    1943             :       {
    1944          81 :          if (receive_chunked_client_request_body(csp) != JB_ERR_OK)
    1945             :          {
    1946          34 :             return JB_ERR_PARSE;
    1947             :          }
    1948             :       }
    1949             :       else
    1950             :       {
    1951       30624 :          csp->expected_client_content_length = get_expected_content_length(csp->headers);
    1952             :       }
    1953       30671 :       verify_request_length(csp);
    1954             :    }
    1955             : #ifndef FEATURE_HTTPS_INSPECTION
    1956             :    else
    1957             :    {
    1958             :       csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    1959             :    }
    1960             : #endif
    1961             : 
    1962       31143 :    err = sed(csp, FILTER_CLIENT_HEADERS);
    1963       31143 :    if (JB_ERR_OK != err)
    1964             :    {
    1965           2 :       log_error(LOG_LEVEL_ERROR, "Failed to parse client request from %s.",
    1966             :          csp->ip_addr_str);
    1967           2 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
    1968             :          csp->ip_addr_str, csp->http->cmd);
    1969           2 :       write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), get_write_delay(csp));
    1970           2 :       return JB_ERR_PARSE;
    1971             :    }
    1972       31141 :    csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
    1973             : 
    1974             :    /* Check request line for rewrites. */
    1975       31141 :    if ((NULL == csp->headers->first->str)
    1976       31192 :       || (strcmp(http->cmd, csp->headers->first->str) &&
    1977          52 :          (JB_ERR_OK != change_request_destination(csp))))
    1978             :    {
    1979             :       /*
    1980             :        * A header filter broke the request line - bail out.
    1981             :        */
    1982           3 :       write_socket_delayed(csp->cfd, MESSED_UP_REQUEST_RESPONSE,
    1983             :          strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp));
    1984             :       /* XXX: Use correct size */
    1985           3 :       log_error(LOG_LEVEL_CLF,
    1986             :          "%s - - [%T] \"Invalid request generated\" 400 0", csp->ip_addr_str);
    1987           3 :       log_error(LOG_LEVEL_ERROR,
    1988             :          "Invalid request line after applying header filters.");
    1989           3 :       free_http_request(http);
    1990             : 
    1991           3 :       return JB_ERR_PARSE;
    1992             :    }
    1993             : 
    1994       31138 :    if (client_has_unsupported_expectations(csp))
    1995             :    {
    1996          20 :       return JB_ERR_PARSE;
    1997             :    }
    1998             : 
    1999       31118 :    return JB_ERR_OK;
    2000             : 
    2001             : }
    2002             : 
    2003             : 
    2004             : /*********************************************************************
    2005             :  *
    2006             :  * Function    : read_http_request_body
    2007             :  *
    2008             :  * Description : Reads remaining request body from the client.
    2009             :  *
    2010             :  * Parameters  :
    2011             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2012             :  *
    2013             :  * Returns     :  0 on success, anything else is an error.
    2014             :  *
    2015             :  *********************************************************************/
    2016         833 : static int read_http_request_body(struct client_state *csp)
    2017             : {
    2018         833 :    size_t to_read = csp->expected_client_content_length;
    2019             :    int len;
    2020             : 
    2021         833 :    assert(to_read != 0);
    2022             : 
    2023             :    /* check if all data has been already read */
    2024         833 :    if (to_read <= (csp->client_iob->eod - csp->client_iob->cur))
    2025             :    {
    2026         786 :       return 0;
    2027             :    }
    2028             : 
    2029         574 :    for (to_read -= (size_t)(csp->client_iob->eod - csp->client_iob->cur);
    2030         550 :         to_read > 0 && data_is_available(csp->cfd, csp->config->socket_timeout);
    2031         527 :         to_read -= (unsigned)len)
    2032             :    {
    2033             :       char buf[BUFFER_SIZE];
    2034         527 :       size_t max_bytes_to_read = to_read < sizeof(buf) ? to_read : sizeof(buf);
    2035             : 
    2036         527 :       log_error(LOG_LEVEL_CONNECT,
    2037             :          "Waiting for up to %d bytes of request body from the client.",
    2038             :          max_bytes_to_read);
    2039         527 :       len = read_socket(csp->cfd, buf, (int)max_bytes_to_read);
    2040         527 :       if (len <= -1)
    2041             :       {
    2042           0 :          log_error(LOG_LEVEL_CONNECT, "Failed receiving request body from %s: %E", csp->ip_addr_str);
    2043           0 :          return 1;
    2044             :       }
    2045         527 :       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, (char *)buf, len))
    2046             :       {
    2047           0 :          return 1;
    2048             :       }
    2049         527 :       assert(to_read >= len);
    2050             :    }
    2051             : 
    2052          47 :    if (to_read != 0)
    2053             :    {
    2054          23 :       log_error(LOG_LEVEL_CONNECT, "Not enough request body has been read: expected %d more bytes",
    2055             :          csp->expected_client_content_length);
    2056          23 :       return 1;
    2057             :    }
    2058          24 :    log_error(LOG_LEVEL_CONNECT, "The last %d bytes of the request body have been read",
    2059             :       csp->expected_client_content_length);
    2060          24 :    return 0;
    2061             : }
    2062             : 
    2063             : 
    2064             : /*********************************************************************
    2065             :  *
    2066             :  * Function    : update_client_headers
    2067             :  *
    2068             :  * Description : Updates the HTTP headers from the client request.
    2069             :  *
    2070             :  * Parameters  :
    2071             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2072             :  *          2  :  new_content_length = new content length value to set
    2073             :  *
    2074             :  * Returns     :  0 on success, anything else is an error.
    2075             :  *
    2076             :  *********************************************************************/
    2077         246 : static int update_client_headers(struct client_state *csp, size_t new_content_length)
    2078             : {
    2079             :    static const char content_length[] = "Content-Length:";
    2080         246 :    int updated = 0;
    2081             :    struct list_entry *p;
    2082             : 
    2083             : #ifndef FEATURE_HTTPS_INSPECTION
    2084             :    for (p = csp->headers->first;
    2085             : #else
    2086        3217 :    for (p = csp->http->client_ssl ? csp->https_headers->first : csp->headers->first;
    2087             : #endif
    2088        5948 :         !updated  && (p != NULL); p = p->next)
    2089             :    {
    2090             :       /* Header crunch()ed in previous run? -> ignore */
    2091        2971 :       if (p->str == NULL)
    2092             :       {
    2093           0 :          continue;
    2094             :       }
    2095             : 
    2096             :       /* Does the current parser handle this header? */
    2097        2971 :       if (0 == strncmpic(p->str, content_length, sizeof(content_length) - 1))
    2098             :       {
    2099         240 :          updated = (JB_ERR_OK == header_adjust_content_length((char **)&(p->str), new_content_length));
    2100         240 :          if (!updated)
    2101             :          {
    2102           0 :             return 1;
    2103             :          }
    2104             :       }
    2105             :    }
    2106             : 
    2107         246 :    return !updated;
    2108             : }
    2109             : 
    2110             : 
    2111             : /*********************************************************************
    2112             :  *
    2113             :  * Function    : can_filter_request_body
    2114             :  *
    2115             :  * Description : Checks if the current request body can be stored in
    2116             :  *               the client_iob without hitting buffer limit.
    2117             :  *
    2118             :  * Parameters  :
    2119             :  *          1  : csp = Current client state (buffers, headers, etc...)
    2120             :  *
    2121             :  * Returns     : TRUE if the current request size do not exceed buffer limit
    2122             :  *               FALSE otherwise.
    2123             :  *
    2124             :  *********************************************************************/
    2125         926 : static int can_filter_request_body(const struct client_state *csp)
    2126             : {
    2127         926 :    if (!can_add_to_iob(csp->client_iob, csp->config->buffer_limit,
    2128         926 :                        csp->expected_client_content_length))
    2129             :    {
    2130          29 :       log_error(LOG_LEVEL_INFO,
    2131             :          "Not filtering request body from %s: buffer limit %d will be exceeded "
    2132          29 :          "(content length %d)", csp->ip_addr_str, csp->config->buffer_limit,
    2133             :          csp->expected_client_content_length);
    2134          29 :       return FALSE;
    2135             :    }
    2136         897 :    return TRUE;
    2137             : }
    2138             : 
    2139             : 
    2140             : /*********************************************************************
    2141             :  *
    2142             :  * Function    : send_http_request
    2143             :  *
    2144             :  * Description : Sends the HTTP headers from the client request
    2145             :  *               and all the body data that has already been received.
    2146             :  *
    2147             :  * Parameters  :
    2148             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2149             :  *
    2150             :  * Returns     :  0 on success, anything else is an error.
    2151             :  *
    2152             :  *********************************************************************/
    2153        6316 : static int send_http_request(struct client_state *csp)
    2154             : {
    2155             :    char *hdr;
    2156             :    int write_failure;
    2157             :    const char *to_send;
    2158             :    size_t to_send_len;
    2159       13756 :    int filter_client_body = csp->expected_client_content_length != 0 &&
    2160        7440 :       client_body_filters_enabled(csp->action) && can_filter_request_body(csp);
    2161             : 
    2162        6316 :    if (filter_client_body)
    2163             :    {
    2164         833 :       if (read_http_request_body(csp))
    2165             :       {
    2166          23 :          return 1;
    2167             :       }
    2168         810 :       to_send_len = csp->expected_client_content_length;
    2169         810 :       to_send = execute_client_body_filters(csp, &to_send_len);
    2170         810 :       if (to_send == NULL)
    2171             :       {
    2172             :          /* just flush client_iob */
    2173         590 :          filter_client_body = FALSE;
    2174             :       }
    2175         439 :       else if (to_send_len != csp->expected_client_content_length &&
    2176         219 :          update_client_headers(csp, to_send_len))
    2177             :       {
    2178           1 :          log_error(LOG_LEVEL_HEADER, "Error updating client headers");
    2179           1 :          return 1;
    2180             :       }
    2181         809 :       csp->expected_client_content_length = 0;
    2182             :    }
    2183             : 
    2184        6292 :    hdr = list_to_text(csp->headers);
    2185        6292 :    if (hdr == NULL)
    2186             :    {
    2187             :       /* FIXME Should handle error properly */
    2188           0 :       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
    2189             :    }
    2190        6292 :    list_remove_all(csp->headers);
    2191             : 
    2192             :    /*
    2193             :     * Write the client's (modified) header to the server
    2194             :     * (along with anything else that may be in the buffer)
    2195             :     */
    2196        6292 :    write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
    2197        6292 :    freez(hdr);
    2198             : 
    2199        6292 :    if (write_failure)
    2200             :    {
    2201           0 :       log_error(LOG_LEVEL_CONNECT, "Failed sending request headers to: %s: %E",
    2202             :          csp->http->hostport);
    2203           0 :       return 1;
    2204             :    }
    2205             : 
    2206        6292 :    if (filter_client_body)
    2207             :    {
    2208         219 :       write_failure = 0 != write_socket(csp->server_connection.sfd, to_send, to_send_len);
    2209         219 :       freez(to_send);
    2210         219 :       if (write_failure)
    2211             :       {
    2212           0 :          log_error(LOG_LEVEL_CONNECT, "Failed sending filtered request body to: %s: %E",
    2213             :             csp->http->hostport);
    2214           0 :          return 1;
    2215             :       }
    2216             :    }
    2217             : 
    2218        6292 :    if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
    2219        6090 :       && (flush_iob(csp->server_connection.sfd, csp->client_iob, 0) < 0))
    2220             :    {
    2221           0 :       log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
    2222             :          csp->http->hostport);
    2223           0 :       return 1;
    2224             :    }
    2225        6292 :    return 0;
    2226             : }
    2227             : 
    2228             : 
    2229             : #ifdef FEATURE_HTTPS_INSPECTION
    2230             : /*********************************************************************
    2231             :  *
    2232             :  * Function    : read_https_request_body
    2233             :  *
    2234             :  * Description : Reads remaining request body from the client.
    2235             :  *
    2236             :  * Parameters  :
    2237             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2238             :  *
    2239             :  * Returns     :  0 on success, anything else is an error.
    2240             :  *
    2241             :  *********************************************************************/
    2242          64 : static int read_https_request_body(struct client_state *csp)
    2243             : {
    2244          64 :    size_t to_read = csp->expected_client_content_length;
    2245             :    int len;
    2246             : 
    2247          64 :    assert(to_read != 0);
    2248             : 
    2249             :    /* check if all data has been already read */
    2250          64 :    if (to_read <= (csp->client_iob->eod - csp->client_iob->cur))
    2251             :    {
    2252          42 :       return 0;
    2253             :    }
    2254             : 
    2255         438 :    for (to_read -= (size_t)(csp->client_iob->eod - csp->client_iob->cur);
    2256         429 :         to_read > 0 && (is_ssl_pending(&(csp->ssl_client_attr)) ||
    2257           0 :           data_is_available(csp->cfd, csp->config->socket_timeout));
    2258         416 :         to_read -= (unsigned)len)
    2259             :    {
    2260             :       unsigned char buf[BUFFER_SIZE];
    2261         429 :       size_t max_bytes_to_read = to_read < sizeof(buf) ? to_read : sizeof(buf);
    2262             : 
    2263         429 :       log_error(LOG_LEVEL_CONNECT,
    2264             :          "Waiting for up to %d bytes of request body from the client.",
    2265             :          max_bytes_to_read);
    2266         429 :       len = read_socket(csp->cfd, (char *)buf,
    2267             : //      len = ssl_recv_data(&(csp->ssl_client_attr), buf,
    2268             :          (unsigned)max_bytes_to_read);
    2269         429 :       if (len <= 0)
    2270             :       {
    2271          13 :          log_error(LOG_LEVEL_CONNECT, "Failed receiving request body from %s", csp->ip_addr_str);
    2272          13 :          return 1;
    2273             :       }
    2274         416 :       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, (char *)buf, len))
    2275             :       {
    2276           0 :          return 1;
    2277             :       }
    2278         416 :       assert(to_read >= len);
    2279             :    }
    2280             : 
    2281           9 :    if (to_read != 0)
    2282             :    {
    2283           0 :       log_error(LOG_LEVEL_CONNECT, "Not enough request body has been read: expected %d more bytes", to_read);
    2284           0 :       return 1;
    2285             :    }
    2286             : 
    2287           9 :    log_error(LOG_LEVEL_CONNECT, "The last %d bytes of the request body have been read",
    2288             :       csp->expected_client_content_length);
    2289           9 :    return 0;
    2290             : }
    2291             : 
    2292             : 
    2293             : /*********************************************************************
    2294             :  *
    2295             :  * Function    : receive_and_send_encrypted_post_data
    2296             :  *
    2297             :  * Description : Reads remaining request body from the client and sends
    2298             :  *               it to the server.
    2299             :  *
    2300             :  * Parameters  :
    2301             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2302             :  *
    2303             :  * Returns     :  0 on success, anything else is an error.
    2304             :  *
    2305             :  *********************************************************************/
    2306          26 : static int receive_and_send_encrypted_post_data(struct client_state *csp)
    2307             : {
    2308          26 :    int content_length_known = csp->expected_client_content_length != 0;
    2309             : 
    2310         597 :    while (is_ssl_pending(&(csp->ssl_client_attr))
    2311           0 :       || (content_length_known && csp->expected_client_content_length != 0))
    2312             :    {
    2313             :       unsigned char buf[BUFFER_SIZE];
    2314             :       int len;
    2315         597 :       int max_bytes_to_read = sizeof(buf);
    2316             : 
    2317         597 :       if (content_length_known && csp->expected_client_content_length < sizeof(buf))
    2318             :       {
    2319           1 :          max_bytes_to_read = (int)csp->expected_client_content_length;
    2320             :       }
    2321         597 :       log_error(LOG_LEVEL_CONNECT,
    2322             :          "Waiting for up to %d bytes of request body from the client.",
    2323             :          max_bytes_to_read);
    2324         597 :         len = read_socket(csp->cfd, (char *)buf,
    2325             : //      len = ssl_recv_data(&(csp->ssl_client_attr), buf,
    2326             :          (unsigned)max_bytes_to_read);
    2327         597 :       if (len == -1)
    2328             :       {
    2329           0 :          return 1;
    2330             :       }
    2331         597 :       if (len == 0)
    2332             :       {
    2333             :          /* XXX: Does this actually happen? */
    2334          26 :          break;
    2335             :       }
    2336         572 :       log_error(LOG_LEVEL_CONNECT, "Forwarding %d bytes of encrypted request body",
    2337             :          len);
    2338         572 :       len = ssl_send_data(&(csp->ssl_server_attr), buf, (size_t)len);
    2339         572 :       if (len == -1)
    2340             :       {
    2341           0 :          return 1;
    2342             :       }
    2343         572 :       if (csp->expected_client_content_length != 0)
    2344             :       {
    2345         312 :          if (csp->expected_client_content_length >= len)
    2346             :          {
    2347         312 :             csp->expected_client_content_length -= (unsigned)len;
    2348             :          }
    2349         312 :          if (csp->expected_client_content_length == 0)
    2350             :          {
    2351           1 :             log_error(LOG_LEVEL_CONNECT, "Forwarded the last %d bytes", len);
    2352           1 :             break;
    2353             :          }
    2354             :       }
    2355             :    }
    2356             : 
    2357          26 :    log_error(LOG_LEVEL_CONNECT, "Done forwarding encrypted request body");
    2358             : 
    2359          26 :    return 0;
    2360             : 
    2361             : }
    2362             : 
    2363             : 
    2364             : /*********************************************************************
    2365             :  *
    2366             :  * Function    : send_https_request
    2367             :  *
    2368             :  * Description : Sends the HTTP headers from the client request
    2369             :  *               and all the body data that has already been received.
    2370             :  *
    2371             :  * Parameters  :
    2372             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2373             :  *
    2374             :  * Returns     :  0 on success, anything else is an error.
    2375             :  *
    2376             :  *********************************************************************/
    2377         199 : static int send_https_request(struct client_state *csp)
    2378             : {
    2379             :    char *hdr;
    2380             :    int ret;
    2381         199 :    long flushed = 0;
    2382             :    const char *to_send;
    2383             :    size_t to_send_len;
    2384         489 :    int filter_client_body = csp->expected_client_content_length != 0 &&
    2385         290 :       client_body_filters_enabled(csp->action) && can_filter_request_body(csp);
    2386             : 
    2387         199 :    if (filter_client_body)
    2388             :    {
    2389          64 :       if (read_https_request_body(csp))
    2390             :       {
    2391          13 :          return 1;
    2392             :       }
    2393          51 :       to_send_len = csp->expected_client_content_length;
    2394          51 :       to_send = execute_client_body_filters(csp, &to_send_len);
    2395          51 :       if (to_send == NULL)
    2396             :       {
    2397             :          /* just flush client_iob */
    2398          23 :          filter_client_body = FALSE;
    2399             :       }
    2400          55 :       else if (to_send_len != csp->expected_client_content_length &&
    2401          27 :          update_client_headers(csp, to_send_len))
    2402             :       {
    2403           5 :          log_error(LOG_LEVEL_HEADER, "Error updating client headers");
    2404           5 :          return 1;
    2405             :       }
    2406          46 :       csp->expected_client_content_length = 0;
    2407             :    }
    2408             : 
    2409         181 :    hdr = list_to_text(csp->https_headers);
    2410         181 :    if (hdr == NULL)
    2411             :    {
    2412             :       /* FIXME Should handle error properly */
    2413           0 :       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
    2414             :    }
    2415         181 :    list_remove_all(csp->https_headers);
    2416             : 
    2417             :    /*
    2418             :     * Write the client's (modified) header to the server
    2419             :     * (along with anything else that may be in the buffer)
    2420             :     */
    2421         181 :    ret = ssl_send_data(&(csp->ssl_server_attr),
    2422             :       (const unsigned char *)hdr, strlen(hdr));
    2423         181 :    freez(hdr);
    2424             : 
    2425         181 :    if (ret < 0)
    2426             :    {
    2427           0 :       log_error(LOG_LEVEL_CONNECT,
    2428             :          "Failed sending encrypted request headers to: %s: %E",
    2429             :          csp->http->hostport);
    2430           0 :       mark_server_socket_tainted(csp);
    2431           0 :       return 1;
    2432             :    }
    2433             : 
    2434         181 :    if (filter_client_body)
    2435             :    {
    2436          23 :       ret = ssl_send_data(&(csp->ssl_server_attr), (const unsigned char *)to_send, to_send_len);
    2437          23 :       freez(to_send);
    2438          23 :       if (ret < 0)
    2439             :       {
    2440           0 :          log_error(LOG_LEVEL_CONNECT, "Failed sending filtered request body to: %s",
    2441             :             csp->http->hostport);
    2442           0 :          return 1;
    2443             :       }
    2444             :    }
    2445             : 
    2446         181 :    if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
    2447         180 :       && ((flushed = ssl_flush_socket(&(csp->ssl_server_attr),
    2448         180 :             csp->client_iob)) < 0))
    2449             :    {
    2450           0 :       log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
    2451             :          csp->http->hostport);
    2452           0 :       return 1;
    2453             :    }
    2454         181 :    if (flushed != 0 || csp->expected_client_content_length != 0)
    2455             :    {
    2456          67 :       if (csp->expected_client_content_length != 0)
    2457             :       {
    2458          27 :          if (csp->expected_client_content_length < flushed)
    2459             :          {
    2460           1 :             log_error(LOG_LEVEL_ERROR,
    2461             :                "Flushed %ld bytes of request body while only expecting %llu",
    2462             :                flushed, csp->expected_client_content_length);
    2463           1 :             csp->expected_client_content_length = 0;
    2464             :          }
    2465             :          else
    2466             :          {
    2467          26 :             log_error(LOG_LEVEL_CONNECT,
    2468             :                "Flushed %ld bytes of request body while expecting %llu",
    2469             :                flushed, csp->expected_client_content_length);
    2470          26 :             csp->expected_client_content_length -= (unsigned)flushed;
    2471          26 :             if (receive_and_send_encrypted_post_data(csp))
    2472             :             {
    2473           0 :                return 1;
    2474             :             }
    2475             :          }
    2476             :       }
    2477             :       else
    2478             :       {
    2479          40 :          log_error(LOG_LEVEL_CONNECT,
    2480             :             "Flushed %ld bytes of request body", flushed);
    2481             :       }
    2482             :    }
    2483             : 
    2484         181 :    log_error(LOG_LEVEL_CONNECT, "Encrypted request sent");
    2485             : 
    2486         181 :    return 0;
    2487             : 
    2488             : }
    2489             : 
    2490             : 
    2491             : /*********************************************************************
    2492             :  *
    2493             :  * Function    :  receive_encrypted_request
    2494             :  *
    2495             :  * Description :  Receives an encrypted request.
    2496             :  *
    2497             :  * Parameters  :
    2498             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2499             :  *
    2500             :  * Returns     :  JB_ERR_OK on success,
    2501             :  *                JB_ERR_PARSE or JB_ERR_MEMORY otherwise
    2502             :  *
    2503             :  *********************************************************************/
    2504        3789 : static jb_err receive_encrypted_request(struct client_state *csp)
    2505             : {
    2506             :    char buf[BUFFER_SIZE];
    2507             :    int len;
    2508             :    char *p;
    2509             : 
    2510             :    do
    2511             :    {
    2512        3789 :       log_error(LOG_LEVEL_HEADER, "Reading encrypted headers");
    2513        3789 :       if (!is_ssl_pending(&(csp->ssl_client_attr)) &&
    2514           0 :           !data_is_available(csp->cfd, csp->config->socket_timeout))
    2515             :       {
    2516           0 :          log_error(LOG_LEVEL_CONNECT,
    2517             :             "Socket %d timed out while waiting for client headers", csp->cfd);
    2518           0 :          return JB_ERR_PARSE;
    2519             :       }
    2520             : //      len = ssl_recv_data(&(csp->ssl_client_attr),
    2521        3789 :         len = read_socket(csp->cfd,
    2522             :          buf, sizeof(buf));
    2523        3789 :       if (len == 0)
    2524             :       {
    2525          75 :          log_error(LOG_LEVEL_CONNECT,
    2526             :             "Socket %d closed while waiting for client headers", csp->cfd);
    2527          75 :          return JB_ERR_PARSE;
    2528             :       }
    2529        3714 :       if (len == -1)
    2530             :       {
    2531           0 :          return JB_ERR_PARSE;
    2532             :       }
    2533        3714 :       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
    2534             :       {
    2535           0 :          return JB_ERR_MEMORY;
    2536             :       }
    2537        3714 :       p = strstr(csp->client_iob->cur, "\r\n\r\n");
    2538        3714 :    } while (p == NULL);
    2539             : 
    2540        2177 :    log_error(LOG_LEVEL_HEADER, "Encrypted headers received completely");
    2541             : 
    2542        2177 :    return JB_ERR_OK;
    2543             : }
    2544             : 
    2545             : 
    2546             : /*********************************************************************
    2547             :  *
    2548             :  * Function    :  change_encrypted_request_destination
    2549             :  *
    2550             :  * Description :  Parse a (rewritten) request line from an encrypted
    2551             :  *                request and regenerate the http request data.
    2552             :  *
    2553             :  * Parameters  :
    2554             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2555             :  *
    2556             :  * Returns     :  Forwards the parse_http_request() return code.
    2557             :  *                Terminates in case of memory problems.
    2558             :  *
    2559             :  *********************************************************************/
    2560          51 : static jb_err change_encrypted_request_destination(struct client_state *csp)
    2561             : {
    2562             :    jb_err err;
    2563          51 :    char *original_host = csp->http->host;
    2564          51 :    int original_port = csp->http->port;
    2565             : 
    2566          51 :    log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s",
    2567          51 :       csp->https_headers->first->str);
    2568          51 :    csp->http->host = NULL;
    2569          51 :    free_http_request(csp->http);
    2570          51 :    err = parse_http_request(csp->https_headers->first->str, csp->http);
    2571          51 :    if (JB_ERR_OK != err)
    2572             :    {
    2573           0 :       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
    2574             :          jb_err_to_string(err));
    2575           0 :       freez(original_host);
    2576           0 :       return err;
    2577             :    }
    2578             : 
    2579          51 :    if (csp->http->host == NULL)
    2580             :    {
    2581             :       char port_string[10];
    2582             :       /*
    2583             :        * The rewritten request line did not specify a host
    2584             :        * which means we can use the original host specified
    2585             :        * by the client.
    2586             :        */
    2587          43 :       csp->http->host = original_host;
    2588          43 :       csp->http->port = original_port;
    2589          43 :       log_error(LOG_LEVEL_REDIRECTS, "Keeping the original host: %s",
    2590             :          csp->http->host);
    2591             :       /*
    2592             :        * If the rewritten request line didn't contain a host
    2593             :        * it also didn't contain a port so we can reuse the host
    2594             :        * port.
    2595             :        */
    2596          43 :       freez(csp->http->hostport);
    2597          43 :       csp->http->hostport = strdup_or_die(csp->http->host);
    2598          43 :       snprintf(port_string, sizeof(port_string), ":%d", original_port);
    2599          43 :       err = string_append(&csp->http->hostport, port_string);
    2600          43 :       if (err != JB_ERR_OK)
    2601             :       {
    2602           0 :          log_error(LOG_LEVEL_ERROR, "Failed to rebuild hostport: %s.",
    2603             :             jb_err_to_string(err));
    2604           0 :          return err;
    2605             :       }
    2606             : 
    2607             :       /*
    2608             :        * While the request line didn't mention it,
    2609             :        * we're https-inspecting and want to speak TLS
    2610             :        * with the server.
    2611             :        */
    2612          43 :       csp->http->server_ssl = 1;
    2613          43 :       csp->http->ssl = 1;
    2614             :    }
    2615             :    else
    2616             :    {
    2617             :       /* The rewrite filter added a host so we can ditch the original */
    2618           8 :       freez(original_host);
    2619           8 :       csp->http->server_ssl = csp->http->ssl;
    2620             :    }
    2621             : 
    2622          51 :    csp->http->client_ssl = 1;
    2623             : 
    2624          51 :    freez(csp->https_headers->first->str);
    2625          51 :    build_request_line(csp, NULL, &csp->https_headers->first->str);
    2626             : 
    2627          51 :    if (!server_use_ssl(csp))
    2628             :    {
    2629           8 :       log_error(LOG_LEVEL_REDIRECTS,
    2630             :          "Rewritten request line results in downgrade to http");
    2631             :       /*
    2632             :        * Replace the unencryptd headers received with the
    2633             :        * CONNECT request with the ones we received securely.
    2634             :        */
    2635           8 :       destroy_list(csp->headers);
    2636           8 :       csp->headers->first = csp->https_headers->first;
    2637           8 :       csp->headers->last  = csp->https_headers->last;
    2638           8 :       csp->https_headers->first = NULL;
    2639           8 :       csp->https_headers->last = NULL;
    2640             :    }
    2641             : 
    2642          51 :    return JB_ERR_OK;
    2643             : 
    2644             : }
    2645             : 
    2646             : 
    2647             : /*********************************************************************
    2648             :  *
    2649             :  * Function    :  process_encrypted_request
    2650             :  *
    2651             :  * Description :  Receives and parses an encrypted request.
    2652             :  *
    2653             :  * Parameters  :
    2654             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2655             :  *
    2656             :  * Returns     :  JB_ERR_OK on success,
    2657             :  *                JB_ERR_PARSE or JB_ERR_MEMORY otherwise
    2658             :  *
    2659             :  *********************************************************************/
    2660        2252 : static jb_err process_encrypted_request(struct client_state *csp)
    2661             : {
    2662             :    char *p;
    2663             :    char *request_line;
    2664             :    jb_err err;
    2665             :    /* Temporary copy of the client's headers before they get enlisted in csp->https_headers */
    2666             :    struct list header_list;
    2667        2252 :    struct list *headers = &header_list;
    2668             : 
    2669        2252 :    assert(csp->ssl_with_client_is_opened);
    2670             : 
    2671             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    2672        2252 :    if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
    2673             :    {
    2674        2252 :       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    2675             :    }
    2676             : #endif
    2677        2252 :    err = receive_encrypted_request(csp);
    2678        2252 :    if (err != JB_ERR_OK)
    2679             :    {
    2680          75 :       if (csp->client_iob->cur == NULL ||
    2681          72 :           csp->client_iob->cur == csp->client_iob->eod)
    2682             :       {
    2683             :          /*
    2684             :           * We did not receive any data, most likely because the
    2685             :           * client is done. Don't log this as a parse failure.
    2686             :           */
    2687           5 :          return JB_ERR_PARSE;
    2688             :       }
    2689             :       /* XXX: Also used for JB_ERR_MEMORY */
    2690          70 :       log_error(LOG_LEVEL_ERROR, "Failed to receive encrypted request: %s",
    2691             :          jb_err_to_string(err));
    2692          70 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2693             :          (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
    2694          70 :       return err;
    2695             :    }
    2696             : 
    2697             :    /* We don't need get_request_line() because the whole HTTP head is buffered. */
    2698        2177 :    request_line = get_header(csp->client_iob);
    2699        2177 :    if (request_line == NULL)
    2700             :    {
    2701           4 :       log_error(LOG_LEVEL_ERROR, "Failed to get the encrypted request line");
    2702           4 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2703             :          (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
    2704           4 :       return JB_ERR_PARSE;
    2705             :    }
    2706        2173 :    assert(*request_line != '\0');
    2707             : 
    2708        2173 :    if (client_protocol_is_unsupported(csp, request_line))
    2709             :    {
    2710             :       /*
    2711             :        * If the protocol is unsupported we're done here.
    2712             :        * client_protocol_is_unsupported() took care of sending
    2713             :        * the error response and logging the error message.
    2714             :        */
    2715           1 :       return JB_ERR_PARSE;
    2716             :    }
    2717             : 
    2718             : #ifdef FEATURE_FORCE_LOAD
    2719        2172 :    if (force_required(csp, request_line))
    2720             :    {
    2721          10 :       csp->flags |= CSP_FLAG_FORCED;
    2722             :    }
    2723             : #endif /* def FEATURE_FORCE_LOAD */
    2724             : 
    2725        2172 :    free_http_request(csp->http);
    2726             : 
    2727        2172 :    err = parse_http_request(request_line, csp->http);
    2728             :    /* XXX: Restore ssl setting. This is ugly */
    2729        2172 :    csp->http->client_ssl = 1;
    2730        2172 :    csp->http->server_ssl = 1;
    2731             : 
    2732        2172 :    freez(request_line);
    2733        2172 :    if (JB_ERR_OK != err)
    2734             :    {
    2735          36 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2736             :          (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
    2737             :       /* XXX: Use correct size */
    2738          36 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
    2739          36 :       log_error(LOG_LEVEL_ERROR,
    2740             :          "Couldn't parse request line received from %s: %s",
    2741             :          csp->ip_addr_str, jb_err_to_string(err));
    2742             : 
    2743          36 :       free_http_request(csp->http);
    2744          36 :       return JB_ERR_PARSE;
    2745             :    }
    2746             : 
    2747             :    /* Parse the rest of the client's headers. */
    2748        2136 :    init_list(headers);
    2749             :    for (;;)
    2750             :    {
    2751       26163 :       p = get_header(csp->client_iob);
    2752             : 
    2753       26163 :       if (p == NULL)
    2754             :       {
    2755             :          /* There are no additional headers to read. */
    2756        2136 :          break;
    2757             :       }
    2758       24027 :       enlist(headers, p);
    2759       24027 :       freez(p);
    2760             :    }
    2761             : 
    2762        2136 :    if (JB_ERR_OK != get_destination_from_https_headers(headers, csp->http))
    2763             :    {
    2764             :       /*
    2765             :        * Our attempts to get the request destination
    2766             :        * elsewhere failed.
    2767             :        */
    2768           7 :       log_error(LOG_LEVEL_ERROR,
    2769             :          "Failed to get the encrypted request destination");
    2770           7 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2771             :          (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
    2772           7 :       return JB_ERR_PARSE;
    2773             :    }
    2774             : 
    2775             :    /* Split the domain we just got for pattern matching */
    2776        2129 :    init_domain_components(csp->http);
    2777             : 
    2778             : #ifdef FEATURE_CLIENT_TAGS
    2779             :    /* XXX: If the headers were enlisted sooner, passing csp would do. */
    2780        2129 :    if (csp->client_address == NULL)
    2781             :    {
    2782        1833 :       set_client_address(csp, headers);
    2783        1833 :       get_tag_list_for_client(csp->client_tags, csp->client_address);
    2784             :    }
    2785             : #endif
    2786             : 
    2787             : #ifdef FEATURE_TOGGLE
    2788        2129 :    if ((csp->flags & CSP_FLAG_TOGGLED_ON) != 0)
    2789             : #endif
    2790             :    {
    2791             :       /*
    2792             :        * Determine the actions for this request after
    2793             :        * clearing the ones from the previous one.
    2794             :        */
    2795        2042 :       free_current_action(csp->action);
    2796        2042 :       get_url_actions(csp, csp->http);
    2797             :    }
    2798             : 
    2799        2129 :    enlist(csp->https_headers, csp->http->cmd);
    2800             : 
    2801             :    /* Append the previously read headers */
    2802        2129 :    err = list_append_list_unique(csp->https_headers, headers);
    2803        2129 :    destroy_list(headers);
    2804        2129 :    if (JB_ERR_OK != err)
    2805             :    {
    2806             :       /* XXX: Send error message */
    2807           0 :       return err;
    2808             :    }
    2809             : 
    2810             :    /* XXX: Work around crash */
    2811        2129 :    csp->error_message = NULL;
    2812             : 
    2813             :    /* XXX: Why do this here? */
    2814        2129 :    csp->http->ssl = 1;
    2815             : 
    2816        2129 :    err = sed_https(csp);
    2817        2129 :    if (JB_ERR_OK != err)
    2818             :    {
    2819           1 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2820             :          (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
    2821           1 :       log_error(LOG_LEVEL_ERROR, "Failed to parse client request from %s.",
    2822             :          csp->ip_addr_str);
    2823           1 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
    2824             :          csp->ip_addr_str, csp->http->cmd);
    2825           1 :       return JB_ERR_PARSE;
    2826             :    }
    2827             : 
    2828        2128 :    if ((NULL == csp->https_headers->first->str)
    2829        2178 :       || (strcmp(csp->http->cmd, csp->https_headers->first->str) &&
    2830          51 :          (JB_ERR_OK != change_encrypted_request_destination(csp))))
    2831             :    {
    2832           1 :       ssl_send_data_delayed(&(csp->ssl_client_attr),
    2833             :          (const unsigned char *)MESSED_UP_REQUEST_RESPONSE,
    2834             :          strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp));
    2835           1 :       log_error(LOG_LEVEL_ERROR,
    2836             :          "Invalid request line after applying header filters.");
    2837             :       /* XXX: Use correct size */
    2838           1 :       log_error(LOG_LEVEL_CLF,
    2839             :          "%s - - [%T] \"Invalid request generated\" 400 0", csp->ip_addr_str);
    2840             : 
    2841           1 :       return JB_ERR_PARSE;
    2842             :    }
    2843             : 
    2844        2127 :    log_error(LOG_LEVEL_HEADER, "Encrypted request processed");
    2845        2127 :    log_applied_actions(csp->action);
    2846        2127 :    log_error(LOG_LEVEL_REQUEST, "https://%s%s", csp->http->hostport,
    2847             :       csp->http->path);
    2848             : 
    2849        2127 :    return err;
    2850             : 
    2851             : }
    2852             : 
    2853             : /*********************************************************************
    2854             :  *
    2855             :  * Function    :  cgi_page_requested
    2856             :  *
    2857             :  * Description :  Checks if a request is for an internal CGI page.
    2858             :  *
    2859             :  * Parameters  :
    2860             :  *          1  :  host = The host requested by the client.
    2861             :  *
    2862             :  * Returns     :  1 if a CGI page has been requested, 0 otherwise
    2863             :  *
    2864             :  *********************************************************************/
    2865          41 : static int cgi_page_requested(const char *host)
    2866             : {
    2867          41 :    if ((0 == strcmpic(host, CGI_SITE_1_HOST))
    2868          24 :     || (0 == strcmpic(host, CGI_SITE_1_HOST "."))
    2869          23 :     || (0 == strcmpic(host, CGI_SITE_2_HOST))
    2870          21 :     || (0 == strcmpic(host, CGI_SITE_2_HOST ".")))
    2871             :    {
    2872          20 :       return 1;
    2873             :    }
    2874             : 
    2875          21 :    return 0;
    2876             : 
    2877             : }
    2878             : 
    2879             : 
    2880             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    2881             : /*********************************************************************
    2882             :  *
    2883             :  * Function    :  continue_https_chat
    2884             :  *
    2885             :  * Description :  Behaves similar to chat() but only deals with
    2886             :  *                https-inspected requests that arrive on an already
    2887             :  *                established connection. The first request is always
    2888             :  *                served by chat() which is a lot more complex as it
    2889             :  *                has to deal with forwarding settings and connection
    2890             :  *                failures etc.
    2891             :  *
    2892             :  *                If a connection to the server has already been
    2893             :  *                opened it is reused unless the request is blocked
    2894             :  *                or the forwarder changed.
    2895             :  *
    2896             :  *                If a connection to the server has not yet been
    2897             :  *                opened (because the previous request was crunched),
    2898             :  *                or the forwarder changed, the connection is dropped
    2899             :  *                so that the client retries on a fresh one.
    2900             :  *
    2901             :  * Parameters  :
    2902             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2903             :  *
    2904             :  * Returns     :  Nothing.
    2905             :  *
    2906             :  *********************************************************************/
    2907        1918 : static void continue_https_chat(struct client_state *csp)
    2908             : {
    2909             :    const struct forward_spec *fwd;
    2910             : 
    2911        1918 :    if (JB_ERR_OK != process_encrypted_request(csp))
    2912             :    {
    2913          85 :       csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    2914          85 :       return;
    2915             :    }
    2916             : 
    2917        1833 :    csp->requests_received_total++;
    2918             : 
    2919             :    /*
    2920             :     * We have an encrypted request. Check if one of the crunchers wants it.
    2921             :     */
    2922        1833 :    if (crunch_response_triggered(csp, crunchers_all))
    2923             :    {
    2924             :       /*
    2925             :        * Yes. The client got the crunch response and we're done here.
    2926             :        */
    2927        1746 :       return;
    2928             :    }
    2929          87 :    if (csp->ssl_with_server_is_opened == 0)
    2930             :    {
    2931          46 :       log_error(LOG_LEVEL_CONNECT,
    2932             :          "Dropping the client connection on socket %d. "
    2933             :          "The server connection has not been established yet.",
    2934             :          csp->cfd);
    2935          46 :       csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    2936          46 :       return;
    2937             :    }
    2938          41 :    assert(csp->server_connection.sfd != JB_INVALID_SOCKET);
    2939             : 
    2940          41 :    fwd = forward_url(csp, csp->http);
    2941          41 :    if (!connection_destination_matches(&csp->server_connection, csp->http, fwd))
    2942             :    {
    2943           1 :       log_error(LOG_LEVEL_CONNECT,
    2944             :          "Dropping the client connection on socket %d with "
    2945             :          "server socket %d connected to %s. The forwarder has changed.",
    2946             :          csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
    2947           1 :       csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    2948           1 :       return;
    2949             :    }
    2950             : 
    2951          40 :    log_error(LOG_LEVEL_CONNECT,
    2952             :       "Reusing server socket %d connected to %s. Requests already sent: %u.",
    2953             :       csp->server_connection.sfd, csp->server_connection.host,
    2954             :       csp->server_connection.requests_sent_total);
    2955             : 
    2956          40 :    if (send_https_request(csp))
    2957             :    {
    2958             :       /*
    2959             :        * Most likely the server connection timed out. We can't easily
    2960             :        * create a new one so simply drop the client connection without a
    2961             :        * error response to let the client retry.
    2962             :        */
    2963           1 :       log_error(LOG_LEVEL_CONNECT,
    2964             :          "Dropping client connection on socket %d. "
    2965             :          "Forwarding the encrypted client request failed.",
    2966             :          csp->cfd);
    2967           1 :       return;
    2968             :    }
    2969          39 :    csp->server_connection.requests_sent_total++;
    2970          39 :    handle_established_connection(csp);
    2971          39 :    freez(csp->receive_buffer);
    2972             : }
    2973             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    2974             : #endif
    2975             : 
    2976             : 
    2977             : /*********************************************************************
    2978             :  *
    2979             :  * Function    :  handle_established_connection
    2980             :  *
    2981             :  * Description :  Shuffle data between client and server once the
    2982             :  *                connection has been established.
    2983             :  *
    2984             :  * Parameters  :
    2985             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    2986             :  *
    2987             :  * Returns     :  Nothing.
    2988             :  *
    2989             :  *********************************************************************/
    2990        6494 : static void handle_established_connection(struct client_state *csp)
    2991             : {
    2992             :    char *hdr;
    2993             :    char *p;
    2994             :    int n;
    2995             : #ifdef HAVE_POLL
    2996             :    struct pollfd poll_fds[2];
    2997             : #else
    2998             :    fd_set rfds;
    2999             :    jb_socket maxfd;
    3000             :    struct timeval timeout;
    3001             : #endif
    3002             :    int server_body;
    3003        6494 :    int ms_iis5_hack = 0;
    3004        6494 :    unsigned long long byte_count = 0;
    3005             :    struct http_request *http;
    3006        6494 :    long len = 0; /* for buffer sizes (and negative error codes) */
    3007        6494 :    int buffer_and_filter_content = 0;
    3008             :    unsigned int write_delay;
    3009             : #ifdef FEATURE_HTTPS_INSPECTION
    3010        6494 :    int ret = 0;
    3011        6494 :    int use_ssl_tunnel = 0;
    3012        6494 :    csp->dont_verify_certificate = 0;
    3013        6494 :    if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION))
    3014             :    {
    3015             :       /* Pass encrypted content without filtering. */
    3016          35 :       use_ssl_tunnel = 1;
    3017             :    }
    3018             : #endif
    3019             : 
    3020             :    /* Skeleton for HTTP response, if we should intercept the request */
    3021             :    struct http_response *rsp;
    3022             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3023             :    int watch_client_socket;
    3024             : #endif
    3025             : 
    3026        6494 :    csp->receive_buffer_size = csp->config->receive_buffer_size;
    3027        6494 :    csp->receive_buffer = zalloc(csp->receive_buffer_size + 1);
    3028        6494 :    if (csp->receive_buffer == NULL)
    3029             :    {
    3030           0 :       log_error(LOG_LEVEL_ERROR,
    3031             :          "Out of memory. Failed to allocate the receive buffer.");
    3032           0 :       rsp = cgi_error_memory();
    3033           0 :       send_crunch_response(csp, rsp);
    3034         465 :       return;
    3035             :    }
    3036             : 
    3037        6494 :    http = csp->http;
    3038             : 
    3039             : #ifndef HAVE_POLL
    3040             :    maxfd = (csp->cfd > csp->server_connection.sfd) ?
    3041             :       csp->cfd : csp->server_connection.sfd;
    3042             : #endif
    3043             : 
    3044             :    /* pass data between the client and server
    3045             :     * until one or the other shuts down the connection.
    3046             :     */
    3047             : 
    3048        6494 :    server_body = 0;
    3049             : 
    3050             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3051        6494 :    watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING);
    3052             : #endif
    3053        6494 :    write_delay = get_write_delay(csp);
    3054             : 
    3055             :    for (;;)
    3056             :    {
    3057             : #ifndef HAVE_POLL
    3058             :       FD_ZERO(&rfds);
    3059             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3060             :       if (!watch_client_socket)
    3061             :       {
    3062             :          maxfd = csp->server_connection.sfd;
    3063             :       }
    3064             :       else
    3065             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    3066             :       {
    3067             :          FD_SET(csp->cfd, &rfds);
    3068             :       }
    3069             : 
    3070             :       FD_SET(csp->server_connection.sfd, &rfds);
    3071             : #endif /* ndef HAVE_POLL */
    3072             : 
    3073             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3074       27710 :       if ((csp->flags & CSP_FLAG_CHUNKED)
    3075        3858 :          && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
    3076        1395 :          && ((csp->iob->eod - csp->iob->cur) >= 5)
    3077         632 :          && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
    3078             :       {
    3079             :          /*
    3080             :           * XXX: This check should be obsolete now,
    3081             :           *      but let's wait a while to be sure.
    3082             :           */
    3083          10 :          log_error(LOG_LEVEL_CONNECT,
    3084             :             "Looks like we got the last chunk together with "
    3085             :             "the server headers but didn't detect it earlier. "
    3086             :             "We better stop reading.");
    3087          10 :          byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
    3088          10 :          csp->expected_content_length = byte_count;
    3089          10 :          csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
    3090             :       }
    3091       27710 :       if (server_body && server_response_is_complete(csp, byte_count))
    3092             :       {
    3093        5706 :          if (csp->expected_content_length == byte_count)
    3094             :          {
    3095        3659 :             log_error(LOG_LEVEL_CONNECT,
    3096             :                "Done reading from server. Content length: %llu as expected. "
    3097             :                "Bytes most recently read: %ld.",
    3098             :                byte_count, len);
    3099             :          }
    3100             :          else
    3101             :          {
    3102        2047 :             log_error(LOG_LEVEL_CONNECT,
    3103             :                "Done reading from server. Expected content length: %llu. "
    3104             :                "Actual content length: %llu. Bytes most recently read: %ld.",
    3105             :                csp->expected_content_length, byte_count, len);
    3106             :          }
    3107        5706 :          len = 0;
    3108             :          /*
    3109             :           * XXX: Should not jump around, handle_established_connection()
    3110             :           * is complicated enough already.
    3111             :           */
    3112        5706 :          goto reading_done;
    3113             :       }
    3114             : #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
    3115             : 
    3116             : #ifdef HAVE_POLL
    3117       22004 :       poll_fds[0].fd = csp->cfd;
    3118             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3119       22004 :       if (!watch_client_socket)
    3120             :       {
    3121             :          /*
    3122             :           * Ignore incoming data, but still watch out
    3123             :           * for disconnects etc. These flags are always
    3124             :           * implied anyway but explicitly setting them
    3125             :           * doesn't hurt.
    3126             :           */
    3127       15000 :          poll_fds[0].events = POLLERR|POLLHUP;
    3128             :       }
    3129             :       else
    3130             : #endif
    3131             :       {
    3132        7004 :          poll_fds[0].events = POLLIN;
    3133             :       }
    3134       22004 :       poll_fds[1].fd = csp->server_connection.sfd;
    3135       22004 :       poll_fds[1].events = POLLIN;
    3136       22004 :       n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
    3137             : #else
    3138             :       timeout.tv_sec = csp->config->socket_timeout;
    3139             :       timeout.tv_usec = 0;
    3140             :       n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
    3141             : #endif /* def HAVE_POLL */
    3142             : 
    3143             :       /*server or client not responding in timeout */
    3144       22004 :       if (n == 0)
    3145             :       {
    3146           0 :          log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s",
    3147           0 :             csp->config->socket_timeout, http->url);
    3148           0 :          if ((byte_count == 0) && (http->ssl == 0))
    3149             :          {
    3150           0 :             send_crunch_response(csp, error_response(csp, "connection-timeout"));
    3151             :          }
    3152           0 :          mark_server_socket_tainted(csp);
    3153             : #ifdef FEATURE_HTTPS_INSPECTION
    3154           0 :          close_client_and_server_ssl_connections(csp);
    3155             : #endif
    3156           0 :          return;
    3157             :       }
    3158       22004 :       else if (n < 0)
    3159             :       {
    3160             : #ifdef HAVE_POLL
    3161           0 :          log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
    3162             : #else
    3163             :          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
    3164             : #endif
    3165           0 :          mark_server_socket_tainted(csp);
    3166             : #ifdef FEATURE_HTTPS_INSPECTION
    3167           0 :          close_client_and_server_ssl_connections(csp);
    3168             : #endif
    3169           0 :          return;
    3170             :       }
    3171             : 
    3172             :       /*
    3173             :        * This is the body of the browser's request,
    3174             :        * just read and write it.
    3175             :        *
    3176             :        * Receives data from browser and sends it to server
    3177             :        *
    3178             :        * XXX: Make sure the client doesn't use pipelining
    3179             :        * behind Privoxy's back.
    3180             :        */
    3181             : #ifdef HAVE_POLL
    3182       22004 :       if ((poll_fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) != 0)
    3183             :       {
    3184           0 :          log_error(LOG_LEVEL_CONNECT,
    3185             :             "The client socket %d has become unusable while "
    3186             :             "the server socket %d is still open.",
    3187             :             csp->cfd, csp->server_connection.sfd);
    3188           0 :          mark_server_socket_tainted(csp);
    3189           0 :          break;
    3190             :       }
    3191             : 
    3192       22004 :       if (poll_fds[0].revents != 0)
    3193             : #else
    3194             :       if (FD_ISSET(csp->cfd, &rfds))
    3195             : #endif /* def HAVE_POLL*/
    3196             :       {
    3197        7004 :          int max_bytes_to_read = (int)csp->receive_buffer_size;
    3198             : 
    3199             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3200        7004 :          if ((csp->http->ssl) || (csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
    3201             :          {
    3202        6203 :             if (data_is_available(csp->cfd, 0))
    3203             :             {
    3204             :                /*
    3205             :                 * If the next request is already waiting, we have
    3206             :                 * to stop select()ing the client socket. Otherwise
    3207             :                 * we would always return right away and get nothing
    3208             :                 * else done.
    3209             :                 */
    3210        6128 :                watch_client_socket = 0;
    3211        6128 :                log_error(LOG_LEVEL_CONNECT,
    3212             :                   "Stop watching client socket %d. "
    3213             :                   "There's already another request waiting.",
    3214             :                   csp->cfd);
    3215        6128 :                continue;
    3216             :             }
    3217             :             /*
    3218             :              * If the client socket is set, but there's no data
    3219             :              * available on the socket, the client went fishing
    3220             :              * and continuing talking to the server makes no sense.
    3221             :              */
    3222          75 :             log_error(LOG_LEVEL_CONNECT,
    3223             :                "The client closed socket %d while "
    3224             :                "the server socket %d is still open.",
    3225             :                csp->cfd, csp->server_connection.sfd);
    3226          75 :             mark_server_socket_tainted(csp);
    3227          75 :             break;
    3228             :          }
    3229         801 :          if (csp->expected_client_content_length != 0)
    3230             :          {
    3231         260 :             if (csp->expected_client_content_length < csp->receive_buffer_size)
    3232             :             {
    3233           1 :                max_bytes_to_read = (int)csp->expected_client_content_length;
    3234             :             }
    3235         260 :             log_error(LOG_LEVEL_CONNECT,
    3236             :                "Waiting for up to %d bytes from the client.",
    3237             :                max_bytes_to_read);
    3238             :          }
    3239         801 :          assert(max_bytes_to_read <= csp->receive_buffer_size);
    3240             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    3241             : 
    3242             : #ifdef FEATURE_HTTPS_INSPECTION
    3243         801 :          if (client_use_ssl(csp))
    3244             :          {
    3245           8 :             if (csp->http->status == 101)
    3246             :             {
    3247             : //               len = ssl_recv_data(&(csp->ssl_client_attr),
    3248           0 :                  len = read_socket(csp->server_connection.sfd,
    3249             :                   csp->receive_buffer,
    3250             :                   (int)max_bytes_to_read);
    3251           0 :                if (len == -1)
    3252             :                {
    3253           0 :                   log_error(LOG_LEVEL_ERROR, "Failed to receive data "
    3254             :                      "on client socket %d for an upgraded connection",
    3255             :                      csp->cfd);
    3256           0 :                   break;
    3257             :                }
    3258           0 :                if (len == 0)
    3259             :                {
    3260           0 :                   log_error(LOG_LEVEL_CONNECT, "Done receiving data "
    3261             :                      "on client socket %d for an upgraded connection",
    3262             :                      csp->cfd);
    3263           0 :                   break;
    3264             :                }
    3265           0 :                byte_count += (unsigned long long)len;
    3266           0 :                len = ssl_send_data(&(csp->ssl_server_attr),
    3267           0 :                   (unsigned char *)csp->receive_buffer, (size_t)len);
    3268           0 :                if (len == -1)
    3269             :                {
    3270           0 :                   log_error(LOG_LEVEL_ERROR, "Failed to send data "
    3271             :                      "on server socket %d for an upgraded connection",
    3272             :                      csp->server_connection.sfd);
    3273           0 :                   break;
    3274             :                }
    3275           0 :                continue;
    3276             :             }
    3277           8 :             log_error(LOG_LEVEL_CONNECT, "Breaking with TLS/SSL.");
    3278           8 :             break;
    3279             :          }
    3280             :          else
    3281             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3282             :          {
    3283         793 :             len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read);
    3284             : 
    3285         793 :             if (len <= 0)
    3286             :             {
    3287             :                /* XXX: not sure if this is necessary. */
    3288          80 :                mark_server_socket_tainted(csp);
    3289          80 :                break; /* "game over, man" */
    3290             :             }
    3291             : 
    3292             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3293         713 :             if (csp->expected_client_content_length != 0)
    3294             :             {
    3295         249 :                assert(len <= max_bytes_to_read);
    3296         249 :                csp->expected_client_content_length -= (unsigned)len;
    3297         249 :                log_error(LOG_LEVEL_CONNECT,
    3298             :                   "Expected client content length set to %llu "
    3299             :                   "after reading %ld bytes.",
    3300             :                   csp->expected_client_content_length, len);
    3301         249 :                if (csp->expected_client_content_length == 0)
    3302             :                {
    3303           1 :                   log_error(LOG_LEVEL_CONNECT,
    3304             :                      "Done reading from the client.");
    3305           1 :                   csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
    3306             :                }
    3307             :             }
    3308             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    3309             : 
    3310         713 :             if (write_socket(csp->server_connection.sfd, csp->receive_buffer, (size_t)len))
    3311             :             {
    3312           0 :                log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
    3313           0 :                mark_server_socket_tainted(csp);
    3314           0 :                return;
    3315             :             }
    3316             :          }
    3317         713 :          continue;
    3318             :       }
    3319             : 
    3320             :       /*
    3321             :        * The server wants to talk. It could be the header or the body.
    3322             :        * If `hdr' is null, then it's the header otherwise it's the body.
    3323             :        * FIXME: Does `hdr' really mean `host'? No.
    3324             :        */
    3325             : #ifdef HAVE_POLL
    3326       15000 :       if (poll_fds[1].revents != 0)
    3327             : #else
    3328             :       if (FD_ISSET(csp->server_connection.sfd, &rfds))
    3329             : #endif /* HAVE_POLL */
    3330             :       {
    3331             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3332             :          /*
    3333             :           * If we are buffering content, we don't want to eat up to
    3334             :           * buffer-limit bytes if the client no longer cares about them.
    3335             :           * If we aren't buffering, however, a dead client socket will be
    3336             :           * noticed pretty much right away anyway, so we can reduce the
    3337             :           * overhead by skipping the check.
    3338             :           */
    3339       15000 :          if (buffer_and_filter_content && !socket_is_still_alive(csp->cfd))
    3340             :          {
    3341             : #ifdef _WIN32
    3342             :             log_error(LOG_LEVEL_CONNECT,
    3343             :                "The server still wants to talk, but the client may already have hung up on us.");
    3344             : #else
    3345         119 :             log_error(LOG_LEVEL_CONNECT,
    3346             :                "The server still wants to talk, but the client hung up on us.");
    3347         119 :             mark_server_socket_tainted(csp);
    3348             : #ifdef FEATURE_HTTPS_INSPECTION
    3349         119 :             close_client_and_server_ssl_connections(csp);
    3350             : #endif
    3351         119 :             return;
    3352             : #endif /* def _WIN32 */
    3353             :          }
    3354             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    3355             : 
    3356             : #ifdef FEATURE_HTTPS_INSPECTION
    3357             :          /*
    3358             :           * Reading data from standard or secured connection (HTTP/HTTPS)
    3359             :           */
    3360             : /*         if (server_use_ssl(csp))
    3361             :          {
    3362             :             len = ssl_recv_data(&(csp->ssl_server_attr),
    3363             :                (unsigned char *)csp->receive_buffer, csp->receive_buffer_size);
    3364             :          }
    3365             :          else
    3366             : */
    3367             : #endif
    3368             :          {
    3369       14881 :             len = read_socket(csp->server_connection.sfd, csp->receive_buffer,
    3370       14881 :                (int)csp->receive_buffer_size);
    3371             :          }
    3372             : 
    3373       14881 :          if (len < 0)
    3374             :          {
    3375           0 :             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
    3376             : 
    3377           0 :             if ((http->ssl && (csp->fwd == NULL))
    3378             : #ifdef FEATURE_HTTPS_INSPECTION
    3379           0 :                && use_ssl_tunnel
    3380             : #endif
    3381             :                 )
    3382             :             {
    3383             :                /*
    3384             :                 * Just hang up. We already confirmed the client's CONNECT
    3385             :                 * request with status code 200 and unencrypted content is
    3386             :                 * no longer welcome.
    3387             :                 */
    3388           0 :                log_error(LOG_LEVEL_ERROR,
    3389             :                   "CONNECT already confirmed. Unable to tell the client about the problem.");
    3390           0 :                return;
    3391             :             }
    3392           0 :             else if (byte_count)
    3393             :             {
    3394             :                /*
    3395             :                 * Just hang up. We already transmitted the original headers
    3396             :                 * and parts of the original content and therefore missed the
    3397             :                 * chance to send an error message (without risking data corruption).
    3398             :                 *
    3399             :                 * XXX: we could retry with a fancy range request here.
    3400             :                 */
    3401           0 :                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
    3402             :                   "Unable to tell the client about the problem.");
    3403           0 :                mark_server_socket_tainted(csp);
    3404             : #ifdef FEATURE_HTTPS_INSPECTION
    3405           0 :                close_client_and_server_ssl_connections(csp);
    3406             : #endif
    3407           0 :                return;
    3408             :             }
    3409             :             /*
    3410             :              * XXX: Consider handling the cases above the same.
    3411             :              */
    3412           0 :             mark_server_socket_tainted(csp);
    3413           0 :             len = 0;
    3414             :          }
    3415             : 
    3416             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    3417       14881 :          if (csp->flags & CSP_FLAG_CHUNKED)
    3418             :          {
    3419        1321 :             if ((len >= 5) && !memcmp(csp->receive_buffer+len-5, "0\r\n\r\n", 5))
    3420             :             {
    3421             :                /* XXX: this is a temporary hack */
    3422         669 :                log_error(LOG_LEVEL_CONNECT,
    3423             :                   "Looks like we reached the end of the last chunk. "
    3424             :                   "We better stop reading.");
    3425         669 :                csp->expected_content_length = byte_count + (unsigned long long)len;
    3426         669 :                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
    3427             :             }
    3428             :          }
    3429       20587 :          reading_done:
    3430             : #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
    3431             : 
    3432             :          /*
    3433             :           * This is guaranteed by allocating with zalloc_or_die()
    3434             :           * and never (intentionally) writing to the last byte.
    3435             :           *
    3436             :           * csp->receive_buffer_size is the size of the part of the
    3437             :           * buffer we intentionally write to, but we actually
    3438             :           * allocated csp->receive_buffer_size+1 bytes so the assertion
    3439             :           * stays within the allocated range.
    3440             :           */
    3441       20587 :          assert(csp->receive_buffer[csp->receive_buffer_size] == '\0');
    3442             : 
    3443             :          /*
    3444             :           * Add a trailing zero to let be able to use string operations.
    3445             :           * XXX: do we still need this with filter_popups gone?
    3446             :           */
    3447       20587 :          assert(len <= csp->receive_buffer_size);
    3448       20587 :          csp->receive_buffer[len] = '\0';
    3449             : 
    3450             :          /*
    3451             :           * Normally, this would indicate that we've read
    3452             :           * as much as the server has sent us and we can
    3453             :           * close the client connection.  However, Microsoft
    3454             :           * in its wisdom has released IIS/5 with a bug that
    3455             :           * prevents it from sending the trailing \r\n in
    3456             :           * a 302 redirect header (and possibly other headers).
    3457             :           * To work around this if we've haven't parsed
    3458             :           * a full header we'll append a trailing \r\n
    3459             :           * and see if this now generates a valid one.
    3460             :           *
    3461             :           * This hack shouldn't have any impacts.  If we've
    3462             :           * already transmitted the header or if this is a
    3463             :           * SSL connection, then we won't bother with this
    3464             :           * hack.  So we only work on partially received
    3465             :           * headers.  If we append a \r\n and this still
    3466             :           * doesn't generate a valid header, then we won't
    3467             :           * transmit anything to the client.
    3468             :           */
    3469       20587 :          if (len == 0)
    3470             :          {
    3471             : 
    3472        6074 :             if (server_body || (http->ssl
    3473             : #ifdef FEATURE_HTTPS_INSPECTION
    3474          54 :                   && use_ssl_tunnel
    3475             : #endif
    3476             :                ))
    3477             :             {
    3478             :                /*
    3479             :                 * If we have been buffering up the document,
    3480             :                 * now is the time to apply content modification
    3481             :                 * and send the result to the client.
    3482             :                 */
    3483        5866 :                if (buffer_and_filter_content)
    3484             :                {
    3485        4492 :                   p = execute_content_filters(csp);
    3486             :                   /*
    3487             :                    * If content filtering fails, use the original
    3488             :                    * buffer and length.
    3489             :                    * (see p != NULL ? p : csp->iob->cur below)
    3490             :                    */
    3491        4492 :                   if (NULL == p)
    3492             :                   {
    3493        4473 :                      csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur);
    3494             :                   }
    3495             : #ifdef FEATURE_COMPRESSION
    3496          19 :                   else if ((csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE)
    3497          13 :                      && (csp->content_length > LOWER_LENGTH_LIMIT_FOR_COMPRESSION))
    3498             :                   {
    3499          12 :                      char *compressed_content = compress_buffer(p,
    3500          12 :                         (size_t *)&csp->content_length, csp->config->compression_level);
    3501          12 :                      if (compressed_content != NULL)
    3502             :                      {
    3503          12 :                         freez(p);
    3504          12 :                         p = compressed_content;
    3505          12 :                         csp->flags |= CSP_FLAG_BUFFERED_CONTENT_DEFLATED;
    3506             :                      }
    3507             :                   }
    3508             : #endif
    3509             : 
    3510        4492 :                   if (JB_ERR_OK != update_server_headers(csp))
    3511             :                   {
    3512           0 :                      log_error(LOG_LEVEL_FATAL,
    3513             :                         "Failed to update server headers. after filtering.");
    3514             :                   }
    3515             : 
    3516        4492 :                   hdr = list_to_text(csp->headers);
    3517        4492 :                   if (hdr == NULL)
    3518             :                   {
    3519             :                      /* FIXME Should handle error properly */
    3520           0 :                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
    3521             :                   }
    3522             : 
    3523             : #ifdef FEATURE_HTTPS_INSPECTION
    3524             :                   /*
    3525             :                    * Sending data with standard or secured connection (HTTP/HTTPS)
    3526             :                    */
    3527        4492 :                   if (client_use_ssl(csp))
    3528             :                   {
    3529          65 :                      if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
    3530             :                               (const unsigned char *)hdr, strlen(hdr),
    3531             :                               get_write_delay(csp)) < 0)
    3532          65 :                         || (ssl_send_data_delayed(&(csp->ssl_client_attr),
    3533             :                               (const unsigned char *) ((p != NULL) ? p : csp->iob->cur),
    3534          65 :                               csp->content_length, get_write_delay(csp)) < 0))
    3535             :                      {
    3536           0 :                         log_error(LOG_LEVEL_ERROR, "write modified content to "
    3537             :                            "client over TLS/SSL failed");
    3538           0 :                         freez(hdr);
    3539           0 :                         freez(p);
    3540           0 :                         mark_server_socket_tainted(csp);
    3541           0 :                         close_client_and_server_ssl_connections(csp);
    3542           0 :                         return;
    3543             :                      }
    3544             :                   }
    3545             :                   else
    3546             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3547             :                   {
    3548        4427 :                      if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
    3549        4427 :                       || write_socket_delayed(csp->cfd, ((p != NULL) ? p : csp->iob->cur),
    3550        4427 :                          (size_t)csp->content_length, write_delay))
    3551             :                      {
    3552           0 :                         log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
    3553           0 :                         freez(hdr);
    3554           0 :                         freez(p);
    3555           0 :                         mark_server_socket_tainted(csp);
    3556           0 :                         return;
    3557             :                      }
    3558             :                   }
    3559             : 
    3560        4492 :                   freez(hdr);
    3561        4492 :                   freez(p);
    3562             :                }
    3563             : 
    3564        5866 :                break; /* "game over, man" */
    3565             :             }
    3566             : 
    3567             :             /*
    3568             :              * This is NOT the body, so
    3569             :              * Let's pretend the server just sent us a blank line.
    3570             :              */
    3571         208 :             snprintf(csp->receive_buffer, csp->receive_buffer_size, "\r\n");
    3572         208 :             len = (int)strlen(csp->receive_buffer);
    3573             : 
    3574             :             /*
    3575             :              * Now, let the normal header parsing algorithm below do its
    3576             :              * job.  If it fails, we'll exit instead of continuing.
    3577             :              */
    3578             : 
    3579         208 :             ms_iis5_hack = 1;
    3580             :          }
    3581             : 
    3582             :          /*
    3583             :           * If we're in the body of the server document, just write it to
    3584             :           * the client, unless we need to buffer the body for later
    3585             :           * content-filtering.
    3586             :           */
    3587       14721 :          if (server_body || (http->ssl
    3588             : #ifdef FEATURE_HTTPS_INSPECTION
    3589        1259 :                && use_ssl_tunnel
    3590             : #endif
    3591             :             ))
    3592             :          {
    3593        3890 :             if (buffer_and_filter_content)
    3594             :             {
    3595             :                /*
    3596             :                 * If there is no memory left for buffering the content, or the buffer limit
    3597             :                 * has been reached, switch to non-filtering mode, i.e. make & write the
    3598             :                 * header, flush the iob and buf, and get out of the way.
    3599             :                 */
    3600        2527 :                if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len))
    3601             :                {
    3602             :                   size_t hdrlen;
    3603             :                   long flushed;
    3604             : 
    3605           0 :                   log_error(LOG_LEVEL_INFO,
    3606             :                      "Flushing header and buffers. Stepping back from filtering.");
    3607             : 
    3608           0 :                   hdr = list_to_text(csp->headers);
    3609           0 :                   if (hdr == NULL)
    3610             :                   {
    3611             :                      /*
    3612             :                       * Memory is too tight to even generate the header.
    3613             :                       * Send our static "Out-of-memory" page.
    3614             :                       */
    3615           0 :                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
    3616           0 :                      rsp = cgi_error_memory();
    3617           0 :                      send_crunch_response(csp, rsp);
    3618           0 :                      mark_server_socket_tainted(csp);
    3619             : #ifdef FEATURE_HTTPS_INSPECTION
    3620           0 :                      close_client_and_server_ssl_connections(csp);
    3621             : #endif
    3622           0 :                      return;
    3623             :                   }
    3624           0 :                   hdrlen = strlen(hdr);
    3625             : 
    3626             : #ifdef FEATURE_HTTPS_INSPECTION
    3627             :                   /*
    3628             :                    * Sending data with standard or secured connection (HTTP/HTTPS)
    3629             :                    */
    3630           0 :                   if (client_use_ssl(csp))
    3631             :                   {
    3632           0 :                      if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
    3633             :                              (const unsigned char *)hdr, hdrlen, get_write_delay(csp)) < 0)
    3634           0 :                         || ((flushed = ssl_flush_socket(&(csp->ssl_client_attr),
    3635           0 :                                 csp->iob)) < 0)
    3636           0 :                         || (ssl_send_data_delayed(&(csp->ssl_client_attr),
    3637           0 :                               (const unsigned char *)csp->receive_buffer, (size_t)len,
    3638             :                               get_write_delay(csp)) < 0))
    3639             :                      {
    3640           0 :                         log_error(LOG_LEVEL_CONNECT,
    3641             :                            "Flush header and buffers to client failed");
    3642           0 :                         freez(hdr);
    3643           0 :                         mark_server_socket_tainted(csp);
    3644           0 :                         close_client_and_server_ssl_connections(csp);
    3645           0 :                         return;
    3646             :                      }
    3647             :                   }
    3648             :                   else
    3649             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3650             :                   {
    3651           0 :                      if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay)
    3652           0 :                       || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)
    3653           0 :                       || write_socket_delayed(csp->cfd, csp->receive_buffer, (size_t)len,
    3654             :                             write_delay))
    3655             :                      {
    3656           0 :                         log_error(LOG_LEVEL_CONNECT,
    3657             :                            "Flush header and buffers to client failed: %E");
    3658           0 :                         freez(hdr);
    3659           0 :                         mark_server_socket_tainted(csp);
    3660           0 :                         return;
    3661             :                      }
    3662             :                   }
    3663             : 
    3664             :                   /*
    3665             :                    * Reset the byte_count to the amount of bytes
    3666             :                    * we just flushed. len will be added a few lines below,
    3667             :                    * hdrlen doesn't matter for LOG_LEVEL_CLF.
    3668             :                    */
    3669           0 :                   byte_count = (unsigned long long)flushed;
    3670           0 :                   freez(hdr);
    3671           0 :                   buffer_and_filter_content = 0;
    3672           0 :                   server_body = 1;
    3673             :                }
    3674             :             }
    3675             :             else
    3676             :             {
    3677             : #ifdef FEATURE_HTTPS_INSPECTION
    3678             :                /*
    3679             :                 * Sending data with standard or secured connection (HTTP/HTTPS)
    3680             :                 */
    3681        1363 :                if (client_use_ssl(csp))
    3682             :                {
    3683         336 :                   ret = ssl_send_data_delayed(&(csp->ssl_client_attr),
    3684         336 :                      (const unsigned char *)csp->receive_buffer, (size_t)len,
    3685             :                      get_write_delay(csp));
    3686         336 :                   if (ret < 0)
    3687             :                   {
    3688           0 :                      log_error(LOG_LEVEL_ERROR,
    3689             :                         "Sending data to client failed");
    3690           0 :                      mark_server_socket_tainted(csp);
    3691           0 :                      close_client_and_server_ssl_connections(csp);
    3692           0 :                      return;
    3693             :                   }
    3694             :                }
    3695             :                else
    3696             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3697             :                {
    3698        1027 :                   if (write_socket_delayed(csp->cfd, csp->receive_buffer,
    3699             :                         (size_t)len, write_delay))
    3700             :                   {
    3701           0 :                      log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
    3702           0 :                      mark_server_socket_tainted(csp);
    3703           0 :                      return;
    3704             :                   }
    3705             :                }
    3706             :             }
    3707        3890 :             byte_count += (unsigned long long)len;
    3708        3890 :             continue;
    3709             :          }
    3710             :          else
    3711             :          {
    3712             :             /*
    3713             :              * We're still looking for the end of the server's header.
    3714             :              * Buffer up the data we just read.  If that fails, there's
    3715             :              * little we can do but send our static out-of-memory page.
    3716             :              */
    3717       10831 :             if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len))
    3718             :             {
    3719           0 :                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
    3720           0 :                rsp = cgi_error_memory();
    3721           0 :                send_crunch_response(csp, rsp);
    3722           0 :                mark_server_socket_tainted(csp);
    3723             : #ifdef FEATURE_HTTPS_INSPECTION
    3724           0 :                close_client_and_server_ssl_connections(csp);
    3725             : #endif
    3726           0 :                return;
    3727             :             }
    3728             : 
    3729             :             /* Convert iob into something sed() can digest */
    3730       10831 :             if (JB_ERR_PARSE == get_server_headers(csp))
    3731             :             {
    3732        4642 :                if (ms_iis5_hack)
    3733             :                {
    3734             :                   /*
    3735             :                    * Well, we tried our MS IIS/5 hack and it didn't work.
    3736             :                    * The header is incomplete and there isn't anything
    3737             :                    * we can do about it.
    3738             :                    */
    3739         116 :                   log_error(LOG_LEVEL_ERROR, "Invalid server headers. "
    3740             :                      "Applying the MS IIS5 hack didn't help.");
    3741         116 :                   log_error(LOG_LEVEL_CLF,
    3742             :                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
    3743             : #ifdef FEATURE_HTTPS_INSPECTION
    3744             :                   /*
    3745             :                    * Sending data with standard or secured connection (HTTP/HTTPS)
    3746             :                    */
    3747         116 :                   if (client_use_ssl(csp))
    3748             :                   {
    3749          24 :                      ssl_send_data_delayed(&(csp->ssl_client_attr),
    3750             :                         (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
    3751             :                         strlen(INVALID_SERVER_HEADERS_RESPONSE), get_write_delay(csp));
    3752             :                   }
    3753             :                   else
    3754             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3755             :                   {
    3756          92 :                      write_socket_delayed(csp->cfd,
    3757             :                         INVALID_SERVER_HEADERS_RESPONSE,
    3758             :                         strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
    3759             :                   }
    3760         116 :                   mark_server_socket_tainted(csp);
    3761             : #ifdef FEATURE_HTTPS_INSPECTION
    3762         116 :                   close_client_and_server_ssl_connections(csp);
    3763             : #endif
    3764         116 :                   return;
    3765             :                }
    3766             :                else
    3767             :                {
    3768             :                   /*
    3769             :                    * Since we have to wait for more from the server before
    3770             :                    * we can parse the headers we just continue here.
    3771             :                    */
    3772        4526 :                   log_error(LOG_LEVEL_CONNECT,
    3773             :                      "Continuing buffering server headers from socket %d. "
    3774             :                      "Bytes most recently read: %ld.", csp->cfd, len);
    3775        4526 :                   continue;
    3776             :                }
    3777             :             }
    3778             :             else
    3779             :             {
    3780             :                /*
    3781             :                 * Account for the content bytes we
    3782             :                 * might have gotten with the headers.
    3783             :                 */
    3784        6189 :                assert(csp->iob->eod >= csp->iob->cur);
    3785        6189 :                byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
    3786             :             }
    3787             : 
    3788             :             /* Did we actually get anything? */
    3789        6189 :             if (NULL == csp->headers->first)
    3790             :             {
    3791          77 :                if ((csp->flags & CSP_FLAG_REUSED_CLIENT_CONNECTION))
    3792             :                {
    3793          10 :                   log_error(LOG_LEVEL_ERROR,
    3794             :                      "No server or forwarder response received on socket %d. "
    3795             :                      "Closing client socket %d without sending data.",
    3796             :                      csp->server_connection.sfd, csp->cfd);
    3797          10 :                   log_error(LOG_LEVEL_CLF,
    3798             :                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
    3799             :                }
    3800             :                else
    3801             :                {
    3802          67 :                   log_error(LOG_LEVEL_ERROR,
    3803             :                      "No server or forwarder response received on socket %d.",
    3804             :                      csp->server_connection.sfd);
    3805          67 :                   send_crunch_response(csp, error_response(csp, "no-server-data"));
    3806             :                }
    3807          77 :                free_http_request(http);
    3808          77 :                mark_server_socket_tainted(csp);
    3809             : #ifdef FEATURE_HTTPS_INSPECTION
    3810          77 :                close_client_and_server_ssl_connections(csp);
    3811             : #endif
    3812          77 :                return;
    3813             :             }
    3814             : 
    3815        6112 :             if (!csp->headers->first->str)
    3816             :             {
    3817           0 :                log_error(LOG_LEVEL_ERROR, "header search: csp->headers->first->str == NULL, assert will be called");
    3818             :             }
    3819        6112 :             assert(csp->headers->first->str);
    3820             : 
    3821        6225 :             if (strncmpic(csp->headers->first->str, "HTTP", 4) &&
    3822         113 :                 strncmpic(csp->headers->first->str, "ICY", 3))
    3823             :             {
    3824             :                /*
    3825             :                 * It doesn't look like a HTTP (or Shoutcast) response:
    3826             :                 * tell the client and log the problem.
    3827             :                 */
    3828         103 :                if (strlen(csp->headers->first->str) > 30)
    3829             :                {
    3830          38 :                   csp->headers->first->str[30] = '\0';
    3831             :                }
    3832         103 :                log_error(LOG_LEVEL_ERROR,
    3833             :                   "Invalid server or forwarder response. Starts with: %s",
    3834         103 :                   csp->headers->first->str);
    3835         103 :                log_error(LOG_LEVEL_CLF,
    3836             :                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
    3837             : #ifdef FEATURE_HTTPS_INSPECTION
    3838             :                /*
    3839             :                 * Sending data with standard or secured connection (HTTP/HTTPS)
    3840             :                 */
    3841         103 :                if (client_use_ssl(csp))
    3842             :                {
    3843           4 :                   ssl_send_data_delayed(&(csp->ssl_client_attr),
    3844             :                      (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
    3845             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE),
    3846             :                      get_write_delay(csp));
    3847             :                }
    3848             :                else
    3849             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3850             :                {
    3851          99 :                   write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
    3852             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
    3853             :                }
    3854         103 :                free_http_request(http);
    3855         103 :                mark_server_socket_tainted(csp);
    3856             : #ifdef FEATURE_HTTPS_INSPECTION
    3857         103 :                close_client_and_server_ssl_connections(csp);
    3858             : #endif
    3859         103 :                return;
    3860             :             }
    3861             : 
    3862             :             /*
    3863             :              * We have now received the entire server header,
    3864             :              * filter it and send the result to the client
    3865             :              */
    3866        6009 :             if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS))
    3867             :             {
    3868          25 :                log_error(LOG_LEVEL_CLF,
    3869             :                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
    3870             : #ifdef FEATURE_HTTPS_INSPECTION
    3871             :                /*
    3872             :                 * Sending data with standard or secured connection (HTTP/HTTPS)
    3873             :                 */
    3874          25 :                if (client_use_ssl(csp))
    3875             :                {
    3876           3 :                   ssl_send_data_delayed(&(csp->ssl_client_attr),
    3877             :                      (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
    3878             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE),
    3879             :                      get_write_delay(csp));
    3880             :                }
    3881             :                else
    3882             : #endif
    3883             :                {
    3884          22 :                   write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
    3885             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
    3886             :                }
    3887          25 :                free_http_request(http);
    3888          25 :                mark_server_socket_tainted(csp);
    3889             : #ifdef FEATURE_HTTPS_INSPECTION
    3890          25 :                close_client_and_server_ssl_connections(csp);
    3891             : #endif
    3892          25 :                return;
    3893             :             }
    3894        5984 :             hdr = list_to_text(csp->headers);
    3895        5984 :             if (hdr == NULL)
    3896             :             {
    3897             :                /* FIXME Should handle error properly */
    3898           0 :                log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
    3899             :             }
    3900             : 
    3901        5984 :             if ((csp->flags & CSP_FLAG_CHUNKED)
    3902        2578 :                && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
    3903        2564 :                && ((csp->iob->eod - csp->iob->cur) >= 5)
    3904        2142 :                && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
    3905             :             {
    3906        1777 :                log_error(LOG_LEVEL_CONNECT,
    3907             :                   "Looks like we got the last chunk together with "
    3908             :                   "the server headers. We better stop reading.");
    3909        1777 :                byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
    3910        1777 :                csp->expected_content_length = byte_count;
    3911        1777 :                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
    3912             :             }
    3913             : 
    3914        5984 :             csp->server_connection.response_received = time(NULL);
    3915             : 
    3916        5984 :             if (crunch_response_triggered(csp, crunchers_light))
    3917             :             {
    3918             :                /*
    3919             :                 * One of the tags created by a server-header
    3920             :                 * tagger triggered a crunch. We already
    3921             :                 * delivered the crunch response to the client
    3922             :                 * and are done here after cleaning up.
    3923             :                 */
    3924           0 :                freez(hdr);
    3925           0 :                mark_server_socket_tainted(csp);
    3926             : #ifdef FEATURE_HTTPS_INSPECTION
    3927           0 :                close_client_and_server_ssl_connections(csp);
    3928             : #endif
    3929           0 :                return;
    3930             :             }
    3931             : 
    3932             :             /* Buffer and pcrs filter this if appropriate. */
    3933        5984 :             buffer_and_filter_content = content_requires_filtering(csp);
    3934             : 
    3935        5984 :             if (!buffer_and_filter_content)
    3936             :             {
    3937             :                /*
    3938             :                 * Write the server's (modified) header to
    3939             :                 * the client (along with anything else that
    3940             :                 * may be in the buffer). Use standard or secured
    3941             :                 * connection.
    3942             :                 */
    3943             : #ifdef FEATURE_HTTPS_INSPECTION
    3944        1352 :                if (client_use_ssl(csp))
    3945             :                {
    3946          28 :                   if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
    3947             :                           (const unsigned char *)hdr, strlen(hdr),
    3948             :                           get_write_delay(csp)) < 0)
    3949          28 :                      || ((len = ssl_flush_socket(&(csp->ssl_client_attr),
    3950          28 :                             csp->iob)) < 0))
    3951             :                   {
    3952           0 :                      log_error(LOG_LEVEL_CONNECT, "Write header to client failed");
    3953             : 
    3954             :                      /*
    3955             :                       * The write failed, so don't bother mentioning it
    3956             :                       * to the client... it probably can't hear us anyway.
    3957             :                       */
    3958           0 :                      freez(hdr);
    3959           0 :                      mark_server_socket_tainted(csp);
    3960             : #ifdef FEATURE_HTTPS_INSPECTION
    3961           0 :                      close_client_and_server_ssl_connections(csp);
    3962             : #endif
    3963           0 :                      return;
    3964             :                   }
    3965             :                }
    3966             :                else
    3967             : #endif /* def FEATURE_HTTPS_INSPECTION */
    3968             :                {
    3969        1324 :                   if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
    3970        1324 :                      || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0))
    3971             :                   {
    3972           0 :                      log_error(LOG_LEVEL_ERROR,
    3973             :                         "write header to client failed");
    3974             :                      /*
    3975             :                       * The write failed, so don't bother mentioning it
    3976             :                       * to the client... it probably can't hear us anyway.
    3977             :                       */
    3978           0 :                      freez(hdr);
    3979           0 :                      mark_server_socket_tainted(csp);
    3980           0 :                      return;
    3981             :                   }
    3982             :                }
    3983             :             }
    3984             : 
    3985             :             /* we're finished with the server's header */
    3986             : 
    3987        5984 :             freez(hdr);
    3988        5984 :             server_body = 1;
    3989             : 
    3990             :             /*
    3991             :              * If this was a MS IIS/5 hack then it means the server
    3992             :              * has already closed the connection. Nothing more to read.
    3993             :              * Time to bail.
    3994             :              */
    3995        5984 :             if (ms_iis5_hack)
    3996             :             {
    3997          25 :                log_error(LOG_LEVEL_ERROR,
    3998             :                   "Closed server connection detected. "
    3999             :                   "Applying the MS IIS5 hack didn't help.");
    4000          25 :                log_error(LOG_LEVEL_CLF,
    4001             :                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
    4002             : #ifdef FEATURE_HTTPS_INSPECTION
    4003             :                /*
    4004             :                 * Sending data with standard or secured connection (HTTP/HTTPS)
    4005             :                 */
    4006          25 :                if (client_use_ssl(csp))
    4007             :                {
    4008           1 :                   ssl_send_data_delayed(&(csp->ssl_client_attr),
    4009             :                      (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
    4010             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE),
    4011             :                      get_write_delay(csp));
    4012             :                }
    4013             :                else
    4014             : #endif /* def FEATURE_HTTPS_INSPECTION */
    4015             :                {
    4016          24 :                   write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
    4017             :                      strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
    4018             :                }
    4019          25 :                mark_server_socket_tainted(csp);
    4020             : #ifdef FEATURE_HTTPS_INSPECTION
    4021          25 :                close_client_and_server_ssl_connections(csp);
    4022             : #endif
    4023          25 :                return;
    4024             :             }
    4025             :          }
    4026        5959 :          continue;
    4027             :       }
    4028           0 :       mark_server_socket_tainted(csp);
    4029             : #ifdef FEATURE_HTTPS_INSPECTION
    4030           0 :       close_client_and_server_ssl_connections(csp);
    4031             : #endif
    4032           0 :       return; /* huh? we should never get here */
    4033             :    }
    4034             : 
    4035        6029 :    if (csp->content_length == 0)
    4036             :    {
    4037             :       /*
    4038             :        * If Privoxy didn't recalculate the Content-Length,
    4039             :        * byte_count is still correct.
    4040             :        */
    4041        3032 :       csp->content_length = byte_count;
    4042             :    }
    4043             : 
    4044             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4045        6029 :    if ((csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
    4046        2635 :       && (csp->expected_content_length != byte_count))
    4047             :    {
    4048         139 :       log_error(LOG_LEVEL_CONNECT,
    4049             :          "Received %llu bytes while expecting %llu.",
    4050             :          byte_count, csp->expected_content_length);
    4051         139 :       mark_server_socket_tainted(csp);
    4052             :    }
    4053             : #endif
    4054             : 
    4055             : #ifdef FEATURE_HTTPS_INSPECTION
    4056        6029 :    if (client_use_ssl(csp))
    4057             :    {
    4058         135 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" 200 %llu",
    4059             :          csp->ip_addr_str, http->gpc, http->hostport, http->path,
    4060             :          http->version, csp->content_length);
    4061             :    }
    4062             :    else
    4063             : #endif
    4064             :    {
    4065        5894 :       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
    4066             :          csp->ip_addr_str, http->ocmd, csp->content_length);
    4067             :    }
    4068        6029 :    csp->server_connection.timestamp = time(NULL);
    4069             : }
    4070             : 
    4071             : 
    4072             : /*********************************************************************
    4073             :  *
    4074             :  * Function    :  chat
    4075             :  *
    4076             :  * Description :  Once a connection from the client has been accepted,
    4077             :  *                this function is called (via serve()) to handle the
    4078             :  *                main business of the communication.  This function
    4079             :  *                returns after dealing with a single request. It can
    4080             :  *                be called multiple times with the same client socket
    4081             :  *                if the client is keeping the connection alive.
    4082             :  *
    4083             :  *                The decision whether or not a client connection will
    4084             :  *                be kept alive is up to the caller which also must
    4085             :  *                close the client socket when done.
    4086             :  *
    4087             :  *                FIXME: chat is nearly thousand lines long.
    4088             :  *                Ridiculous.
    4089             :  *
    4090             :  * Parameters  :
    4091             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    4092             :  *
    4093             :  * Returns     :  Nothing.
    4094             :  *
    4095             :  *********************************************************************/
    4096       32220 : static void chat(struct client_state *csp)
    4097             : {
    4098             :    const struct forward_spec *fwd;
    4099             :    struct http_request *http;
    4100             :    /* Skeleton for HTTP response, if we should intercept the request */
    4101             :    struct http_response *rsp;
    4102             : #ifdef FEATURE_HTTPS_INSPECTION
    4103       32220 :    int use_ssl_tunnel = 0;
    4104             : #endif
    4105             : 
    4106       32220 :    http = csp->http;
    4107             : 
    4108       32220 :    if (receive_client_request(csp) != JB_ERR_OK)
    4109             :    {
    4110        1043 :       return;
    4111             :    }
    4112       31177 :    if (parse_client_request(csp) != JB_ERR_OK)
    4113             :    {
    4114          59 :       return;
    4115             :    }
    4116             : 
    4117             :    /* decide how to route the HTTP request */
    4118       31118 :    fwd = forward_url(csp, http);
    4119             : 
    4120             : #ifdef FEATURE_HTTPS_INSPECTION
    4121             :    /*
    4122             :     * Setting flags to use old solution with SSL tunnel and to disable
    4123             :     * certificate verification.
    4124             :     */
    4125       31118 :    if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION)
    4126          41 :       && !cgi_page_requested(csp->http->host))
    4127             :    {
    4128          21 :       use_ssl_tunnel = 1;
    4129             :    }
    4130             : 
    4131       31118 :    if (http->ssl && (csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS))
    4132             :    {
    4133         410 :       csp->dont_verify_certificate = 1;
    4134             :    }
    4135             : #endif
    4136             : 
    4137             :    /*
    4138             :     * build the http request to send to the server
    4139             :     * we have to do one of the following:
    4140             :     *
    4141             :     * create =    use the original HTTP request to create a new
    4142             :     *             HTTP request that has either the path component
    4143             :     *             without the http://domainspec (w/path) or the
    4144             :     *             full orininal URL (w/url)
    4145             :     *             Note that the path and/or the HTTP version may
    4146             :     *             have been altered by now.
    4147             :     *
    4148             :     * SSL proxy = Open a socket to the host:port of the server
    4149             :     *             and create TLS/SSL connection with server and
    4150             :     *             with client. Then behave like mediator between
    4151             :     *             client and server over TLS/SSL.
    4152             :     *
    4153             :     * SSL proxy = Pass the request unchanged if forwarding a CONNECT
    4154             :     *    with     request to a parent proxy. Note that we'll be sending
    4155             :     * forwarding  the CFAIL message ourselves if connecting to the parent
    4156             :     *             fails, but we won't send a CSUCCEED message if it works,
    4157             :     *             since that would result in a double message (ours and the
    4158             :     *             parent's). After sending the request to the parent, we
    4159             :     *             must parse answer and send it to client. If connection
    4160             :     *             with server is established, we do TLS/SSL proxy. Otherwise
    4161             :     *             we send parent response to client and close connections.
    4162             :     *
    4163             :     * here's the matrix:
    4164             :     *                        SSL
    4165             :     *                    0        1
    4166             :     *                +--------+--------+
    4167             :     *                |        |        |
    4168             :     *             0  | create |   SSL  |
    4169             :     *                | w/path |  proxy |
    4170             :     *  Forwarding    +--------+--------+
    4171             :     *                |        |   SSL  |
    4172             :     *             1  | create |  proxy |
    4173             :     *                | w/url  |+forward|
    4174             :     *                +--------+--------+
    4175             :     *
    4176             :     */
    4177             : 
    4178             : #ifdef FEATURE_HTTPS_INSPECTION
    4179             :    /*
    4180             :     * Presetting SSL client and server flags
    4181             :     */
    4182       31118 :    if (http->ssl && !use_ssl_tunnel)
    4183             :    {
    4184         432 :       http->client_ssl = 1;
    4185         432 :       http->server_ssl = 1;
    4186             :    }
    4187             :    else
    4188             :    {
    4189       30686 :       http->client_ssl = 0;
    4190       30686 :       http->server_ssl = 0;
    4191             :    }
    4192             : #endif
    4193             : 
    4194             : #ifdef FEATURE_HTTPS_INSPECTION
    4195             :    /*
    4196             :     * Log the request unless we're https inspecting
    4197             :     * in which case we don't have the path yet and
    4198             :     * will log the request later.
    4199             :     */
    4200       31118 :    if (!client_use_ssl(csp))
    4201             : #endif
    4202             :    {
    4203       30686 :       log_error(LOG_LEVEL_REQUEST, "%s%s", http->hostport, http->path);
    4204             :    }
    4205             : 
    4206       31118 :    if (http->ssl && connect_port_is_forbidden(csp))
    4207             :    {
    4208          98 :       const char *acceptable_connect_ports =
    4209             :          csp->action->string[ACTION_STRING_LIMIT_CONNECT];
    4210          98 :       assert(NULL != acceptable_connect_ports);
    4211          98 :       log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
    4212             :          "limit-connect{%s} doesn't allow CONNECT requests to %s",
    4213             :          csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
    4214          98 :       csp->action->flags |= ACTION_BLOCK;
    4215          98 :       http->ssl = 0;
    4216             : #ifdef FEATURE_HTTPS_INSPECTION
    4217          98 :       http->client_ssl = 0;
    4218          98 :       http->server_ssl = 0;
    4219             : #endif
    4220             :    }
    4221             : 
    4222             : 
    4223       31118 :    freez(csp->headers->first->str);
    4224       31118 :    build_request_line(csp, fwd, &csp->headers->first->str);
    4225             : 
    4226             :    /*
    4227             :     * We have a request. Check if one of the crunchers wants it
    4228             :     * unless the client wants to use TLS/SSL in which case we
    4229             :     * haven't setup the TLS context yet and will send the crunch
    4230             :     * response later.
    4231             :     */
    4232       31118 :    if (
    4233             : #ifdef FEATURE_HTTPS_INSPECTION
    4234       61902 :        !client_use_ssl(csp) &&
    4235             : #endif
    4236       30784 :        crunch_response_triggered(csp, crunchers_all))
    4237             :    {
    4238             :       /*
    4239             :        * Yes. The client got the crunch response and we're done here.
    4240             :        */
    4241       24455 :       return;
    4242             :    }
    4243             : 
    4244        6663 :    log_applied_actions(csp->action);
    4245        6663 :    if (fwd->forward_host)
    4246             :    {
    4247           0 :       log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
    4248             :          fwd->forward_host, fwd->forward_port, http->hostport);
    4249             :    }
    4250             :    else
    4251             :    {
    4252        6663 :       log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
    4253             :    }
    4254             : 
    4255             :    /* here we connect to the server, gateway, or the forwarder */
    4256             : 
    4257             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4258        6663 :    if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
    4259         196 :       && socket_is_still_alive(csp->server_connection.sfd)
    4260         193 :       && connection_destination_matches(&csp->server_connection, http, fwd))
    4261             :    {
    4262          22 :       log_error(LOG_LEVEL_CONNECT,
    4263             :          "Reusing server socket %d connected to %s. Total requests: %u.",
    4264             :          csp->server_connection.sfd, csp->server_connection.host,
    4265             :          csp->server_connection.requests_sent_total);
    4266             :    }
    4267             :    else
    4268             :    {
    4269        6641 :       if (csp->server_connection.sfd != JB_INVALID_SOCKET)
    4270             :       {
    4271             : #ifdef FEATURE_CONNECTION_SHARING
    4272         174 :          if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING
    4273             : #ifdef FEATURE_HTTPS_INSPECTION
    4274           0 :             && !server_use_ssl(csp)
    4275             : #endif
    4276             :             )
    4277             :          {
    4278           0 :             remember_connection(&csp->server_connection);
    4279             :          }
    4280             :          else
    4281             : #endif /* def FEATURE_CONNECTION_SHARING */
    4282             :          {
    4283         174 :             log_error(LOG_LEVEL_CONNECT,
    4284             :                "Closing server socket %d connected to %s. Total requests: %u.",
    4285             :                csp->server_connection.sfd, csp->server_connection.host,
    4286             :                csp->server_connection.requests_sent_total);
    4287         174 :             close_socket(csp->server_connection.sfd);
    4288             :          }
    4289         174 :          mark_connection_closed(&csp->server_connection);
    4290             :       }
    4291             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    4292             : #ifdef FEATURE_HTTPS_INSPECTION
    4293        6641 :       if (client_use_ssl(csp) && !use_ssl_tunnel)
    4294             :       {
    4295             :          int ret;
    4296             :          /*
    4297             :           * Creating a SSL proxy.
    4298             :           *
    4299             :           * By sending the CSUCCEED message we're lying to the client as
    4300             :           * the connection hasn't actually been established yet. We don't
    4301             :           * establish the connection until we have seen and parsed the
    4302             :           * encrypted client headers.
    4303             :           */
    4304         334 :          if (write_socket_delayed(csp->cfd, CSUCCEED,
    4305             :                strlen(CSUCCEED), get_write_delay(csp)) != 0)
    4306             :          {
    4307           0 :             log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed");
    4308           0 :             return;
    4309             :          }
    4310             : 
    4311         334 :          ret = create_client_ssl_connection(csp);
    4312         334 :          if (ret != 0)
    4313             :          {
    4314           0 :             log_error(LOG_LEVEL_ERROR,
    4315             :                "Failed to open a secure connection with the client");
    4316           0 :             return;
    4317             :          }
    4318         334 :          if (JB_ERR_OK != process_encrypted_request(csp))
    4319             :          {
    4320          40 :             close_client_ssl_connection(csp);
    4321          40 :             return;
    4322             :          }
    4323             :          /*
    4324             :           * We have an encrypted request. Check if one of the crunchers now
    4325             :           * wants it (for example because the previously invisible path was
    4326             :           * required to match).
    4327             :           */
    4328         294 :          if (crunch_response_triggered(csp, crunchers_all))
    4329             :          {
    4330             :             /*
    4331             :              * Yes. The client got the crunch response and we're done here.
    4332             :              */
    4333         127 :             return;
    4334             :          }
    4335             :       }
    4336             : #endif
    4337             :       /*
    4338             :        * Connecting to destination server
    4339             :        */
    4340        6474 :       csp->server_connection.sfd = forwarded_connect(fwd, http, csp);
    4341             : 
    4342        6474 :       if (csp->server_connection.sfd == JB_INVALID_SOCKET)
    4343             :       {
    4344           0 :          if (fwd->type != SOCKS_NONE)
    4345             :          {
    4346             :             /* Socks error. */
    4347           0 :             rsp = error_response(csp, "forwarding-failed");
    4348             :          }
    4349           0 :          else if (errno == EINVAL)
    4350             :          {
    4351           0 :             rsp = error_response(csp, "no-such-domain");
    4352             :          }
    4353             :          else
    4354             :          {
    4355           0 :             rsp = error_response(csp, "connect-failed");
    4356             :          }
    4357             : 
    4358             :          /* Write the answer to the client */
    4359           0 :          if (rsp != NULL)
    4360             :          {
    4361           0 :             send_crunch_response(csp, rsp);
    4362             :          }
    4363             : 
    4364             :          /*
    4365             :           * Temporary workaround to prevent already-read client
    4366             :           * bodies from being parsed as new requests. For now we
    4367             :           * err on the safe side and throw all the following
    4368             :           * requests under the bus, even if no client body has been
    4369             :           * buffered. A compliant client will repeat the dropped
    4370             :           * requests on an untainted connection.
    4371             :           *
    4372             :           * The proper fix is to discard the no longer needed
    4373             :           * client body in the buffer (if there is one) and to
    4374             :           * continue parsing the bytes that follow.
    4375             :           */
    4376             : #ifdef FEATURE_HTTPS_INSPECTION
    4377           0 :          close_client_ssl_connection(csp);
    4378             : #endif
    4379           0 :          drain_and_close_socket(csp->cfd);
    4380           0 :          csp->cfd = JB_INVALID_SOCKET;
    4381             : 
    4382           0 :          return;
    4383             :       }
    4384             : 
    4385             : #ifdef FEATURE_HTTPS_INSPECTION
    4386             :       /*
    4387             :        * Creating TLS/SSL connections with destination server or parent
    4388             :        * proxy. If forwarding is enabled, we must send client request to
    4389             :        * parent proxy and receive, parse and resend parent proxy answer.
    4390             :        */
    4391        6474 :       if (http->ssl && !use_ssl_tunnel)
    4392             :       {
    4393         159 :          if (fwd->forward_host != NULL)
    4394             :          {
    4395             :             char server_response[BUFFER_SIZE];
    4396           0 :             int ret = 0;
    4397           0 :             int len = 0;
    4398           0 :             char *hdr = list_to_text(csp->headers);
    4399           0 :             memset(server_response, 0, sizeof(server_response));
    4400             : 
    4401           0 :             if (hdr == NULL)
    4402             :             {
    4403           0 :                log_error(LOG_LEVEL_FATAL,
    4404             :                   "Out of memory parsing client header");
    4405             :             }
    4406           0 :             list_remove_all(csp->headers);
    4407             : 
    4408             :             /*
    4409             :              * Sending client's CONNECT request to the parent proxy
    4410             :              */
    4411           0 :             ret = write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
    4412             : 
    4413           0 :             freez(hdr);
    4414             : 
    4415           0 :             if (ret != 0)
    4416             :             {
    4417           0 :                log_error(LOG_LEVEL_CONNECT,
    4418             :                   "Sending request headers to: %s failed", http->hostport);
    4419           0 :                mark_server_socket_tainted(csp);
    4420           0 :                close_client_ssl_connection(csp);
    4421           0 :                return;
    4422             :             }
    4423             : 
    4424             :             /* Waiting for parent proxy server response */
    4425           0 :             len = read_socket(csp->server_connection.sfd, server_response,
    4426             :                sizeof(server_response)-1);
    4427             : 
    4428           0 :             if (len <= 0)
    4429             :             {
    4430           0 :                log_error(LOG_LEVEL_ERROR, "No response from parent proxy "
    4431             :                   "server on socket %d.", csp->server_connection.sfd);
    4432             : 
    4433           0 :                rsp = error_response(csp, "no-server-data");
    4434           0 :                if (rsp)
    4435             :                {
    4436           0 :                   send_crunch_response(csp, rsp);
    4437             :                }
    4438           0 :                mark_server_socket_tainted(csp);
    4439           0 :                close_client_ssl_connection(csp);
    4440           0 :                return;
    4441             :             }
    4442             : 
    4443             :             /*
    4444             :              * Test if the connection to the destination server was
    4445             :              * established successfully by the parent proxy.
    4446             :              */
    4447           0 :             if (!tunnel_established_successfully(server_response, (unsigned int)len))
    4448             :             {
    4449           0 :                log_error(LOG_LEVEL_ERROR,
    4450             :                   "The forwarder %s failed to establish a connection with %s",
    4451             :                   fwd->forward_host, http->host);
    4452           0 :                rsp = error_response(csp, "connect-failed");
    4453           0 :                if (rsp)
    4454             :                {
    4455           0 :                   send_crunch_response(csp, rsp);
    4456             :                }
    4457           0 :                mark_server_socket_tainted(csp);
    4458           0 :                close_client_ssl_connection(csp);
    4459           0 :                return;
    4460             :             }
    4461             :          } /* -END- if (fwd->forward_host != NULL) */
    4462             : 
    4463             :          /*
    4464             :           * We can now create the TLS/SSL connection with the destination server.
    4465             :           */
    4466         159 :          int ret = 0;
    4467         159 :          csp->ssl_with_server_is_opened = 1;//         int ret = create_server_ssl_connection(csp);
    4468         159 :          if (ret != 0)
    4469             :          {
    4470           0 :             if (csp->server_cert_verification_result != SSL_CERT_VALID &&
    4471           0 :                 csp->server_cert_verification_result != SSL_CERT_NOT_VERIFIED)
    4472             :             {
    4473             :                /*
    4474             :                 * If the server certificate is invalid, we must inform
    4475             :                 * the client and then close connection to the client.
    4476             :                 */
    4477           0 :                ssl_send_certificate_error(csp);
    4478           0 :                close_client_and_server_ssl_connections(csp);
    4479           0 :                return;
    4480             :             }
    4481           0 :             if (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED
    4482           0 :              || csp->server_cert_verification_result == SSL_CERT_VALID)
    4483             :             {
    4484             :                /*
    4485             :                 * The TLS/SSL connection wasn't created but an invalid
    4486             :                 * certificate wasn't detected. Report it as connection
    4487             :                 * failure.
    4488             :                 */
    4489           0 :                rsp = error_response(csp, "connect-failed");
    4490           0 :                if (rsp)
    4491             :                {
    4492           0 :                   send_crunch_response(csp, rsp);
    4493             :                }
    4494           0 :                close_client_and_server_ssl_connections(csp);
    4495           0 :                return;
    4496             :             }
    4497             :          }
    4498             : 
    4499             :       }/* -END- if (http->ssl) */
    4500             : #endif /* def FEATURE_HTTPS_INSPECTION */
    4501             : 
    4502             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4503        6474 :       save_connection_destination(csp->server_connection.sfd,
    4504             :          http, fwd, &csp->server_connection);
    4505        6474 :       csp->server_connection.keep_alive_timeout =
    4506        6474 :          (unsigned)csp->config->keep_alive_timeout;
    4507             :    }
    4508             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    4509             : 
    4510        6496 :    csp->server_connection.requests_sent_total++;
    4511             : 
    4512        6496 :    if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first))
    4513             :    {
    4514             :       /* Client headers have been sent optimistically */
    4515           0 :       assert(csp->headers->last == NULL);
    4516             :    }
    4517        6496 :    else if (http->ssl == 0 || (fwd->forward_host
    4518             : #ifdef FEATURE_HTTPS_INSPECTION
    4519           0 :          && use_ssl_tunnel
    4520             : #endif
    4521             :            ))
    4522             :    {
    4523        6316 :       if (send_http_request(csp))
    4524             :       {
    4525          24 :          rsp = error_response(csp, "connect-failed");
    4526          24 :          if (rsp)
    4527             :          {
    4528          24 :             send_crunch_response(csp, rsp);
    4529             :          }
    4530          24 :          return;
    4531             :       }
    4532             :    }
    4533             :    else
    4534             :    {
    4535             :       /*
    4536             :        * Using old solution with SSL tunnel or new solution with SSL proxy
    4537             :        */
    4538         180 :       list_remove_all(csp->headers);
    4539             : #ifdef FEATURE_HTTPS_INSPECTION
    4540         180 :       if (use_ssl_tunnel)
    4541             : #endif
    4542             :       {
    4543             :          /*
    4544             :          * We're running an SSL tunnel and we're not forwarding,
    4545             :          * so just ditch the client headers, send the "connect succeeded"
    4546             :          * message to the client, flush the rest, and get out of the way.
    4547             :          */
    4548          21 :          if (write_socket_delayed(csp->cfd, CSUCCEED,
    4549             :                strlen(CSUCCEED), get_write_delay(csp)))
    4550             :          {
    4551           0 :             return;
    4552             :          }
    4553             :       }
    4554             : #ifdef FEATURE_HTTPS_INSPECTION
    4555             :       else
    4556             :       {
    4557             :          /*
    4558             :           * If server certificate has been verified and is invalid,
    4559             :           * we must inform the client and then close the connection
    4560             :           * with client and server.
    4561             :           */
    4562             : /*         if (csp->server_cert_verification_result != SSL_CERT_VALID &&
    4563             :              csp->server_cert_verification_result != SSL_CERT_NOT_VERIFIED)
    4564             :          {
    4565             :             ssl_send_certificate_error(csp);
    4566             :             close_client_and_server_ssl_connections(csp);
    4567             :             return;
    4568             :          }
    4569             : */
    4570         159 :          if (send_https_request(csp))
    4571             :          {
    4572          17 :             rsp = error_response(csp, "connect-failed");
    4573          17 :             if (rsp)
    4574             :             {
    4575          17 :                send_crunch_response(csp, rsp);
    4576             :             }
    4577          17 :             close_client_and_server_ssl_connections(csp);
    4578          17 :             return;
    4579             :          }
    4580             :       }
    4581             : #endif /* def FEATURE_HTTPS_INSPECTION */
    4582         163 :       clear_iob(csp->client_iob);
    4583             :    }/* -END- else ... if (http->ssl == 1) */
    4584             : 
    4585        6455 :    log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
    4586             : 
    4587             :    /* XXX: should the time start earlier for optimistically sent data? */
    4588        6455 :    csp->server_connection.request_sent = time(NULL);
    4589             : 
    4590        6455 :    handle_established_connection(csp);
    4591        6455 :    freez(csp->receive_buffer);
    4592             : }
    4593             : 
    4594             : 
    4595             : #ifdef FUZZ
    4596             : /*********************************************************************
    4597             :  *
    4598             :  * Function    :  fuzz_server_response
    4599             :  *
    4600             :  * Description :  Treat the input as a whole server response.
    4601             :  *
    4602             :  * Parameters  :
    4603             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    4604             :  *          2  :  fuzz_input_file = File to read the input from.
    4605             :  *
    4606             :  * Returns     :  0
    4607             :  *
    4608             :  *********************************************************************/
    4609           0 : extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file)
    4610             : {
    4611             :    static struct forward_spec fwd; /* Zero'd due to being static */
    4612           0 :    csp->cfd = 0;
    4613             : 
    4614           0 :    if (strcmp(fuzz_input_file, "-") == 0)
    4615             :    {
    4616             :       /* XXX: Doesn't work yet. */
    4617           0 :       csp->server_connection.sfd = 0;
    4618             :    }
    4619             :    else
    4620             :    {
    4621           0 :       csp->server_connection.sfd = open(fuzz_input_file, O_RDONLY);
    4622           0 :       if (csp->server_connection.sfd == -1)
    4623             :       {
    4624           0 :          log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E",
    4625             :             fuzz_input_file);
    4626             :       }
    4627             :    }
    4628           0 :    csp->fwd = &fwd;
    4629           0 :    csp->content_type |= CT_GIF;
    4630           0 :    csp->action->flags |= ACTION_DEANIMATE;
    4631           0 :    csp->action->string[ACTION_STRING_DEANIMATE] = "last";
    4632             : 
    4633           0 :    csp->http->path = strdup_or_die("/");
    4634           0 :    csp->http->host = strdup_or_die("fuzz.example.org");
    4635           0 :    csp->http->hostport = strdup_or_die("fuzz.example.org:80");
    4636             :    /* Prevent client socket monitoring */
    4637           0 :    csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
    4638           0 :    csp->flags |= CSP_FLAG_CHUNKED;
    4639             : 
    4640           0 :    csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
    4641           0 :    csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
    4642             : 
    4643           0 :    csp->content_type |= CT_DECLARED|CT_GIF;
    4644             : 
    4645           0 :    csp->config->socket_timeout = 0;
    4646             : 
    4647           0 :    cgi_init_error_messages();
    4648             : 
    4649           0 :    handle_established_connection(csp);
    4650           0 :    freez(csp->receive_buffer);
    4651             : 
    4652           0 :    return 0;
    4653             : }
    4654             : #endif
    4655             : 
    4656             : 
    4657             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4658             : /*********************************************************************
    4659             :  *
    4660             :  * Function    :  prepare_csp_for_next_request
    4661             :  *
    4662             :  * Description :  Put the csp in a mostly vergin state.
    4663             :  *
    4664             :  * Parameters  :
    4665             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    4666             :  *
    4667             :  * Returns     :  N/A
    4668             :  *
    4669             :  *********************************************************************/
    4670       31040 : static void prepare_csp_for_next_request(struct client_state *csp)
    4671             : {
    4672       31040 :    csp->content_type = 0;
    4673       31040 :    csp->content_length = 0;
    4674       31040 :    csp->expected_content_length = 0;
    4675       31040 :    csp->expected_client_content_length = 0;
    4676       31040 :    list_remove_all(csp->headers);
    4677       31040 :    clear_iob(csp->iob);
    4678       31040 :    freez(csp->error_message);
    4679       31040 :    free_http_request(csp->http);
    4680       31040 :    destroy_list(csp->headers);
    4681             : #ifdef FEATURE_HTTPS_INSPECTION
    4682       31040 :    destroy_list(csp->https_headers);
    4683             : #endif
    4684       31040 :    destroy_list(csp->tags);
    4685             : #ifdef FEATURE_CLIENT_TAGS
    4686       31040 :    destroy_list(csp->client_tags);
    4687       31040 :    freez(csp->client_address);
    4688             : #endif
    4689       31040 :    free_current_action(csp->action);
    4690       31040 :    if (NULL != csp->fwd)
    4691             :    {
    4692           0 :       unload_forward_spec(csp->fwd);
    4693           0 :       csp->fwd = NULL;
    4694             :    }
    4695             :    /* XXX: Store per-connection flags someplace else. */
    4696       31040 :    csp->flags = (CSP_FLAG_ACTIVE | CSP_FLAG_REUSED_CLIENT_CONNECTION);
    4697             : #ifdef FEATURE_TOGGLE
    4698       31040 :    if (global_toggle_state)
    4699             : #endif /* def FEATURE_TOGGLE */
    4700             :    {
    4701       29835 :       csp->flags |= CSP_FLAG_TOGGLED_ON;
    4702             :    }
    4703             : 
    4704       31040 :    if (csp->client_iob->eod > csp->client_iob->cur)
    4705             :    {
    4706       11356 :       long bytes_to_shift = csp->client_iob->cur - csp->client_iob->buf;
    4707       11356 :       size_t data_length  = (size_t)(csp->client_iob->eod - csp->client_iob->cur);
    4708             : 
    4709       11356 :       assert(bytes_to_shift > 0);
    4710       11356 :       assert(data_length > 0);
    4711             : 
    4712       11356 :       log_error(LOG_LEVEL_CONNECT, "Shifting %lu pipelined bytes by %ld bytes",
    4713             :          data_length, bytes_to_shift);
    4714       11356 :       memmove(csp->client_iob->buf, csp->client_iob->cur, data_length);
    4715       11356 :       csp->client_iob->cur = csp->client_iob->buf;
    4716       11356 :       assert(csp->client_iob->eod == csp->client_iob->buf + bytes_to_shift + data_length);
    4717       11356 :       csp->client_iob->eod = csp->client_iob->buf + data_length;
    4718       11356 :       memset(csp->client_iob->eod, '\0', (size_t)bytes_to_shift);
    4719             : 
    4720       11356 :       csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
    4721             :    }
    4722             :    else
    4723             :    {
    4724             :       /*
    4725             :        * We mainly care about resetting client_iob->cur so we don't
    4726             :        * waste buffer space at the beginning and don't mess up the
    4727             :        * request restoration done by cgi_show_request().
    4728             :        *
    4729             :        * Freeing the buffer itself isn't technically necessary,
    4730             :        * but makes debugging more convenient.
    4731             :        */
    4732       19684 :       clear_iob(csp->client_iob);
    4733             :    }
    4734       31040 : }
    4735             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    4736             : 
    4737             : 
    4738             : /*********************************************************************
    4739             :  *
    4740             :  * Function    :  serve
    4741             :  *
    4742             :  * Description :  This is little more than chat.  We only "serve" to
    4743             :  *                to close (or remember) any socket that chat may have
    4744             :  *                opened.
    4745             :  *
    4746             :  * Parameters  :
    4747             :  *          1  :  csp = Current client state (buffers, headers, etc...)
    4748             :  *
    4749             :  * Returns     :  N/A
    4750             :  *
    4751             :  *********************************************************************/
    4752        3098 : static void serve(struct client_state *csp)
    4753             : {
    4754        3098 :    int config_file_change_detected = 0; /* Only used for debugging */
    4755             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4756             : #ifdef FEATURE_CONNECTION_SHARING
    4757             :    static int monitor_thread_running = 0;
    4758             : #endif /* def FEATURE_CONNECTION_SHARING */
    4759        3098 :    int continue_chatting = 0;
    4760             : 
    4761        3098 :    log_error(LOG_LEVEL_CONNECT, "Accepted connection from %s on socket %d",
    4762             :       csp->ip_addr_str, csp->cfd);
    4763             :    do
    4764             :    {
    4765             :       unsigned int latency;
    4766             : #ifdef FEATURE_HTTPS_INSPECTION
    4767       34138 :       if (continue_chatting && client_use_ssl(csp))
    4768             :       {
    4769        1918 :          continue_https_chat(csp);
    4770             :       }
    4771             :       else
    4772             : #endif
    4773             :       {
    4774       32220 :          chat(csp);
    4775             :       }
    4776             : 
    4777             :       /*
    4778             :        * If the request has been crunched,
    4779             :        * the calculated latency is zero.
    4780             :        */
    4781       34138 :       latency = (unsigned)(csp->server_connection.response_received -
    4782       34138 :          csp->server_connection.request_sent) / 2;
    4783             : 
    4784       34138 :       if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
    4785       32438 :          && (csp->flags & CSP_FLAG_CRUNCHED)
    4786       26057 :          && (csp->expected_client_content_length != 0))
    4787             :       {
    4788          26 :          csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
    4789          26 :          log_error(LOG_LEVEL_CONNECT,
    4790             :             "Tainting client socket %d due to unread data.", csp->cfd);
    4791             :       }
    4792             : 
    4793       68276 :       continue_chatting = (csp->config->feature_flags
    4794       34138 :          & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
    4795       34138 :          && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
    4796       33159 :          && (csp->cfd != JB_INVALID_SOCKET)
    4797       33159 :          && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
    4798       69783 :          && ((csp->flags & CSP_FLAG_SERVER_CONTENT_LENGTH_SET)
    4799        1507 :             || (csp->flags & CSP_FLAG_CHUNKED));
    4800             : 
    4801       34138 :       if (!(csp->flags & CSP_FLAG_CRUNCHED)
    4802        7810 :          && (csp->server_connection.sfd != JB_INVALID_SOCKET))
    4803             :       {
    4804        6543 :          if (!(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET))
    4805             :          {
    4806        6285 :             csp->server_connection.keep_alive_timeout = csp->config->default_server_timeout;
    4807             :          }
    4808        6543 :          if (!(csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
    4809        4974 :             || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
    4810        4802 :             || !socket_is_still_alive(csp->server_connection.sfd)
    4811        4686 :             || !(latency < csp->server_connection.keep_alive_timeout))
    4812             :          {
    4813        6298 :             log_error(LOG_LEVEL_CONNECT,
    4814             :                "Closing server socket %d connected to %s. "
    4815             :                "Keep-alive: %u. Tainted: %u. Socket alive: %u. Timeout: %u.",
    4816             :                csp->server_connection.sfd, csp->server_connection.host,
    4817        6298 :                0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
    4818        6298 :                0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
    4819             :                socket_is_still_alive(csp->server_connection.sfd),
    4820             :                csp->server_connection.keep_alive_timeout);
    4821             : #ifdef FEATURE_CONNECTION_SHARING
    4822        6298 :             if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
    4823             :             {
    4824           0 :                forget_connection(csp->server_connection.sfd);
    4825             :             }
    4826             : #endif /* def FEATURE_CONNECTION_SHARING */
    4827             : #ifdef FEATURE_HTTPS_INSPECTION
    4828        6298 :             close_server_ssl_connection(csp);
    4829             : #endif
    4830        6298 :             close_socket(csp->server_connection.sfd);
    4831        6298 :             mark_connection_closed(&csp->server_connection);
    4832             :          }
    4833             :       }
    4834             : 
    4835       34138 :       if (continue_chatting && any_loaded_file_changed(csp))
    4836             :       {
    4837           0 :          continue_chatting = 0;
    4838           0 :          config_file_change_detected = 1;
    4839             :       }
    4840             : #ifdef FEATURE_HTTPS_INSPECTION
    4841       34138 :       if (continue_chatting && client_use_ssl(csp) &&
    4842        1952 :          csp->ssl_with_client_is_opened == 0)
    4843             :       {
    4844          16 :          continue_chatting = 0;
    4845          16 :          log_error(LOG_LEVEL_CONNECT, "Client socket %d is no longer usable. "
    4846             :             "The TLS session has been terminated.", csp->cfd);
    4847             :       }
    4848             : #endif
    4849             : 
    4850       34138 :       if (continue_chatting)
    4851             :       {
    4852       31620 :          if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
    4853       11533 :             && socket_is_still_alive(csp->cfd))
    4854             :          {
    4855       11226 :             log_error(LOG_LEVEL_CONNECT, "Client request %d has been "
    4856             :                "pipelined on socket %d and the socket is still alive.",
    4857       11226 :                csp->requests_received_total+1, csp->cfd);
    4858       11226 :             prepare_csp_for_next_request(csp);
    4859       11226 :             continue;
    4860             :          }
    4861             : 
    4862       20394 :          if (0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
    4863             :          {
    4864       20394 :             if (csp->server_connection.sfd != JB_INVALID_SOCKET)
    4865             :             {
    4866         247 :                log_error(LOG_LEVEL_CONNECT,
    4867             :                   "Waiting for the next client request on socket %d. "
    4868             :                   "Keeping the server socket %d to %s open.",
    4869             :                   csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
    4870             :             }
    4871             :             else
    4872             :             {
    4873       20147 :                log_error(LOG_LEVEL_CONNECT,
    4874             :                   "Waiting for the next client request on socket %d. "
    4875             :                   "No server socket to keep open.", csp->cfd);
    4876             :             }
    4877             :          }
    4878             : 
    4879       20394 :          if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
    4880       20394 :             && data_is_available(csp->cfd, (int)csp->config->keep_alive_timeout)
    4881       19814 :             && socket_is_still_alive(csp->cfd))
    4882             :          {
    4883       19814 :             log_error(LOG_LEVEL_CONNECT,
    4884             :                "Data arrived in time on client socket %d. Requests so far: %u",
    4885             :                csp->cfd, csp->requests_received_total);
    4886       19814 :               prepare_csp_for_next_request(csp);
    4887             :          }
    4888             :          else
    4889             :          {
    4890             : #ifdef FEATURE_CONNECTION_SHARING
    4891         580 :             if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
    4892           0 :                && (csp->server_connection.sfd != JB_INVALID_SOCKET)
    4893           0 :                && (socket_is_still_alive(csp->server_connection.sfd))
    4894             : #ifdef FEATURE_HTTPS_INSPECTION
    4895           0 :                && !server_use_ssl(csp)
    4896             : #endif
    4897             :                 )
    4898             :             {
    4899           0 :                time_t time_open = time(NULL) - csp->server_connection.timestamp;
    4900             : 
    4901           0 :                if (csp->server_connection.keep_alive_timeout < time_open - (time_t)latency)
    4902             :                {
    4903           0 :                   break;
    4904             :                }
    4905           0 :                remember_connection(&csp->server_connection);
    4906           0 :                csp->server_connection.sfd = JB_INVALID_SOCKET;
    4907           0 :                drain_and_close_socket(csp->cfd);
    4908           0 :                csp->cfd = JB_INVALID_SOCKET;
    4909           0 :                privoxy_mutex_lock(&connection_reuse_mutex);
    4910           0 :                if (!monitor_thread_running)
    4911             :                {
    4912           0 :                   monitor_thread_running = 1;
    4913           0 :                   privoxy_mutex_unlock(&connection_reuse_mutex);
    4914           0 :                   wait_for_alive_connections();
    4915           0 :                   privoxy_mutex_lock(&connection_reuse_mutex);
    4916           0 :                   monitor_thread_running = 0;
    4917             :                }
    4918           0 :                privoxy_mutex_unlock(&connection_reuse_mutex);
    4919             :             }
    4920             : #endif /* def FEATURE_CONNECTION_SHARING */
    4921         580 :             break;
    4922             :          }
    4923             :       }
    4924        2518 :       else if (csp->server_connection.sfd != JB_INVALID_SOCKET)
    4925             :       {
    4926           1 :          log_error(LOG_LEVEL_CONNECT,
    4927             :             "Closing server socket %d connected to %s. Keep-alive: %u. "
    4928             :             "Tainted: %u. Socket alive: %u. Timeout: %u. "
    4929             :             "Configuration file change detected: %u",
    4930             :             csp->server_connection.sfd, csp->server_connection.host,
    4931           1 :             0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
    4932           1 :             0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
    4933             :             socket_is_still_alive(csp->server_connection.sfd),
    4934             :             csp->server_connection.keep_alive_timeout,
    4935             :             config_file_change_detected);
    4936             :       }
    4937       33558 :    } while (continue_chatting);
    4938             : //      return;
    4939             : #else
    4940             :    chat(csp);
    4941             : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
    4942             : 
    4943        3098 :    if (csp->cfd != JB_INVALID_SOCKET)
    4944             :    {
    4945        3098 :       log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. "
    4946             :          "Keep-alive: %u. Socket alive: %u. Data available: %u. "
    4947             :          "Configuration file change detected: %u. Requests received: %u.",
    4948        3098 :          csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE),
    4949             :          socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0),
    4950             :          config_file_change_detected, csp->requests_received_total);
    4951             : #ifdef FEATURE_HTTPS_INSPECTION
    4952        3098 :       close_client_ssl_connection(csp);
    4953             : #endif
    4954        3098 :       drain_and_close_socket(csp->cfd);
    4955             :    }
    4956             : 
    4957        3098 :    if (csp->server_connection.sfd != JB_INVALID_SOCKET)
    4958             :    {
    4959             : #ifdef FEATURE_CONNECTION_SHARING
    4960           2 :       if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
    4961             :       {
    4962           0 :          forget_connection(csp->server_connection.sfd);
    4963             :       }
    4964             : #endif /* def FEATURE_CONNECTION_SHARING */
    4965             : 
    4966             : #ifdef FEATURE_HTTPS_INSPECTION
    4967           2 :       close_server_ssl_connection(csp);
    4968             : #endif /* def FEATURE_HTTPS_INSPECTION */
    4969             : 
    4970           2 :       close_socket(csp->server_connection.sfd);
    4971             :    }
    4972             : 
    4973             : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    4974        3098 :    mark_connection_closed(&csp->server_connection);
    4975             : #endif
    4976             : 
    4977             :    //free_csp_resources(csp); now static
    4978        3098 :    csp->flags &= ~CSP_FLAG_ACTIVE;
    4979             : 
    4980        3098 : }
    4981             : 
    4982             : 
    4983             : #ifdef __BEOS__
    4984             : /*********************************************************************
    4985             :  *
    4986             :  * Function    :  server_thread
    4987             :  *
    4988             :  * Description :  We only exist to call `serve' in a threaded environment.
    4989             :  *
    4990             :  * Parameters  :
    4991             :  *          1  :  data = Current client state (buffers, headers, etc...)
    4992             :  *
    4993             :  * Returns     :  Always 0.
    4994             :  *
    4995             :  *********************************************************************/
    4996             : static int32 server_thread(void *data)
    4997             : {
    4998             :    serve((struct client_state *) data);
    4999             :    return 0;
    5000             : 
    5001             : }
    5002             : #endif
    5003             : 
    5004             : 
    5005             : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
    5006             : /*********************************************************************
    5007             :  *
    5008             :  * Function    :  usage
    5009             :  *
    5010             :  * Description :  Print usage info & exit.
    5011             :  *
    5012             :  * Parameters  :  Pointer to argv[0] for identifying ourselves
    5013             :  *
    5014             :  * Returns     :  No. ,-)
    5015             :  *
    5016             :  *********************************************************************/
    5017           0 : static void usage(const char *name)
    5018             : {
    5019           0 :    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
    5020             :           "Usage: %s [--config-test] "
    5021             : #if defined(unix)
    5022             :           "[--chroot] "
    5023             : #endif /* defined(unix) */
    5024             :           "[--help] "
    5025             : #if defined(unix)
    5026             :           "[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
    5027             : #endif /* defined(unix) */
    5028             :          "[--version] [configfile]\n",
    5029             :           name);
    5030             : 
    5031             : #ifdef FUZZ
    5032           0 :    show_fuzz_usage(name);
    5033             : #endif
    5034             : 
    5035           0 :    printf("Aborting\n");
    5036             : 
    5037           0 :    exit(2);
    5038             : 
    5039             : }
    5040             : #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */
    5041             : 
    5042             : 
    5043             : #ifdef MUTEX_LOCKS_AVAILABLE
    5044             : /*********************************************************************
    5045             :  *
    5046             :  * Function    :  privoxy_mutex_lock
    5047             :  *
    5048             :  * Description :  Locks a mutex.
    5049             :  *
    5050             :  * Parameters  :
    5051             :  *          1  :  mutex = The mutex to lock.
    5052             :  *
    5053             :  * Returns     :  Void. May exit in case of errors.
    5054             :  *
    5055             :  *********************************************************************/
    5056     4074961 : void privoxy_mutex_lock(privoxy_mutex_t *mutex)
    5057             : {
    5058             : #ifdef FEATURE_PTHREAD
    5059     4074961 :    int err = pthread_mutex_lock(mutex);
    5060     4074961 :    if (err)
    5061             :    {
    5062           0 :       if (mutex != &log_mutex)
    5063             :       {
    5064           0 :          log_error(LOG_LEVEL_FATAL,
    5065             :             "Mutex locking failed: %s.\n", strerror(err));
    5066             :       }
    5067           0 :       exit(1);
    5068             :    }
    5069             : #else
    5070             :    EnterCriticalSection(mutex);
    5071             : #endif /* def FEATURE_PTHREAD */
    5072     4074961 : }
    5073             : 
    5074             : 
    5075             : /*********************************************************************
    5076             :  *
    5077             :  * Function    :  privoxy_mutex_unlock
    5078             :  *
    5079             :  * Description :  Unlocks a mutex.
    5080             :  *
    5081             :  * Parameters  :
    5082             :  *          1  :  mutex = The mutex to unlock.
    5083             :  *
    5084             :  * Returns     :  Void. May exit in case of errors.
    5085             :  *
    5086             :  *********************************************************************/
    5087     4074961 : void privoxy_mutex_unlock(privoxy_mutex_t *mutex)
    5088             : {
    5089             : #ifdef FEATURE_PTHREAD
    5090     4074961 :    int err = pthread_mutex_unlock(mutex);
    5091     4074961 :    if (err)
    5092             :    {
    5093           0 :       if (mutex != &log_mutex)
    5094             :       {
    5095           0 :          log_error(LOG_LEVEL_FATAL,
    5096             :             "Mutex unlocking failed: %s.\n", strerror(err));
    5097             :       }
    5098           0 :       exit(1);
    5099             :    }
    5100             : #else
    5101             :    LeaveCriticalSection(mutex);
    5102             : #endif /* def FEATURE_PTHREAD */
    5103     4074961 : }
    5104             : 
    5105             : 
    5106             : /*********************************************************************
    5107             :  *
    5108             :  * Function    :  privoxy_mutex_init
    5109             :  *
    5110             :  * Description :  Prepares a mutex.
    5111             :  *
    5112             :  * Parameters  :
    5113             :  *          1  :  mutex = The mutex to initialize.
    5114             :  *
    5115             :  * Returns     :  Void. May exit in case of errors.
    5116             :  *
    5117             :  *********************************************************************/
    5118       27882 : static void privoxy_mutex_init(privoxy_mutex_t *mutex)
    5119             : {
    5120             : #ifdef FEATURE_PTHREAD
    5121       27882 :    int err = pthread_mutex_init(mutex, 0);
    5122       27882 :    if (err)
    5123             :    {
    5124           0 :       printf("Fatal error. Mutex initialization failed: %s.\n",
    5125             :          strerror(err));
    5126           0 :       exit(1);
    5127             :    }
    5128             : #else
    5129             :    InitializeCriticalSection(mutex);
    5130             : #endif /* def FEATURE_PTHREAD */
    5131       27882 : }
    5132             : #endif /* def MUTEX_LOCKS_AVAILABLE */
    5133             : 
    5134             : /*********************************************************************
    5135             :  *
    5136             :  * Function    :  initialize_mutexes
    5137             :  *
    5138             :  * Description :  Prepares mutexes if mutex support is available.
    5139             :  *
    5140             :  * Parameters  :  None
    5141             :  *
    5142             :  * Returns     :  Void, exits in case of errors.
    5143             :  *
    5144             :  *********************************************************************/
    5145        3098 : static void initialize_mutexes(void)
    5146             : {
    5147             : #ifdef MUTEX_LOCKS_AVAILABLE
    5148             :    /*
    5149             :     * Prepare global mutex semaphores
    5150             :     */
    5151             : 
    5152             : #ifdef FEATURE_HTTPS_INSPECTION
    5153        3098 :    privoxy_mutex_init(&certificate_mutex);
    5154        3098 :    privoxy_mutex_init(&ssl_init_mutex);
    5155             : #endif
    5156             : 
    5157        3098 :    privoxy_mutex_init(&log_mutex);
    5158        3098 :    privoxy_mutex_init(&log_init_mutex);
    5159        3098 :    privoxy_mutex_init(&connection_reuse_mutex);
    5160             : #ifdef FEATURE_EXTERNAL_FILTERS
    5161        3098 :    privoxy_mutex_init(&external_filter_mutex);
    5162             : #endif
    5163             : #ifdef FEATURE_CLIENT_TAGS
    5164        3098 :    privoxy_mutex_init(&client_tags_mutex);
    5165             : #endif
    5166             : #ifdef FEATURE_EXTENDED_STATISTICS
    5167        3098 :    privoxy_mutex_init(&filter_statistics_mutex);
    5168        3098 :    privoxy_mutex_init(&block_statistics_mutex);
    5169             : #endif
    5170             : 
    5171             :    /*
    5172             :     * XXX: The assumptions below are a bit naive
    5173             :     * and can cause locks that aren't necessary.
    5174             :     *
    5175             :     * For example older FreeBSD versions (< 6.x?)
    5176             :     * have no gethostbyname_r, but gethostbyname is
    5177             :     * thread safe.
    5178             :     */
    5179             : #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
    5180             :    privoxy_mutex_init(&resolver_mutex);
    5181             : #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
    5182             :    /*
    5183             :     * XXX: should we use a single mutex for
    5184             :     * localtime() and gmtime() as well?
    5185             :     */
    5186             : #ifndef HAVE_GMTIME_R
    5187             :    privoxy_mutex_init(&gmtime_mutex);
    5188             : #endif /* ndef HAVE_GMTIME_R */
    5189             : 
    5190             : #ifndef HAVE_LOCALTIME_R
    5191             :    privoxy_mutex_init(&localtime_mutex);
    5192             : #endif /* ndef HAVE_GMTIME_R */
    5193             : 
    5194             : #if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
    5195             :    privoxy_mutex_init(&rand_mutex);
    5196             : #endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
    5197             : 
    5198             : #endif /* def MUTEX_LOCKS_AVAILABLE */
    5199        3098 : }
    5200             : 
    5201             : /*********************************************************************
    5202             :  *
    5203             :  * Function    :  main
    5204             :  *
    5205             :  * Description :  Load the config file and start the listen loop.
    5206             :  *                This function is a lot more *sane* with the `load_config'
    5207             :  *                and `listen_loop' functions; although it stills does
    5208             :  *                a *little* too much for my taste.
    5209             :  *
    5210             :  * Parameters  :
    5211             :  *          1  :  argc = Number of parameters (including $0).
    5212             :  *          2  :  argv = Array of (char *)'s to the parameters.
    5213             :  *
    5214             :  * Returns     :  1 if : can't open config file, unrecognized directive,
    5215             :  *                stats requested in multi-thread mode, can't open the
    5216             :  *                log file, can't open the jar file, listen port is invalid,
    5217             :  *                any load fails, and can't bind port.
    5218             :  *
    5219             :  *                Else main never returns, the process must be signaled
    5220             :  *                to terminate execution.  Or, on Windows, use the
    5221             :  *                "File", "Exit" menu option.
    5222             :  *
    5223             :  *********************************************************************/
    5224             : #ifdef __MINGW32__
    5225             : int real_main(int argc, char **argv)
    5226             : #else
    5227        3098 : int main(int argc, char **argv)
    5228             : #endif
    5229             : {
    5230             : 
    5231             : 
    5232        3098 :    int argc_pos = 0;
    5233        3098 :    int do_config_test = 0;
    5234             : #ifndef HAVE_ARC4RANDOM
    5235             :    unsigned int random_seed;
    5236             : #endif
    5237             : #ifdef unix
    5238        3098 :    struct passwd *pw = NULL;
    5239        3098 :    struct group *grp = NULL;
    5240        3098 :    int do_chroot = 0;
    5241        3098 :    char *pre_chroot_nslookup_to_load_resolver = NULL;
    5242             : #endif
    5243             : #ifdef FUZZ
    5244        3098 :    char *fuzz_input_type = NULL;
    5245        3098 :    char *fuzz_input_file = NULL;
    5246             : #endif
    5247             : 
    5248        3098 :    Argc = argc;
    5249        3098 :    Argv = argv;
    5250             : 
    5251        3098 :    configfile =
    5252             : #if !defined(_WIN32)
    5253             :    "config"
    5254             : #else
    5255             :    "config.txt"
    5256             : #endif
    5257             :       ;
    5258             : 
    5259             : 
    5260             :    /* Prepare mutexes if supported and necessary. */
    5261        3098 :    initialize_mutexes();
    5262             : 
    5263             :    /* Enable logging until further notice. */
    5264        3098 :    init_log_module();
    5265             : 
    5266             :    /*
    5267             :     * Parse the command line arguments
    5268             :     *
    5269             :     * XXX: simply printing usage information in case of
    5270             :     * invalid arguments isn't particularly user friendly.
    5271             :     */
    5272        9294 :    while (++argc_pos < argc)
    5273             :    {
    5274             : #ifdef _WIN32
    5275             :       /* Check to see if the service must be installed or uninstalled */
    5276             :       if (strncmp(argv[argc_pos], "--install", 9) == 0)
    5277             :       {
    5278             :          const char *pName = argv[argc_pos] + 9;
    5279             :          if (*pName == ':')
    5280             :             pName++;
    5281             :          exit((install_service(pName)) ? 0 : 1);
    5282             :       }
    5283             :       else if (strncmp(argv[argc_pos], "--uninstall", 11) == 0)
    5284             :       {
    5285             :          const char *pName = argv[argc_pos] + 11;
    5286             :          if (*pName == ':')
    5287             :             pName++;
    5288             :          exit((uninstall_service(pName)) ? 0 : 1);
    5289             :       }
    5290             :       else if (strcmp(argv[argc_pos], "--service") == 0)
    5291             :       {
    5292             :          bRunAsService = TRUE;
    5293             :          w32_set_service_cwd();
    5294             :          atexit(w32_service_exit_notify);
    5295             :       }
    5296             :       else
    5297             : #endif /* defined(_WIN32) */
    5298             : 
    5299             : 
    5300             : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
    5301             : 
    5302        6196 :       if (strcmp(argv[argc_pos], "--help") == 0)
    5303             :       {
    5304           0 :          usage(argv[0]);
    5305             :       }
    5306             : 
    5307        6196 :       else if (strcmp(argv[argc_pos], "--version") == 0)
    5308             :       {
    5309           0 :          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
    5310           0 :          exit(0);
    5311             :       }
    5312             : 
    5313             : #if defined(unix)
    5314             : 
    5315        6196 :       else if (strcmp(argv[argc_pos], "--no-daemon") == 0)
    5316             :       {
    5317        3098 :          set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
    5318        3098 :          daemon_mode = 0;
    5319             :       }
    5320             : 
    5321        3098 :       else if (strcmp(argv[argc_pos], "--pidfile") == 0)
    5322             :       {
    5323           0 :          if (++argc_pos == argc) usage(argv[0]);
    5324           0 :          pidfile = strdup_or_die(argv[argc_pos]);
    5325             :       }
    5326             : 
    5327        3098 :       else if (strcmp(argv[argc_pos], "--user") == 0)
    5328             :       {
    5329             :          char *user_arg;
    5330             :          char *group_name;
    5331             : 
    5332           0 :          if (++argc_pos == argc) usage(argv[argc_pos]);
    5333             : 
    5334           0 :          user_arg = strdup_or_die(argv[argc_pos]);
    5335           0 :          group_name = strchr(user_arg, '.');
    5336           0 :          if (NULL != group_name)
    5337             :          {
    5338             :             /* Nul-terminate the user name */
    5339           0 :             *group_name = '\0';
    5340             : 
    5341             :             /* Skip the former delimiter to actually reach the group name */
    5342           0 :             group_name++;
    5343             : 
    5344           0 :             grp = getgrnam(group_name);
    5345           0 :             if (NULL == grp)
    5346             :             {
    5347           0 :                log_error(LOG_LEVEL_FATAL, "Group '%s' not found.", group_name);
    5348             :             }
    5349             :          }
    5350           0 :          pw = getpwnam(user_arg);
    5351           0 :          if (NULL == pw)
    5352             :          {
    5353           0 :             log_error(LOG_LEVEL_FATAL, "User '%s' not found.", user_arg);
    5354             :          }
    5355             : 
    5356           0 :          freez(user_arg);
    5357             :       }
    5358             : 
    5359        3098 :       else if (strcmp(argv[argc_pos], "--pre-chroot-nslookup") == 0)
    5360             :       {
    5361           0 :          if (++argc_pos == argc) usage(argv[0]);
    5362           0 :          pre_chroot_nslookup_to_load_resolver = strdup_or_die(argv[argc_pos]);
    5363             :       }
    5364             : 
    5365        3098 :       else if (strcmp(argv[argc_pos], "--chroot") == 0)
    5366             :       {
    5367           0 :          do_chroot = 1;
    5368             :       }
    5369             : #endif /* defined(unix) */
    5370             : 
    5371        3098 :       else if (strcmp(argv[argc_pos], "--config-test") == 0)
    5372             :       {
    5373           0 :          do_config_test = 1;
    5374             :       }
    5375             : #ifdef FUZZ
    5376        3098 :       else if (strcmp(argv[argc_pos], "--fuzz") == 0)
    5377             :       {
    5378        3098 :          argc_pos++;
    5379        3098 :          if (argc < argc_pos + 2) usage(argv[0]);
    5380        3098 :          fuzz_input_type = argv[argc_pos];
    5381        3098 :          argc_pos++;
    5382        3098 :          fuzz_input_file = argv[argc_pos];
    5383             :       }
    5384           0 :       else if (strcmp(argv[argc_pos], "--stfu") == 0)
    5385             :       {
    5386           0 :          set_debug_level(LOG_LEVEL_STFU);
    5387             :       }
    5388             : #endif
    5389           0 :       else if (argc_pos + 1 != argc)
    5390             :       {
    5391             :          /*
    5392             :           * This is neither the last command line
    5393             :           * option, nor was it recognized before,
    5394             :           * therefore it must be invalid.
    5395             :           */
    5396           0 :          usage(argv[0]);
    5397             :       }
    5398             :       else
    5399             : 
    5400             : #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
    5401             :       {
    5402           0 :          configfile = argv[argc_pos];
    5403             :       }
    5404             : 
    5405             :    } /* -END- while (more arguments) */
    5406             : 
    5407        3098 :    show_version(Argv[0]);
    5408             : 
    5409             : #if defined(unix)
    5410        3098 :    if (*configfile != '/')
    5411             :    {
    5412             :       char cwd[BUFFER_SIZE];
    5413             :       char *abs_file;
    5414             :       size_t abs_file_size;
    5415             : 
    5416             :       /* make config-filename absolute here */
    5417        3098 :       if (NULL == getcwd(cwd, sizeof(cwd)))
    5418             :       {
    5419           0 :          perror("failed to get current working directory");
    5420           0 :          exit(1);
    5421             :       }
    5422             : 
    5423        3098 :       basedir = strdup_or_die(cwd);
    5424             :       /* XXX: why + 5? */
    5425        3098 :       abs_file_size = strlen(cwd) + strlen(configfile) + 5;
    5426        3098 :       abs_file = malloc_or_die(abs_file_size);
    5427        3098 :       strlcpy(abs_file, basedir, abs_file_size);
    5428        3098 :       strlcat(abs_file, "/", abs_file_size);
    5429        3098 :       strlcat(abs_file, configfile, abs_file_size);
    5430        3098 :       configfile = abs_file;
    5431             :    }
    5432             : #endif /* defined unix */
    5433             : 
    5434             : 
    5435        3098 :    files->next = NULL;
    5436        3098 :    clients->next = NULL;
    5437             : 
    5438             :    /* XXX: factor out initialising after the next stable release. */
    5439             : #ifdef _WIN32
    5440             :    InitWin32();
    5441             : #endif
    5442             : 
    5443             : #ifndef HAVE_ARC4RANDOM
    5444        3098 :    random_seed = (unsigned int)time(NULL);
    5445             : #ifdef HAVE_RANDOM
    5446        3098 :    srandom(random_seed);
    5447             : #else
    5448             :    srand(random_seed);
    5449             : #endif /* ifdef HAVE_RANDOM */
    5450             : #endif /* ifndef HAVE_ARC4RANDOM */
    5451             : 
    5452             :    /*
    5453             :     * Unix signal handling
    5454             :     *
    5455             :     * Catch the abort, interrupt and terminate signals for a graceful exit
    5456             :     * Catch the hangup signal so the errlog can be reopened.
    5457             :     *
    5458             :     * Ignore the broken pipe signal as connection failures
    5459             :     * are handled when and where they occur without relying
    5460             :     * on a signal.
    5461             :     */
    5462             : #if !defined(_WIN32)
    5463             : {
    5464             :    int idx;
    5465        3098 :    const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP };
    5466             : 
    5467       12392 :    for (idx = 0; idx < SZ(catched_signals); idx++)
    5468             :    {
    5469             : #ifdef sun /* FIXME: Is it safe to check for HAVE_SIGSET instead? */
    5470             :       if (sigset(catched_signals[idx], sig_handler) == SIG_ERR)
    5471             : #else
    5472        9294 :       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
    5473             : #endif /* ifdef sun */
    5474             :       {
    5475           0 :          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
    5476             :       }
    5477             :    }
    5478             : 
    5479        3098 :    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
    5480             :    {
    5481           0 :       log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for SIGPIPE: %E");
    5482             :    }
    5483             : 
    5484             : }
    5485             : #else /* ifdef _WIN32 */
    5486             : # ifdef _WIN_CONSOLE
    5487             :    /*
    5488             :     * We *are* in a windows console app.
    5489             :     * Print a verbose messages about FAQ's and such
    5490             :     */
    5491             :    printf("%s", win32_blurb);
    5492             : # endif /* def _WIN_CONSOLE */
    5493             : #endif /* def _WIN32 */
    5494             : 
    5495             : #ifdef FUZZ
    5496        3098 :    if (fuzz_input_type != NULL)
    5497             :    {
    5498        3098 :       process_fuzzed_input(fuzz_input_type, fuzz_input_file);
    5499        3098 :                 exit(0);
    5500             :         }
    5501           0 :    log_error(LOG_LEVEL_FATAL,
    5502             :       "When compiled with fuzzing support, Privoxy should only be used for fuzzing. "
    5503             :       "Various data structures are static which is unsafe when using threads.");
    5504             : #endif
    5505             : 
    5506           0 :    if (do_config_test)
    5507             :    {
    5508           0 :       exit(NULL == load_config());
    5509             :    }
    5510             : 
    5511             :    /* Initialize the CGI subsystem */
    5512           0 :    cgi_init_error_messages();
    5513             : 
    5514             :    /*
    5515             :     * If running on unix and without the --no-daemon
    5516             :     * option, become a daemon. I.e. fork, detach
    5517             :     * from tty and get process group leadership
    5518             :     */
    5519             : #if defined(unix)
    5520             : {
    5521           0 :    if (daemon_mode)
    5522             :    {
    5523             :       int fd;
    5524           0 :       pid_t pid = fork();
    5525             : 
    5526           0 :       if (pid < 0) /* error */
    5527             :       {
    5528           0 :          perror("fork");
    5529           0 :          exit(3);
    5530             :       }
    5531           0 :       else if (pid != 0) /* parent */
    5532             :       {
    5533             :          int status;
    5534             :          pid_t wpid;
    5535             :          /*
    5536             :           * must check for errors
    5537             :           * child died due to missing files aso
    5538             :           */
    5539           0 :          sleep(1);
    5540           0 :          wpid = waitpid(pid, &status, WNOHANG);
    5541           0 :          if (wpid != 0)
    5542             :          {
    5543           0 :             exit(1);
    5544             :          }
    5545           0 :          exit(0);
    5546             :       }
    5547             :       /* child */
    5548             : 
    5549           0 :       setsid();
    5550             : 
    5551             :       /*
    5552             :        * stderr (fd 2) will be closed later on,
    5553             :        * when the config file has been parsed.
    5554             :        */
    5555           0 :       close(0);
    5556           0 :       close(1);
    5557             : 
    5558             :       /*
    5559             :        * Reserve fd 0 and 1 to prevent abort() and friends
    5560             :        * from sending stuff to the clients or servers.
    5561             :        */
    5562           0 :       fd = open("/dev/null", O_RDONLY);
    5563           0 :       if (fd == -1)
    5564             :       {
    5565           0 :          log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
    5566             :       }
    5567           0 :       else if (fd != 0)
    5568             :       {
    5569           0 :          if (dup2(fd, 0) == -1)
    5570             :          {
    5571           0 :             log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 0: %E");
    5572             :          }
    5573           0 :          close(fd);
    5574             :       }
    5575           0 :       fd = open("/dev/null", O_WRONLY);
    5576           0 :       if (fd == -1)
    5577             :       {
    5578           0 :          log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
    5579             :       }
    5580           0 :       else if (fd != 1)
    5581             :       {
    5582           0 :          if (dup2(fd, 1) == -1)
    5583             :          {
    5584           0 :             log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 1: %E");
    5585             :          }
    5586           0 :          close(fd);
    5587             :       }
    5588             : 
    5589             : #ifdef FEATURE_EXTERNAL_FILTERS
    5590           0 :       for (fd = 0; fd < 3; fd++)
    5591             :       {
    5592           0 :          mark_socket_for_close_on_execute(fd);
    5593             :       }
    5594             : #endif
    5595             : 
    5596           0 :       if (chdir("/") != 0)
    5597             :       {
    5598           0 :          log_error(LOG_LEVEL_FATAL, "Failed to cd into '/': %E");
    5599             :       }
    5600             : 
    5601             :    } /* -END- if (daemon_mode) */
    5602             : 
    5603             :    /*
    5604             :     * As soon as we have written the PID file, we can switch
    5605             :     * to the user and group ID indicated by the --user option
    5606             :     */
    5607           0 :    if (pidfile != NULL)
    5608             :    {
    5609           0 :       write_pid_file(pidfile);
    5610             :    }
    5611           0 :    if (NULL != pw)
    5612             :    {
    5613           0 :       if (setgid((NULL != grp) ? grp->gr_gid : pw->pw_gid))
    5614             :       {
    5615           0 :          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
    5616             :       }
    5617           0 :       if (NULL != grp)
    5618             :       {
    5619           0 :          if (setgroups(1, &grp->gr_gid))
    5620             :          {
    5621           0 :             log_error(LOG_LEVEL_FATAL, "setgroups() failed: %E");
    5622             :          }
    5623             :       }
    5624           0 :       else if (initgroups(pw->pw_name, pw->pw_gid))
    5625             :       {
    5626           0 :          log_error(LOG_LEVEL_FATAL, "initgroups() failed: %E");
    5627             :       }
    5628           0 :       if (do_chroot)
    5629             :       {
    5630           0 :          if (!pw->pw_dir)
    5631             :          {
    5632           0 :             log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
    5633             :          }
    5634             :          /* Read the time zone file from /etc before doing chroot. */
    5635           0 :          tzset();
    5636           0 :          if (NULL != pre_chroot_nslookup_to_load_resolver
    5637           0 :              && '\0' != pre_chroot_nslookup_to_load_resolver[0])
    5638             :          {
    5639             :             /* Initialize resolver library. */
    5640           0 :             (void) resolve_hostname_to_ip(pre_chroot_nslookup_to_load_resolver);
    5641             :          }
    5642           0 :          if (chroot(pw->pw_dir) < 0)
    5643             :          {
    5644           0 :             log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
    5645             :          }
    5646           0 :          if (chdir ("/"))
    5647             :          {
    5648           0 :             log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
    5649             :          }
    5650             :       }
    5651           0 :       if (setuid(pw->pw_uid))
    5652             :       {
    5653           0 :          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
    5654             :       }
    5655           0 :       if (do_chroot)
    5656             :       {
    5657             :          char putenv_dummy[64];
    5658             : 
    5659           0 :          strlcpy(putenv_dummy, "HOME=/", sizeof(putenv_dummy));
    5660           0 :          if (putenv(putenv_dummy) != 0)
    5661             :          {
    5662           0 :             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
    5663             :          }
    5664             : 
    5665           0 :          snprintf(putenv_dummy, sizeof(putenv_dummy), "USER=%s", pw->pw_name);
    5666           0 :          if (putenv(putenv_dummy) != 0)
    5667             :          {
    5668           0 :             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
    5669             :          }
    5670             :       }
    5671             :    }
    5672           0 :    else if (do_chroot)
    5673             :    {
    5674           0 :       log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
    5675             :    }
    5676             : }
    5677             : #endif /* defined unix */
    5678             : 
    5679             : #ifdef _WIN32
    5680             :    /* This will be FALSE unless the command line specified --service
    5681             :     */
    5682             :    if (bRunAsService)
    5683             :    {
    5684             :       /* Yup, so now we must attempt to establish a connection
    5685             :        * with the service dispatcher. This will only work if this
    5686             :        * process was launched by the service control manager to
    5687             :        * actually run as a service. If this isn't the case, i've
    5688             :        * known it take around 30 seconds or so for the call to return.
    5689             :        */
    5690             : 
    5691             :       /* The StartServiceCtrlDispatcher won't return until the service is stopping */
    5692             :       if (w32_start_service_ctrl_dispatcher(w32ServiceDispatchTable))
    5693             :       {
    5694             :          /* Service has run, and at this point is now being stopped, so just return */
    5695             :          return 0;
    5696             :       }
    5697             : 
    5698             : #ifdef _WIN_CONSOLE
    5699             :       printf("Warning: Failed to connect to Service Control Dispatcher\nwhen starting as a service!\n");
    5700             : #endif
    5701             :       /* An error occurred. Usually it's because --service was wrongly specified
    5702             :        * and we were unable to connect to the Service Control Dispatcher because
    5703             :        * it wasn't expecting us and is therefore not listening.
    5704             :        *
    5705             :        * For now, just continue below to call the listen_loop function.
    5706             :        */
    5707             :    }
    5708             : #endif /* def _WIN32 */
    5709             : 
    5710           0 :    listen_loop();
    5711             : 
    5712             :    /* NOTREACHED */
    5713           0 :    return(-1);
    5714             : 
    5715             : }
    5716             : 
    5717             : 
    5718             : /*********************************************************************
    5719             :  *
    5720             :  * Function    :  bind_port_helper
    5721             :  *
    5722             :  * Description :  Bind the listen port.  Handles logging, and aborts
    5723             :  *                on failure.
    5724             :  *
    5725             :  * Parameters  :
    5726             :  *          1  :  haddr = Host address to bind to. Use NULL to bind to
    5727             :  *                        INADDR_ANY.
    5728             :  *          2  :  hport = Specifies port to bind to.
    5729             :  *          3  :  backlog = Listen backlog.
    5730             :  *
    5731             :  * Returns     :  Port that was opened.
    5732             :  *
    5733             :  *********************************************************************/
    5734           0 : static jb_socket bind_port_helper(const char *haddr, int hport, int backlog)
    5735             : {
    5736             :    int result;
    5737             :    jb_socket bfd;
    5738             : 
    5739           0 :    result = bind_port(haddr, hport, backlog, &bfd);
    5740             : 
    5741           0 :    if (result < 0)
    5742             :    {
    5743           0 :       const char *bind_address = (NULL != haddr) ? haddr : "INADDR_ANY";
    5744           0 :       switch(result)
    5745             :       {
    5746           0 :          case -3:
    5747           0 :             log_error(LOG_LEVEL_FATAL,
    5748             :                "can't bind to %s:%d: There may be another Privoxy "
    5749             :                "or some other proxy running on port %d",
    5750             :                bind_address, hport, hport);
    5751             : 
    5752           0 :          case -2:
    5753           0 :             log_error(LOG_LEVEL_FATAL,
    5754             :                "can't bind to %s:%d: The hostname is not resolvable",
    5755             :                bind_address, hport);
    5756             : 
    5757           0 :          default:
    5758           0 :             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: %E",
    5759             :                bind_address, hport);
    5760             :       }
    5761             : 
    5762             :       /* shouldn't get here */
    5763           0 :       return JB_INVALID_SOCKET;
    5764             :    }
    5765             : 
    5766             : #ifndef HAVE_POLL
    5767             : #ifndef _WIN32
    5768             :    if (bfd >= FD_SETSIZE)
    5769             :    {
    5770             :       log_error(LOG_LEVEL_FATAL,
    5771             :          "Bind socket number too high to use select(): %d >= %d",
    5772             :          bfd, FD_SETSIZE);
    5773             :    }
    5774             : #endif
    5775             : #endif
    5776             : 
    5777           0 :    if (haddr == NULL)
    5778             :    {
    5779           0 :       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
    5780             :          hport);
    5781             :    }
    5782             :    else
    5783             :    {
    5784           0 :       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
    5785             :          hport, haddr);
    5786             :    }
    5787             : 
    5788           0 :    return bfd;
    5789             : }
    5790             : 
    5791             : 
    5792             : /*********************************************************************
    5793             :  *
    5794             :  * Function    :  bind_ports_helper
    5795             :  *
    5796             :  * Description :  Bind the listen ports.  Handles logging, and aborts
    5797             :  *                on failure.
    5798             :  *
    5799             :  * Parameters  :
    5800             :  *          1  :  config = Privoxy configuration.  Specifies ports
    5801             :  *                         to bind to.
    5802             :  *          2  :  sockets = Preallocated array of opened sockets
    5803             :  *                          corresponding to specification in config.
    5804             :  *                          All non-opened sockets will be set to
    5805             :  *                          JB_INVALID_SOCKET.
    5806             :  *
    5807             :  * Returns     :  Nothing. Inspect sockets argument.
    5808             :  *
    5809             :  *********************************************************************/
    5810           0 : static void bind_ports_helper(struct configuration_spec * config,
    5811             :                               jb_socket sockets[])
    5812             : {
    5813             :    int i;
    5814             : 
    5815           0 :    for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
    5816             :    {
    5817           0 :       if (config->hport[i])
    5818             :       {
    5819           0 :          sockets[i] = bind_port_helper(config->haddr[i],
    5820             :             config->hport[i], config->listen_backlog);
    5821             : #if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER)
    5822             :          if (config->enable_accept_filter && sockets[i] != JB_INVALID_SOCKET)
    5823             :          {
    5824             :             struct accept_filter_arg af_options;
    5825             :             bzero(&af_options, sizeof(af_options));
    5826             :             strlcpy(af_options.af_name, "httpready", sizeof(af_options.af_name));
    5827             :             if (setsockopt(sockets[i], SOL_SOCKET, SO_ACCEPTFILTER, &af_options,
    5828             :                   sizeof(af_options)))
    5829             :             {
    5830             :                log_error(LOG_LEVEL_ERROR,
    5831             :                   "Enabling accept filter for socket %d failed: %E", sockets[i]);
    5832             :             }
    5833             :          }
    5834             : #endif
    5835             :       }
    5836             :       else
    5837             :       {
    5838           0 :          sockets[i] = JB_INVALID_SOCKET;
    5839             :       }
    5840             :    }
    5841           0 :    config->need_bind = 0;
    5842           0 : }
    5843             : 
    5844             : 
    5845             : /*********************************************************************
    5846             :  *
    5847             :  * Function    :  close_ports_helper
    5848             :  *
    5849             :  * Description :  Close listenings ports.
    5850             :  *
    5851             :  * Parameters  :
    5852             :  *          1  :  sockets = Array of opened and non-opened sockets to
    5853             :  *                          close. All sockets will be set to
    5854             :  *                          JB_INVALID_SOCKET.
    5855             :  *
    5856             :  * Returns     :  Nothing.
    5857             :  *
    5858             :  *********************************************************************/
    5859           0 : static void close_ports_helper(jb_socket sockets[])
    5860             : {
    5861             :    int i;
    5862             : 
    5863           0 :    for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
    5864             :    {
    5865           0 :       if (JB_INVALID_SOCKET != sockets[i])
    5866             :       {
    5867           0 :          close_socket(sockets[i]);
    5868             :       }
    5869           0 :       sockets[i] = JB_INVALID_SOCKET;
    5870             :    }
    5871           0 : }
    5872             : 
    5873             : 
    5874             : #ifdef _WIN32
    5875             : /* Without this simple workaround we get this compiler warning from _beginthread
    5876             :  *     warning C4028: formal parameter 1 different from declaration
    5877             :  */
    5878             : void w32_service_listen_loop(void *p)
    5879             : {
    5880             :    listen_loop();
    5881             : }
    5882             : #endif /* def _WIN32 */
    5883             : 
    5884             : 
    5885             : /*********************************************************************
    5886             :  *
    5887             :  * Function    :  listen_loop
    5888             :  *
    5889             :  * Description :  bind the listen port and enter a "FOREVER" listening loop.
    5890             :  *
    5891             :  * Parameters  :  N/A
    5892             :  *
    5893             :  * Returns     :  Never.
    5894             :  *
    5895             :  *********************************************************************/
    5896           0 : static void listen_loop(void)
    5897             : {
    5898           0 :    struct client_states *csp_list = NULL;
    5899           0 :    struct client_state *csp = NULL;
    5900             :    jb_socket bfds[MAX_LISTENING_SOCKETS];
    5901             :    struct configuration_spec *config;
    5902           0 :    unsigned int active_threads = 0;
    5903             : #if defined(FEATURE_PTHREAD)
    5904             :    pthread_attr_t attrs;
    5905             : 
    5906           0 :    pthread_attr_init(&attrs);
    5907           0 :    pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
    5908             : #endif
    5909             : 
    5910           0 :    config = load_config();
    5911             : 
    5912             : #ifdef FEATURE_CONNECTION_SHARING
    5913             :    /*
    5914             :     * XXX: Should be relocated once it no
    5915             :     * longer needs to emit log messages.
    5916             :     */
    5917           0 :    initialize_reusable_connections();
    5918             : #endif /* def FEATURE_CONNECTION_SHARING */
    5919             : 
    5920           0 :    bind_ports_helper(config, bfds);
    5921             : 
    5922             : #ifdef FEATURE_GRACEFUL_TERMINATION
    5923             :    while (!g_terminate)
    5924             : #else
    5925             :    for (;;)
    5926             : #endif
    5927             :    {
    5928             : #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__)
    5929             :       while (waitpid(-1, NULL, WNOHANG) > 0)
    5930             :       {
    5931             :          /* zombie children */
    5932             :       }
    5933             : #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) */
    5934             : 
    5935             :       /*
    5936             :        * Free data that was used by died threads
    5937             :        */
    5938           0 :       active_threads = sweep();
    5939             : 
    5940             : #if defined(unix)
    5941             :       /*
    5942             :        * Re-open the errlog after HUP signal
    5943             :        */
    5944           0 :       if (received_hup_signal)
    5945             :       {
    5946           0 :          if (NULL != config->logfile)
    5947             :          {
    5948           0 :             init_error_log(Argv[0], config->logfile);
    5949             :          }
    5950           0 :          received_hup_signal = 0;
    5951             :       }
    5952             : #endif
    5953             : 
    5954           0 :       csp_list = zalloc_or_die(sizeof(*csp_list));
    5955           0 :       csp = &csp_list->csp;
    5956             : 
    5957           0 :       log_error(LOG_LEVEL_CONNECT,
    5958             :          "Waiting for the next client connection. Currently active threads: %u",
    5959             :          active_threads);
    5960             : 
    5961             :       /*
    5962             :        * This config may be outdated, but for accept_connection()
    5963             :        * it's fresh enough.
    5964             :        */
    5965           0 :       csp->config = config;
    5966             : 
    5967           0 :       if (!accept_connection(csp, bfds))
    5968             :       {
    5969           0 :          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
    5970           0 :          freez(csp_list);
    5971           0 :          continue;
    5972             :       }
    5973             : 
    5974           0 :       csp->flags |= CSP_FLAG_ACTIVE;
    5975           0 :       csp->server_connection.sfd = JB_INVALID_SOCKET;
    5976             : 
    5977           0 :       csp->config = config = load_config();
    5978             : 
    5979           0 :       if (config->need_bind)
    5980             :       {
    5981             :          /*
    5982             :           * Since we were listening to the "old port", we will not see
    5983             :           * a "listen" param change until the next request.  So, at
    5984             :           * least 1 more request must be made for us to find the new
    5985             :           * setting.  I am simply closing the old socket and binding the
    5986             :           * new one.
    5987             :           *
    5988             :           * Which-ever is correct, we will serve 1 more page via the
    5989             :           * old settings.  This should probably be a "show-status"
    5990             :           * request.  This should not be a so common of an operation
    5991             :           * that this will hurt people's feelings.
    5992             :           */
    5993             : 
    5994           0 :          close_ports_helper(bfds);
    5995             : 
    5996           0 :          bind_ports_helper(config, bfds);
    5997             :       }
    5998             : 
    5999             : #ifdef FEATURE_TOGGLE
    6000           0 :       if (global_toggle_state)
    6001             : #endif /* def FEATURE_TOGGLE */
    6002             :       {
    6003           0 :          csp->flags |= CSP_FLAG_TOGGLED_ON;
    6004             :       }
    6005             : 
    6006           0 :       if (run_loader(csp))
    6007             :       {
    6008           0 :          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
    6009             :          /* Never get here - LOG_LEVEL_FATAL causes program exit */
    6010             :       }
    6011             : 
    6012             : #ifdef FEATURE_ACL
    6013           0 :       if (block_acl(NULL,csp))
    6014             :       {
    6015           0 :          log_error(LOG_LEVEL_CONNECT,
    6016             :             "Connection from %s on %s (socket %d) dropped due to ACL",
    6017             :             csp->ip_addr_str, csp->listen_addr_str, csp->cfd);
    6018           0 :          close_socket(csp->cfd);
    6019           0 :          freez(csp->ip_addr_str);
    6020           0 :          freez(csp->listen_addr_str);
    6021           0 :          freez(csp_list);
    6022           0 :          continue;
    6023             :       }
    6024             : #endif /* def FEATURE_ACL */
    6025             : 
    6026           0 :       if ((0 != config->max_client_connections)
    6027           0 :          && (active_threads >= config->max_client_connections))
    6028             :       {
    6029           0 :          log_error(LOG_LEVEL_CONNECT,
    6030             :             "Rejecting connection from %s. Maximum number of connections reached.",
    6031             :             csp->ip_addr_str);
    6032           0 :          write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
    6033             :             strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
    6034           0 :          close_socket(csp->cfd);
    6035           0 :          freez(csp->ip_addr_str);
    6036           0 :          freez(csp->listen_addr_str);
    6037           0 :          freez(csp_list);
    6038           0 :          continue;
    6039             :       }
    6040             : 
    6041             :       /* add it to the list of clients */
    6042           0 :       csp_list->next = clients->next;
    6043           0 :       clients->next = csp_list;
    6044             : 
    6045           0 :       if (config->multi_threaded)
    6046             :       {
    6047             :          int child_id;
    6048             : 
    6049             : /* this is a switch () statement in the C preprocessor - ugh */
    6050             : #undef SELECTED_ONE_OPTION
    6051             : 
    6052             : /* Use Pthreads in preference to native code */
    6053             : #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
    6054             : #define SELECTED_ONE_OPTION
    6055             :          {
    6056             :             pthread_t the_thread;
    6057             :             int ret;
    6058             : 
    6059           0 :             ret = pthread_create(&the_thread, &attrs,
    6060             :                (void * (*)(void *))serve, csp);
    6061           0 :             child_id = ret ? -1 : 0;
    6062             :          }
    6063             : #endif
    6064             : 
    6065             : #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
    6066             : #define SELECTED_ONE_OPTION
    6067             :          child_id = _beginthread(
    6068             :             (void (*)(void *))serve,
    6069             :             64 * 1024,
    6070             :             csp);
    6071             : #endif
    6072             : 
    6073             : #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
    6074             : #define SELECTED_ONE_OPTION
    6075             :          {
    6076             :             thread_id tid = spawn_thread
    6077             :                (server_thread, "server", B_NORMAL_PRIORITY, csp);
    6078             : 
    6079             :             if ((tid >= 0) && (resume_thread(tid) == B_OK))
    6080             :             {
    6081             :                child_id = (int) tid;
    6082             :             }
    6083             :             else
    6084             :             {
    6085             :                child_id = -1;
    6086             :             }
    6087             :          }
    6088             : #endif
    6089             : 
    6090             : #if !defined(SELECTED_ONE_OPTION)
    6091             :          child_id = fork();
    6092             : 
    6093             :          /* This block is only needed when using fork().
    6094             :           * When using threads, the server thread was
    6095             :           * created and run by the call to _beginthread().
    6096             :           */
    6097             :          if (child_id == 0)   /* child */
    6098             :          {
    6099             :             int rc = 0;
    6100             : #ifdef FEATURE_TOGGLE
    6101             :             int inherited_toggle_state = global_toggle_state;
    6102             : #endif /* def FEATURE_TOGGLE */
    6103             : 
    6104             :             serve(csp);
    6105             : 
    6106             :             /*
    6107             :              * If we've been toggled or we've blocked the request, tell Mom
    6108             :              */
    6109             : 
    6110             : #ifdef FEATURE_TOGGLE
    6111             :             if (inherited_toggle_state != global_toggle_state)
    6112             :             {
    6113             :                rc |= RC_FLAG_TOGGLED;
    6114             :             }
    6115             : #endif /* def FEATURE_TOGGLE */
    6116             : 
    6117             : #ifdef FEATURE_STATISTICS
    6118             :             if (csp->flags & CSP_FLAG_REJECTED)
    6119             :             {
    6120             :                rc |= RC_FLAG_BLOCKED;
    6121             :             }
    6122             : #endif /* ndef FEATURE_STATISTICS */
    6123             : 
    6124             :             _exit(rc);
    6125             :          }
    6126             :          else if (child_id > 0) /* parent */
    6127             :          {
    6128             :             /* in a fork()'d environment, the parent's
    6129             :              * copy of the client socket and the CSP
    6130             :              * are not used.
    6131             :              */
    6132             :             int child_status;
    6133             : #if !defined(_WIN32) && !defined(__CYGWIN__)
    6134             : 
    6135             :             wait(&child_status);
    6136             : 
    6137             :             /*
    6138             :              * Evaluate child's return code: If the child has
    6139             :              *  - been toggled, toggle ourselves
    6140             :              *  - blocked its request, bump up the stats counter
    6141             :              */
    6142             : 
    6143             : #ifdef FEATURE_TOGGLE
    6144             :             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
    6145             :             {
    6146             :                global_toggle_state = !global_toggle_state;
    6147             :             }
    6148             : #endif /* def FEATURE_TOGGLE */
    6149             : 
    6150             : #ifdef FEATURE_STATISTICS
    6151             :             urls_read++;
    6152             :             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
    6153             :             {
    6154             :                urls_rejected++;
    6155             :             }
    6156             : #endif /* def FEATURE_STATISTICS */
    6157             : 
    6158             : #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
    6159             :             close_socket(csp->cfd);
    6160             :             csp->flags &= ~CSP_FLAG_ACTIVE;
    6161             :          }
    6162             : #endif
    6163             : 
    6164             : #undef SELECTED_ONE_OPTION
    6165             : /* end of cpp switch () */
    6166             : 
    6167           0 :          if (child_id < 0)
    6168             :          {
    6169             :             /*
    6170             :              * Spawning the child failed, assume it's because
    6171             :              * there are too many children running already.
    6172             :              * XXX: If you assume ...
    6173             :              */
    6174           0 :             log_error(LOG_LEVEL_ERROR,
    6175             :                "Unable to take any additional connections: %E. Active threads: %u",
    6176             :                active_threads);
    6177           0 :             write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
    6178             :                strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
    6179           0 :             close_socket(csp->cfd);
    6180           0 :             csp->flags &= ~CSP_FLAG_ACTIVE;
    6181             :          }
    6182             :       }
    6183             :       else
    6184             :       {
    6185           0 :          serve(csp);
    6186             :       }
    6187             :    }
    6188             : 
    6189             : #if defined(FEATURE_PTHREAD)
    6190             :    pthread_attr_destroy(&attrs);
    6191             : #endif
    6192             : 
    6193             :    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
    6194             : 
    6195             : #ifdef FEATURE_GRACEFUL_TERMINATION
    6196             : 
    6197             :    log_error(LOG_LEVEL_INFO, "Graceful termination requested.");
    6198             : 
    6199             :    unload_current_config_file();
    6200             :    unload_current_actions_file();
    6201             :    unload_current_re_filterfile();
    6202             : #ifdef FEATURE_TRUST
    6203             :    unload_current_trust_file();
    6204             : #endif
    6205             : 
    6206             :    if (config->multi_threaded)
    6207             :    {
    6208             :       int i = 60;
    6209             :       do
    6210             :       {
    6211             :          sleep(1);
    6212             :          sweep();
    6213             :       } while ((clients->next != NULL) && (--i > 0));
    6214             : 
    6215             :       if (i <= 0)
    6216             :       {
    6217             :          log_error(LOG_LEVEL_ERROR, "Graceful termination failed "
    6218             :             "- still some live clients after 1 minute wait.");
    6219             :       }
    6220             :    }
    6221             :    sweep();
    6222             :    sweep();
    6223             : 
    6224             : #if defined(unix)
    6225             :    freez(basedir);
    6226             : #endif
    6227             : 
    6228             : #ifdef FEATURE_HTTPS_INSPECTION
    6229             :    /*
    6230             :     * Only release TLS backed resources if there
    6231             :     * are no active connections left.
    6232             :     */
    6233             :    if (clients->next == NULL)
    6234             :    {
    6235             :       ssl_release();
    6236             :    }
    6237             : #endif
    6238             : 
    6239             :    log_error(LOG_LEVEL_INFO, "Exiting gracefully.");
    6240             : 
    6241             : #if defined(_WIN32) && !defined(_WIN_CONSOLE)
    6242             :    /* Cleanup - remove taskbar icon etc. */
    6243             :    TermLogWindow();
    6244             : #endif
    6245             : 
    6246             :    exit(0);
    6247             : #endif /* FEATURE_GRACEFUL_TERMINATION */
    6248             : 
    6249             : }
    6250             : 
    6251             : 
    6252             : /*
    6253             :   Local Variables:
    6254             :   tab-width: 3
    6255             :   end:
    6256             : */

Generated by: LCOV version 1.14