"Fossies" - the Fresh Open Source Software Archive

Member "privoxy-3.0.26-stable/jcc.c" (25 May 2016, 133878 Bytes) of package /linux/www/privoxy-3.0.26-stable-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "jcc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.0.24-stable-src_vs_3.0.26-stable-src.

    1 const char jcc_rcs[] = "$Id: jcc.c,v 1.446 2016/05/25 10:54:01 fabiankeil Exp $";
    2 /*********************************************************************
    3  *
    4  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
    5  *
    6  * Purpose     :  Main file.  Contains main() method, main loop, and
    7  *                the main connection-handling function.
    8  *
    9  * Copyright   :  Written by and Copyright (C) 2001-2016 the
   10  *                Privoxy team. http://www.privoxy.org/
   11  *
   12  *                Based on the Internet Junkbuster originally written
   13  *                by and Copyright (C) 1997 Anonymous Coders and
   14  *                Junkbusters Corporation.  http://www.junkbusters.com
   15  *
   16  *                This program is free software; you can redistribute it
   17  *                and/or modify it under the terms of the GNU General
   18  *                Public License as published by the Free Software
   19  *                Foundation; either version 2 of the License, or (at
   20  *                your option) any later version.
   21  *
   22  *                This program is distributed in the hope that it will
   23  *                be useful, but WITHOUT ANY WARRANTY; without even the
   24  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
   25  *                PARTICULAR PURPOSE.  See the GNU General Public
   26  *                License for more details.
   27  *
   28  *                The GNU General Public License should be included with
   29  *                this file.  If not, you can view it at
   30  *                http://www.gnu.org/copyleft/gpl.html
   31  *                or write to the Free Software Foundation, Inc., 59
   32  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   33  *
   34  *********************************************************************/
   35 
   36 
   37 #include "config.h"
   38 
   39 #include <stdio.h>
   40 #include <sys/types.h>
   41 #include <stdlib.h>
   42 #include <string.h>
   43 #include <signal.h>
   44 #include <fcntl.h>
   45 #include <errno.h>
   46 #include <assert.h>
   47 
   48 #ifdef _WIN32
   49 # ifndef FEATURE_PTHREAD
   50 #  ifndef STRICT
   51 #   define STRICT
   52 #  endif
   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 # if !defined (__OS2__)
   66 # include <unistd.h>
   67 # include <sys/wait.h>
   68 # endif /* ndef __OS2__ */
   69 # include <sys/time.h>
   70 # include <sys/stat.h>
   71 # include <sys/ioctl.h>
   72 
   73 #ifdef sun
   74 #include <sys/termios.h>
   75 #endif /* sun */
   76 
   77 #ifdef unix
   78 #include <pwd.h>
   79 #include <grp.h>
   80 #endif
   81 
   82 # include <signal.h>
   83 
   84 # ifdef __BEOS__
   85 #  include <socket.h>  /* BeOS has select() for sockets only. */
   86 #  include <OS.h>      /* declarations for threads and stuff. */
   87 # endif
   88 
   89 # if defined(__EMX__) || defined(__OS2__)
   90 #  include <sys/select.h>  /* OS/2/EMX needs a little help with select */
   91 # endif
   92 # ifdef __OS2__
   93 #define INCL_DOS
   94 # include <os2.h>
   95 #define bzero(B,N) memset(B,0x00,n)
   96 # endif
   97 
   98 # ifndef FD_ZERO
   99 #  include <select.h>
  100 # endif
  101 
  102 #endif
  103 
  104 #include "project.h"
  105 #include "list.h"
  106 #include "jcc.h"
  107 #include "filters.h"
  108 #include "loaders.h"
  109 #include "parsers.h"
  110 #include "miscutil.h"
  111 #include "errlog.h"
  112 #include "jbsockets.h"
  113 #include "gateway.h"
  114 #include "actions.h"
  115 #include "cgi.h"
  116 #include "loadcfg.h"
  117 #include "urlmatch.h"
  118 #ifdef FEATURE_CLIENT_TAGS
  119 #include "client-tags.h"
  120 #endif
  121 
  122 const char jcc_h_rcs[] = JCC_H_VERSION;
  123 const char project_h_rcs[] = PROJECT_H_VERSION;
  124 
  125 int daemon_mode = 1;
  126 struct client_states clients[1];
  127 struct file_list     files[1];
  128 
  129 #ifdef FEATURE_STATISTICS
  130 int urls_read     = 0;     /* total nr of urls read inc rejected */
  131 int urls_rejected = 0;     /* total nr of urls rejected */
  132 #endif /* def FEATURE_STATISTICS */
  133 
  134 #ifdef FEATURE_GRACEFUL_TERMINATION
  135 int g_terminate = 0;
  136 #endif
  137 
  138 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
  139 static void sig_handler(int the_signal);
  140 #endif
  141 static int client_protocol_is_unsupported(const struct client_state *csp, char *req);
  142 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
  143 static jb_err get_server_headers(struct client_state *csp);
  144 static const char *crunch_reason(const struct http_response *rsp);
  145 static void send_crunch_response(const struct client_state *csp, struct http_response *rsp);
  146 static char *get_request_line(struct client_state *csp);
  147 static jb_err receive_client_request(struct client_state *csp);
  148 static jb_err parse_client_request(struct client_state *csp);
  149 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line);
  150 static jb_err change_request_destination(struct client_state *csp);
  151 static void chat(struct client_state *csp);
  152 static void serve(struct client_state *csp);
  153 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
  154 static void usage(const char *myname);
  155 #endif
  156 static void initialize_mutexes(void);
  157 static jb_socket bind_port_helper(const char *haddr, int hport);
  158 static void bind_ports_helper(struct configuration_spec *config, jb_socket sockets[]);
  159 static void close_ports_helper(jb_socket sockets[]);
  160 static void listen_loop(void);
  161 
  162 #ifdef AMIGA
  163 void serve(struct client_state *csp);
  164 #else /* ifndef AMIGA */
  165 static void serve(struct client_state *csp);
  166 #endif /* def AMIGA */
  167 
  168 #ifdef __BEOS__
  169 static int32 server_thread(void *data);
  170 #endif /* def __BEOS__ */
  171 
  172 #ifdef _WIN32
  173 #define sleep(N)  Sleep(((N) * 1000))
  174 #endif
  175 
  176 #ifdef __OS2__
  177 #define sleep(N)  DosSleep(((N) * 100))
  178 #endif
  179 
  180 #ifdef MUTEX_LOCKS_AVAILABLE
  181 /*
  182  * XXX: Does the locking stuff really belong in this file?
  183  */
  184 privoxy_mutex_t log_mutex;
  185 privoxy_mutex_t log_init_mutex;
  186 privoxy_mutex_t connection_reuse_mutex;
  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 
  195 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
  196 privoxy_mutex_t resolver_mutex;
  197 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
  198 
  199 #ifndef HAVE_GMTIME_R
  200 privoxy_mutex_t gmtime_mutex;
  201 #endif /* ndef HAVE_GMTIME_R */
  202 
  203 #ifndef HAVE_LOCALTIME_R
  204 privoxy_mutex_t localtime_mutex;
  205 #endif /* ndef HAVE_GMTIME_R */
  206 
  207 #ifndef HAVE_RANDOM
  208 privoxy_mutex_t rand_mutex;
  209 #endif /* ndef HAVE_RANDOM */
  210 
  211 #endif /* def MUTEX_LOCKS_AVAILABLE */
  212 
  213 #if defined(unix)
  214 const char *basedir = NULL;
  215 const char *pidfile = NULL;
  216 static int received_hup_signal = 0;
  217 #endif /* defined unix */
  218 
  219 /* HTTP snipplets. */
  220 static const char CSUCCEED[] =
  221    "HTTP/1.1 200 Connection established\r\n\r\n";
  222 
  223 static const char CHEADER[] =
  224    "HTTP/1.1 400 Invalid header received from client\r\n"
  225    "Content-Type: text/plain\r\n"
  226    "Connection: close\r\n\r\n"
  227    "Invalid header received from client.\r\n";
  228 
  229 static const char FTP_RESPONSE[] =
  230    "HTTP/1.1 400 Invalid request received from client\r\n"
  231    "Content-Type: text/plain\r\n"
  232    "Connection: close\r\n\r\n"
  233    "Invalid request. Privoxy doesn't support FTP.\r\n";
  234 
  235 static const char GOPHER_RESPONSE[] =
  236    "HTTP/1.1 400 Invalid request received from client\r\n"
  237    "Content-Type: text/plain\r\n"
  238    "Connection: close\r\n\r\n"
  239    "Invalid request. Privoxy doesn't support gopher.\r\n";
  240 
  241 /* XXX: should be a template */
  242 static const char MISSING_DESTINATION_RESPONSE[] =
  243    "HTTP/1.1 400 Bad request received from client\r\n"
  244    "Content-Type: text/plain\r\n"
  245    "Connection: close\r\n\r\n"
  246    "Bad request. Privoxy was unable to extract the destination.\r\n";
  247 
  248 /* XXX: should be a template */
  249 static const char INVALID_SERVER_HEADERS_RESPONSE[] =
  250    "HTTP/1.1 502 Server or forwarder response invalid\r\n"
  251    "Content-Type: text/plain\r\n"
  252    "Connection: close\r\n\r\n"
  253    "Bad response. The server or forwarder response doesn't look like HTTP.\r\n";
  254 
  255 /* XXX: should be a template */
  256 static const char MESSED_UP_REQUEST_RESPONSE[] =
  257    "HTTP/1.1 400 Malformed request after rewriting\r\n"
  258    "Content-Type: text/plain\r\n"
  259    "Connection: close\r\n\r\n"
  260    "Bad request. Messed up with header filters.\r\n";
  261 
  262 static const char TOO_MANY_CONNECTIONS_RESPONSE[] =
  263    "HTTP/1.1 503 Too many open connections\r\n"
  264    "Content-Type: text/plain\r\n"
  265    "Connection: close\r\n\r\n"
  266    "Maximum number of open connections reached.\r\n";
  267 
  268 static const char CLIENT_CONNECTION_TIMEOUT_RESPONSE[] =
  269    "HTTP/1.1 504 Connection timeout\r\n"
  270    "Content-Type: text/plain\r\n"
  271    "Connection: close\r\n\r\n"
  272    "The connection timed out because the client request didn't arrive in time.\r\n";
  273 
  274 static const char CLIENT_BODY_PARSE_ERROR_RESPONSE[] =
  275    "HTTP/1.1 400 Failed reading client body\r\n"
  276    "Content-Type: text/plain\r\n"
  277    "Connection: close\r\n\r\n"
  278    "Failed parsing or buffering the chunk-encoded client body.\r\n";
  279 
  280 static const char UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE[] =
  281    "HTTP/1.1 417 Expecting too much\r\n"
  282    "Content-Type: text/plain\r\n"
  283    "Connection: close\r\n\r\n"
  284    "Privoxy detected an unsupported Expect header value.\r\n";
  285 
  286 /* A function to crunch a response */
  287 typedef struct http_response *(*crunch_func_ptr)(struct client_state *);
  288 
  289 /* Crunch function flags */
  290 #define CF_NO_FLAGS        0
  291 /* Cruncher applies to forced requests as well */
  292 #define CF_IGNORE_FORCE    1
  293 /* Crunched requests are counted for the block statistics */
  294 #define CF_COUNT_AS_REJECT 2
  295 
  296 /* A crunch function and its flags */
  297 struct cruncher
  298 {
  299    const crunch_func_ptr cruncher;
  300    const int flags;
  301 };
  302 
  303 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]);
  304 
  305 /* Complete list of cruncher functions */
  306 static const struct cruncher crunchers_all[] = {
  307    { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE},
  308    { block_url,       CF_COUNT_AS_REJECT },
  309 #ifdef FEATURE_TRUST
  310    { trust_url,       CF_COUNT_AS_REJECT },
  311 #endif /* def FEATURE_TRUST */
  312    { redirect_url,    CF_NO_FLAGS  },
  313    { dispatch_cgi,    CF_IGNORE_FORCE},
  314    { NULL,            0 }
  315 };
  316 
  317 /* Light version, used after tags are applied */
  318 static const struct cruncher crunchers_light[] = {
  319    { block_url,       CF_COUNT_AS_REJECT },
  320    { redirect_url,    CF_NO_FLAGS },
  321    { NULL,            0 }
  322 };
  323 
  324 
  325 /*
  326  * XXX: Don't we really mean
  327  *
  328  * #if defined(unix)
  329  *
  330  * here?
  331  */
  332 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
  333 /*********************************************************************
  334  *
  335  * Function    :  sig_handler
  336  *
  337  * Description :  Signal handler for different signals.
  338  *                Exit gracefully on TERM and INT
  339  *                or set a flag that will cause the errlog
  340  *                to be reopened by the main thread on HUP.
  341  *
  342  * Parameters  :
  343  *          1  :  the_signal = the signal cause this function to call
  344  *
  345  * Returns     :  -
  346  *
  347  *********************************************************************/
  348 static void sig_handler(int the_signal)
  349 {
  350    switch(the_signal)
  351    {
  352       case SIGTERM:
  353       case SIGINT:
  354          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
  355 #if defined(unix)
  356          if (pidfile)
  357          {
  358             unlink(pidfile);
  359          }
  360 #endif /* unix */
  361          exit(the_signal);
  362          break;
  363 
  364       case SIGHUP:
  365 #if defined(unix)
  366          received_hup_signal = 1;
  367 #endif
  368          break;
  369 
  370       default:
  371          /*
  372           * We shouldn't be here, unless we catch signals
  373           * in main() that we can't handle here!
  374           */
  375          log_error(LOG_LEVEL_FATAL, "sig_handler: exiting on unexpected signal %d", the_signal);
  376    }
  377    return;
  378 
  379 }
  380 #endif
  381 
  382 
  383 /*********************************************************************
  384  *
  385  * Function    :  client_protocol_is_unsupported
  386  *
  387  * Description :  Checks if the client used a known unsupported
  388  *                protocol and deals with it by sending an error
  389  *                response.
  390  *
  391  * Parameters  :
  392  *          1  :  csp = Current client state (buffers, headers, etc...)
  393  *          2  :  req = the first request line send by the client
  394  *
  395  * Returns     :  TRUE if an error response has been generated, or
  396  *                FALSE if the request doesn't look invalid.
  397  *
  398  *********************************************************************/
  399 static int client_protocol_is_unsupported(const struct client_state *csp, char *req)
  400 {
  401    /*
  402     * If it's a FTP or gopher request, we don't support it.
  403     *
  404     * These checks are better than nothing, but they might
  405     * not work in all configurations and some clients might
  406     * have problems digesting the answer.
  407     *
  408     * They should, however, never cause more problems than
  409     * Privoxy's old behaviour (returning the misleading HTML
  410     * error message:
  411     *
  412     * "Could not resolve http://(ftp|gopher)://example.org").
  413     */
  414    if (!strncmpic(req, "GET ftp://", 10) || !strncmpic(req, "GET gopher://", 13))
  415    {
  416       const char *response = NULL;
  417       const char *protocol = NULL;
  418 
  419       if (!strncmpic(req, "GET ftp://", 10))
  420       {
  421          response = FTP_RESPONSE;
  422          protocol = "FTP";
  423       }
  424       else
  425       {
  426          response = GOPHER_RESPONSE;
  427          protocol = "GOPHER";
  428       }
  429       log_error(LOG_LEVEL_ERROR,
  430          "%s tried to use Privoxy as %s proxy: %s",
  431          csp->ip_addr_str, protocol, req);
  432       log_error(LOG_LEVEL_CLF,
  433          "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
  434       freez(req);
  435       write_socket(csp->cfd, response, strlen(response));
  436 
  437       return TRUE;
  438    }
  439 
  440    return FALSE;
  441 }
  442 
  443 
  444 /*********************************************************************
  445  *
  446  * Function    :  client_has_unsupported_expectations
  447  *
  448  * Description :  Checks if the client used an unsupported expectation
  449  *                in which case an error message is delivered.
  450  *
  451  * Parameters  :
  452  *          1  :  csp = Current client state (buffers, headers, etc...)
  453  *
  454  * Returns     :  TRUE if an error response has been generated, or
  455  *                FALSE if the request doesn't look invalid.
  456  *
  457  *********************************************************************/
  458 static int client_has_unsupported_expectations(const struct client_state *csp)
  459 {
  460    if ((csp->flags & CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION))
  461    {
  462       log_error(LOG_LEVEL_ERROR,
  463          "Rejecting request from client %s with unsupported Expect header value",
  464          csp->ip_addr_str);
  465       log_error(LOG_LEVEL_CLF,
  466          "%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd);
  467       write_socket(csp->cfd, UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE,
  468          strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE));
  469 
  470       return TRUE;
  471    }
  472 
  473    return FALSE;
  474 
  475 }
  476 
  477 
  478 /*********************************************************************
  479  *
  480  * Function    :  get_request_destination_elsewhere
  481  *
  482  * Description :  If the client's request was redirected into
  483  *                Privoxy without the client's knowledge,
  484  *                the request line lacks the destination host.
  485  *
  486  *                This function tries to get it elsewhere,
  487  *                provided accept-intercepted-requests is enabled.
  488  *
  489  *                "Elsewhere" currently only means "Host: header",
  490  *                but in the future we may ask the redirecting
  491  *                packet filter to look the destination up.
  492  *
  493  *                If the destination stays unknown, an error
  494  *                response is send to the client and headers
  495  *                are freed so that chat() can return directly.
  496  *
  497  * Parameters  :
  498  *          1  :  csp = Current client state (buffers, headers, etc...)
  499  *          2  :  headers = a header list
  500  *
  501  * Returns     :  JB_ERR_OK if the destination is now known, or
  502  *                JB_ERR_PARSE if it isn't.
  503  *
  504  *********************************************************************/
  505 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
  506 {
  507    char *req;
  508 
  509    if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
  510    {
  511       log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
  512          " Privoxy isn't configured to accept intercepted requests.",
  513          csp->ip_addr_str, csp->http->cmd);
  514       /* XXX: Use correct size */
  515       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
  516          csp->ip_addr_str, csp->http->cmd);
  517 
  518       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
  519       destroy_list(headers);
  520 
  521       return JB_ERR_PARSE;
  522    }
  523    else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http))
  524    {
  525 #ifndef FEATURE_EXTENDED_HOST_PATTERNS
  526       /* Split the domain we just got for pattern matching */
  527       init_domain_components(csp->http);
  528 #endif
  529 
  530       return JB_ERR_OK;
  531    }
  532    else
  533    {
  534       /* We can't work without destination. Go spread the news.*/
  535 
  536       req = list_to_text(headers);
  537       chomp(req);
  538       /* XXX: Use correct size */
  539       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
  540          csp->ip_addr_str, csp->http->cmd);
  541       log_error(LOG_LEVEL_ERROR,
  542          "Privoxy was unable to get the destination for %s's request:\n%s\n%s",
  543          csp->ip_addr_str, csp->http->cmd, req);
  544       freez(req);
  545 
  546       write_socket(csp->cfd, MISSING_DESTINATION_RESPONSE, strlen(MISSING_DESTINATION_RESPONSE));
  547       destroy_list(headers);
  548 
  549       return JB_ERR_PARSE;
  550    }
  551    /*
  552     * TODO: If available, use PF's ioctl DIOCNATLOOK as last resort
  553     * to get the destination IP address, use it as host directly
  554     * or do a reverse DNS lookup first.
  555     */
  556 }
  557 
  558 
  559 /*********************************************************************
  560  *
  561  * Function    :  get_server_headers
  562  *
  563  * Description :  Parses server headers in iob and fills them
  564  *                into csp->headers so that they can later be
  565  *                handled by sed().
  566  *
  567  * Parameters  :
  568  *          1  :  csp = Current client state (buffers, headers, etc...)
  569  *
  570  * Returns     :  JB_ERR_OK if everything went fine, or
  571  *                JB_ERR_PARSE if the headers were incomplete.
  572  *
  573  *********************************************************************/
  574 static jb_err get_server_headers(struct client_state *csp)
  575 {
  576    int continue_hack_in_da_house = 0;
  577    char * header;
  578 
  579    while (((header = get_header(csp->iob)) != NULL) || continue_hack_in_da_house)
  580    {
  581       if (header == NULL)
  582       {
  583          /*
  584           * continue hack in da house. Ignore the ending of
  585           * this head and continue enlisting header lines.
  586           * The reason is described below.
  587           */
  588          enlist(csp->headers, "");
  589          continue_hack_in_da_house = 0;
  590          continue;
  591       }
  592       else if (0 == strncmpic(header, "HTTP/1.1 100", 12))
  593       {
  594          /*
  595           * It's a bodyless continue response, don't
  596           * stop header parsing after reaching its end.
  597           *
  598           * As a result Privoxy will concatenate the
  599           * next response's head and parse and deliver
  600           * the headers as if they belonged to one request.
  601           *
  602           * The client will separate them because of the
  603           * empty line between them.
  604           *
  605           * XXX: What we're doing here is clearly against
  606           * the intended purpose of the continue header,
  607           * and under some conditions (HTTP/1.0 client request)
  608           * it's a standard violation.
  609           *
  610           * Anyway, "sort of against the spec" is preferable
  611           * to "always getting confused by Continue responses"
  612           * (Privoxy's behaviour before this hack was added)
  613           */
  614          log_error(LOG_LEVEL_HEADER, "Continue hack in da house.");
  615          continue_hack_in_da_house = 1;
  616       }
  617       else if (*header == '\0')
  618       {
  619          /*
  620           * If the header is empty, but the Continue hack
  621           * isn't active, we can assume that we reached the
  622           * end of the buffer before we hit the end of the
  623           * head.
  624           *
  625           * Inform the caller an let it decide how to handle it.
  626           */
  627          return JB_ERR_PARSE;
  628       }
  629 
  630       if (JB_ERR_MEMORY == enlist(csp->headers, header))
  631       {
  632          /*
  633           * XXX: Should we quit the request and return a
  634           * out of memory error page instead?
  635           */
  636          log_error(LOG_LEVEL_ERROR,
  637             "Out of memory while enlisting server headers. %s lost.",
  638             header);
  639       }
  640       freez(header);
  641    }
  642 
  643    return JB_ERR_OK;
  644 }
  645 
  646 
  647 /*********************************************************************
  648  *
  649  * Function    :  crunch_reason
  650  *
  651  * Description :  Translates the crunch reason code into a string.
  652  *
  653  * Parameters  :
  654  *          1  :  rsp = a http_response
  655  *
  656  * Returns     :  A string with the crunch reason or an error description.
  657  *
  658  *********************************************************************/
  659 static const char *crunch_reason(const struct http_response *rsp)
  660 {
  661    char * reason = NULL;
  662 
  663    assert(rsp != NULL);
  664    if (rsp == NULL)
  665    {
  666       return "Internal error while searching for crunch reason";
  667    }
  668 
  669    switch (rsp->crunch_reason)
  670    {
  671       case UNSUPPORTED:
  672          reason = "Unsupported HTTP feature";
  673          break;
  674       case BLOCKED:
  675          reason = "Blocked";
  676          break;
  677       case UNTRUSTED:
  678          reason = "Untrusted";
  679          break;
  680       case REDIRECTED:
  681          reason = "Redirected";
  682          break;
  683       case CGI_CALL:
  684          reason = "CGI Call";
  685          break;
  686       case NO_SUCH_DOMAIN:
  687          reason = "DNS failure";
  688          break;
  689       case FORWARDING_FAILED:
  690          reason = "Forwarding failed";
  691          break;
  692       case CONNECT_FAILED:
  693          reason = "Connection failure";
  694          break;
  695       case OUT_OF_MEMORY:
  696          reason = "Out of memory (may mask other reasons)";
  697          break;
  698       case CONNECTION_TIMEOUT:
  699          reason = "Connection timeout";
  700          break;
  701       case NO_SERVER_DATA:
  702          reason = "No server data received";
  703          break;
  704       default:
  705          reason = "No reason recorded";
  706          break;
  707    }
  708 
  709    return reason;
  710 }
  711 
  712 
  713 /*********************************************************************
  714  *
  715  * Function    :  log_applied_actions
  716  *
  717  * Description :  Logs the applied actions if LOG_LEVEL_ACTIONS is
  718  *                enabled.
  719  *
  720  * Parameters  :
  721  *          1  :  actions = Current action spec to log
  722  *
  723  * Returns     :  Nothing.
  724  *
  725  *********************************************************************/
  726 static void log_applied_actions(const struct current_action_spec *actions)
  727 {
  728    /*
  729     * The conversion to text requires lots of memory allocations so
  730     * we only do the conversion if the user is actually interested.
  731     */
  732    if (debug_level_is_enabled(LOG_LEVEL_ACTIONS))
  733    {
  734       char *actions_as_text = actions_to_line_of_text(actions);
  735       log_error(LOG_LEVEL_ACTIONS, "%s", actions_as_text);
  736       freez(actions_as_text);
  737    }
  738 }
  739 
  740 
  741 /*********************************************************************
  742  *
  743  * Function    :  send_crunch_response
  744  *
  745  * Description :  Delivers already prepared response for
  746  *                intercepted requests, logs the interception
  747  *                and frees the response.
  748  *
  749  * Parameters  :
  750  *          1  :  csp = Current client state (buffers, headers, etc...)
  751  *          1  :  rsp = Fully prepared response. Will be freed on exit.
  752  *
  753  * Returns     :  Nothing.
  754  *
  755  *********************************************************************/
  756 static void send_crunch_response(const struct client_state *csp, struct http_response *rsp)
  757 {
  758       const struct http_request *http = csp->http;
  759       char status_code[4];
  760 
  761       assert(rsp != NULL);
  762       assert(rsp->head != NULL);
  763 
  764       if (rsp == NULL)
  765       {
  766          log_error(LOG_LEVEL_FATAL, "NULL response in send_crunch_response.");
  767       }
  768 
  769       /*
  770        * Extract the status code from the actual head
  771        * that will be send to the client. It is the only
  772        * way to get it right for all requests, including
  773        * the fixed ones for out-of-memory problems.
  774        *
  775        * A head starts like this: 'HTTP/1.1 200...'
  776        *                           0123456789|11
  777        *                                     10
  778        */
  779       status_code[0] = rsp->head[9];
  780       status_code[1] = rsp->head[10];
  781       status_code[2] = rsp->head[11];
  782       status_code[3] = '\0';
  783 
  784       /* Log that the request was crunched and why. */
  785       log_applied_actions(csp->action);
  786       log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
  787       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u",
  788          csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
  789 
  790       /* Write the answer to the client */
  791       if (write_socket(csp->cfd, rsp->head, rsp->head_length)
  792        || write_socket(csp->cfd, rsp->body, rsp->content_length))
  793       {
  794          /* There is nothing we can do about it. */
  795          log_error(LOG_LEVEL_ERROR,
  796             "Couldn't deliver the error message through client socket %d: %E",
  797             csp->cfd);
  798       }
  799 
  800       /* Clean up and return */
  801       if (cgi_error_memory() != rsp)
  802       {
  803          free_http_response(rsp);
  804       }
  805       return;
  806 }
  807 
  808 
  809 /*********************************************************************
  810  *
  811  * Function    :  crunch_response_triggered
  812  *
  813  * Description :  Checks if the request has to be crunched,
  814  *                and delivers the crunch response if necessary.
  815  *
  816  * Parameters  :
  817  *          1  :  csp = Current client state (buffers, headers, etc...)
  818  *          2  :  crunchers = list of cruncher functions to run
  819  *
  820  * Returns     :  TRUE if the request was answered with a crunch response
  821  *                FALSE otherwise.
  822  *
  823  *********************************************************************/
  824 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[])
  825 {
  826    struct http_response *rsp = NULL;
  827    const struct cruncher *c;
  828 
  829    /*
  830     * If CGI request crunching is disabled,
  831     * check the CGI dispatcher out of order to
  832     * prevent unintentional blocks or redirects.
  833     */
  834    if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING)
  835        && (NULL != (rsp = dispatch_cgi(csp))))
  836    {
  837       /* Deliver, log and free the interception response. */
  838       send_crunch_response(csp, rsp);
  839       csp->flags |= CSP_FLAG_CRUNCHED;
  840       return TRUE;
  841    }
  842 
  843    for (c = crunchers; c->cruncher != NULL; c++)
  844    {
  845       /*
  846        * Check the cruncher if either Privoxy is toggled
  847        * on and the request isn't forced, or if the cruncher
  848        * applies to forced requests as well.
  849        */
  850       if (((csp->flags & CSP_FLAG_TOGGLED_ON) &&
  851           !(csp->flags & CSP_FLAG_FORCED)) ||
  852           (c->flags & CF_IGNORE_FORCE))
  853       {
  854          rsp = c->cruncher(csp);
  855          if (NULL != rsp)
  856          {
  857             /* Deliver, log and free the interception response. */
  858             send_crunch_response(csp, rsp);
  859             csp->flags |= CSP_FLAG_CRUNCHED;
  860 #ifdef FEATURE_STATISTICS
  861             if (c->flags & CF_COUNT_AS_REJECT)
  862             {
  863                csp->flags |= CSP_FLAG_REJECTED;
  864             }
  865 #endif /* def FEATURE_STATISTICS */
  866 
  867             return TRUE;
  868          }
  869       }
  870    }
  871 
  872    return FALSE;
  873 }
  874 
  875 
  876 /*********************************************************************
  877  *
  878  * Function    :  build_request_line
  879  *
  880  * Description :  Builds the HTTP request line.
  881  *
  882  *                If a HTTP forwarder is used it expects the whole URL,
  883  *                web servers only get the path.
  884  *
  885  * Parameters  :
  886  *          1  :  csp = Current client state (buffers, headers, etc...)
  887  *          2  :  fwd = The forwarding spec used for the request
  888  *                XXX: Should use http->fwd instead.
  889  *          3  :  request_line = The old request line which will be replaced.
  890  *
  891  * Returns     :  Nothing. Terminates in case of memory problems.
  892  *
  893  *********************************************************************/
  894 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line)
  895 {
  896    struct http_request *http = csp->http;
  897 
  898    assert(http->ssl == 0);
  899 
  900    /*
  901     * Downgrade http version from 1.1 to 1.0
  902     * if +downgrade action applies.
  903     */
  904    if ((csp->action->flags & ACTION_DOWNGRADE)
  905      && (!strcmpic(http->ver, "HTTP/1.1")))
  906    {
  907       freez(http->ver);
  908       http->ver = strdup_or_die("HTTP/1.0");
  909    }
  910 
  911    /*
  912     * Rebuild the request line.
  913     */
  914    freez(*request_line);
  915    *request_line = strdup(http->gpc);
  916    string_append(request_line, " ");
  917 
  918    if (fwd->forward_host && fwd->type != FORWARD_WEBSERVER)
  919    {
  920       string_append(request_line, http->url);
  921    }
  922    else
  923    {
  924       string_append(request_line, http->path);
  925    }
  926    string_append(request_line, " ");
  927    string_append(request_line, http->ver);
  928 
  929    if (*request_line == NULL)
  930    {
  931       log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
  932    }
  933    log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line);
  934 }
  935 
  936 
  937 /*********************************************************************
  938  *
  939  * Function    :  change_request_destination
  940  *
  941  * Description :  Parse a (rewritten) request line and regenerate
  942  *                the http request data.
  943  *
  944  * Parameters  :
  945  *          1  :  csp = Current client state (buffers, headers, etc...)
  946  *
  947  * Returns     :  Forwards the parse_http_request() return code.
  948  *                Terminates in case of memory problems.
  949  *
  950  *********************************************************************/
  951 static jb_err change_request_destination(struct client_state *csp)
  952 {
  953    struct http_request *http = csp->http;
  954    jb_err err;
  955 
  956    log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s",
  957       csp->headers->first->str);
  958    free_http_request(http);
  959    err = parse_http_request(csp->headers->first->str, http);
  960    if (JB_ERR_OK != err)
  961    {
  962       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
  963          jb_err_to_string(err));
  964    }
  965 
  966    return err;
  967 }
  968 
  969 
  970 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
  971 /*********************************************************************
  972  *
  973  * Function    :  server_response_is_complete
  974  *
  975  * Description :  Determines whether we should stop reading
  976  *                from the server socket.
  977  *
  978  * Parameters  :
  979  *          1  :  csp = Current client state (buffers, headers, etc...)
  980  *          2  :  content_length = Length of content received so far.
  981  *
  982  * Returns     :  TRUE if the response is complete,
  983  *                FALSE otherwise.
  984  *
  985  *********************************************************************/
  986 static int server_response_is_complete(struct client_state *csp,
  987    unsigned long long content_length)
  988 {
  989    int content_length_known = !!(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET);
  990 
  991    if (!strcmpic(csp->http->gpc, "HEAD"))
  992    {
  993       /*
  994        * "HEAD" implies no body, we are thus expecting
  995        * no content. XXX: incomplete "list" of methods?
  996        */
  997       csp->expected_content_length = 0;
  998       content_length_known = TRUE;
  999       csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
 1000    }
 1001 
 1002    if (csp->http->status == 204 || csp->http->status == 304)
 1003    {
 1004       /*
 1005        * Expect no body. XXX: incomplete "list" of status codes?
 1006        */
 1007       csp->expected_content_length = 0;
 1008       content_length_known = TRUE;
 1009       csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
 1010    }
 1011 
 1012    return (content_length_known && ((0 == csp->expected_content_length)
 1013             || (csp->expected_content_length <= content_length)));
 1014 }
 1015 
 1016 
 1017 #ifdef FEATURE_CONNECTION_SHARING
 1018 /*********************************************************************
 1019  *
 1020  * Function    :  wait_for_alive_connections
 1021  *
 1022  * Description :  Waits for alive connections to timeout.
 1023  *
 1024  * Parameters  :  N/A
 1025  *
 1026  * Returns     :  N/A
 1027  *
 1028  *********************************************************************/
 1029 static void wait_for_alive_connections(void)
 1030 {
 1031    int connections_alive = close_unusable_connections();
 1032 
 1033    while (0 < connections_alive)
 1034    {
 1035       log_error(LOG_LEVEL_CONNECT,
 1036          "Waiting for %d connections to timeout.",
 1037          connections_alive);
 1038       sleep(60);
 1039       connections_alive = close_unusable_connections();
 1040    }
 1041 
 1042    log_error(LOG_LEVEL_CONNECT, "No connections to wait for left.");
 1043 
 1044 }
 1045 #endif /* def FEATURE_CONNECTION_SHARING */
 1046 
 1047 
 1048 /*********************************************************************
 1049  *
 1050  * Function    :  save_connection_destination
 1051  *
 1052  * Description :  Remembers a connection for reuse later on.
 1053  *
 1054  * Parameters  :
 1055  *          1  :  sfd  = Open socket to remember.
 1056  *          2  :  http = The destination for the connection.
 1057  *          3  :  fwd  = The forwarder settings used.
 1058  *          3  :  server_connection  = storage.
 1059  *
 1060  * Returns     : void
 1061  *
 1062  *********************************************************************/
 1063 void save_connection_destination(jb_socket sfd,
 1064                                  const struct http_request *http,
 1065                                  const struct forward_spec *fwd,
 1066                                  struct reusable_connection *server_connection)
 1067 {
 1068    assert(sfd != JB_INVALID_SOCKET);
 1069    assert(NULL != http->host);
 1070 
 1071    server_connection->sfd = sfd;
 1072    server_connection->host = strdup_or_die(http->host);
 1073    server_connection->port = http->port;
 1074 
 1075    assert(NULL != fwd);
 1076    assert(server_connection->gateway_host == NULL);
 1077    assert(server_connection->gateway_port == 0);
 1078    assert(server_connection->forwarder_type == 0);
 1079    assert(server_connection->forward_host == NULL);
 1080    assert(server_connection->forward_port == 0);
 1081 
 1082    server_connection->forwarder_type = fwd->type;
 1083    if (NULL != fwd->gateway_host)
 1084    {
 1085       server_connection->gateway_host = strdup_or_die(fwd->gateway_host);
 1086    }
 1087    else
 1088    {
 1089       server_connection->gateway_host = NULL;
 1090    }
 1091    server_connection->gateway_port = fwd->gateway_port;
 1092 
 1093    if (NULL != fwd->forward_host)
 1094    {
 1095       server_connection->forward_host = strdup_or_die(fwd->forward_host);
 1096    }
 1097    else
 1098    {
 1099       server_connection->forward_host = NULL;
 1100    }
 1101    server_connection->forward_port = fwd->forward_port;
 1102 }
 1103 
 1104 
 1105 /*********************************************************************
 1106  *
 1107  * Function    : verify_request_length
 1108  *
 1109  * Description : Checks if we already got the whole client requests
 1110  *               and sets CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ if
 1111  *               we do.
 1112  *
 1113  *               Data that doesn't belong to the current request is
 1114  *               either thrown away to let the client retry on a clean
 1115  *               socket, or stashed to be dealt with after the current
 1116  *               request is served.
 1117  *
 1118  * Parameters  :
 1119  *          1  :  csp = Current client state (buffers, headers, etc...)
 1120  *
 1121  * Returns     :  void
 1122  *
 1123  *********************************************************************/
 1124 static void verify_request_length(struct client_state *csp)
 1125 {
 1126    unsigned long long buffered_request_bytes =
 1127       (unsigned long long)(csp->client_iob->eod - csp->client_iob->cur);
 1128 
 1129    if ((csp->expected_client_content_length != 0)
 1130       && (buffered_request_bytes != 0))
 1131    {
 1132       if (csp->expected_client_content_length >= buffered_request_bytes)
 1133       {
 1134          csp->expected_client_content_length -= buffered_request_bytes;
 1135          log_error(LOG_LEVEL_CONNECT, "Reduced expected bytes to %llu "
 1136             "to account for the %llu ones we already got.",
 1137             csp->expected_client_content_length, buffered_request_bytes);
 1138       }
 1139       else
 1140       {
 1141          assert(csp->client_iob->eod > csp->client_iob->cur + csp->expected_client_content_length);
 1142          csp->client_iob->eod = csp->client_iob->cur + csp->expected_client_content_length;
 1143          log_error(LOG_LEVEL_CONNECT, "Reducing expected bytes to 0. "
 1144             "Marking the server socket tainted after throwing %llu bytes away.",
 1145             buffered_request_bytes - csp->expected_client_content_length);
 1146          csp->expected_client_content_length = 0;
 1147          csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
 1148       }
 1149 
 1150       if (csp->expected_client_content_length == 0)
 1151       {
 1152          csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
 1153       }
 1154    }
 1155 
 1156    if (!(csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)
 1157       && ((csp->client_iob->cur < csp->client_iob->eod)
 1158          || (csp->expected_client_content_length != 0)))
 1159    {
 1160       if (strcmpic(csp->http->gpc, "GET")
 1161          && strcmpic(csp->http->gpc, "HEAD")
 1162          && strcmpic(csp->http->gpc, "TRACE")
 1163          && strcmpic(csp->http->gpc, "OPTIONS")
 1164          && strcmpic(csp->http->gpc, "DELETE"))
 1165       {
 1166          /* XXX: this is an incomplete hack */
 1167          csp->flags &= ~CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
 1168          log_error(LOG_LEVEL_CONNECT, "There better be a request body.");
 1169       }
 1170       else
 1171       {
 1172          csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
 1173 
 1174          if ((csp->config->feature_flags & RUNTIME_FEATURE_TOLERATE_PIPELINING) == 0)
 1175          {
 1176             csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
 1177             log_error(LOG_LEVEL_CONNECT,
 1178                "Possible pipeline attempt detected. The connection will not "
 1179                "be kept alive and we will only serve the first request.");
 1180             /* Nuke the pipelined requests from orbit, just to be sure. */
 1181             clear_iob(csp->client_iob);
 1182          }
 1183          else
 1184          {
 1185             /*
 1186              * Keep the pipelined data around for now, we'll deal with
 1187              * it once we're done serving the current request.
 1188              */
 1189             csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
 1190             assert(csp->client_iob->eod >= csp->client_iob->cur);
 1191             log_error(LOG_LEVEL_CONNECT, "Complete client request followed by "
 1192                "%d bytes of pipelined data received.",
 1193                (int)(csp->client_iob->eod - csp->client_iob->cur));
 1194          }
 1195       }
 1196    }
 1197    else
 1198    {
 1199       csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
 1200       log_error(LOG_LEVEL_CONNECT, "Complete client request received.");
 1201    }
 1202 }
 1203 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
 1204 
 1205 
 1206 /*********************************************************************
 1207  *
 1208  * Function    :  mark_server_socket_tainted
 1209  *
 1210  * Description :  Makes sure we don't reuse a server socket
 1211  *                (if we didn't read everything the server sent
 1212  *                us reusing the socket would lead to garbage).
 1213  *
 1214  * Parameters  :
 1215  *          1  :  csp = Current client state (buffers, headers, etc...)
 1216  *
 1217  * Returns     :  void.
 1218  *
 1219  *********************************************************************/
 1220 static void mark_server_socket_tainted(struct client_state *csp)
 1221 {
 1222    /*
 1223     * For consistency we always mark the server socket
 1224     * tainted, however, to reduce the log noise we only
 1225     * emit a log message if the server socket could have
 1226     * actually been reused.
 1227     */
 1228    if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
 1229       && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
 1230    {
 1231       log_error(LOG_LEVEL_CONNECT,
 1232          "Marking the server socket %d tainted.",
 1233          csp->server_connection.sfd);
 1234    }
 1235    csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
 1236 }
 1237 
 1238 /*********************************************************************
 1239  *
 1240  * Function    :  get_request_line
 1241  *
 1242  * Description : Read the client request line.
 1243  *
 1244  * Parameters  :
 1245  *          1  :  csp = Current client state (buffers, headers, etc...)
 1246  *
 1247  * Returns     :  Pointer to request line or NULL in case of errors.
 1248  *
 1249  *********************************************************************/
 1250 static char *get_request_line(struct client_state *csp)
 1251 {
 1252    char buf[BUFFER_SIZE];
 1253    char *request_line = NULL;
 1254    int len;
 1255 
 1256    memset(buf, 0, sizeof(buf));
 1257 
 1258    if ((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
 1259    {
 1260       /*
 1261        * If there are multiple pipelined requests waiting,
 1262        * the flag will be set again once the next request
 1263        * has been parsed.
 1264        */
 1265       csp->flags &= ~CSP_FLAG_PIPELINED_REQUEST_WAITING;
 1266 
 1267       request_line = get_header(csp->client_iob);
 1268       if ((NULL != request_line) && ('\0' != *request_line))
 1269       {
 1270          return request_line;
 1271       }
 1272       else
 1273       {
 1274          log_error(LOG_LEVEL_CONNECT, "No complete request line "
 1275             "received yet. Continuing reading from %d.", csp->cfd);
 1276       }
 1277    }
 1278 
 1279    do
 1280    {
 1281       if (!data_is_available(csp->cfd, csp->config->socket_timeout))
 1282       {
 1283          if (socket_is_still_alive(csp->cfd))
 1284          {
 1285             log_error(LOG_LEVEL_CONNECT,
 1286                "No request line on socket %d received in time. Timeout: %d.",
 1287                csp->cfd, csp->config->socket_timeout);
 1288             write_socket(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
 1289                strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE));
 1290          }
 1291          else
 1292          {
 1293             log_error(LOG_LEVEL_CONNECT,
 1294                "The client side of the connection on socket %d got "
 1295                "closed without sending a complete request line.", csp->cfd);
 1296          }
 1297          return NULL;
 1298       }
 1299 
 1300       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
 1301 
 1302       if (len <= 0) return NULL;
 1303 
 1304       /*
 1305        * If there is no memory left for buffering the
 1306        * request, there is nothing we can do but hang up
 1307        */
 1308       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
 1309       {
 1310          return NULL;
 1311       }
 1312 
 1313       request_line = get_header(csp->client_iob);
 1314 
 1315    } while ((NULL != request_line) && ('\0' == *request_line));
 1316 
 1317    return request_line;
 1318 
 1319 }
 1320 
 1321 enum chunk_status
 1322 {
 1323    CHUNK_STATUS_MISSING_DATA,
 1324    CHUNK_STATUS_BODY_COMPLETE,
 1325    CHUNK_STATUS_PARSE_ERROR
 1326 };
 1327 
 1328 
 1329 /*********************************************************************
 1330  *
 1331  * Function    :  chunked_body_is_complete
 1332  *
 1333  * Description :  Figures out whether or not a chunked body is complete.
 1334  *
 1335  *                Currently it always starts at the beginning of the
 1336  *                buffer which is somewhat wasteful and prevents Privoxy
 1337  *                from starting to forward the correctly parsed chunks
 1338  *                as soon as theoretically possible.
 1339  *
 1340  *                Should be modified to work with a common buffer,
 1341  *                and allow the caller to skip already parsed chunks.
 1342  *
 1343  *                This would allow the function to be used for unbuffered
 1344  *                response bodies as well.
 1345  *
 1346  * Parameters  :
 1347  *          1  :  iob = Buffer with the body to check.
 1348  *          2  :  length = Length of complete body
 1349  *
 1350  * Returns     :  Enum with the result of the check.
 1351  *
 1352  *********************************************************************/
 1353 static enum chunk_status chunked_body_is_complete(struct iob *iob, size_t *length)
 1354 {
 1355    unsigned int chunksize;
 1356    char *p = iob->cur;
 1357 
 1358    do
 1359    {
 1360       /*
 1361        * We need at least a single digit, followed by "\r\n",
 1362        * followed by an unknown amount of data, followed by "\r\n".
 1363        */
 1364       if (p + 5 > iob->eod)
 1365       {
 1366          return CHUNK_STATUS_MISSING_DATA;
 1367       }
 1368       if (sscanf(p, "%x", &chunksize) != 1)
 1369       {
 1370          return CHUNK_STATUS_PARSE_ERROR;
 1371       }
 1372 
 1373       /*
 1374        * We want at least a single digit, followed by "\r\n",
 1375        * followed by the specified amount of data, followed by "\r\n".
 1376        */
 1377       if (p + chunksize + 5 > iob->eod)
 1378       {
 1379          return CHUNK_STATUS_MISSING_DATA;
 1380       }
 1381 
 1382       /* Skip chunk-size. */
 1383       p = strstr(p, "\r\n");
 1384       if (NULL == p)
 1385       {
 1386          return CHUNK_STATUS_PARSE_ERROR;
 1387       }
 1388       /* Move beyond the chunkdata. */
 1389       p += 2 + chunksize;
 1390 
 1391       /* There should be another "\r\n" to skip */
 1392       if (memcmp(p, "\r\n", 2))
 1393       {
 1394          return CHUNK_STATUS_PARSE_ERROR;
 1395       }
 1396       p += 2;
 1397    } while (chunksize > 0U);
 1398 
 1399    *length = (size_t)(p - iob->cur);
 1400    assert(*length <= (size_t)(iob->eod - iob->cur));
 1401    assert(p <= iob->eod);
 1402 
 1403    return CHUNK_STATUS_BODY_COMPLETE;
 1404 
 1405 }
 1406 
 1407 
 1408 /*********************************************************************
 1409  *
 1410  * Function    : receive_chunked_client_request_body
 1411  *
 1412  * Description : Read the chunk-encoded client request body.
 1413  *               Failures are dealt with.
 1414  *
 1415  * Parameters  :
 1416  *          1  :  csp = Current client state (buffers, headers, etc...)
 1417  *
 1418  * Returns     :  JB_ERR_OK or JB_ERR_PARSE
 1419  *
 1420  *********************************************************************/
 1421 static jb_err receive_chunked_client_request_body(struct client_state *csp)
 1422 {
 1423    size_t body_length;
 1424    enum chunk_status status;
 1425 
 1426    while (CHUNK_STATUS_MISSING_DATA ==
 1427       (status = chunked_body_is_complete(csp->client_iob,&body_length)))
 1428    {
 1429       char buf[BUFFER_SIZE];
 1430       int len;
 1431 
 1432       if (!data_is_available(csp->cfd, csp->config->socket_timeout))
 1433       {
 1434          log_error(LOG_LEVEL_ERROR,
 1435             "Timeout while waiting for the client body.");
 1436          break;
 1437       }
 1438       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
 1439       if (len <= 0)
 1440       {
 1441          log_error(LOG_LEVEL_ERROR, "Read the client body failed: %E");
 1442          break;
 1443       }
 1444       if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
 1445       {
 1446          break;
 1447       }
 1448    }
 1449    if (status != CHUNK_STATUS_BODY_COMPLETE)
 1450    {
 1451       write_socket(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE,
 1452          strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE));
 1453       log_error(LOG_LEVEL_CLF,
 1454          "%s - - [%T] \"Failed reading chunked client body\" 400 0", csp->ip_addr_str);
 1455       return JB_ERR_PARSE;
 1456    }
 1457    log_error(LOG_LEVEL_CONNECT,
 1458       "Chunked client body completely read. Length: %d", body_length);
 1459    csp->expected_client_content_length = body_length;
 1460 
 1461    return JB_ERR_OK;
 1462 
 1463 }
 1464 
 1465 
 1466 #ifdef FEATURE_FORCE_LOAD
 1467 /*********************************************************************
 1468  *
 1469  * Function    :  force_required
 1470  *
 1471  * Description : Checks a request line to see if it contains
 1472  *               the FORCE_PREFIX. If it does, it is removed
 1473  *               unless enforcing requests has beend disabled.
 1474  *
 1475  * Parameters  :
 1476  *          1  :  request_line = HTTP request line
 1477  *
 1478  * Returns     :  TRUE if force is required, FALSE otherwise.
 1479  *
 1480  *********************************************************************/
 1481 static int force_required(const struct client_state *csp, char *request_line)
 1482 {
 1483    char *p;
 1484 
 1485    p = strstr(request_line, "http://");
 1486    if (p != NULL)
 1487    {
 1488       /* Skip protocol */
 1489       p += strlen("http://");
 1490    }
 1491    else
 1492    {
 1493       /* Intercepted request usually don't specify the protocol. */
 1494       p = request_line;
 1495    }
 1496 
 1497    /* Go to the beginning of the path */
 1498    p = strstr(p, "/");
 1499    if (p == NULL)
 1500    {
 1501       /*
 1502        * If the path is missing the request line is invalid and we
 1503        * are done here. The client-visible rejection happens later on.
 1504        */
 1505       return 0;
 1506    }
 1507 
 1508    if (0 == strncmpic(p, FORCE_PREFIX, strlen(FORCE_PREFIX) - 1))
 1509    {
 1510       if (!(csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS))
 1511       {
 1512          /* XXX: Should clean more carefully */
 1513          strclean(request_line, FORCE_PREFIX);
 1514          log_error(LOG_LEVEL_FORCE,
 1515             "Enforcing request: \"%s\".", request_line);
 1516 
 1517          return 1;
 1518       }
 1519       log_error(LOG_LEVEL_FORCE,
 1520          "Ignored force prefix in request: \"%s\".", request_line);
 1521    }
 1522 
 1523    return 0;
 1524 
 1525 }
 1526 #endif /* def FEATURE_FORCE_LOAD */
 1527 
 1528 
 1529 /*********************************************************************
 1530  *
 1531  * Function    :  receive_client_request
 1532  *
 1533  * Description : Read the client's request (more precisely the
 1534  *               client headers) and answer it if necessary.
 1535  *
 1536  * Parameters  :
 1537  *          1  :  csp = Current client state (buffers, headers, etc...)
 1538  *
 1539  * Returns     :  JB_ERR_OK, JB_ERR_PARSE or JB_ERR_MEMORY
 1540  *
 1541  *********************************************************************/
 1542 static jb_err receive_client_request(struct client_state *csp)
 1543 {
 1544    char buf[BUFFER_SIZE];
 1545    char *p;
 1546    char *req = NULL;
 1547    struct http_request *http;
 1548    int len;
 1549    jb_err err;
 1550 
 1551    /* Temporary copy of the client's headers before they get enlisted in csp->headers */
 1552    struct list header_list;
 1553    struct list *headers = &header_list;
 1554 
 1555    /* We don't care if the arriving data is a valid HTTP request or not. */
 1556    csp->requests_received_total++;
 1557 
 1558    http = csp->http;
 1559 
 1560    memset(buf, 0, sizeof(buf));
 1561 
 1562    req = get_request_line(csp);
 1563    if (req == NULL)
 1564    {
 1565       mark_server_socket_tainted(csp);
 1566       return JB_ERR_PARSE;
 1567    }
 1568    assert(*req != '\0');
 1569 
 1570    if (client_protocol_is_unsupported(csp, req))
 1571    {
 1572       return JB_ERR_PARSE;
 1573    }
 1574 
 1575 #ifdef FEATURE_FORCE_LOAD
 1576    if (force_required(csp, req))
 1577    {
 1578       csp->flags |= CSP_FLAG_FORCED;
 1579    }
 1580 #endif /* def FEATURE_FORCE_LOAD */
 1581 
 1582    err = parse_http_request(req, http);
 1583    freez(req);
 1584    if (JB_ERR_OK != err)
 1585    {
 1586       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
 1587       /* XXX: Use correct size */
 1588       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
 1589       log_error(LOG_LEVEL_ERROR,
 1590          "Couldn't parse request line received from %s: %s",
 1591          csp->ip_addr_str, jb_err_to_string(err));
 1592 
 1593       free_http_request(http);
 1594       return JB_ERR_PARSE;
 1595    }
 1596 
 1597    /* grab the rest of the client's headers */
 1598    init_list(headers);
 1599    for (;;)
 1600    {
 1601       p = get_header(csp->client_iob);
 1602 
 1603       if (p == NULL)
 1604       {
 1605          /* There are no additional headers to read. */
 1606          break;
 1607       }
 1608 
 1609       if (*p == '\0')
 1610       {
 1611          /*
 1612           * We didn't receive a complete header
 1613           * line yet, get the rest of it.
 1614           */
 1615          if (!data_is_available(csp->cfd, csp->config->socket_timeout))
 1616          {
 1617             log_error(LOG_LEVEL_ERROR,
 1618                "Stopped grabbing the client headers.");
 1619             destroy_list(headers);
 1620             return JB_ERR_PARSE;
 1621          }
 1622 
 1623          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
 1624          if (len <= 0)
 1625          {
 1626             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
 1627             destroy_list(headers);
 1628             return JB_ERR_PARSE;
 1629          }
 1630 
 1631          if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
 1632          {
 1633             /*
 1634              * If there is no memory left for buffering the
 1635              * request, there is nothing we can do but hang up
 1636              */
 1637             destroy_list(headers);
 1638             return JB_ERR_MEMORY;
 1639          }
 1640       }
 1641       else
 1642       {
 1643          if (!strncmpic(p, "Transfer-Encoding:", 18))
 1644          {
 1645             /*
 1646              * XXX: should be called through sed()
 1647              *      but currently can't.
 1648              */
 1649             client_transfer_encoding(csp, &p);
 1650          }
 1651          /*
 1652           * We were able to read a complete
 1653           * header and can finally enlist it.
 1654           */
 1655          enlist(headers, p);
 1656          freez(p);
 1657       }
 1658    }
 1659 
 1660    if (http->host == NULL)
 1661    {
 1662       /*
 1663        * If we still don't know the request destination,
 1664        * the request is invalid or the client uses
 1665        * Privoxy without its knowledge.
 1666        */
 1667       if (JB_ERR_OK != get_request_destination_elsewhere(csp, headers))
 1668       {
 1669          /*
 1670           * Our attempts to get the request destination
 1671           * elsewhere failed or Privoxy is configured
 1672           * to only accept proxy requests.
 1673           *
 1674           * An error response has already been send
 1675           * and we're done here.
 1676           */
 1677          return JB_ERR_PARSE;
 1678       }
 1679    }
 1680 
 1681 #ifdef FEATURE_CLIENT_TAGS
 1682    /* XXX: If the headers were enlisted sooner, passing csp would do. */
 1683    set_client_address(csp, headers);
 1684    get_tag_list_for_client(csp->client_tags, csp->client_address);
 1685 #endif
 1686 
 1687    /*
 1688     * Determine the actions for this URL
 1689     */
 1690 #ifdef FEATURE_TOGGLE
 1691    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
 1692    {
 1693       /* Most compatible set of actions (i.e. none) */
 1694       init_current_action(csp->action);
 1695    }
 1696    else
 1697 #endif /* ndef FEATURE_TOGGLE */
 1698    {
 1699       get_url_actions(csp, http);
 1700    }
 1701 
 1702    enlist(csp->headers, http->cmd);
 1703 
 1704    /* Append the previously read headers */
 1705    err = list_append_list_unique(csp->headers, headers);
 1706    destroy_list(headers);
 1707 
 1708    return err;
 1709 
 1710 }
 1711 
 1712 
 1713 /*********************************************************************
 1714  *
 1715  * Function    : parse_client_request
 1716  *
 1717  * Description : Parses the client's request and decides what to do
 1718  *               with it.
 1719  *
 1720  *               Note that since we're not using select() we could get
 1721  *               blocked here if a client connected, then didn't say
 1722  *               anything!
 1723  *
 1724  * Parameters  :
 1725  *          1  :  csp = Current client state (buffers, headers, etc...)
 1726  *
 1727  * Returns     :  JB_ERR_OK or JB_ERR_PARSE
 1728  *
 1729  *********************************************************************/
 1730 static jb_err parse_client_request(struct client_state *csp)
 1731 {
 1732    struct http_request *http = csp->http;
 1733    jb_err err;
 1734 
 1735 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 1736    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
 1737     && (!strcmpic(csp->http->ver, "HTTP/1.1"))
 1738     && (csp->http->ssl == 0))
 1739    {
 1740       /* Assume persistence until further notice */
 1741       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
 1742    }
 1743 
 1744    if (csp->http->ssl == 0)
 1745    {
 1746       /*
 1747        * This whole block belongs to chat() but currently
 1748        * has to be executed before sed().
 1749        */
 1750       if (csp->flags & CSP_FLAG_CHUNKED_CLIENT_BODY)
 1751       {
 1752          if (receive_chunked_client_request_body(csp) != JB_ERR_OK)
 1753          {
 1754             return JB_ERR_PARSE;
 1755          }
 1756       }
 1757       else
 1758       {
 1759          csp->expected_client_content_length = get_expected_content_length(csp->headers);
 1760       }
 1761       verify_request_length(csp);
 1762    }
 1763 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 1764 
 1765    err = sed(csp, FILTER_CLIENT_HEADERS);
 1766    if (JB_ERR_OK != err)
 1767    {
 1768       log_error(LOG_LEVEL_ERROR, "Failed to parse client request from %s.",
 1769          csp->ip_addr_str);
 1770       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
 1771          csp->ip_addr_str, csp->http->cmd);
 1772       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
 1773       return JB_ERR_PARSE;
 1774    }
 1775    csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
 1776 
 1777    /* Check request line for rewrites. */
 1778    if ((NULL == csp->headers->first->str)
 1779       || (strcmp(http->cmd, csp->headers->first->str) &&
 1780          (JB_ERR_OK != change_request_destination(csp))))
 1781    {
 1782       /*
 1783        * A header filter broke the request line - bail out.
 1784        */
 1785       write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE));
 1786       /* XXX: Use correct size */
 1787       log_error(LOG_LEVEL_CLF,
 1788          "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str);
 1789       log_error(LOG_LEVEL_ERROR,
 1790          "Invalid request line after applying header filters.");
 1791       free_http_request(http);
 1792 
 1793       return JB_ERR_PARSE;
 1794    }
 1795 
 1796    if (client_has_unsupported_expectations(csp))
 1797    {
 1798       return JB_ERR_PARSE;
 1799    }
 1800 
 1801    return JB_ERR_OK;
 1802 
 1803 }
 1804 
 1805 
 1806 /*********************************************************************
 1807  *
 1808  * Function    :  chat
 1809  *
 1810  * Description :  Once a connection from the client has been accepted,
 1811  *                this function is called (via serve()) to handle the
 1812  *                main business of the communication.  This function
 1813  *                returns after dealing with a single request. It can
 1814  *                be called multiple times with the same client socket
 1815  *                if the client is keeping the connection alive.
 1816  *
 1817  *                The decision whether or not a client connection will
 1818  *                be kept alive is up to the caller which also must
 1819  *                close the client socket when done.
 1820  *
 1821  *                FIXME: chat is nearly thousand lines long.
 1822  *                Ridiculous.
 1823  *
 1824  * Parameters  :
 1825  *          1  :  csp = Current client state (buffers, headers, etc...)
 1826  *
 1827  * Returns     :  Nothing.
 1828  *
 1829  *********************************************************************/
 1830 static void chat(struct client_state *csp)
 1831 {
 1832    char buf[BUFFER_SIZE];
 1833    char *hdr;
 1834    char *p;
 1835    fd_set rfds;
 1836    int n;
 1837    jb_socket maxfd;
 1838    int server_body;
 1839    int ms_iis5_hack = 0;
 1840    unsigned long long byte_count = 0;
 1841    const struct forward_spec *fwd;
 1842    struct http_request *http;
 1843    long len = 0; /* for buffer sizes (and negative error codes) */
 1844    int buffer_and_filter_content = 0;
 1845 
 1846    /* Skeleton for HTTP response, if we should intercept the request */
 1847    struct http_response *rsp;
 1848    struct timeval timeout;
 1849 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 1850    int watch_client_socket;
 1851 #endif
 1852 
 1853    memset(buf, 0, sizeof(buf));
 1854 
 1855    http = csp->http;
 1856 
 1857    if (receive_client_request(csp) != JB_ERR_OK)
 1858    {
 1859       return;
 1860    }
 1861    if (parse_client_request(csp) != JB_ERR_OK)
 1862    {
 1863       return;
 1864    }
 1865 
 1866    /* decide how to route the HTTP request */
 1867    fwd = forward_url(csp, http);
 1868    if (NULL == fwd)
 1869    {
 1870       log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
 1871       /* Never get here - LOG_LEVEL_FATAL causes program exit */
 1872       return;
 1873    }
 1874 
 1875    /*
 1876     * build the http request to send to the server
 1877     * we have to do one of the following:
 1878     *
 1879     * create = use the original HTTP request to create a new
 1880     *          HTTP request that has either the path component
 1881     *          without the http://domainspec (w/path) or the
 1882     *          full orininal URL (w/url)
 1883     *          Note that the path and/or the HTTP version may
 1884     *          have been altered by now.
 1885     *
 1886     * connect = Open a socket to the host:port of the server
 1887     *           and short-circuit server and client socket.
 1888     *
 1889     * pass =  Pass the request unchanged if forwarding a CONNECT
 1890     *         request to a parent proxy. Note that we'll be sending
 1891     *         the CFAIL message ourselves if connecting to the parent
 1892     *         fails, but we won't send a CSUCCEED message if it works,
 1893     *         since that would result in a double message (ours and the
 1894     *         parent's). After sending the request to the parent, we simply
 1895     *         tunnel.
 1896     *
 1897     * here's the matrix:
 1898     *                        SSL
 1899     *                    0        1
 1900     *                +--------+--------+
 1901     *                |        |        |
 1902     *             0  | create | connect|
 1903     *                | w/path |        |
 1904     *  Forwarding    +--------+--------+
 1905     *                |        |        |
 1906     *             1  | create | pass   |
 1907     *                | w/url  |        |
 1908     *                +--------+--------+
 1909     *
 1910     */
 1911 
 1912    if (http->ssl && connect_port_is_forbidden(csp))
 1913    {
 1914       const char *acceptable_connect_ports =
 1915          csp->action->string[ACTION_STRING_LIMIT_CONNECT];
 1916       assert(NULL != acceptable_connect_ports);
 1917       log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
 1918          "limit-connect{%s} doesn't allow CONNECT requests to %s",
 1919          csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
 1920       csp->action->flags |= ACTION_BLOCK;
 1921       http->ssl = 0;
 1922    }
 1923 
 1924    if (http->ssl == 0)
 1925    {
 1926       freez(csp->headers->first->str);
 1927       build_request_line(csp, fwd, &csp->headers->first->str);
 1928    }
 1929 
 1930    /*
 1931     * We have a request. Check if one of the crunchers wants it.
 1932     */
 1933    if (crunch_response_triggered(csp, crunchers_all))
 1934    {
 1935       /*
 1936        * Yes. The client got the crunch response and we're done here.
 1937        */
 1938       return;
 1939    }
 1940 
 1941    log_applied_actions(csp->action);
 1942    log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
 1943 
 1944    if (fwd->forward_host)
 1945    {
 1946       log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
 1947          fwd->forward_host, fwd->forward_port, http->hostport);
 1948    }
 1949    else
 1950    {
 1951       log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
 1952    }
 1953 
 1954    /* here we connect to the server, gateway, or the forwarder */
 1955 
 1956 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 1957    if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
 1958       && socket_is_still_alive(csp->server_connection.sfd)
 1959       && connection_destination_matches(&csp->server_connection, http, fwd))
 1960    {
 1961       log_error(LOG_LEVEL_CONNECT,
 1962          "Reusing server socket %d connected to %s. Total requests: %u.",
 1963          csp->server_connection.sfd, csp->server_connection.host,
 1964          csp->server_connection.requests_sent_total);
 1965    }
 1966    else
 1967    {
 1968       if (csp->server_connection.sfd != JB_INVALID_SOCKET)
 1969       {
 1970 #ifdef FEATURE_CONNECTION_SHARING
 1971          if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
 1972          {
 1973             remember_connection(&csp->server_connection);
 1974          }
 1975          else
 1976 #endif /* def FEATURE_CONNECTION_SHARING */
 1977          {
 1978             log_error(LOG_LEVEL_CONNECT,
 1979                "Closing server socket %d connected to %s. Total requests: %u.",
 1980                csp->server_connection.sfd, csp->server_connection.host,
 1981                csp->server_connection.requests_sent_total);
 1982             close_socket(csp->server_connection.sfd);
 1983          }
 1984          mark_connection_closed(&csp->server_connection);
 1985       }
 1986 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 1987 
 1988       csp->server_connection.sfd = forwarded_connect(fwd, http, csp);
 1989 
 1990       if (csp->server_connection.sfd == JB_INVALID_SOCKET)
 1991       {
 1992          if ((fwd->type != SOCKS_NONE) && (fwd->type != FORWARD_WEBSERVER))
 1993          {
 1994             /* Socks error. */
 1995             rsp = error_response(csp, "forwarding-failed");
 1996          }
 1997          else if (errno == EINVAL)
 1998          {
 1999             rsp = error_response(csp, "no-such-domain");
 2000          }
 2001          else
 2002          {
 2003             rsp = error_response(csp, "connect-failed");
 2004          }
 2005 
 2006          /* Write the answer to the client */
 2007          if (rsp != NULL)
 2008          {
 2009             send_crunch_response(csp, rsp);
 2010          }
 2011 
 2012          /*
 2013           * Temporary workaround to prevent already-read client
 2014           * bodies from being parsed as new requests. For now we
 2015           * err on the safe side and throw all the following
 2016           * requests under the bus, even if no client body has been
 2017           * buffered. A compliant client will repeat the dropped
 2018           * requests on an untainted connection.
 2019           *
 2020           * The proper fix is to discard the no longer needed
 2021           * client body in the buffer (if there is one) and to
 2022           * continue parsing the bytes that follow.
 2023           */
 2024          drain_and_close_socket(csp->cfd);
 2025          csp->cfd = JB_INVALID_SOCKET;
 2026 
 2027          return;
 2028       }
 2029 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2030       save_connection_destination(csp->server_connection.sfd,
 2031          http, fwd, &csp->server_connection);
 2032       csp->server_connection.keep_alive_timeout =
 2033          (unsigned)csp->config->keep_alive_timeout;
 2034    }
 2035 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2036 
 2037    csp->server_connection.requests_sent_total++;
 2038 
 2039    if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first))
 2040    {
 2041       /* Client headers have been sent optimistically */
 2042       assert(csp->headers->last == NULL);
 2043    }
 2044    else if (fwd->forward_host || (http->ssl == 0))
 2045    {
 2046       int write_failure;
 2047       hdr = list_to_text(csp->headers);
 2048       if (hdr == NULL)
 2049       {
 2050          /* FIXME Should handle error properly */
 2051          log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
 2052       }
 2053       list_remove_all(csp->headers);
 2054 
 2055       /*
 2056        * Write the client's (modified) header to the server
 2057        * (along with anything else that may be in the buffer)
 2058        */
 2059       write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
 2060       freez(hdr);
 2061 
 2062       if (write_failure)
 2063       {
 2064          log_error(LOG_LEVEL_CONNECT,
 2065             "Failed sending request headers to: %s: %E", http->hostport);
 2066       }
 2067       else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
 2068          && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
 2069       {
 2070          write_failure = 1;
 2071          log_error(LOG_LEVEL_CONNECT,
 2072             "Failed sending request body to: %s: %E", http->hostport);
 2073       }
 2074 
 2075       if (write_failure)
 2076       {
 2077          rsp = error_response(csp, "connect-failed");
 2078          if (rsp)
 2079          {
 2080             send_crunch_response(csp, rsp);
 2081          }
 2082          return;
 2083       }
 2084    }
 2085    else
 2086    {
 2087       /*
 2088        * We're running an SSL tunnel and we're not forwarding,
 2089        * so just ditch the client headers, send the "connect succeeded"
 2090        * message to the client, flush the rest, and get out of the way.
 2091        */
 2092       list_remove_all(csp->headers);
 2093       if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
 2094       {
 2095          return;
 2096       }
 2097       clear_iob(csp->client_iob);
 2098    }
 2099 
 2100    log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
 2101 
 2102    /* XXX: should the time start earlier for optimistically sent data? */
 2103    csp->server_connection.request_sent = time(NULL);
 2104 
 2105    maxfd = (csp->cfd > csp->server_connection.sfd) ?
 2106       csp->cfd : csp->server_connection.sfd;
 2107 
 2108    /* pass data between the client and server
 2109     * until one or the other shuts down the connection.
 2110     */
 2111 
 2112    server_body = 0;
 2113 
 2114 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2115    watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING);
 2116 #endif
 2117 
 2118    for (;;)
 2119    {
 2120 #ifdef __OS2__
 2121       /*
 2122        * FD_ZERO here seems to point to an errant macro which crashes.
 2123        * So do this by hand for now...
 2124        */
 2125       memset(&rfds,0x00,sizeof(fd_set));
 2126 #else
 2127       FD_ZERO(&rfds);
 2128 #endif
 2129 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2130       if (!watch_client_socket)
 2131       {
 2132          maxfd = csp->server_connection.sfd;
 2133       }
 2134       else
 2135 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2136       {
 2137          FD_SET(csp->cfd, &rfds);
 2138       }
 2139 
 2140       FD_SET(csp->server_connection.sfd, &rfds);
 2141 
 2142 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2143       if ((csp->flags & CSP_FLAG_CHUNKED)
 2144          && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
 2145          && ((csp->iob->eod - csp->iob->cur) >= 5)
 2146          && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
 2147       {
 2148          /*
 2149           * XXX: This check should be obsolete now,
 2150           *      but let's wait a while to be sure.
 2151           */
 2152          log_error(LOG_LEVEL_CONNECT,
 2153             "Looks like we got the last chunk together with "
 2154             "the server headers but didn't detect it earlier. "
 2155             "We better stop reading.");
 2156          byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
 2157          csp->expected_content_length = byte_count;
 2158          csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
 2159       }
 2160       if (server_body && server_response_is_complete(csp, byte_count))
 2161       {
 2162          if (csp->expected_content_length == byte_count)
 2163          {
 2164             log_error(LOG_LEVEL_CONNECT,
 2165                "Done reading from server. Content length: %llu as expected. "
 2166                "Bytes most recently read: %d.",
 2167                byte_count, len);
 2168          }
 2169          else
 2170          {
 2171             log_error(LOG_LEVEL_CONNECT,
 2172                "Done reading from server. Expected content length: %llu. "
 2173                "Actual content length: %llu. Bytes most recently read: %d.",
 2174                csp->expected_content_length, byte_count, len);
 2175          }
 2176          len = 0;
 2177          /*
 2178           * XXX: should not jump around,
 2179           * chat() is complicated enough already.
 2180           */
 2181          goto reading_done;
 2182       }
 2183 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
 2184 
 2185       timeout.tv_sec = csp->config->socket_timeout;
 2186       timeout.tv_usec = 0;
 2187       n = select((int)maxfd+1, &rfds, NULL, NULL, &timeout);
 2188 
 2189       if (n == 0)
 2190       {
 2191          log_error(LOG_LEVEL_ERROR,
 2192             "Didn't receive data in time: %s", http->url);
 2193          if ((byte_count == 0) && (http->ssl == 0))
 2194          {
 2195             send_crunch_response(csp, error_response(csp, "connection-timeout"));
 2196          }
 2197          mark_server_socket_tainted(csp);
 2198          return;
 2199       }
 2200       else if (n < 0)
 2201       {
 2202          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
 2203          mark_server_socket_tainted(csp);
 2204          return;
 2205       }
 2206 
 2207       /*
 2208        * This is the body of the browser's request,
 2209        * just read and write it.
 2210        *
 2211        * XXX: Make sure the client doesn't use pipelining
 2212        * behind Privoxy's back.
 2213        */
 2214       if (FD_ISSET(csp->cfd, &rfds))
 2215       {
 2216          int max_bytes_to_read = sizeof(buf) - 1;
 2217 
 2218 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2219          if ((csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
 2220          {
 2221             if (data_is_available(csp->cfd, 0))
 2222             {
 2223                /*
 2224                 * If the next request is already waiting, we have
 2225                 * to stop select()ing the client socket. Otherwise
 2226                 * we would always return right away and get nothing
 2227                 * else done.
 2228                 */
 2229                watch_client_socket = 0;
 2230                log_error(LOG_LEVEL_CONNECT,
 2231                   "Stopping to watch the client socket %d. "
 2232                   "There's already another request waiting.",
 2233                   csp->cfd);
 2234                continue;
 2235             }
 2236             /*
 2237              * If the client socket is set, but there's no data
 2238              * available on the socket, the client went fishing
 2239              * and continuing talking to the server makes no sense.
 2240              */
 2241             log_error(LOG_LEVEL_CONNECT,
 2242                "The client closed socket %d while "
 2243                "the server socket %d is still open.",
 2244                csp->cfd, csp->server_connection.sfd);
 2245             mark_server_socket_tainted(csp);
 2246             break;
 2247          }
 2248          if (csp->expected_client_content_length != 0)
 2249          {
 2250             if (csp->expected_client_content_length < (sizeof(buf) - 1))
 2251             {
 2252                max_bytes_to_read = (int)csp->expected_client_content_length;
 2253             }
 2254             log_error(LOG_LEVEL_CONNECT,
 2255                "Waiting for up to %d bytes from the client.",
 2256                max_bytes_to_read);
 2257          }
 2258          assert(max_bytes_to_read < sizeof(buf));
 2259 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2260 
 2261          len = read_socket(csp->cfd, buf, max_bytes_to_read);
 2262 
 2263          if (len <= 0)
 2264          {
 2265             /* XXX: not sure if this is necessary. */
 2266             mark_server_socket_tainted(csp);
 2267             break; /* "game over, man" */
 2268          }
 2269 
 2270 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2271          if (csp->expected_client_content_length != 0)
 2272          {
 2273             assert(len <= max_bytes_to_read);
 2274             csp->expected_client_content_length -= (unsigned)len;
 2275             log_error(LOG_LEVEL_CONNECT,
 2276                "Expected client content length set to %llu "
 2277                "after reading %d bytes.",
 2278                csp->expected_client_content_length, len);
 2279             if (csp->expected_client_content_length == 0)
 2280             {
 2281                log_error(LOG_LEVEL_CONNECT,
 2282                   "Done reading from the client.");
 2283                csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
 2284             }
 2285          }
 2286 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2287 
 2288          if (write_socket(csp->server_connection.sfd, buf, (size_t)len))
 2289          {
 2290             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
 2291             mark_server_socket_tainted(csp);
 2292             return;
 2293          }
 2294          continue;
 2295       }
 2296 
 2297       /*
 2298        * The server wants to talk. It could be the header or the body.
 2299        * If `hdr' is null, then it's the header otherwise it's the body.
 2300        * FIXME: Does `hdr' really mean `host'? No.
 2301        */
 2302       if (FD_ISSET(csp->server_connection.sfd, &rfds))
 2303       {
 2304 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2305          /*
 2306           * If we are buffering content, we don't want to eat up to
 2307           * buffer-limit bytes if the client no longer cares about them.
 2308           * If we aren't buffering, however, a dead client socket will be
 2309           * noticed pretty much right away anyway, so we can reduce the
 2310           * overhead by skipping the check.
 2311           */
 2312          if (buffer_and_filter_content && !socket_is_still_alive(csp->cfd))
 2313          {
 2314 #ifdef _WIN32
 2315             log_error(LOG_LEVEL_CONNECT,
 2316                "The server still wants to talk, but the client may already have hung up on us.");
 2317 #else
 2318             log_error(LOG_LEVEL_CONNECT,
 2319                "The server still wants to talk, but the client hung up on us.");
 2320             mark_server_socket_tainted(csp);
 2321             return;
 2322 #endif /* def _WIN32 */
 2323          }
 2324 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2325 
 2326          len = read_socket(csp->server_connection.sfd, buf, sizeof(buf) - 1);
 2327 
 2328          if (len < 0)
 2329          {
 2330             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
 2331 
 2332             if (http->ssl && (fwd->forward_host == NULL))
 2333             {
 2334                /*
 2335                 * Just hang up. We already confirmed the client's CONNECT
 2336                 * request with status code 200 and unencrypted content is
 2337                 * no longer welcome.
 2338                 */
 2339                log_error(LOG_LEVEL_ERROR,
 2340                   "CONNECT already confirmed. Unable to tell the client about the problem.");
 2341                return;
 2342             }
 2343             else if (byte_count)
 2344             {
 2345                /*
 2346                 * Just hang up. We already transmitted the original headers
 2347                 * and parts of the original content and therefore missed the
 2348                 * chance to send an error message (without risking data corruption).
 2349                 *
 2350                 * XXX: we could retry with a fancy range request here.
 2351                 */
 2352                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
 2353                   "Unable to tell the client about the problem.");
 2354                mark_server_socket_tainted(csp);
 2355                return;
 2356             }
 2357             /*
 2358              * XXX: Consider handling the cases above the same.
 2359              */
 2360             mark_server_socket_tainted(csp);
 2361             len = 0;
 2362          }
 2363 
 2364 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2365          if (csp->flags & CSP_FLAG_CHUNKED)
 2366          {
 2367             if ((len >= 5) && !memcmp(buf+len-5, "0\r\n\r\n", 5))
 2368             {
 2369                /* XXX: this is a temporary hack */
 2370                log_error(LOG_LEVEL_CONNECT,
 2371                   "Looks like we reached the end of the last chunk. "
 2372                   "We better stop reading.");
 2373                csp->expected_content_length = byte_count + (unsigned long long)len;
 2374                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
 2375             }
 2376          }
 2377          reading_done:
 2378 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
 2379 
 2380          /*
 2381           * Add a trailing zero to let be able to use string operations.
 2382           * XXX: do we still need this with filter_popups gone?
 2383           */
 2384          buf[len] = '\0';
 2385 
 2386          /*
 2387           * Normally, this would indicate that we've read
 2388           * as much as the server has sent us and we can
 2389           * close the client connection.  However, Microsoft
 2390           * in its wisdom has released IIS/5 with a bug that
 2391           * prevents it from sending the trailing \r\n in
 2392           * a 302 redirect header (and possibly other headers).
 2393           * To work around this if we've haven't parsed
 2394           * a full header we'll append a trailing \r\n
 2395           * and see if this now generates a valid one.
 2396           *
 2397           * This hack shouldn't have any impacts.  If we've
 2398           * already transmitted the header or if this is a
 2399           * SSL connection, then we won't bother with this
 2400           * hack.  So we only work on partially received
 2401           * headers.  If we append a \r\n and this still
 2402           * doesn't generate a valid header, then we won't
 2403           * transmit anything to the client.
 2404           */
 2405          if (len == 0)
 2406          {
 2407 
 2408             if (server_body || http->ssl)
 2409             {
 2410                /*
 2411                 * If we have been buffering up the document,
 2412                 * now is the time to apply content modification
 2413                 * and send the result to the client.
 2414                 */
 2415                if (buffer_and_filter_content)
 2416                {
 2417                   p = execute_content_filters(csp);
 2418                   /*
 2419                    * If content filtering fails, use the original
 2420                    * buffer and length.
 2421                    * (see p != NULL ? p : csp->iob->cur below)
 2422                    */
 2423                   if (NULL == p)
 2424                   {
 2425                      csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur);
 2426                   }
 2427 #ifdef FEATURE_COMPRESSION
 2428                   else if ((csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE)
 2429                      && (csp->content_length > LOWER_LENGTH_LIMIT_FOR_COMPRESSION))
 2430                   {
 2431                      char *compressed_content = compress_buffer(p,
 2432                         (size_t *)&csp->content_length, csp->config->compression_level);
 2433                      if (compressed_content != NULL)
 2434                      {
 2435                         freez(p);
 2436                         p = compressed_content;
 2437                         csp->flags |= CSP_FLAG_BUFFERED_CONTENT_DEFLATED;
 2438                      }
 2439                   }
 2440 #endif
 2441 
 2442                   if (JB_ERR_OK != update_server_headers(csp))
 2443                   {
 2444                      log_error(LOG_LEVEL_FATAL,
 2445                         "Failed to update server headers. after filtering.");
 2446                   }
 2447 
 2448                   hdr = list_to_text(csp->headers);
 2449                   if (hdr == NULL)
 2450                   {
 2451                      /* FIXME Should handle error properly */
 2452                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
 2453                   }
 2454 
 2455                   if (write_socket(csp->cfd, hdr, strlen(hdr))
 2456                    || write_socket(csp->cfd,
 2457                          ((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length))
 2458                   {
 2459                      log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
 2460                      freez(hdr);
 2461                      freez(p);
 2462                      mark_server_socket_tainted(csp);
 2463                      return;
 2464                   }
 2465 
 2466                   freez(hdr);
 2467                   freez(p);
 2468                }
 2469 
 2470                break; /* "game over, man" */
 2471             }
 2472 
 2473             /*
 2474              * This is NOT the body, so
 2475              * Let's pretend the server just sent us a blank line.
 2476              */
 2477             snprintf(buf, sizeof(buf), "\r\n");
 2478             len = (int)strlen(buf);
 2479 
 2480             /*
 2481              * Now, let the normal header parsing algorithm below do its
 2482              * job.  If it fails, we'll exit instead of continuing.
 2483              */
 2484 
 2485             ms_iis5_hack = 1;
 2486          }
 2487 
 2488          /*
 2489           * If this is an SSL connection or we're in the body
 2490           * of the server document, just write it to the client,
 2491           * unless we need to buffer the body for later content-filtering
 2492           */
 2493          if (server_body || http->ssl)
 2494          {
 2495             if (buffer_and_filter_content)
 2496             {
 2497                /*
 2498                 * If there is no memory left for buffering the content, or the buffer limit
 2499                 * has been reached, switch to non-filtering mode, i.e. make & write the
 2500                 * header, flush the iob and buf, and get out of the way.
 2501                 */
 2502                if (add_to_iob(csp->iob, csp->config->buffer_limit, buf, len))
 2503                {
 2504                   size_t hdrlen;
 2505                   long flushed;
 2506 
 2507                   log_error(LOG_LEVEL_INFO,
 2508                      "Flushing header and buffers. Stepping back from filtering.");
 2509 
 2510                   hdr = list_to_text(csp->headers);
 2511                   if (hdr == NULL)
 2512                   {
 2513                      /*
 2514                       * Memory is too tight to even generate the header.
 2515                       * Send our static "Out-of-memory" page.
 2516                       */
 2517                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
 2518                      rsp = cgi_error_memory();
 2519                      send_crunch_response(csp, rsp);
 2520                      mark_server_socket_tainted(csp);
 2521                      return;
 2522                   }
 2523                   hdrlen = strlen(hdr);
 2524 
 2525                   if (write_socket(csp->cfd, hdr, hdrlen)
 2526                    || ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
 2527                    || (write_socket(csp->cfd, buf, (size_t)len)))
 2528                   {
 2529                      log_error(LOG_LEVEL_CONNECT,
 2530                         "Flush header and buffers to client failed: %E");
 2531                      freez(hdr);
 2532                      mark_server_socket_tainted(csp);
 2533                      return;
 2534                   }
 2535 
 2536                   /*
 2537                    * Reset the byte_count to the amount of bytes
 2538                    * we just flushed. len will be added a few lines below,
 2539                    * hdrlen doesn't matter for LOG_LEVEL_CLF.
 2540                    */
 2541                   byte_count = (unsigned long long)flushed;
 2542                   freez(hdr);
 2543                   buffer_and_filter_content = 0;
 2544                   server_body = 1;
 2545                }
 2546             }
 2547             else
 2548             {
 2549                if (write_socket(csp->cfd, buf, (size_t)len))
 2550                {
 2551                   log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
 2552                   mark_server_socket_tainted(csp);
 2553                   return;
 2554                }
 2555             }
 2556             byte_count += (unsigned long long)len;
 2557             continue;
 2558          }
 2559          else
 2560          {
 2561             /*
 2562              * We're still looking for the end of the server's header.
 2563              * Buffer up the data we just read.  If that fails, there's
 2564              * little we can do but send our static out-of-memory page.
 2565              */
 2566             if (add_to_iob(csp->iob, csp->config->buffer_limit, buf, len))
 2567             {
 2568                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
 2569                rsp = cgi_error_memory();
 2570                send_crunch_response(csp, rsp);
 2571                mark_server_socket_tainted(csp);
 2572                return;
 2573             }
 2574 
 2575             /* Convert iob into something sed() can digest */
 2576             if (JB_ERR_PARSE == get_server_headers(csp))
 2577             {
 2578                if (ms_iis5_hack)
 2579                {
 2580                   /*
 2581                    * Well, we tried our MS IIS/5 hack and it didn't work.
 2582                    * The header is incomplete and there isn't anything
 2583                    * we can do about it.
 2584                    */
 2585                   log_error(LOG_LEVEL_ERROR, "Invalid server headers. "
 2586                      "Applying the MS IIS5 hack didn't help.");
 2587                   log_error(LOG_LEVEL_CLF,
 2588                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
 2589                   write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
 2590                      strlen(INVALID_SERVER_HEADERS_RESPONSE));
 2591                   mark_server_socket_tainted(csp);
 2592                   return;
 2593                }
 2594                else
 2595                {
 2596                   /*
 2597                    * Since we have to wait for more from the server before
 2598                    * we can parse the headers we just continue here.
 2599                    */
 2600                   log_error(LOG_LEVEL_CONNECT,
 2601                      "Continuing buffering server headers from socket %d. "
 2602                      "Bytes most recently read: %d.", csp->cfd, len);
 2603                   continue;
 2604                }
 2605             }
 2606             else
 2607             {
 2608                /*
 2609                 * Account for the content bytes we
 2610                 * might have gotten with the headers.
 2611                 */
 2612                assert(csp->iob->eod >= csp->iob->cur);
 2613                byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
 2614             }
 2615 
 2616             /* Did we actually get anything? */
 2617             if (NULL == csp->headers->first)
 2618             {
 2619                if ((csp->flags & CSP_FLAG_REUSED_CLIENT_CONNECTION))
 2620                {
 2621                   log_error(LOG_LEVEL_ERROR,
 2622                      "No server or forwarder response received on socket %d. "
 2623                      "Closing client socket %d without sending data.",
 2624                      csp->server_connection.sfd, csp->cfd);
 2625                   log_error(LOG_LEVEL_CLF,
 2626                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
 2627                }
 2628                else
 2629                {
 2630                   log_error(LOG_LEVEL_ERROR,
 2631                      "No server or forwarder response received on socket %d.",
 2632                      csp->server_connection.sfd);
 2633                   send_crunch_response(csp, error_response(csp, "no-server-data"));
 2634                }
 2635                free_http_request(http);
 2636                mark_server_socket_tainted(csp);
 2637                return;
 2638             }
 2639 
 2640             assert(csp->headers->first->str);
 2641             assert(!http->ssl);
 2642             if (strncmpic(csp->headers->first->str, "HTTP", 4) &&
 2643                 strncmpic(csp->headers->first->str, "ICY", 3))
 2644             {
 2645                /*
 2646                 * It doesn't look like a HTTP (or Shoutcast) response:
 2647                 * tell the client and log the problem.
 2648                 */
 2649                if (strlen(csp->headers->first->str) > 30)
 2650                {
 2651                   csp->headers->first->str[30] = '\0';
 2652                }
 2653                log_error(LOG_LEVEL_ERROR,
 2654                   "Invalid server or forwarder response. Starts with: %s",
 2655                   csp->headers->first->str);
 2656                log_error(LOG_LEVEL_CLF,
 2657                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
 2658                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
 2659                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
 2660                free_http_request(http);
 2661                mark_server_socket_tainted(csp);
 2662                return;
 2663             }
 2664 
 2665             /*
 2666              * We have now received the entire server header,
 2667              * filter it and send the result to the client
 2668              */
 2669             if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS))
 2670             {
 2671                log_error(LOG_LEVEL_CLF,
 2672                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
 2673                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
 2674                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
 2675                free_http_request(http);
 2676                mark_server_socket_tainted(csp);
 2677                return;
 2678             }
 2679             hdr = list_to_text(csp->headers);
 2680             if (hdr == NULL)
 2681             {
 2682                /* FIXME Should handle error properly */
 2683                log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
 2684             }
 2685 
 2686             if ((csp->flags & CSP_FLAG_CHUNKED)
 2687                && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
 2688                && ((csp->iob->eod - csp->iob->cur) >= 5)
 2689                && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
 2690             {
 2691                log_error(LOG_LEVEL_CONNECT,
 2692                   "Looks like we got the last chunk together with "
 2693                   "the server headers. We better stop reading.");
 2694                byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
 2695                csp->expected_content_length = byte_count;
 2696                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
 2697             }
 2698 
 2699             csp->server_connection.response_received = time(NULL);
 2700 
 2701             if (crunch_response_triggered(csp, crunchers_light))
 2702             {
 2703                /*
 2704                 * One of the tags created by a server-header
 2705                 * tagger triggered a crunch. We already
 2706                 * delivered the crunch response to the client
 2707                 * and are done here after cleaning up.
 2708                 */
 2709                 freez(hdr);
 2710                 mark_server_socket_tainted(csp);
 2711                 return;
 2712             }
 2713             /* Buffer and pcrs filter this if appropriate. */
 2714 
 2715             if (!http->ssl) /* We talk plaintext */
 2716             {
 2717                buffer_and_filter_content = content_requires_filtering(csp);
 2718             }
 2719             /*
 2720              * Only write if we're not buffering for content modification
 2721              */
 2722             if (!buffer_and_filter_content)
 2723             {
 2724                /*
 2725                 * Write the server's (modified) header to
 2726                 * the client (along with anything else that
 2727                 * may be in the buffer)
 2728                 */
 2729 
 2730                if (write_socket(csp->cfd, hdr, strlen(hdr))
 2731                 || ((len = flush_socket(csp->cfd, csp->iob)) < 0))
 2732                {
 2733                   log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
 2734 
 2735                   /*
 2736                    * The write failed, so don't bother mentioning it
 2737                    * to the client... it probably can't hear us anyway.
 2738                    */
 2739                   freez(hdr);
 2740                   mark_server_socket_tainted(csp);
 2741                   return;
 2742                }
 2743             }
 2744 
 2745             /* we're finished with the server's header */
 2746 
 2747             freez(hdr);
 2748             server_body = 1;
 2749 
 2750             /*
 2751              * If this was a MS IIS/5 hack then it means the server
 2752              * has already closed the connection. Nothing more to read.
 2753              * Time to bail.
 2754              */
 2755             if (ms_iis5_hack)
 2756             {
 2757                log_error(LOG_LEVEL_ERROR,
 2758                   "Closed server connection detected. "
 2759                   "Applying the MS IIS5 hack didn't help.");
 2760                log_error(LOG_LEVEL_CLF,
 2761                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
 2762                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
 2763                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
 2764                mark_server_socket_tainted(csp);
 2765                return;
 2766             }
 2767          }
 2768          continue;
 2769       }
 2770       mark_server_socket_tainted(csp);
 2771       return; /* huh? we should never get here */
 2772    }
 2773 
 2774    if (csp->content_length == 0)
 2775    {
 2776       /*
 2777        * If Privoxy didn't recalculate the Content-Length,
 2778        * byte_count is still correct.
 2779        */
 2780       csp->content_length = byte_count;
 2781    }
 2782 
 2783 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2784    if ((csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
 2785       && (csp->expected_content_length != byte_count))
 2786    {
 2787       log_error(LOG_LEVEL_CONNECT,
 2788          "Received %llu bytes while expecting %llu.",
 2789          byte_count, csp->expected_content_length);
 2790       mark_server_socket_tainted(csp);
 2791    }
 2792 #endif
 2793 
 2794    log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
 2795       csp->ip_addr_str, http->ocmd, csp->content_length);
 2796 
 2797    csp->server_connection.timestamp = time(NULL);
 2798 }
 2799 
 2800 
 2801 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2802 /*********************************************************************
 2803  *
 2804  * Function    :  prepare_csp_for_next_request
 2805  *
 2806  * Description :  Put the csp in a mostly vergin state.
 2807  *
 2808  * Parameters  :
 2809  *          1  :  csp = Current client state (buffers, headers, etc...)
 2810  *
 2811  * Returns     :  N/A
 2812  *
 2813  *********************************************************************/
 2814 static void prepare_csp_for_next_request(struct client_state *csp)
 2815 {
 2816    csp->content_type = 0;
 2817    csp->content_length = 0;
 2818    csp->expected_content_length = 0;
 2819    csp->expected_client_content_length = 0;
 2820    list_remove_all(csp->headers);
 2821    clear_iob(csp->iob);
 2822    freez(csp->error_message);
 2823    free_http_request(csp->http);
 2824    destroy_list(csp->headers);
 2825    destroy_list(csp->tags);
 2826 #ifdef FEATURE_CLIENT_TAGS
 2827    destroy_list(csp->client_tags);
 2828    freez(csp->client_address);
 2829 #endif
 2830    free_current_action(csp->action);
 2831    if (NULL != csp->fwd)
 2832    {
 2833       unload_forward_spec(csp->fwd);
 2834       csp->fwd = NULL;
 2835    }
 2836    /* XXX: Store per-connection flags someplace else. */
 2837    csp->flags = (CSP_FLAG_ACTIVE | CSP_FLAG_REUSED_CLIENT_CONNECTION);
 2838 #ifdef FEATURE_TOGGLE
 2839    if (global_toggle_state)
 2840 #endif /* def FEATURE_TOGGLE */
 2841    {
 2842       csp->flags |= CSP_FLAG_TOGGLED_ON;
 2843    }
 2844 
 2845    if (csp->client_iob->eod > csp->client_iob->cur)
 2846    {
 2847       long bytes_to_shift = csp->client_iob->cur - csp->client_iob->buf;
 2848       size_t data_length  = (size_t)(csp->client_iob->eod - csp->client_iob->cur);
 2849 
 2850       assert(bytes_to_shift > 0);
 2851       assert(data_length > 0);
 2852 
 2853       log_error(LOG_LEVEL_CONNECT, "Shifting %d pipelined bytes by %d bytes",
 2854          data_length, bytes_to_shift);
 2855       memmove(csp->client_iob->buf, csp->client_iob->cur, data_length);
 2856       csp->client_iob->cur = csp->client_iob->buf;
 2857       assert(csp->client_iob->eod == csp->client_iob->buf + bytes_to_shift + data_length);
 2858       csp->client_iob->eod = csp->client_iob->buf + data_length;
 2859       memset(csp->client_iob->eod, '\0', (size_t)bytes_to_shift);
 2860 
 2861       csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
 2862    }
 2863    else
 2864    {
 2865       /*
 2866        * We mainly care about resetting client_iob->cur so we don't
 2867        * waste buffer space at the beginning and don't mess up the
 2868        * request restoration done by cgi_show_request().
 2869        *
 2870        * Freeing the buffer itself isn't technically necessary,
 2871        * but makes debugging more convenient.
 2872        */
 2873       clear_iob(csp->client_iob);
 2874    }
 2875 }
 2876 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 2877 
 2878 
 2879 /*********************************************************************
 2880  *
 2881  * Function    :  serve
 2882  *
 2883  * Description :  This is little more than chat.  We only "serve" to
 2884  *                to close (or remember) any socket that chat may have
 2885  *                opened.
 2886  *
 2887  * Parameters  :
 2888  *          1  :  csp = Current client state (buffers, headers, etc...)
 2889  *
 2890  * Returns     :  N/A
 2891  *
 2892  *********************************************************************/
 2893 #ifdef AMIGA
 2894 void serve(struct client_state *csp)
 2895 #else /* ifndef AMIGA */
 2896 static void serve(struct client_state *csp)
 2897 #endif /* def AMIGA */
 2898 {
 2899    int config_file_change_detected = 0; /* Only used for debugging */
 2900 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 2901 #ifdef FEATURE_CONNECTION_SHARING
 2902    static int monitor_thread_running = 0;
 2903 #endif /* def FEATURE_CONNECTION_SHARING */
 2904    int continue_chatting = 0;
 2905 
 2906    log_error(LOG_LEVEL_CONNECT, "Accepted connection from %s on socket %d",
 2907       csp->ip_addr_str, csp->cfd);
 2908 
 2909    do
 2910    {
 2911       unsigned int latency;
 2912 
 2913       chat(csp);
 2914 
 2915       /*
 2916        * If the request has been crunched,
 2917        * the calculated latency is zero.
 2918        */
 2919       latency = (unsigned)(csp->server_connection.response_received -
 2920          csp->server_connection.request_sent) / 2;
 2921 
 2922       if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
 2923          && (csp->flags & CSP_FLAG_CRUNCHED)
 2924          && (csp->expected_client_content_length != 0))
 2925       {
 2926          csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
 2927          log_error(LOG_LEVEL_CONNECT,
 2928             "Tainting client socket %d due to unread data.", csp->cfd);
 2929       }
 2930 
 2931       continue_chatting = (csp->config->feature_flags
 2932          & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
 2933          && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
 2934          && (csp->cfd != JB_INVALID_SOCKET)
 2935          && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
 2936          && ((csp->flags & CSP_FLAG_SERVER_CONTENT_LENGTH_SET)
 2937             || (csp->flags & CSP_FLAG_CHUNKED));
 2938 
 2939       if (!(csp->flags & CSP_FLAG_CRUNCHED)
 2940          && (csp->server_connection.sfd != JB_INVALID_SOCKET))
 2941       {
 2942          if (!(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET))
 2943          {
 2944             csp->server_connection.keep_alive_timeout = csp->config->default_server_timeout;
 2945          }
 2946          if (!(csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
 2947             || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
 2948             || !socket_is_still_alive(csp->server_connection.sfd)
 2949             || !(latency < csp->server_connection.keep_alive_timeout))
 2950          {
 2951             log_error(LOG_LEVEL_CONNECT,
 2952                "Closing server socket %d connected to %s. "
 2953                "Keep-alive %u. Tainted: %u. Socket alive %u. Timeout: %u.",
 2954                csp->server_connection.sfd, csp->server_connection.host,
 2955                0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
 2956                0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
 2957                socket_is_still_alive(csp->server_connection.sfd),
 2958                csp->server_connection.keep_alive_timeout);
 2959 #ifdef FEATURE_CONNECTION_SHARING
 2960             if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
 2961             {
 2962                forget_connection(csp->server_connection.sfd);
 2963             }
 2964 #endif /* def FEATURE_CONNECTION_SHARING */
 2965             close_socket(csp->server_connection.sfd);
 2966             mark_connection_closed(&csp->server_connection);
 2967          }
 2968       }
 2969 
 2970       if (continue_chatting && any_loaded_file_changed(csp))
 2971       {
 2972          continue_chatting = 0;
 2973          config_file_change_detected = 1;
 2974       }
 2975 
 2976       if (continue_chatting)
 2977       {
 2978          if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
 2979             && socket_is_still_alive(csp->cfd))
 2980          {
 2981             log_error(LOG_LEVEL_CONNECT, "Client request %d has been "
 2982                "pipelined on socket %d and the socket is still alive.",
 2983                csp->requests_received_total+1, csp->cfd);
 2984             prepare_csp_for_next_request(csp);
 2985             continue;
 2986          }
 2987 
 2988          if (0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
 2989          {
 2990             if (csp->server_connection.sfd != JB_INVALID_SOCKET)
 2991             {
 2992                log_error(LOG_LEVEL_CONNECT,
 2993                   "Waiting for the next client request on socket %d. "
 2994                   "Keeping the server socket %d to %s open.",
 2995                   csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
 2996             }
 2997             else
 2998             {
 2999                log_error(LOG_LEVEL_CONNECT,
 3000                   "Waiting for the next client request on socket %d. "
 3001                   "No server socket to keep open.", csp->cfd);
 3002             }
 3003          }
 3004 
 3005          if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
 3006             && data_is_available(csp->cfd, (int)csp->config->keep_alive_timeout)
 3007             && socket_is_still_alive(csp->cfd))
 3008          {
 3009             log_error(LOG_LEVEL_CONNECT,
 3010                "Client request %u arrived in time on socket %d.",
 3011                csp->requests_received_total+1, csp->cfd);
 3012             prepare_csp_for_next_request(csp);
 3013          }
 3014          else
 3015          {
 3016 #ifdef FEATURE_CONNECTION_SHARING
 3017             if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
 3018                && (csp->server_connection.sfd != JB_INVALID_SOCKET)
 3019                && (socket_is_still_alive(csp->server_connection.sfd)))
 3020             {
 3021                time_t time_open = time(NULL) - csp->server_connection.timestamp;
 3022 
 3023                if (csp->server_connection.keep_alive_timeout < time_open - (time_t)latency)
 3024                {
 3025                   break;
 3026                }
 3027 
 3028                remember_connection(&csp->server_connection);
 3029                csp->server_connection.sfd = JB_INVALID_SOCKET;
 3030                drain_and_close_socket(csp->cfd);
 3031                csp->cfd = JB_INVALID_SOCKET;
 3032                privoxy_mutex_lock(&connection_reuse_mutex);
 3033                if (!monitor_thread_running)
 3034                {
 3035                   monitor_thread_running = 1;
 3036                   privoxy_mutex_unlock(&connection_reuse_mutex);
 3037                   wait_for_alive_connections();
 3038                   privoxy_mutex_lock(&connection_reuse_mutex);
 3039                   monitor_thread_running = 0;
 3040                }
 3041                privoxy_mutex_unlock(&connection_reuse_mutex);
 3042             }
 3043 #endif /* def FEATURE_CONNECTION_SHARING */
 3044             break;
 3045          }
 3046       }
 3047       else if (csp->server_connection.sfd != JB_INVALID_SOCKET)
 3048       {
 3049          log_error(LOG_LEVEL_CONNECT,
 3050             "Closing server socket %d connected to %s. Keep-alive: %u. "
 3051             "Tainted: %u. Socket alive: %u. Timeout: %u. "
 3052             "Configuration file change detected: %u",
 3053             csp->server_connection.sfd, csp->server_connection.host,
 3054             0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
 3055             0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
 3056             socket_is_still_alive(csp->server_connection.sfd),
 3057             csp->server_connection.keep_alive_timeout,
 3058             config_file_change_detected);
 3059       }
 3060    } while (continue_chatting);
 3061 
 3062 #else
 3063    chat(csp);
 3064 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 3065 
 3066    if (csp->server_connection.sfd != JB_INVALID_SOCKET)
 3067    {
 3068 #ifdef FEATURE_CONNECTION_SHARING
 3069       if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
 3070       {
 3071          forget_connection(csp->server_connection.sfd);
 3072       }
 3073 #endif /* def FEATURE_CONNECTION_SHARING */
 3074       close_socket(csp->server_connection.sfd);
 3075    }
 3076 
 3077 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
 3078    mark_connection_closed(&csp->server_connection);
 3079 #endif
 3080 
 3081    if (csp->cfd != JB_INVALID_SOCKET)
 3082    {
 3083       log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. "
 3084          "Keep-alive: %u. Socket alive: %u. Data available: %u. "
 3085          "Configuration file change detected: %u. Requests received: %u.",
 3086          csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE),
 3087          socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0),
 3088          config_file_change_detected, csp->requests_received_total);
 3089       drain_and_close_socket(csp->cfd);
 3090    }
 3091 
 3092    csp->flags &= ~CSP_FLAG_ACTIVE;
 3093 
 3094 }
 3095 
 3096 
 3097 #ifdef __BEOS__
 3098 /*********************************************************************
 3099  *
 3100  * Function    :  server_thread
 3101  *
 3102  * Description :  We only exist to call `serve' in a threaded environment.
 3103  *
 3104  * Parameters  :
 3105  *          1  :  data = Current client state (buffers, headers, etc...)
 3106  *
 3107  * Returns     :  Always 0.
 3108  *
 3109  *********************************************************************/
 3110 static int32 server_thread(void *data)
 3111 {
 3112    serve((struct client_state *) data);
 3113    return 0;
 3114 
 3115 }
 3116 #endif
 3117 
 3118 
 3119 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
 3120 /*********************************************************************
 3121  *
 3122  * Function    :  usage
 3123  *
 3124  * Description :  Print usage info & exit.
 3125  *
 3126  * Parameters  :  Pointer to argv[0] for identifying ourselves
 3127  *
 3128  * Returns     :  No. ,-)
 3129  *
 3130  *********************************************************************/
 3131 static void usage(const char *myname)
 3132 {
 3133    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
 3134           "Usage: %s [--config-test] "
 3135 #if defined(unix)
 3136           "[--chroot] "
 3137 #endif /* defined(unix) */
 3138           "[--help] "
 3139 #if defined(unix)
 3140           "[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
 3141 #endif /* defined(unix) */
 3142           "[--version] [configfile]\n"
 3143           "Aborting\n", myname);
 3144 
 3145    exit(2);
 3146 
 3147 }
 3148 #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */
 3149 
 3150 
 3151 #ifdef MUTEX_LOCKS_AVAILABLE
 3152 /*********************************************************************
 3153  *
 3154  * Function    :  privoxy_mutex_lock
 3155  *
 3156  * Description :  Locks a mutex.
 3157  *
 3158  * Parameters  :
 3159  *          1  :  mutex = The mutex to lock.
 3160  *
 3161  * Returns     :  Void. May exit in case of errors.
 3162  *
 3163  *********************************************************************/
 3164 void privoxy_mutex_lock(privoxy_mutex_t *mutex)
 3165 {
 3166 #ifdef FEATURE_PTHREAD
 3167    int err = pthread_mutex_lock(mutex);
 3168    if (err)
 3169    {
 3170       if (mutex != &log_mutex)
 3171       {
 3172          log_error(LOG_LEVEL_FATAL,
 3173             "Mutex locking failed: %s.\n", strerror(err));
 3174       }
 3175       exit(1);
 3176    }
 3177 #else
 3178    EnterCriticalSection(mutex);
 3179 #endif /* def FEATURE_PTHREAD */
 3180 }
 3181 
 3182 
 3183 /*********************************************************************
 3184  *
 3185  * Function    :  privoxy_mutex_unlock
 3186  *
 3187  * Description :  Unlocks a mutex.
 3188  *
 3189  * Parameters  :
 3190  *          1  :  mutex = The mutex to unlock.
 3191  *
 3192  * Returns     :  Void. May exit in case of errors.
 3193  *
 3194  *********************************************************************/
 3195 void privoxy_mutex_unlock(privoxy_mutex_t *mutex)
 3196 {
 3197 #ifdef FEATURE_PTHREAD
 3198    int err = pthread_mutex_unlock(mutex);
 3199    if (err)
 3200    {
 3201       if (mutex != &log_mutex)
 3202       {
 3203          log_error(LOG_LEVEL_FATAL,
 3204             "Mutex unlocking failed: %s.\n", strerror(err));
 3205       }
 3206       exit(1);
 3207    }
 3208 #else
 3209    LeaveCriticalSection(mutex);
 3210 #endif /* def FEATURE_PTHREAD */
 3211 }
 3212 
 3213 
 3214 /*********************************************************************
 3215  *
 3216  * Function    :  privoxy_mutex_init
 3217  *
 3218  * Description :  Prepares a mutex.
 3219  *
 3220  * Parameters  :
 3221  *          1  :  mutex = The mutex to initialize.
 3222  *
 3223  * Returns     :  Void. May exit in case of errors.
 3224  *
 3225  *********************************************************************/
 3226 static void privoxy_mutex_init(privoxy_mutex_t *mutex)
 3227 {
 3228 #ifdef FEATURE_PTHREAD
 3229    int err = pthread_mutex_init(mutex, 0);
 3230    if (err)
 3231    {
 3232       printf("Fatal error. Mutex initialization failed: %s.\n",
 3233          strerror(err));
 3234       exit(1);
 3235    }
 3236 #else
 3237    InitializeCriticalSection(mutex);
 3238 #endif /* def FEATURE_PTHREAD */
 3239 }
 3240 #endif /* def MUTEX_LOCKS_AVAILABLE */
 3241 
 3242 /*********************************************************************
 3243  *
 3244  * Function    :  initialize_mutexes
 3245  *
 3246  * Description :  Prepares mutexes if mutex support is available.
 3247  *
 3248  * Parameters  :  None
 3249  *
 3250  * Returns     :  Void, exits in case of errors.
 3251  *
 3252  *********************************************************************/
 3253 static void initialize_mutexes(void)
 3254 {
 3255 #ifdef MUTEX_LOCKS_AVAILABLE
 3256    /*
 3257     * Prepare global mutex semaphores
 3258     */
 3259    privoxy_mutex_init(&log_mutex);
 3260    privoxy_mutex_init(&log_init_mutex);
 3261    privoxy_mutex_init(&connection_reuse_mutex);
 3262 #ifdef FEATURE_EXTERNAL_FILTERS
 3263    privoxy_mutex_init(&external_filter_mutex);
 3264 #endif
 3265 #ifdef FEATURE_CLIENT_TAGS
 3266    privoxy_mutex_init(&client_tags_mutex);
 3267 #endif
 3268 
 3269    /*
 3270     * XXX: The assumptions below are a bit naive
 3271     * and can cause locks that aren't necessary.
 3272     *
 3273     * For example older FreeBSD versions (< 6.x?)
 3274     * have no gethostbyname_r, but gethostbyname is
 3275     * thread safe.
 3276     */
 3277 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
 3278    privoxy_mutex_init(&resolver_mutex);
 3279 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
 3280    /*
 3281     * XXX: should we use a single mutex for
 3282     * localtime() and gmtime() as well?
 3283     */
 3284 #ifndef HAVE_GMTIME_R
 3285    privoxy_mutex_init(&gmtime_mutex);
 3286 #endif /* ndef HAVE_GMTIME_R */
 3287 
 3288 #ifndef HAVE_LOCALTIME_R
 3289    privoxy_mutex_init(&localtime_mutex);
 3290 #endif /* ndef HAVE_GMTIME_R */
 3291 
 3292 #ifndef HAVE_RANDOM
 3293    privoxy_mutex_init(&rand_mutex);
 3294 #endif /* ndef HAVE_RANDOM */
 3295 
 3296 #endif /* def MUTEX_LOCKS_AVAILABLE */
 3297 }
 3298 
 3299 
 3300 /*********************************************************************
 3301  *
 3302  * Function    :  main
 3303  *
 3304  * Description :  Load the config file and start the listen loop.
 3305  *                This function is a lot more *sane* with the `load_config'
 3306  *                and `listen_loop' functions; although it stills does
 3307  *                a *little* too much for my taste.
 3308  *
 3309  * Parameters  :
 3310  *          1  :  argc = Number of parameters (including $0).
 3311  *          2  :  argv = Array of (char *)'s to the parameters.
 3312  *
 3313  * Returns     :  1 if : can't open config file, unrecognized directive,
 3314  *                stats requested in multi-thread mode, can't open the
 3315  *                log file, can't open the jar file, listen port is invalid,
 3316  *                any load fails, and can't bind port.
 3317  *
 3318  *                Else main never returns, the process must be signaled
 3319  *                to terminate execution.  Or, on Windows, use the
 3320  *                "File", "Exit" menu option.
 3321  *
 3322  *********************************************************************/
 3323 #ifdef __MINGW32__
 3324 int real_main(int argc, char **argv)
 3325 #else
 3326 int main(int argc, char **argv)
 3327 #endif
 3328 {
 3329    int argc_pos = 0;
 3330    int do_config_test = 0;
 3331    unsigned int random_seed;
 3332 #ifdef unix
 3333    struct passwd *pw = NULL;
 3334    struct group *grp = NULL;
 3335    int do_chroot = 0;
 3336    char *pre_chroot_nslookup_to_load_resolver = NULL;
 3337 #endif
 3338 
 3339    Argc = argc;
 3340    Argv = argv;
 3341 
 3342    configfile =
 3343 #if !defined(_WIN32)
 3344    "config"
 3345 #else
 3346    "config.txt"
 3347 #endif
 3348       ;
 3349 
 3350    /* Prepare mutexes if supported and necessary. */
 3351    initialize_mutexes();
 3352 
 3353    /* Enable logging until further notice. */
 3354    init_log_module();
 3355 
 3356    /*
 3357     * Parse the command line arguments
 3358     *
 3359     * XXX: simply printing usage information in case of
 3360     * invalid arguments isn't particularly user friendly.
 3361     */
 3362    while (++argc_pos < argc)
 3363    {
 3364 #ifdef _WIN32
 3365       /* Check to see if the service must be installed or uninstalled */
 3366       if (strncmp(argv[argc_pos], "--install", 9) == 0)
 3367       {
 3368          const char *pName = argv[argc_pos] + 9;
 3369          if (*pName == ':')
 3370             pName++;
 3371          exit((install_service(pName)) ? 0 : 1);
 3372       }
 3373       else if (strncmp(argv[argc_pos], "--uninstall", 11) == 0)
 3374       {
 3375          const char *pName = argv[argc_pos] + 11;
 3376          if (*pName == ':')
 3377             pName++;
 3378          exit((uninstall_service(pName)) ? 0 : 1);
 3379       }
 3380       else if (strcmp(argv[argc_pos], "--service") == 0)
 3381       {
 3382          bRunAsService = TRUE;
 3383          w32_set_service_cwd();
 3384          atexit(w32_service_exit_notify);
 3385       }
 3386       else
 3387 #endif /* defined(_WIN32) */
 3388 
 3389 
 3390 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
 3391 
 3392       if (strcmp(argv[argc_pos], "--help") == 0)
 3393       {
 3394          usage(argv[0]);
 3395       }
 3396 
 3397       else if (strcmp(argv[argc_pos], "--version") == 0)
 3398       {
 3399          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
 3400          exit(0);
 3401       }
 3402 
 3403 #if defined(unix)
 3404 
 3405       else if (strcmp(argv[argc_pos], "--no-daemon") == 0)
 3406       {
 3407          set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
 3408          daemon_mode = 0;
 3409       }
 3410 
 3411       else if (strcmp(argv[argc_pos], "--pidfile") == 0)
 3412       {
 3413          if (++argc_pos == argc) usage(argv[0]);
 3414          pidfile = strdup_or_die(argv[argc_pos]);
 3415       }
 3416 
 3417       else if (strcmp(argv[argc_pos], "--user") == 0)
 3418       {
 3419          char *user_arg;
 3420          char *group_name;
 3421 
 3422          if (++argc_pos == argc) usage(argv[argc_pos]);
 3423 
 3424          user_arg = strdup_or_die(argv[argc_pos]);
 3425          group_name = strchr(user_arg, '.');
 3426          if (NULL != group_name)
 3427          {
 3428             /* Nul-terminate the user name */
 3429             *group_name = '\0';
 3430 
 3431             /* Skip the former delimiter to actually reach the group name */
 3432             group_name++;
 3433 
 3434             grp = getgrnam(group_name);
 3435             if (NULL == grp)
 3436             {
 3437                log_error(LOG_LEVEL_FATAL, "Group '%s' not found.", group_name);
 3438             }
 3439          }
 3440          pw = getpwnam(user_arg);
 3441          if (NULL == pw)
 3442          {
 3443             log_error(LOG_LEVEL_FATAL, "User '%s' not found.", user_arg);
 3444          }
 3445 
 3446          freez(user_arg);
 3447       }
 3448 
 3449       else if (strcmp(argv[argc_pos], "--pre-chroot-nslookup") == 0)
 3450       {
 3451          if (++argc_pos == argc) usage(argv[0]);
 3452          pre_chroot_nslookup_to_load_resolver = strdup_or_die(argv[argc_pos]);
 3453       }
 3454 
 3455       else if (strcmp(argv[argc_pos], "--chroot") == 0)
 3456       {
 3457          do_chroot = 1;
 3458       }
 3459 #endif /* defined(unix) */
 3460 
 3461       else if (strcmp(argv[argc_pos], "--config-test") == 0)
 3462       {
 3463          do_config_test = 1;
 3464       }
 3465 
 3466       else if (argc_pos + 1 != argc)
 3467       {
 3468          /*
 3469           * This is neither the last command line
 3470           * option, nor was it recognized before,
 3471           * therefore it must be invalid.
 3472           */
 3473          usage(argv[0]);
 3474       }
 3475       else
 3476 
 3477 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
 3478       {
 3479          configfile = argv[argc_pos];
 3480       }
 3481 
 3482    } /* -END- while (more arguments) */
 3483 
 3484    show_version(Argv[0]);
 3485 
 3486 #if defined(unix)
 3487    if (*configfile != '/')
 3488    {
 3489       char cwd[BUFFER_SIZE];
 3490       char *abs_file;
 3491       size_t abs_file_size;
 3492 
 3493       /* make config-filename absolute here */
 3494       if (NULL == getcwd(cwd, sizeof(cwd)))
 3495       {
 3496          perror("failed to get current working directory");
 3497          exit(1);
 3498       }
 3499 
 3500       basedir = strdup_or_die(cwd);
 3501       /* XXX: why + 5? */
 3502       abs_file_size = strlen(cwd) + strlen(configfile) + 5;
 3503       abs_file = malloc_or_die(abs_file_size);
 3504       strlcpy(abs_file, basedir, abs_file_size);
 3505       strlcat(abs_file, "/", abs_file_size);
 3506       strlcat(abs_file, configfile, abs_file_size);
 3507       configfile = abs_file;
 3508    }
 3509 #endif /* defined unix */
 3510 
 3511 
 3512    files->next = NULL;
 3513    clients->next = NULL;
 3514 
 3515    /* XXX: factor out initialising after the next stable release. */
 3516 #ifdef AMIGA
 3517    InitAmiga();
 3518 #elif defined(_WIN32)
 3519    InitWin32();
 3520 #endif
 3521 
 3522    random_seed = (unsigned int)time(NULL);
 3523 #ifdef HAVE_RANDOM
 3524    srandom(random_seed);
 3525 #else
 3526    srand(random_seed);
 3527 #endif /* ifdef HAVE_RANDOM */
 3528 
 3529    /*
 3530     * Unix signal handling
 3531     *
 3532     * Catch the abort, interrupt and terminate signals for a graceful exit
 3533     * Catch the hangup signal so the errlog can be reopened.
 3534     * Ignore the broken pipe signals (FIXME: Why?)
 3535     */
 3536 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
 3537 {
 3538    int idx;
 3539    const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP };
 3540 
 3541    for (idx = 0; idx < SZ(catched_signals); idx++)
 3542    {
 3543 #ifdef sun /* FIXME: Is it safe to check for HAVE_SIGSET instead? */
 3544       if (sigset(catched_signals[idx], sig_handler) == SIG_ERR)
 3545 #else
 3546       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
 3547 #endif /* ifdef sun */
 3548       {
 3549          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
 3550       }
 3551    }
 3552 
 3553    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
 3554    {
 3555       log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for SIGPIPE: %E");
 3556    }
 3557 
 3558 }
 3559 #else /* ifdef _WIN32 */
 3560 # ifdef _WIN_CONSOLE
 3561    /*
 3562     * We *are* in a windows console app.
 3563     * Print a verbose messages about FAQ's and such
 3564     */
 3565    printf("%s", win32_blurb);
 3566 # endif /* def _WIN_CONSOLE */
 3567 #endif /* def _WIN32 */
 3568 
 3569    if (do_config_test)
 3570    {
 3571       exit(NULL == load_config());
 3572    }
 3573 
 3574    /* Initialize the CGI subsystem */
 3575    cgi_init_error_messages();
 3576 
 3577    /*
 3578     * If running on unix and without the --no-daemon
 3579     * option, become a daemon. I.e. fork, detach
 3580     * from tty and get process group leadership
 3581     */
 3582 #if defined(unix)
 3583 {
 3584    if (daemon_mode)
 3585    {
 3586       int fd;
 3587       pid_t pid = fork();
 3588 
 3589       if (pid < 0) /* error */
 3590       {
 3591          perror("fork");
 3592          exit(3);
 3593       }
 3594       else if (pid != 0) /* parent */
 3595       {
 3596          int status;
 3597          pid_t wpid;
 3598          /*
 3599           * must check for errors
 3600           * child died due to missing files aso
 3601           */
 3602          sleep(1);
 3603          wpid = waitpid(pid, &status, WNOHANG);
 3604          if (wpid != 0)
 3605          {
 3606             exit(1);
 3607          }
 3608          exit(0);
 3609       }
 3610       /* child */
 3611 
 3612       setsid();
 3613 
 3614       /*
 3615        * stderr (fd 2) will be closed later on,
 3616        * when the config file has been parsed.
 3617        */
 3618       close(0);
 3619       close(1);
 3620 
 3621       /*
 3622        * Reserve fd 0 and 1 to prevent abort() and friends
 3623        * from sending stuff to the clients or servers.
 3624        */
 3625       fd = open("/dev/null", O_RDONLY);
 3626       if (fd == -1)
 3627       {
 3628          log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
 3629       }
 3630       else if (fd != 0)
 3631       {
 3632          if (dup2(fd, 0) == -1)
 3633          {
 3634             log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 0: %E");
 3635          }
 3636          close(fd);
 3637       }
 3638       fd = open("/dev/null", O_WRONLY);
 3639       if (fd == -1)
 3640       {
 3641          log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
 3642       }
 3643       else if (fd != 1)
 3644       {
 3645          if (dup2(fd, 1) == -1)
 3646          {
 3647             log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 1: %E");
 3648          }
 3649          close(fd);
 3650       }
 3651 
 3652 #ifdef FEATURE_EXTERNAL_FILTERS
 3653       for (fd = 0; fd < 3; fd++)
 3654       {
 3655          mark_socket_for_close_on_execute(fd);
 3656       }
 3657 #endif
 3658 
 3659       chdir("/");
 3660 
 3661    } /* -END- if (daemon_mode) */
 3662 
 3663    /*
 3664     * As soon as we have written the PID file, we can switch
 3665     * to the user and group ID indicated by the --user option
 3666     */
 3667    write_pid_file();
 3668 
 3669    if (NULL != pw)
 3670    {
 3671       if (setgid((NULL != grp) ? grp->gr_gid : pw->pw_gid))
 3672       {
 3673          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
 3674       }
 3675       if (NULL != grp)
 3676       {
 3677          if (setgroups(1, &grp->gr_gid))
 3678          {
 3679             log_error(LOG_LEVEL_FATAL, "setgroups() failed: %E");
 3680          }
 3681       }
 3682       else if (initgroups(pw->pw_name, pw->pw_gid))
 3683       {
 3684          log_error(LOG_LEVEL_FATAL, "initgroups() failed: %E");
 3685       }
 3686       if (do_chroot)
 3687       {
 3688          if (!pw->pw_dir)
 3689          {
 3690             log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
 3691          }
 3692          /* Read the time zone file from /etc before doing chroot. */
 3693          tzset();
 3694          if (NULL != pre_chroot_nslookup_to_load_resolver
 3695              && '\0' != pre_chroot_nslookup_to_load_resolver[0])
 3696          {
 3697             /* Initialize resolver library. */
 3698             (void) resolve_hostname_to_ip(pre_chroot_nslookup_to_load_resolver);
 3699          }
 3700          if (chroot(pw->pw_dir) < 0)
 3701          {
 3702             log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
 3703          }
 3704          if (chdir ("/"))
 3705          {
 3706             log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
 3707          }
 3708       }
 3709       if (setuid(pw->pw_uid))
 3710       {
 3711          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
 3712       }
 3713       if (do_chroot)
 3714       {
 3715          char putenv_dummy[64];
 3716 
 3717          strlcpy(putenv_dummy, "HOME=/", sizeof(putenv_dummy));
 3718          if (putenv(putenv_dummy) != 0)
 3719          {
 3720             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
 3721          }
 3722 
 3723          snprintf(putenv_dummy, sizeof(putenv_dummy), "USER=%s", pw->pw_name);
 3724          if (putenv(putenv_dummy) != 0)
 3725          {
 3726             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
 3727          }
 3728       }
 3729    }
 3730    else if (do_chroot)
 3731    {
 3732       log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
 3733    }
 3734 }
 3735 #endif /* defined unix */
 3736 
 3737 #ifdef _WIN32
 3738    /* This will be FALSE unless the command line specified --service
 3739     */
 3740    if (bRunAsService)
 3741    {
 3742       /* Yup, so now we must attempt to establish a connection
 3743        * with the service dispatcher. This will only work if this
 3744        * process was launched by the service control manager to
 3745        * actually run as a service. If this isn't the case, i've
 3746        * known it take around 30 seconds or so for the call to return.
 3747        */
 3748 
 3749       /* The StartServiceCtrlDispatcher won't return until the service is stopping */
 3750       if (w32_start_service_ctrl_dispatcher(w32ServiceDispatchTable))
 3751       {
 3752          /* Service has run, and at this point is now being stopped, so just return */
 3753          return 0;
 3754       }
 3755 
 3756 #ifdef _WIN_CONSOLE
 3757       printf("Warning: Failed to connect to Service Control Dispatcher\nwhen starting as a service!\n");
 3758 #endif
 3759       /* An error occurred. Usually it's because --service was wrongly specified
 3760        * and we were unable to connect to the Service Control Dispatcher because
 3761        * it wasn't expecting us and is therefore not listening.
 3762        *
 3763        * For now, just continue below to call the listen_loop function.
 3764        */
 3765    }
 3766 #endif /* def _WIN32 */
 3767 
 3768    listen_loop();
 3769 
 3770    /* NOTREACHED */
 3771    return(-1);
 3772 
 3773 }
 3774 
 3775 
 3776 /*********************************************************************
 3777  *
 3778  * Function    :  bind_port_helper
 3779  *
 3780  * Description :  Bind the listen port.  Handles logging, and aborts
 3781  *                on failure.
 3782  *
 3783  * Parameters  :
 3784  *          1  :  haddr = Host address to bind to. Use NULL to bind to
 3785  *                        INADDR_ANY.
 3786  *          2  :  hport = Specifies port to bind to.
 3787  *
 3788  * Returns     :  Port that was opened.
 3789  *
 3790  *********************************************************************/
 3791 static jb_socket bind_port_helper(const char *haddr, int hport)
 3792 {
 3793    int result;
 3794    jb_socket bfd;
 3795 
 3796    result = bind_port(haddr, hport, &bfd);
 3797 
 3798    if (result < 0)
 3799    {
 3800       const char *bind_address = (NULL != haddr) ? haddr : "INADDR_ANY";
 3801       switch(result)
 3802       {
 3803          case -3:
 3804             log_error(LOG_LEVEL_FATAL,
 3805                "can't bind to %s:%d: There may be another Privoxy "
 3806                "or some other proxy running on port %d",
 3807                bind_address, hport, hport);
 3808 
 3809          case -2:
 3810             log_error(LOG_LEVEL_FATAL,
 3811                "can't bind to %s:%d: The hostname is not resolvable",
 3812                bind_address, hport);
 3813 
 3814          default:
 3815             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: %E",
 3816                bind_address, hport);
 3817       }
 3818 
 3819       /* shouldn't get here */
 3820       return JB_INVALID_SOCKET;
 3821    }
 3822 
 3823 #ifndef _WIN32
 3824    if (bfd >= FD_SETSIZE)
 3825    {
 3826       log_error(LOG_LEVEL_FATAL,
 3827          "Bind socket number too high to use select(): %d >= %d",
 3828          bfd, FD_SETSIZE);
 3829    }
 3830 #endif
 3831 
 3832    if (haddr == NULL)
 3833    {
 3834       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
 3835          hport);
 3836    }
 3837    else
 3838    {
 3839       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
 3840          hport, haddr);
 3841    }
 3842 
 3843    return bfd;
 3844 }
 3845 
 3846 
 3847 /*********************************************************************
 3848  *
 3849  * Function    :  bind_ports_helper
 3850  *
 3851  * Description :  Bind the listen ports.  Handles logging, and aborts
 3852  *                on failure.
 3853  *
 3854  * Parameters  :
 3855  *          1  :  config = Privoxy configuration.  Specifies ports
 3856  *                         to bind to.
 3857  *          2  :  sockets = Preallocated array of opened sockets
 3858  *                          corresponding to specification in config.
 3859  *                          All non-opened sockets will be set to
 3860  *                          JB_INVALID_SOCKET.
 3861  *
 3862  * Returns     :  Nothing. Inspect sockets argument.
 3863  *
 3864  *********************************************************************/
 3865 static void bind_ports_helper(struct configuration_spec * config,
 3866                               jb_socket sockets[])
 3867 {
 3868    int i;
 3869 
 3870    for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
 3871    {
 3872       if (config->hport[i])
 3873       {
 3874          sockets[i] = bind_port_helper(config->haddr[i], config->hport[i]);
 3875       }
 3876       else
 3877       {
 3878          sockets[i] = JB_INVALID_SOCKET;
 3879       }
 3880    }
 3881    config->need_bind = 0;
 3882 }
 3883 
 3884 
 3885 /*********************************************************************
 3886  *
 3887  * Function    :  close_ports_helper
 3888  *
 3889  * Description :  Close listenings ports.
 3890  *
 3891  * Parameters  :
 3892  *          1  :  sockets = Array of opened and non-opened sockets to
 3893  *                          close. All sockets will be set to
 3894  *                          JB_INVALID_SOCKET.
 3895  *
 3896  * Returns     :  Nothing.
 3897  *
 3898  *********************************************************************/
 3899 static void close_ports_helper(jb_socket sockets[])
 3900 {
 3901    int i;
 3902 
 3903    for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
 3904    {
 3905       if (JB_INVALID_SOCKET != sockets[i])
 3906       {
 3907          close_socket(sockets[i]);
 3908       }
 3909       sockets[i] = JB_INVALID_SOCKET;
 3910    }
 3911 }
 3912 
 3913 
 3914 #ifdef _WIN32
 3915 /* Without this simple workaround we get this compiler warning from _beginthread
 3916  *     warning C4028: formal parameter 1 different from declaration
 3917  */
 3918 void w32_service_listen_loop(void *p)
 3919 {
 3920    listen_loop();
 3921 }
 3922 #endif /* def _WIN32 */
 3923 
 3924 
 3925 /*********************************************************************
 3926  *
 3927  * Function    :  listen_loop
 3928  *
 3929  * Description :  bind the listen port and enter a "FOREVER" listening loop.
 3930  *
 3931  * Parameters  :  N/A
 3932  *
 3933  * Returns     :  Never.
 3934  *
 3935  *********************************************************************/
 3936 static void listen_loop(void)
 3937 {
 3938    struct client_states *csp_list = NULL;
 3939    struct client_state *csp = NULL;
 3940    jb_socket bfds[MAX_LISTENING_SOCKETS];
 3941    struct configuration_spec *config;
 3942    unsigned int active_threads = 0;
 3943 
 3944    config = load_config();
 3945 
 3946 #ifdef FEATURE_CONNECTION_SHARING
 3947    /*
 3948     * XXX: Should be relocated once it no
 3949     * longer needs to emit log messages.
 3950     */
 3951    initialize_reusable_connections();
 3952 #endif /* def FEATURE_CONNECTION_SHARING */
 3953 
 3954    bind_ports_helper(config, bfds);
 3955 
 3956 #ifdef FEATURE_GRACEFUL_TERMINATION
 3957    while (!g_terminate)
 3958 #else
 3959    for (;;)
 3960 #endif
 3961    {
 3962 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
 3963       while (waitpid(-1, NULL, WNOHANG) > 0)
 3964       {
 3965          /* zombie children */
 3966       }
 3967 #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
 3968 
 3969       /*
 3970        * Free data that was used by died threads
 3971        */
 3972       active_threads = sweep();
 3973 
 3974 #if defined(unix)
 3975       /*
 3976        * Re-open the errlog after HUP signal
 3977        */
 3978       if (received_hup_signal)
 3979       {
 3980          if (NULL != config->logfile)
 3981          {
 3982             init_error_log(Argv[0], config->logfile);
 3983          }
 3984          received_hup_signal = 0;
 3985       }
 3986 #endif
 3987 
 3988       csp_list = zalloc_or_die(sizeof(*csp_list));
 3989       csp = &csp_list->csp;
 3990 
 3991       log_error(LOG_LEVEL_CONNECT,
 3992          "Waiting for the next client connection. Currently active threads: %d",
 3993          active_threads);
 3994 
 3995       /*
 3996        * This config may be outdated, but for accept_connection()
 3997        * it's fresh enough.
 3998        */
 3999       csp->config = config;
 4000 
 4001       if (!accept_connection(csp, bfds))
 4002       {
 4003          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
 4004 
 4005 #ifdef AMIGA
 4006          if (!childs)
 4007          {
 4008             exit(1);
 4009          }
 4010 #endif
 4011          freez(csp_list);
 4012          continue;
 4013       }
 4014 
 4015       csp->flags |= CSP_FLAG_ACTIVE;
 4016       csp->server_connection.sfd = JB_INVALID_SOCKET;
 4017 
 4018       csp->config = config = load_config();
 4019 
 4020       if (config->need_bind)
 4021       {
 4022          /*
 4023           * Since we were listening to the "old port", we will not see
 4024           * a "listen" param change until the next request.  So, at
 4025           * least 1 more request must be made for us to find the new
 4026           * setting.  I am simply closing the old socket and binding the
 4027           * new one.
 4028           *
 4029           * Which-ever is correct, we will serve 1 more page via the
 4030           * old settings.  This should probably be a "show-proxy-args"
 4031           * request.  This should not be a so common of an operation
 4032           * that this will hurt people's feelings.
 4033           */
 4034 
 4035          close_ports_helper(bfds);
 4036 
 4037          bind_ports_helper(config, bfds);
 4038       }
 4039 
 4040 #ifdef FEATURE_TOGGLE
 4041       if (global_toggle_state)
 4042 #endif /* def FEATURE_TOGGLE */
 4043       {
 4044          csp->flags |= CSP_FLAG_TOGGLED_ON;
 4045       }
 4046 
 4047       if (run_loader(csp))
 4048       {
 4049          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
 4050          /* Never get here - LOG_LEVEL_FATAL causes program exit */
 4051       }
 4052 
 4053 #ifdef FEATURE_ACL
 4054       if (block_acl(NULL,csp))
 4055       {
 4056          log_error(LOG_LEVEL_CONNECT,
 4057             "Connection from %s on %s (socket %d) dropped due to ACL",
 4058             csp->ip_addr_str, csp->listen_addr_str, csp->cfd);
 4059          close_socket(csp->cfd);
 4060          freez(csp->ip_addr_str);
 4061          freez(csp->listen_addr_str);
 4062          freez(csp_list);
 4063          continue;
 4064       }
 4065 #endif /* def FEATURE_ACL */
 4066 
 4067       if ((0 != config->max_client_connections)
 4068          && (active_threads >= config->max_client_connections))
 4069       {
 4070          log_error(LOG_LEVEL_CONNECT,
 4071             "Rejecting connection from %s. Maximum number of connections reached.",
 4072             csp->ip_addr_str);
 4073          write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
 4074             strlen(TOO_MANY_CONNECTIONS_RESPONSE));
 4075          close_socket(csp->cfd);
 4076          freez(csp->ip_addr_str);
 4077          freez(csp->listen_addr_str);
 4078          freez(csp_list);
 4079          continue;
 4080       }
 4081 
 4082       /* add it to the list of clients */
 4083       csp_list->next = clients->next;
 4084       clients->next = csp_list;
 4085 
 4086       if (config->multi_threaded)
 4087       {
 4088          int child_id;
 4089 
 4090 /* this is a switch () statement in the C preprocessor - ugh */
 4091 #undef SELECTED_ONE_OPTION
 4092 
 4093 /* Use Pthreads in preference to native code */
 4094 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
 4095 #define SELECTED_ONE_OPTION
 4096          {
 4097             pthread_t the_thread;
 4098             pthread_attr_t attrs;
 4099 
 4100             pthread_attr_init(&attrs);
 4101             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
 4102             errno = pthread_create(&the_thread, &attrs,
 4103                (void * (*)(void *))serve, csp);
 4104             child_id = errno ? -1 : 0;
 4105             pthread_attr_destroy(&attrs);
 4106          }
 4107 #endif
 4108 
 4109 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
 4110 #define SELECTED_ONE_OPTION
 4111          child_id = _beginthread(
 4112             (void (*)(void *))serve,
 4113             64 * 1024,
 4114             csp);
 4115 #endif
 4116 
 4117 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
 4118 #define SELECTED_ONE_OPTION
 4119          child_id = _beginthread(
 4120             (void(* _Optlink)(void*))serve,
 4121             NULL,
 4122             64 * 1024,
 4123             csp);
 4124 #endif
 4125 
 4126 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
 4127 #define SELECTED_ONE_OPTION
 4128          {
 4129             thread_id tid = spawn_thread
 4130                (server_thread, "server", B_NORMAL_PRIORITY, csp);
 4131 
 4132             if ((tid >= 0) && (resume_thread(tid) == B_OK))
 4133             {
 4134                child_id = (int) tid;
 4135             }
 4136             else
 4137             {
 4138                child_id = -1;
 4139             }
 4140          }
 4141 #endif
 4142 
 4143 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
 4144 #define SELECTED_ONE_OPTION
 4145          csp->cfd = ReleaseSocket(csp->cfd, -1);
 4146 
 4147 #ifdef __amigaos4__
 4148          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
 4149                                            NP_Output, Output(),
 4150                                            NP_CloseOutput, FALSE,
 4151                                            NP_Name, (ULONG)"privoxy child",
 4152                                            NP_Child, TRUE,
 4153                                            TAG_DONE);
 4154 #else
 4155          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
 4156                                            NP_Output, Output(),
 4157                                            NP_CloseOutput, FALSE,
 4158                                            NP_Name, (ULONG)"privoxy child",
 4159                                            NP_StackSize, 200*1024,
 4160                                            TAG_DONE);
 4161 #endif
 4162          if (0 != child_id)
 4163          {
 4164             childs++;
 4165             ((struct Task *)child_id)->tc_UserData = csp;
 4166             Signal((struct Task *)child_id, SIGF_SINGLE);
 4167             Wait(SIGF_SINGLE);
 4168          }
 4169 #endif
 4170 
 4171 #if !defined(SELECTED_ONE_OPTION)
 4172          child_id = fork();
 4173 
 4174          /* This block is only needed when using fork().
 4175           * When using threads, the server thread was
 4176           * created and run by the call to _beginthread().
 4177           */
 4178          if (child_id == 0)   /* child */
 4179          {
 4180             int rc = 0;
 4181 #ifdef FEATURE_TOGGLE
 4182             int inherited_toggle_state = global_toggle_state;
 4183 #endif /* def FEATURE_TOGGLE */
 4184 
 4185             serve(csp);
 4186 
 4187             /*
 4188              * If we've been toggled or we've blocked the request, tell Mom
 4189              */
 4190 
 4191 #ifdef FEATURE_TOGGLE
 4192             if (inherited_toggle_state != global_toggle_state)
 4193             {
 4194                rc |= RC_FLAG_TOGGLED;
 4195             }
 4196 #endif /* def FEATURE_TOGGLE */
 4197 
 4198 #ifdef FEATURE_STATISTICS
 4199             if (csp->flags & CSP_FLAG_REJECTED)
 4200             {
 4201                rc |= RC_FLAG_BLOCKED;
 4202             }
 4203 #endif /* ndef FEATURE_STATISTICS */
 4204 
 4205             _exit(rc);
 4206          }
 4207          else if (child_id > 0) /* parent */
 4208          {
 4209             /* in a fork()'d environment, the parent's
 4210              * copy of the client socket and the CSP
 4211              * are not used.
 4212              */
 4213             int child_status;
 4214 #if !defined(_WIN32) && !defined(__CYGWIN__)
 4215 
 4216             wait(&child_status);
 4217 
 4218             /*
 4219              * Evaluate child's return code: If the child has
 4220              *  - been toggled, toggle ourselves
 4221              *  - blocked its request, bump up the stats counter
 4222              */
 4223 
 4224 #ifdef FEATURE_TOGGLE
 4225             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
 4226             {
 4227                global_toggle_state = !global_toggle_state;
 4228             }
 4229 #endif /* def FEATURE_TOGGLE */
 4230 
 4231 #ifdef FEATURE_STATISTICS
 4232             urls_read++;
 4233             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
 4234             {
 4235                urls_rejected++;
 4236             }
 4237 #endif /* def FEATURE_STATISTICS */
 4238 
 4239 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
 4240             close_socket(csp->cfd);
 4241             csp->flags &= ~CSP_FLAG_ACTIVE;
 4242          }
 4243 #endif
 4244 
 4245 #undef SELECTED_ONE_OPTION
 4246 /* end of cpp switch () */
 4247 
 4248          if (child_id < 0)
 4249          {
 4250             /*
 4251              * Spawning the child failed, assume it's because
 4252              * there are too many children running already.
 4253              * XXX: If you assume ...
 4254              */
 4255             log_error(LOG_LEVEL_ERROR,
 4256                "Unable to take any additional connections: %E. Active threads: %d",
 4257                active_threads);
 4258             write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
 4259                strlen(TOO_MANY_CONNECTIONS_RESPONSE));
 4260             close_socket(csp->cfd);
 4261             csp->flags &= ~CSP_FLAG_ACTIVE;
 4262          }
 4263       }
 4264       else
 4265       {
 4266          serve(csp);
 4267       }
 4268    }
 4269 
 4270    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
 4271 
 4272    /* Clean up.  Aim: free all memory (no leaks) */
 4273 #ifdef FEATURE_GRACEFUL_TERMINATION
 4274 
 4275    log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
 4276 
 4277    unload_current_config_file();
 4278    unload_current_actions_file();
 4279    unload_current_re_filterfile();
 4280 #ifdef FEATURE_TRUST
 4281    unload_current_trust_file();
 4282 #endif
 4283 
 4284    if (config->multi_threaded)
 4285    {
 4286       int i = 60;
 4287       do
 4288       {
 4289          sleep(1);
 4290          sweep();
 4291       } while ((clients->next != NULL) && (--i > 0));
 4292 
 4293       if (i <= 0)
 4294       {
 4295          log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
 4296       }
 4297    }
 4298    sweep();
 4299    sweep();
 4300 
 4301 #if defined(unix)
 4302    freez(basedir);
 4303 #endif
 4304 
 4305 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
 4306    /* Cleanup - remove taskbar icon etc. */
 4307    TermLogWindow();
 4308 #endif
 4309 
 4310    exit(0);
 4311 #endif /* FEATURE_GRACEFUL_TERMINATION */
 4312 
 4313 }
 4314 
 4315 
 4316 /*
 4317   Local Variables:
 4318   tab-width: 3
 4319   end:
 4320 */