Change code status to beta.
[privoxy.git] / jcc.c
1 const char jcc_rcs[] = "$Id: jcc.c,v 1.255 2009/06/11 11:46:22 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-2009 the SourceForge
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
119 const char jcc_h_rcs[] = JCC_H_VERSION;
120 const char project_h_rcs[] = PROJECT_H_VERSION;
121
122 int no_daemon = 0;
123 struct client_state  clients[1];
124 struct file_list     files[1];
125
126 #ifdef FEATURE_STATISTICS
127 int urls_read     = 0;     /* total nr of urls read inc rejected */
128 int urls_rejected = 0;     /* total nr of urls rejected */
129 #endif /* def FEATURE_STATISTICS */
130
131 #ifdef FEATURE_GRACEFUL_TERMINATION
132 int g_terminate = 0;
133 #endif
134
135 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
136 static void sig_handler(int the_signal);
137 #endif
138 static int client_protocol_is_unsupported(const struct client_state *csp, char *req);
139 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
140 static jb_err get_server_headers(struct client_state *csp);
141 static const char *crunch_reason(const struct http_response *rsp);
142 static void send_crunch_response(const struct client_state *csp, struct http_response *rsp);
143 static char *get_request_line(struct client_state *csp);
144 static jb_err receive_client_request(struct client_state *csp);
145 static jb_err parse_client_request(struct client_state *csp);
146 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line);
147 static jb_err change_request_destination(struct client_state *csp);
148 static void chat(struct client_state *csp);
149 static void serve(struct client_state *csp);
150 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
151 static void usage(const char *myname);
152 #endif
153 static void initialize_mutexes(void);
154 static jb_socket bind_port_helper(struct configuration_spec *config);
155 static void listen_loop(void);
156
157 #ifdef AMIGA
158 void serve(struct client_state *csp);
159 #else /* ifndef AMIGA */
160 static void serve(struct client_state *csp);
161 #endif /* def AMIGA */
162
163 #ifdef __BEOS__
164 static int32 server_thread(void *data);
165 #endif /* def __BEOS__ */
166
167 #ifdef _WIN32
168 #define sleep(N)  Sleep(((N) * 1000))
169 #endif
170
171 #ifdef __OS2__
172 #define sleep(N)  DosSleep(((N) * 100))
173 #endif
174
175 #ifdef MUTEX_LOCKS_AVAILABLE
176 /*
177  * XXX: Does the locking stuff really belong in this file?
178  */
179 privoxy_mutex_t log_mutex;
180 privoxy_mutex_t log_init_mutex;
181 privoxy_mutex_t connection_reuse_mutex;
182
183 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
184 privoxy_mutex_t resolver_mutex;
185 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
186
187 #ifndef HAVE_GMTIME_R
188 privoxy_mutex_t gmtime_mutex;
189 #endif /* ndef HAVE_GMTIME_R */
190
191 #ifndef HAVE_LOCALTIME_R
192 privoxy_mutex_t localtime_mutex;
193 #endif /* ndef HAVE_GMTIME_R */
194
195 #ifndef HAVE_RANDOM
196 privoxy_mutex_t rand_mutex;
197 #endif /* ndef HAVE_RANDOM */
198
199 #endif /* def MUTEX_LOCKS_AVAILABLE */
200
201 #if defined(unix)
202 const char *basedir = NULL;
203 const char *pidfile = NULL;
204 static int received_hup_signal = 0;
205 #endif /* defined unix */
206
207 /* HTTP snipplets. */
208 static const char CSUCCEED[] =
209    "HTTP/1.0 200 Connection established\r\n"
210    "Proxy-Agent: Privoxy/" VERSION "\r\n\r\n";
211
212 static const char CHEADER[] =
213    "HTTP/1.0 400 Invalid header received from client\r\n"
214    "Proxy-Agent: Privoxy " VERSION "\r\n"
215    "Content-Type: text/plain\r\n"
216    "Connection: close\r\n\r\n"
217    "Invalid header received from client.\r\n";
218
219 static const char FTP_RESPONSE[] =
220    "HTTP/1.0 400 Invalid request received from client\r\n"
221    "Content-Type: text/plain\r\n"
222    "Connection: close\r\n\r\n"
223    "Invalid request. Privoxy doesn't support FTP.\r\n";
224
225 static const char GOPHER_RESPONSE[] =
226    "HTTP/1.0 400 Invalid request received from client\r\n"
227    "Content-Type: text/plain\r\n"
228    "Connection: close\r\n\r\n"
229    "Invalid request. Privoxy doesn't support gopher.\r\n";
230
231 /* XXX: should be a template */
232 static const char MISSING_DESTINATION_RESPONSE[] =
233    "HTTP/1.0 400 Bad request received from client\r\n"
234    "Proxy-Agent: Privoxy " VERSION "\r\n"
235    "Content-Type: text/plain\r\n"
236    "Connection: close\r\n\r\n"
237    "Bad request. Privoxy was unable to extract the destination.\r\n";
238
239 /* XXX: should be a template */
240 static const char INVALID_SERVER_HEADERS_RESPONSE[] =
241    "HTTP/1.0 502 Server or forwarder response invalid\r\n"
242    "Proxy-Agent: Privoxy " VERSION "\r\n"
243    "Content-Type: text/plain\r\n"
244    "Connection: close\r\n\r\n"
245    "Bad response. The server or forwarder response doesn't look like HTTP.\r\n";
246
247 #if 0
248 /* XXX: should be a template */
249 static const char NULL_BYTE_RESPONSE[] =
250    "HTTP/1.0 400 Bad request received from client\r\n"
251    "Proxy-Agent: Privoxy " VERSION "\r\n"
252    "Content-Type: text/plain\r\n"
253    "Connection: close\r\n\r\n"
254    "Bad request. Null byte(s) before end of request.\r\n";
255 #endif
256
257 /* XXX: should be a template */
258 static const char MESSED_UP_REQUEST_RESPONSE[] =
259    "HTTP/1.0 400 Malformed request after rewriting\r\n"
260    "Proxy-Agent: Privoxy " VERSION "\r\n"
261    "Content-Type: text/plain\r\n"
262    "Connection: close\r\n\r\n"
263    "Bad request. Messed up with header filters.\r\n";
264
265 static const char TOO_MANY_CONNECTIONS_RESPONSE[] =
266    "HTTP/1.0 503 Too many open connections\r\n"
267    "Proxy-Agent: Privoxy " VERSION "\r\n"
268    "Content-Type: text/plain\r\n"
269    "Connection: close\r\n\r\n"
270    "Maximum number of open connections reached.\r\n";
271
272 static const char CLIENT_CONNECTION_TIMEOUT_RESPONSE[] =
273    "HTTP/1.0 504 Connection timeout\r\n"
274    "Proxy-Agent: Privoxy " VERSION "\r\n"
275    "Content-Type: text/plain\r\n"
276    "Connection: close\r\n\r\n"
277    "The connection timed out because the client request didn't arrive in time.\r\n";
278
279 /* A function to crunch a response */
280 typedef struct http_response *(*crunch_func_ptr)(struct client_state *);
281
282 /* Crunch function flags */
283 #define CF_NO_FLAGS        0
284 /* Cruncher applies to forced requests as well */
285 #define CF_IGNORE_FORCE    1
286 /* Crunched requests are counted for the block statistics */
287 #define CF_COUNT_AS_REJECT 2
288
289 /* A crunch function and its flags */
290 struct cruncher
291 {
292    const crunch_func_ptr cruncher;
293    const int flags;
294 };
295
296 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]);
297
298 /* Complete list of cruncher functions */
299 static const struct cruncher crunchers_all[] = {
300    { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE},
301    { block_url,       CF_COUNT_AS_REJECT },
302 #ifdef FEATURE_TRUST
303    { trust_url,       CF_COUNT_AS_REJECT },
304 #endif /* def FEATURE_TRUST */
305    { redirect_url,    CF_NO_FLAGS  },
306    { dispatch_cgi,    CF_IGNORE_FORCE},
307    { NULL,            0 }
308 };
309
310 /* Light version, used after tags are applied */
311 static const struct cruncher crunchers_light[] = {
312    { block_url,       CF_COUNT_AS_REJECT },
313    { redirect_url,    CF_NO_FLAGS },
314    { NULL,            0 }
315 };
316
317
318 /*
319  * XXX: Don't we really mean
320  *
321  * #if defined(unix)
322  *
323  * here?
324  */
325 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
326 /*********************************************************************
327  *
328  * Function    :  sig_handler 
329  *
330  * Description :  Signal handler for different signals.
331  *                Exit gracefully on TERM and INT
332  *                or set a flag that will cause the errlog
333  *                to be reopened by the main thread on HUP.
334  *
335  * Parameters  :
336  *          1  :  the_signal = the signal cause this function to call
337  *
338  * Returns     :  - 
339  *
340  *********************************************************************/
341 static void sig_handler(int the_signal)
342 {
343    switch(the_signal)
344    {
345       case SIGTERM:
346       case SIGINT:
347          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
348 #if defined(unix)
349          if(pidfile)
350          {
351             unlink(pidfile);
352          }
353 #endif /* unix */
354          exit(the_signal);
355          break;
356
357       case SIGHUP:
358 #if defined(unix)
359          received_hup_signal = 1;
360 #endif
361          break;         
362
363       default:
364          /* 
365           * We shouldn't be here, unless we catch signals
366           * in main() that we can't handle here!
367           */
368          log_error(LOG_LEVEL_FATAL, "sig_handler: exiting on unexpected signal %d", the_signal);
369    }
370    return;
371
372 }
373 #endif
374
375
376 /*********************************************************************
377  *
378  * Function    :  client_protocol_is_unsupported
379  *
380  * Description :  Checks if the client used a known unsupported
381  *                protocol and deals with it by sending an error
382  *                response.
383  *
384  * Parameters  :
385  *          1  :  csp = Current client state (buffers, headers, etc...)
386  *          2  :  req = the first request line send by the client
387  *
388  * Returns     :  TRUE if an error response has been generated, or
389  *                FALSE if the request doesn't look invalid.
390  *
391  *********************************************************************/
392 static int client_protocol_is_unsupported(const struct client_state *csp, char *req)
393 {
394    /*
395     * If it's a FTP or gopher request, we don't support it.
396     *
397     * These checks are better than nothing, but they might
398     * not work in all configurations and some clients might
399     * have problems digesting the answer.
400     *
401     * They should, however, never cause more problems than
402     * Privoxy's old behaviour (returning the misleading HTML
403     * error message:
404     *
405     * "Could not resolve http://(ftp|gopher)://example.org").
406     */
407    if (!strncmpic(req, "GET ftp://", 10) || !strncmpic(req, "GET gopher://", 13))
408    {
409       const char *response = NULL;
410       const char *protocol = NULL;
411
412       if (!strncmpic(req, "GET ftp://", 10))
413       {
414          response = FTP_RESPONSE;
415          protocol = "FTP";
416       }
417       else
418       {
419          response = GOPHER_RESPONSE;
420          protocol = "GOPHER";
421       }
422       log_error(LOG_LEVEL_ERROR,
423          "%s tried to use Privoxy as %s proxy: %s",
424          csp->ip_addr_str, protocol, req);
425       log_error(LOG_LEVEL_CLF,
426          "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
427       freez(req);
428       write_socket(csp->cfd, response, strlen(response));
429
430       return TRUE;
431    }
432
433    return FALSE;
434 }
435
436
437 /*********************************************************************
438  *
439  * Function    :  get_request_destination_elsewhere
440  *
441  * Description :  If the client's request was redirected into
442  *                Privoxy without the client's knowledge,
443  *                the request line lacks the destination host.
444  *
445  *                This function tries to get it elsewhere,
446  *                provided accept-intercepted-requests is enabled.
447  *
448  *                "Elsewhere" currently only means "Host: header",
449  *                but in the future we may ask the redirecting
450  *                packet filter to look the destination up.
451  *
452  *                If the destination stays unknown, an error
453  *                response is send to the client and headers
454  *                are freed so that chat() can return directly.
455  *
456  * Parameters  :
457  *          1  :  csp = Current client state (buffers, headers, etc...)
458  *          2  :  headers = a header list
459  *
460  * Returns     :  JB_ERR_OK if the destination is now known, or
461  *                JB_ERR_PARSE if it isn't.
462  *
463  *********************************************************************/
464 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
465 {
466    char *req;
467
468    if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
469    {
470       log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
471          " Privoxy isn't configured to accept intercepted requests.",
472          csp->ip_addr_str, csp->http->cmd);
473       /* XXX: Use correct size */
474       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
475          csp->ip_addr_str, csp->http->cmd);
476
477       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
478       destroy_list(headers);
479
480       return JB_ERR_PARSE;
481    }
482    else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http))
483    {
484 #ifndef FEATURE_EXTENDED_HOST_PATTERNS
485       /* Split the domain we just got for pattern matching */
486       init_domain_components(csp->http);
487 #endif
488
489       return JB_ERR_OK;
490    }
491    else
492    {
493       /* We can't work without destination. Go spread the news.*/
494
495       req = list_to_text(headers);
496       chomp(req);
497       /* XXX: Use correct size */
498       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
499          csp->ip_addr_str, csp->http->cmd);
500       log_error(LOG_LEVEL_ERROR,
501          "Privoxy was unable to get the destination for %s's request:\n%s\n%s",
502          csp->ip_addr_str, csp->http->cmd, req);
503       freez(req);
504
505       write_socket(csp->cfd, MISSING_DESTINATION_RESPONSE, strlen(MISSING_DESTINATION_RESPONSE));
506       destroy_list(headers);
507
508       return JB_ERR_PARSE;
509    }
510    /*
511     * TODO: If available, use PF's ioctl DIOCNATLOOK as last resort
512     * to get the destination IP address, use it as host directly
513     * or do a reverse DNS lookup first.
514     */
515 }
516
517
518 /*********************************************************************
519  *
520  * Function    :  get_server_headers
521  *
522  * Description :  Parses server headers in iob and fills them
523  *                into csp->headers so that they can later be
524  *                handled by sed().
525  *
526  * Parameters  :
527  *          1  :  csp = Current client state (buffers, headers, etc...)
528  *
529  * Returns     :  JB_ERR_OK if everything went fine, or
530  *                JB_ERR_PARSE if the headers were incomplete.
531  *
532  *********************************************************************/
533 static jb_err get_server_headers(struct client_state *csp)
534 {
535    int continue_hack_in_da_house = 0;
536    char * header;
537
538    while (((header = get_header(csp->iob)) != NULL) || continue_hack_in_da_house)
539    {
540       if (header == NULL)
541       {
542          /*
543           * continue hack in da house. Ignore the ending of
544           * this head and continue enlisting header lines.
545           * The reason is described below.
546           */
547          enlist(csp->headers, "");
548          continue_hack_in_da_house = 0;
549          continue;
550       }
551       else if (0 == strncmpic(header, "HTTP/1.1 100", 12))
552       {
553          /*
554           * It's a bodyless continue response, don't
555           * stop header parsing after reaching its end.
556           *
557           * As a result Privoxy will concatenate the
558           * next response's head and parse and deliver
559           * the headers as if they belonged to one request.
560           *
561           * The client will separate them because of the
562           * empty line between them.
563           *
564           * XXX: What we're doing here is clearly against
565           * the intended purpose of the continue header,
566           * and under some conditions (HTTP/1.0 client request)
567           * it's a standard violation.
568           *
569           * Anyway, "sort of against the spec" is preferable
570           * to "always getting confused by Continue responses"
571           * (Privoxy's behaviour before this hack was added)
572           */
573          log_error(LOG_LEVEL_HEADER, "Continue hack in da house.");
574          continue_hack_in_da_house = 1;
575       }
576       else if (*header == '\0') 
577       {
578          /*
579           * If the header is empty, but the Continue hack
580           * isn't active, we can assume that we reached the
581           * end of the buffer before we hit the end of the
582           * head.
583           *
584           * Inform the caller an let it decide how to handle it.
585           */
586          return JB_ERR_PARSE;
587       }
588
589       if (JB_ERR_MEMORY == enlist(csp->headers, header))
590       {
591          /*
592           * XXX: Should we quit the request and return a
593           * out of memory error page instead?
594           */
595          log_error(LOG_LEVEL_ERROR,
596             "Out of memory while enlisting server headers. %s lost.",
597             header);
598       }
599       freez(header);
600    }
601
602    return JB_ERR_OK;
603 }
604
605
606 /*********************************************************************
607  *
608  * Function    :  crunch_reason
609  *
610  * Description :  Translates the crunch reason code into a string.
611  *
612  * Parameters  :
613  *          1  :  rsp = a http_response
614  *
615  * Returns     :  A string with the crunch reason or an error description.
616  *
617  *********************************************************************/
618 static const char *crunch_reason(const struct http_response *rsp)
619 {
620    char * reason = NULL;
621
622    assert(rsp != NULL);
623    if (rsp == NULL)
624    {
625       return "Internal error while searching for crunch reason";
626    }
627
628    switch (rsp->reason)
629    {
630       case RSP_REASON_UNSUPPORTED:
631          reason = "Unsupported HTTP feature";
632          break;
633       case RSP_REASON_BLOCKED:
634          reason = "Blocked";
635          break;
636       case RSP_REASON_UNTRUSTED:
637          reason = "Untrusted";
638          break;
639       case RSP_REASON_REDIRECTED:
640          reason = "Redirected";
641          break;
642       case RSP_REASON_CGI_CALL:
643          reason = "CGI Call";
644          break;
645       case RSP_REASON_NO_SUCH_DOMAIN:
646          reason = "DNS failure";
647          break;
648       case RSP_REASON_FORWARDING_FAILED:
649          reason = "Forwarding failed";
650          break;
651       case RSP_REASON_CONNECT_FAILED:
652          reason = "Connection failure";
653          break;
654       case RSP_REASON_OUT_OF_MEMORY:
655          reason = "Out of memory (may mask other reasons)";
656          break;
657       case RSP_REASON_CONNECTION_TIMEOUT:
658          reason = "Connection timeout";
659          break;
660       default:
661          reason = "No reason recorded";
662          break;
663    }
664
665    return reason;
666 }
667
668
669 /*********************************************************************
670  *
671  * Function    :  send_crunch_response
672  *
673  * Description :  Delivers already prepared response for
674  *                intercepted requests, logs the interception
675  *                and frees the response.
676  *
677  * Parameters  :
678  *          1  :  csp = Current client state (buffers, headers, etc...)
679  *          1  :  rsp = Fully prepared response. Will be freed on exit.
680  *
681  * Returns     :  Nothing.
682  *
683  *********************************************************************/
684 static void send_crunch_response(const struct client_state *csp, struct http_response *rsp)
685 {
686       const struct http_request *http = csp->http;
687       char status_code[4];
688
689       assert(rsp != NULL);
690       assert(rsp->head != NULL);
691
692       if (rsp == NULL)
693       {
694          /*
695           * Not supposed to happen. If it does
696           * anyway, treat it as an unknown error.
697           */
698          cgi_error_unknown(csp, rsp, RSP_REASON_INTERNAL_ERROR);
699          /* return code doesn't matter */
700       }
701
702       if (rsp == NULL)
703       {
704          /* If rsp is still NULL, we have serious internal problems. */
705          log_error(LOG_LEVEL_FATAL,
706             "NULL response in send_crunch_response and cgi_error_unknown failed as well.");
707       }
708
709       /*
710        * Extract the status code from the actual head
711        * that was send to the client. It is the only
712        * way to get it right for all requests, including
713        * the fixed ones for out-of-memory problems.
714        *
715        * A head starts like this: 'HTTP/1.1 200...'
716        *                           0123456789|11
717        *                                     10
718        */
719       status_code[0] = rsp->head[9];
720       status_code[1] = rsp->head[10];
721       status_code[2] = rsp->head[11];
722       status_code[3] = '\0';
723
724       /* Write the answer to the client */
725       if (write_socket(csp->cfd, rsp->head, rsp->head_length)
726        || write_socket(csp->cfd, rsp->body, rsp->content_length))
727       {
728          /* There is nothing we can do about it. */
729          log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", csp->http->host);
730       }
731
732       /* Log that the request was crunched and why. */
733       log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
734       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %u",
735          csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
736
737       /* Clean up and return */
738       if (cgi_error_memory() != rsp)
739       {
740          free_http_response(rsp);
741       } 
742       return;
743 }
744
745
746 #if 0
747 /*********************************************************************
748  *
749  * Function    :  request_contains_null_bytes
750  *
751  * Description :  Checks for NULL bytes in the request and sends
752  *                an error message to the client if any were found.
753  *
754  *                XXX: currently not used, see comment in chat().
755  *
756  * Parameters  :
757  *          1  :  csp = Current client state (buffers, headers, etc...)
758  *          2  :  buf = Data from the client's request to check.
759  *          3  :  len = The data length.
760  *
761  * Returns     :  TRUE if the request contained one or more NULL bytes, or
762  *                FALSE otherwise.
763  *
764  *********************************************************************/
765 static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len)
766 {
767    size_t c_len; /* Request lenght when treated as C string */
768
769    c_len = strlen(buf);
770
771    if (c_len < len)
772    {
773       /*
774        * Null byte(s) found. Log the request,
775        * return an error response and hang up.
776        */
777       size_t tmp_len = c_len;
778
779       do
780       {
781         /*
782          * Replace NULL byte(s) with '°' characters
783          * so the request can be logged as string.
784          * XXX: Is there a better replacement character?
785          */
786          buf[tmp_len]='°';
787          tmp_len += strlen(buf+tmp_len);
788       } while (tmp_len < len);
789
790       log_error(LOG_LEVEL_ERROR, "%s\'s request contains at least one NULL byte "
791          "(length=%d, strlen=%u).", csp->ip_addr_str, len, c_len);
792       log_error(LOG_LEVEL_HEADER, 
793          "Offending request data with NULL bytes turned into \'°\' characters: %s", buf);
794
795       write_socket(csp->cfd, NULL_BYTE_RESPONSE, strlen(NULL_BYTE_RESPONSE));
796
797       /* XXX: Log correct size */
798       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
799
800       return TRUE;
801    }
802
803    return FALSE;
804 }
805 #endif
806
807
808 /*********************************************************************
809  *
810  * Function    :  crunch_response_triggered
811  *
812  * Description :  Checks if the request has to be crunched,
813  *                and delivers the crunch response if necessary.
814  *
815  * Parameters  :
816  *          1  :  csp = Current client state (buffers, headers, etc...)
817  *          2  :  crunchers = list of cruncher functions to run
818  *
819  * Returns     :  TRUE if the request was answered with a crunch response
820  *                FALSE otherwise.
821  *
822  *********************************************************************/
823 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[])
824 {
825    struct http_response *rsp = NULL;
826    const struct cruncher *c;
827
828    /*
829     * If CGI request crunching is disabled,
830     * check the CGI dispatcher out of order to
831     * prevent unintentional blocks or redirects. 
832     */
833    if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING)
834        && (NULL != (rsp = dispatch_cgi(csp))))
835    {
836       /* Deliver, log and free the interception response. */
837       send_crunch_response(csp, rsp);
838       return TRUE;
839    }
840
841    for (c = crunchers; c->cruncher != NULL; c++)
842    {
843       /*
844        * Check the cruncher if either Privoxy is toggled
845        * on and the request isn't forced, or if the cruncher
846        * applies to forced requests as well.
847        */
848       if (((csp->flags & CSP_FLAG_TOGGLED_ON) &&
849           !(csp->flags & CSP_FLAG_FORCED)) ||
850           (c->flags & CF_IGNORE_FORCE))
851       {
852          rsp = c->cruncher(csp);
853          if (NULL != rsp)
854          {
855             /* Deliver, log and free the interception response. */
856             send_crunch_response(csp, rsp);
857 #ifdef FEATURE_STATISTICS
858             if (c->flags & CF_COUNT_AS_REJECT)
859             {
860                csp->flags |= CSP_FLAG_REJECTED;
861             }
862 #endif /* def FEATURE_STATISTICS */
863
864             return TRUE;
865          }
866       }
867    }
868
869    return FALSE;
870 }
871
872
873 /*********************************************************************
874  *
875  * Function    :  build_request_line
876  *
877  * Description :  Builds the HTTP request line.
878  *
879  *                If a HTTP forwarder is used it expects the whole URL,
880  *                web servers only get the path.
881  *
882  * Parameters  :
883  *          1  :  csp = Current client state (buffers, headers, etc...)
884  *          2  :  fwd = The forwarding spec used for the request
885  *                XXX: Should use http->fwd instead.
886  *          3  :  request_line = The old request line which will be replaced.
887  *
888  * Returns     :  Nothing. Terminates in case of memory problems.
889  *
890  *********************************************************************/
891 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line)
892 {
893    struct http_request *http = csp->http;
894
895    assert(http->ssl == 0);
896
897    /*
898     * Downgrade http version from 1.1 to 1.0
899     * if +downgrade action applies.
900     */
901    if ( (csp->action->flags & ACTION_DOWNGRADE)
902      && (!strcmpic(http->ver, "HTTP/1.1")))
903    {
904       freez(http->ver);
905       http->ver = strdup("HTTP/1.0");
906
907       if (http->ver == NULL)
908       {
909          log_error(LOG_LEVEL_FATAL, "Out of memory downgrading HTTP version");
910       }
911    }
912
913    /*
914     * Rebuild the request line.
915     */
916    freez(*request_line);
917    *request_line = strdup(http->gpc);
918    string_append(request_line, " ");
919
920    if (fwd->forward_host)
921    {
922       string_append(request_line, http->url);
923    }
924    else
925    {
926       string_append(request_line, http->path);
927    }
928    string_append(request_line, " ");
929    string_append(request_line, http->ver);
930
931    if (*request_line == NULL)
932    {
933       log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
934    }
935    log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line);
936 }
937
938
939 /*********************************************************************
940  *
941  * Function    :  change_request_destination
942  *
943  * Description :  Parse a (rewritten) request line and regenerate
944  *                the http request data.
945  *
946  * Parameters  :
947  *          1  :  csp = Current client state (buffers, headers, etc...)
948  *
949  * Returns     :  Forwards the parse_http_request() return code.
950  *                Terminates in case of memory problems.
951  *
952  *********************************************************************/
953 static jb_err change_request_destination(struct client_state *csp)
954 {
955    struct http_request *http = csp->http;
956    jb_err err;
957
958    log_error(LOG_LEVEL_INFO, "Rewrite detected: %s", csp->headers->first->str);
959    free_http_request(http);
960    err = parse_http_request(csp->headers->first->str, http);
961    if (JB_ERR_OK != err)
962    {
963       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
964          jb_err_to_string(err));
965    }
966    else
967    {
968       /* XXX: ocmd is a misleading name */
969       http->ocmd = strdup(http->cmd);
970       if (http->ocmd == NULL)
971       {
972          log_error(LOG_LEVEL_FATAL,
973             "Out of memory copying rewritten HTTP request line");
974       }
975    }
976
977    return err;
978 }
979
980
981 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
982 /*********************************************************************
983  *
984  * Function    :  server_response_is_complete
985  *
986  * Description :  Determines whether we should stop reading
987  *                from the server socket.
988  *
989  * Parameters  :
990  *          1  :  csp = Current client state (buffers, headers, etc...)
991  *          2  :  content_length = Length of content received so far.
992  *
993  * Returns     :  TRUE if the response is complete,
994  *                FALSE otherwise.
995  *
996  *********************************************************************/
997 static int server_response_is_complete(struct client_state *csp,
998    unsigned long long content_length)
999 {
1000    int content_length_known = !!(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET);
1001
1002    if (!strcmpic(csp->http->gpc, "HEAD"))
1003    {
1004       /*
1005        * "HEAD" implies no body, we are thus expecting
1006        * no content. XXX: incomplete "list" of methods?
1007        */
1008       csp->expected_content_length = 0;
1009       content_length_known = TRUE;
1010    }
1011
1012    if (csp->http->status == 304)
1013    {
1014       /*
1015        * Expect no body. XXX: incomplete "list" of status codes?
1016        */
1017       csp->expected_content_length = 0;
1018       content_length_known = TRUE;
1019    }
1020
1021    return (content_length_known && ((0 == csp->expected_content_length)
1022             || (csp->expected_content_length <= content_length)));
1023 }
1024
1025
1026 /*********************************************************************
1027  *
1028  * Function    :  wait_for_alive_connections
1029  *
1030  * Description :  Waits for alive connections to timeout.
1031  *
1032  * Parameters  :  N/A
1033  *
1034  * Returns     :  N/A
1035  *
1036  *********************************************************************/
1037 static void wait_for_alive_connections(void)
1038 {
1039    int connections_alive = close_unusable_connections();
1040
1041    while (0 < connections_alive)
1042    {
1043       log_error(LOG_LEVEL_CONNECT,
1044          "Waiting for %d connections to timeout.",
1045          connections_alive);
1046       sleep(60);
1047       connections_alive = close_unusable_connections();
1048    }
1049
1050    log_error(LOG_LEVEL_CONNECT, "No connections to wait for left.");
1051
1052 }
1053
1054
1055 /*********************************************************************
1056  *
1057  * Function    :  save_connection_destination
1058  *
1059  * Description :  Remembers a connection for reuse later on.
1060  *
1061  * Parameters  :
1062  *          1  :  sfd  = Open socket to remember.
1063  *          2  :  http = The destination for the connection.
1064  *          3  :  fwd  = The forwarder settings used.
1065  *          3  :  server_connection  = storage.
1066  *
1067  * Returns     : void
1068  *
1069  *********************************************************************/
1070 void save_connection_destination(jb_socket sfd,
1071                                  const struct http_request *http,
1072                                  const struct forward_spec *fwd,
1073                                  struct reusable_connection *server_connection)
1074 {
1075    assert(sfd != JB_INVALID_SOCKET);
1076    assert(NULL != http->host);
1077    server_connection->host = strdup(http->host);
1078    if (NULL == server_connection->host)
1079    {
1080       log_error(LOG_LEVEL_FATAL, "Out of memory saving socket.");
1081    }
1082    server_connection->port = http->port;
1083
1084    assert(NULL != fwd);
1085    assert(server_connection->gateway_host == NULL);
1086    assert(server_connection->gateway_port == 0);
1087    assert(server_connection->forwarder_type == 0);
1088    assert(server_connection->forward_host == NULL);
1089    assert(server_connection->forward_port == 0);
1090
1091    server_connection->forwarder_type = fwd->type;
1092    if (NULL != fwd->gateway_host)
1093    {
1094       server_connection->gateway_host = strdup(fwd->gateway_host);
1095       if (NULL == server_connection->gateway_host)
1096       {
1097          log_error(LOG_LEVEL_FATAL, "Out of memory saving gateway_host.");
1098       }
1099    }
1100    else
1101    {
1102       server_connection->gateway_host = NULL;
1103    }
1104    server_connection->gateway_port = fwd->gateway_port;
1105
1106    if (NULL != fwd->forward_host)
1107    {
1108       server_connection->forward_host = strdup(fwd->forward_host);
1109       if (NULL == server_connection->forward_host)
1110       {
1111          log_error(LOG_LEVEL_FATAL, "Out of memory saving forward_host.");
1112       }
1113    }
1114    else
1115    {
1116       server_connection->forward_host = NULL;
1117    }
1118    server_connection->forward_port = fwd->forward_port;
1119 }
1120 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
1121
1122
1123 /*********************************************************************
1124  *
1125  * Function    :  mark_server_socket_tainted
1126  *
1127  * Description :  Makes sure we don't reuse a server socket
1128  *                (if we didn't read everything the server sent
1129  *                us reusing the socket would lead to garbage).
1130  *
1131  * Parameters  :
1132  *          1  :  csp = Current client state (buffers, headers, etc...)
1133  *
1134  * Returns     :  void.
1135  *
1136  *********************************************************************/
1137 static void mark_server_socket_tainted(struct client_state *csp)
1138 {
1139    if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE))
1140    {
1141       log_error(LOG_LEVEL_CONNECT, "Unsetting keep-alive flag.");
1142       csp->flags &= ~CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
1143    }
1144 }
1145
1146 /*********************************************************************
1147  *
1148  * Function    :  get_request_line
1149  *
1150  * Description : Read the client request line.
1151  *
1152  * Parameters  :
1153  *          1  :  csp = Current client state (buffers, headers, etc...)
1154  *
1155  * Returns     :  Pointer to request line or NULL in case of errors.
1156  *
1157  *********************************************************************/
1158 static char *get_request_line(struct client_state *csp)
1159 {
1160    char buf[BUFFER_SIZE];
1161    char *request_line = NULL;
1162    int len;
1163
1164    memset(buf, 0, sizeof(buf));
1165
1166    do
1167    {
1168       if (!data_is_available(csp->cfd, csp->config->socket_timeout))
1169       {
1170          log_error(LOG_LEVEL_ERROR,
1171             "Stopped waiting for the request line.");
1172          write_socket(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
1173             strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE));
1174          return NULL;
1175       }
1176
1177       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1178
1179       if (len <= 0) return NULL;
1180
1181       /*
1182        * If there is no memory left for buffering the
1183        * request, there is nothing we can do but hang up
1184        */
1185       if (add_to_iob(csp, buf, len))
1186       {
1187          return NULL;
1188       }
1189
1190       request_line = get_header(csp->iob);
1191
1192    } while ((NULL != request_line) && ('\0' == *request_line));
1193
1194    return request_line;
1195
1196 }
1197
1198
1199 /*********************************************************************
1200  *
1201  * Function    :  receive_client_request
1202  *
1203  * Description : Read the client's request (more precisely the
1204  *               client headers) and answer it if necessary.
1205  *
1206  *               Note that since we're not using select() we could get
1207  *               blocked here if a client connected, then didn't say
1208  *               anything!
1209  *
1210  * Parameters  :
1211  *          1  :  csp = Current client state (buffers, headers, etc...)
1212  *
1213  * Returns     :  JB_ERR_OK, JB_ERR_PARSE or JB_ERR_MEMORY
1214  *
1215  *********************************************************************/
1216 static jb_err receive_client_request(struct client_state *csp)
1217 {
1218    char buf[BUFFER_SIZE];
1219    char *p;
1220    char *req = NULL;
1221    struct http_request *http;
1222    int len;
1223    jb_err err;
1224
1225    /* Temporary copy of the client's headers before they get enlisted in csp->headers */
1226    struct list header_list;
1227    struct list *headers = &header_list;
1228
1229    http = csp->http;
1230
1231    memset(buf, 0, sizeof(buf));
1232
1233    req = get_request_line(csp);
1234    if (req == NULL)
1235    {
1236       return JB_ERR_PARSE;
1237    }
1238    assert(*req != '\0');
1239
1240    if (client_protocol_is_unsupported(csp, req))
1241    {
1242       return JB_ERR_PARSE;
1243    }
1244
1245 #ifdef FEATURE_FORCE_LOAD
1246    /*
1247     * If this request contains the FORCE_PREFIX and blocks
1248     * aren't enforced, get rid of it and set the force flag.
1249     */
1250    if (strstr(req, FORCE_PREFIX))
1251    {
1252       if (csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)
1253       {
1254          log_error(LOG_LEVEL_FORCE,
1255             "Ignored force prefix in request: \"%s\".", req);
1256       }
1257       else
1258       {
1259          strclean(req, FORCE_PREFIX);
1260          log_error(LOG_LEVEL_FORCE, "Enforcing request: \"%s\".", req);
1261          csp->flags |= CSP_FLAG_FORCED;
1262       }
1263    }
1264 #endif /* def FEATURE_FORCE_LOAD */
1265
1266    err = parse_http_request(req, http);
1267    freez(req);
1268    if (JB_ERR_OK != err)
1269    {
1270       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
1271       /* XXX: Use correct size */
1272       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
1273       log_error(LOG_LEVEL_ERROR,
1274          "Couldn't parse request line received from %s: %s",
1275          csp->ip_addr_str, jb_err_to_string(err));
1276
1277       free_http_request(http);
1278       return JB_ERR_PARSE;
1279    }
1280
1281    /* grab the rest of the client's headers */
1282    init_list(headers);
1283    for (;;)
1284    {
1285       p = get_header(csp->iob);
1286
1287       if (p == NULL)
1288       {
1289          /* There are no additional headers to read. */
1290          break;
1291       }
1292
1293       if (*p == '\0')
1294       {
1295          /*
1296           * We didn't receive a complete header
1297           * line yet, get the rest of it.
1298           */
1299          if (!data_is_available(csp->cfd, csp->config->socket_timeout))
1300          {
1301             log_error(LOG_LEVEL_ERROR,
1302                "Stopped grabbing the client headers.");
1303             destroy_list(headers);
1304             return JB_ERR_PARSE;
1305          }
1306
1307          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1308          if (len <= 0)
1309          {
1310             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
1311             destroy_list(headers);
1312             return JB_ERR_PARSE;
1313          }
1314          
1315          if (add_to_iob(csp, buf, len))
1316          {
1317             /*
1318              * If there is no memory left for buffering the
1319              * request, there is nothing we can do but hang up
1320              */
1321             destroy_list(headers);
1322             return JB_ERR_MEMORY;
1323          }
1324       }
1325       else
1326       {
1327          /*
1328           * We were able to read a complete
1329           * header and can finaly enlist it.
1330           */
1331          enlist(headers, p);
1332          freez(p);
1333       }
1334    }
1335
1336    if (http->host == NULL)
1337    {
1338       /*
1339        * If we still don't know the request destination,
1340        * the request is invalid or the client uses
1341        * Privoxy without its knowledge.
1342        */
1343       if (JB_ERR_OK != get_request_destination_elsewhere(csp, headers))
1344       {
1345          /*
1346           * Our attempts to get the request destination
1347           * elsewhere failed or Privoxy is configured
1348           * to only accept proxy requests.
1349           *
1350           * An error response has already been send
1351           * and we're done here.
1352           */
1353          return JB_ERR_PARSE;
1354       }
1355    }
1356
1357    /*
1358     * Determine the actions for this URL
1359     */
1360 #ifdef FEATURE_TOGGLE
1361    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
1362    {
1363       /* Most compatible set of actions (i.e. none) */
1364       init_current_action(csp->action);
1365    }
1366    else
1367 #endif /* ndef FEATURE_TOGGLE */
1368    {
1369       get_url_actions(csp, http);
1370    }
1371
1372    /* 
1373     * Save a copy of the original request for logging
1374     */
1375    http->ocmd = strdup(http->cmd);
1376    if (http->ocmd == NULL)
1377    {
1378       log_error(LOG_LEVEL_FATAL,
1379          "Out of memory copying HTTP request line");
1380    }
1381    enlist(csp->headers, http->cmd);
1382
1383    /* Append the previously read headers */
1384    list_append_list_unique(csp->headers, headers);
1385    destroy_list(headers);
1386
1387    return JB_ERR_OK;
1388
1389 }
1390
1391
1392 /*********************************************************************
1393  *
1394  * Function    : parse_client_request
1395  *
1396  * Description : Parses the client's request and decides what to do
1397  *               with it.
1398  *
1399  *               Note that since we're not using select() we could get
1400  *               blocked here if a client connected, then didn't say
1401  *               anything!
1402  *
1403  * Parameters  :
1404  *          1  :  csp = Current client state (buffers, headers, etc...)
1405  *
1406  * Returns     :  JB_ERR_OK or JB_ERR_PARSE
1407  *
1408  *********************************************************************/
1409 static jb_err parse_client_request(struct client_state *csp)
1410 {
1411    struct http_request *http = csp->http;
1412    jb_err err;
1413
1414    err = sed(csp, FILTER_CLIENT_HEADERS);
1415    if (JB_ERR_OK != err)
1416    {
1417       /* XXX: Should be handled in sed(). */
1418       assert(err == JB_ERR_PARSE);
1419       log_error(LOG_LEVEL_FATAL, "Failed to parse client headers.");
1420    }
1421    csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
1422
1423    /* Check request line for rewrites. */
1424    if ((NULL == csp->headers->first->str)
1425       || (strcmp(http->cmd, csp->headers->first->str) &&
1426          (JB_ERR_OK != change_request_destination(csp))))
1427    {
1428       /*
1429        * A header filter broke the request line - bail out.
1430        */
1431       write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE));
1432       /* XXX: Use correct size */
1433       log_error(LOG_LEVEL_CLF,
1434          "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str);
1435       log_error(LOG_LEVEL_ERROR,
1436          "Invalid request line after applying header filters.");
1437       free_http_request(http);
1438
1439       return JB_ERR_PARSE;
1440    }
1441
1442    return JB_ERR_OK;
1443
1444 }
1445
1446
1447 /*********************************************************************
1448  *
1449  * Function    :  chat
1450  *
1451  * Description :  Once a connection to the client has been accepted,
1452  *                this function is called (via serve()) to handle the
1453  *                main business of the communication.  When this
1454  *                function returns, the caller must close the client
1455  *                socket handle.
1456  *
1457  *                FIXME: chat is nearly thousand lines long.
1458  *                Ridiculous.
1459  *
1460  * Parameters  :
1461  *          1  :  csp = Current client state (buffers, headers, etc...)
1462  *
1463  * Returns     :  Nothing.
1464  *
1465  *********************************************************************/
1466 static void chat(struct client_state *csp)
1467 {
1468    char buf[BUFFER_SIZE];
1469    char *hdr;
1470    char *p;
1471    fd_set rfds;
1472    int n;
1473    jb_socket maxfd;
1474    int server_body;
1475    int ms_iis5_hack = 0;
1476    unsigned long long byte_count = 0;
1477    int forwarded_connect_retries = 0;
1478    int max_forwarded_connect_retries = csp->config->forwarded_connect_retries;
1479    const struct forward_spec *fwd;
1480    struct http_request *http;
1481    long len = 0; /* for buffer sizes (and negative error codes) */
1482
1483    /* Function that does the content filtering for the current request */
1484    filter_function_ptr content_filter = NULL;
1485
1486    /* Skeleton for HTTP response, if we should intercept the request */
1487    struct http_response *rsp;
1488    struct timeval timeout;
1489
1490    memset(buf, 0, sizeof(buf));
1491
1492    http = csp->http;
1493
1494    if (receive_client_request(csp) != JB_ERR_OK)
1495    {
1496       return;
1497    }
1498    if (parse_client_request(csp) != JB_ERR_OK)
1499    {
1500       return;
1501    }
1502
1503    /* decide how to route the HTTP request */
1504    fwd = forward_url(csp, http);
1505    if (NULL == fwd)
1506    {
1507       log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
1508       /* Never get here - LOG_LEVEL_FATAL causes program exit */
1509       return;
1510    }
1511
1512    /*
1513     * build the http request to send to the server
1514     * we have to do one of the following:
1515     *
1516     * create = use the original HTTP request to create a new
1517     *          HTTP request that has either the path component
1518     *          without the http://domainspec (w/path) or the
1519     *          full orininal URL (w/url)
1520     *          Note that the path and/or the HTTP version may
1521     *          have been altered by now.
1522     *
1523     * connect = Open a socket to the host:port of the server
1524     *           and short-circuit server and client socket.
1525     *
1526     * pass =  Pass the request unchanged if forwarding a CONNECT
1527     *         request to a parent proxy. Note that we'll be sending
1528     *         the CFAIL message ourselves if connecting to the parent
1529     *         fails, but we won't send a CSUCCEED message if it works,
1530     *         since that would result in a double message (ours and the
1531     *         parent's). After sending the request to the parent, we simply
1532     *         tunnel.
1533     *
1534     * here's the matrix:
1535     *                        SSL
1536     *                    0        1
1537     *                +--------+--------+
1538     *                |        |        |
1539     *             0  | create | connect|
1540     *                | w/path |        |
1541     *  Forwarding    +--------+--------+
1542     *                |        |        |
1543     *             1  | create | pass   |
1544     *                | w/url  |        |
1545     *                +--------+--------+
1546     *
1547     */
1548
1549    if (http->ssl && connect_port_is_forbidden(csp))
1550    {
1551       const char *acceptable_connect_ports =
1552          csp->action->string[ACTION_STRING_LIMIT_CONNECT];
1553       assert(NULL != acceptable_connect_ports);
1554       log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
1555          "limit-connect{%s} doesn't allow CONNECT requests to port %d.",
1556          csp->ip_addr_str, acceptable_connect_ports, csp->http->port);
1557       csp->action->flags |= ACTION_BLOCK;
1558       http->ssl = 0;
1559    }
1560
1561    if (http->ssl == 0)
1562    {
1563       freez(csp->headers->first->str);
1564       build_request_line(csp, fwd, &csp->headers->first->str);
1565    }
1566
1567    /*
1568     * We have a request. Check if one of the crunchers wants it.
1569     */
1570    if (crunch_response_triggered(csp, crunchers_all))
1571    {
1572       /*
1573        * Yes. The client got the crunch response
1574        * and we are done here after cleaning up.
1575        */
1576       /* XXX: why list_remove_all()? */
1577       list_remove_all(csp->headers);
1578
1579       return;
1580    }
1581
1582    log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
1583
1584    if (fwd->forward_host)
1585    {
1586       log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
1587          fwd->forward_host, fwd->forward_port, http->hostport);
1588    }
1589    else
1590    {
1591       log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
1592    }
1593
1594    /* here we connect to the server, gateway, or the forwarder */
1595
1596 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1597    if ((csp->sfd != JB_INVALID_SOCKET)
1598       && socket_is_still_usable(csp->sfd)
1599       && connection_destination_matches(&csp->server_connection, http, fwd))
1600    {
1601       log_error(LOG_LEVEL_CONNECT,
1602          "Reusing server socket %u. Opened for %s.",
1603          csp->sfd, csp->server_connection.host);
1604    }
1605    else
1606    {
1607       if (csp->sfd != JB_INVALID_SOCKET)
1608       {
1609          log_error(LOG_LEVEL_CONNECT,
1610             "Closing server socket %u. Opened for %s.",
1611             csp->sfd, csp->server_connection.host);
1612          close_socket(csp->sfd);
1613          mark_connection_closed(&csp->server_connection);
1614       }
1615 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
1616
1617       while ((csp->sfd = forwarded_connect(fwd, http, csp))
1618          && (errno == EINVAL)
1619          && (forwarded_connect_retries++ < max_forwarded_connect_retries))
1620       {
1621          log_error(LOG_LEVEL_ERROR,
1622             "failed request #%u to connect to %s. Trying again.",
1623             forwarded_connect_retries, http->hostport);
1624       }
1625
1626       if (csp->sfd == JB_INVALID_SOCKET)
1627       {
1628          if (fwd->type != SOCKS_NONE)
1629          {
1630             /* Socks error. */
1631             rsp = error_response(csp, "forwarding-failed");
1632          }
1633          else if (errno == EINVAL)
1634          {
1635             rsp = error_response(csp, "no-such-domain");
1636          }
1637          else
1638          {
1639             rsp = error_response(csp, "connect-failed");
1640             log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E",
1641                http->hostport);
1642          }
1643
1644          /* Write the answer to the client */
1645          if (rsp != NULL)
1646          {
1647             send_crunch_response(csp, rsp);
1648          }
1649
1650          return;
1651       }
1652 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1653       save_connection_destination(csp->sfd, http, fwd, &csp->server_connection);
1654       csp->server_connection.keep_alive_timeout = (unsigned)csp->config->keep_alive_timeout;
1655    }
1656 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
1657
1658    hdr = list_to_text(csp->headers);
1659    if (hdr == NULL)
1660    {
1661       /* FIXME Should handle error properly */
1662       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
1663    }
1664    list_remove_all(csp->headers);
1665
1666    if (fwd->forward_host || (http->ssl == 0))
1667    {
1668       /*
1669        * Write the client's (modified) header to the server
1670        * (along with anything else that may be in the buffer)
1671        */
1672       if (write_socket(csp->sfd, hdr, strlen(hdr))
1673        || (flush_socket(csp->sfd, csp->iob) <  0))
1674       {
1675          log_error(LOG_LEVEL_CONNECT,
1676             "write header to: %s failed: %E", http->hostport);
1677
1678          rsp = error_response(csp, "connect-failed");
1679          if (rsp)
1680          {
1681             send_crunch_response(csp, rsp);
1682          }
1683
1684          freez(hdr);
1685          return;
1686       }
1687    }
1688    else
1689    {
1690       /*
1691        * We're running an SSL tunnel and we're not forwarding,
1692        * so just send the "connect succeeded" message to the
1693        * client, flush the rest, and get out of the way.
1694        */
1695       if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
1696       {
1697          freez(hdr);
1698          return;
1699       }
1700       IOB_RESET(csp);
1701    }
1702
1703    log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
1704
1705    /* we're finished with the client's header */
1706    freez(hdr);
1707
1708    maxfd = (csp->cfd > csp->sfd) ? csp->cfd : csp->sfd;
1709
1710    /* pass data between the client and server
1711     * until one or the other shuts down the connection.
1712     */
1713
1714    server_body = 0;
1715
1716    for (;;)
1717    {
1718 #ifdef __OS2__
1719       /*
1720        * FD_ZERO here seems to point to an errant macro which crashes.
1721        * So do this by hand for now...
1722        */
1723       memset(&rfds,0x00,sizeof(fd_set));
1724 #else
1725       FD_ZERO(&rfds);
1726 #endif
1727       FD_SET(csp->cfd, &rfds);
1728       FD_SET(csp->sfd, &rfds);
1729
1730 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1731       if ((csp->flags & CSP_FLAG_CHUNKED)
1732          && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
1733          && ((csp->iob->eod - csp->iob->cur) >= 5)
1734          && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
1735       {
1736          log_error(LOG_LEVEL_CONNECT,
1737             "Looks like we read the last chunk together with "
1738             "the server headers. We better stop reading.");
1739          byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
1740          csp->expected_content_length = byte_count;
1741          csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
1742       }
1743       if (server_body && server_response_is_complete(csp, byte_count))
1744       {
1745          log_error(LOG_LEVEL_CONNECT,
1746             "Done reading from server. Expected content length: %llu. "
1747             "Actual content length: %llu. Most recently received: %d.",
1748             csp->expected_content_length, byte_count, len);
1749          len = 0;
1750          /*
1751           * XXX: should not jump around,
1752           * chat() is complicated enough already.
1753           */
1754          goto reading_done;
1755       }
1756 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
1757
1758       timeout.tv_sec = csp->config->socket_timeout;
1759       timeout.tv_usec = 0;
1760       n = select((int)maxfd+1, &rfds, NULL, NULL, &timeout);
1761
1762       if (n == 0)
1763       {
1764          log_error(LOG_LEVEL_ERROR,
1765             "Didn't receive data in time: %s", http->url);
1766          if ((byte_count == 0) && (http->ssl == 0))
1767          {
1768             send_crunch_response(csp, error_response(csp, "connection-timeout"));
1769          }
1770          mark_server_socket_tainted(csp);
1771          return;
1772       }
1773       else if (n < 0)
1774       {
1775          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
1776          mark_server_socket_tainted(csp);
1777          return;
1778       }
1779
1780       /*
1781        * This is the body of the browser's request,
1782        * just read and write it.
1783        *
1784        * XXX: Make sure the client doesn't use pipelining
1785        * behind Privoxy's back.
1786        */
1787       if (FD_ISSET(csp->cfd, &rfds))
1788       {
1789          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1790
1791          if (len <= 0)
1792          {
1793             /* XXX: not sure if this is necessary. */
1794             mark_server_socket_tainted(csp);
1795             break; /* "game over, man" */
1796          }
1797
1798          if (write_socket(csp->sfd, buf, (size_t)len))
1799          {
1800             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
1801             mark_server_socket_tainted(csp);
1802             return;
1803          }
1804          continue;
1805       }
1806
1807       /*
1808        * The server wants to talk. It could be the header or the body.
1809        * If `hdr' is null, then it's the header otherwise it's the body.
1810        * FIXME: Does `hdr' really mean `host'? No.
1811        */
1812       if (FD_ISSET(csp->sfd, &rfds))
1813       {
1814          fflush(NULL);
1815          len = read_socket(csp->sfd, buf, sizeof(buf) - 1);
1816
1817          if (len < 0)
1818          {
1819             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
1820
1821             if (http->ssl && (fwd->forward_host == NULL))
1822             {
1823                /*
1824                 * Just hang up. We already confirmed the client's CONNECT
1825                 * request with status code 200 and unencrypted content is
1826                 * no longer welcome.
1827                 */
1828                log_error(LOG_LEVEL_ERROR,
1829                   "CONNECT already confirmed. Unable to tell the client about the problem.");
1830                return;
1831             }
1832             else if (byte_count)
1833             {
1834                /*
1835                 * Just hang up. We already transmitted the original headers
1836                 * and parts of the original content and therefore missed the
1837                 * chance to send an error message (without risking data corruption).
1838                 *
1839                 * XXX: we could retry with a fancy range request here.
1840                 */
1841                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
1842                   "Unable to tell the client about the problem.");
1843                mark_server_socket_tainted(csp);
1844                return;
1845             }
1846             /*
1847              * XXX: Consider handling the cases above the same.
1848              */
1849             mark_server_socket_tainted(csp);
1850             len = 0;
1851          }
1852
1853 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1854          if (csp->flags & CSP_FLAG_CHUNKED)
1855          {
1856             if ((len >= 5) && !memcmp(buf+len-5, "0\r\n\r\n", 5))
1857             {
1858                /* XXX: this is a temporary hack */
1859                log_error(LOG_LEVEL_CONNECT,
1860                   "Looks like we reached the end of the last chunk. "
1861                   "We better stop reading.");
1862                csp->expected_content_length = byte_count + (unsigned long long)len;
1863                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
1864             }
1865          }
1866          reading_done:
1867 #endif  /* FEATURE_CONNECTION_KEEP_ALIVE */
1868
1869          /*
1870           * Add a trailing zero to let be able to use string operations.
1871           * XXX: do we still need this with filter_popups gone?
1872           */
1873          buf[len] = '\0';
1874
1875          /*
1876           * Normally, this would indicate that we've read
1877           * as much as the server has sent us and we can
1878           * close the client connection.  However, Microsoft
1879           * in its wisdom has released IIS/5 with a bug that
1880           * prevents it from sending the trailing \r\n in
1881           * a 302 redirect header (and possibly other headers).
1882           * To work around this if we've haven't parsed
1883           * a full header we'll append a trailing \r\n
1884           * and see if this now generates a valid one.
1885           *
1886           * This hack shouldn't have any impacts.  If we've
1887           * already transmitted the header or if this is a
1888           * SSL connection, then we won't bother with this
1889           * hack.  So we only work on partially received
1890           * headers.  If we append a \r\n and this still
1891           * doesn't generate a valid header, then we won't
1892           * transmit anything to the client.
1893           */
1894          if (len == 0)
1895          {
1896
1897             if (server_body || http->ssl)
1898             {
1899                /*
1900                 * If we have been buffering up the document,
1901                 * now is the time to apply content modification
1902                 * and send the result to the client.
1903                 */
1904                if (content_filter)
1905                {
1906                   p = execute_content_filter(csp, content_filter);
1907                   /*
1908                    * If the content filter fails, use the original
1909                    * buffer and length.
1910                    * (see p != NULL ? p : csp->iob->cur below)
1911                    */
1912                   if (NULL == p)
1913                   {
1914                      csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur);
1915                   }
1916
1917                   if (JB_ERR_OK != update_server_headers(csp))
1918                   {
1919                      log_error(LOG_LEVEL_FATAL,
1920                         "Failed to update server headers. after filtering.");
1921                   }
1922
1923                   hdr = list_to_text(csp->headers);
1924                   if (hdr == NULL)
1925                   {
1926                      /* FIXME Should handle error properly */
1927                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
1928                   }
1929
1930                   if (write_socket(csp->cfd, hdr, strlen(hdr))
1931                    || write_socket(csp->cfd,
1932                          ((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length))
1933                   {
1934                      log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
1935                      freez(hdr);
1936                      freez(p);
1937                      mark_server_socket_tainted(csp);
1938                      return;
1939                   }
1940
1941                   freez(hdr);
1942                   freez(p);
1943                }
1944
1945                break; /* "game over, man" */
1946             }
1947
1948             /*
1949              * This is NOT the body, so
1950              * Let's pretend the server just sent us a blank line.
1951              */
1952             snprintf(buf, sizeof(buf), "\r\n");
1953             len = (int)strlen(buf);
1954
1955             /*
1956              * Now, let the normal header parsing algorithm below do its
1957              * job.  If it fails, we'll exit instead of continuing.
1958              */
1959
1960             ms_iis5_hack = 1;
1961          }
1962
1963          /*
1964           * If this is an SSL connection or we're in the body
1965           * of the server document, just write it to the client,
1966           * unless we need to buffer the body for later content-filtering
1967           */
1968          if (server_body || http->ssl)
1969          {
1970             if (content_filter)
1971             {
1972                /*
1973                 * If there is no memory left for buffering the content, or the buffer limit
1974                 * has been reached, switch to non-filtering mode, i.e. make & write the
1975                 * header, flush the iob and buf, and get out of the way.
1976                 */
1977                if (add_to_iob(csp, buf, len))
1978                {
1979                   size_t hdrlen;
1980                   long flushed;
1981
1982                   log_error(LOG_LEVEL_INFO,
1983                      "Flushing header and buffers. Stepping back from filtering.");
1984
1985                   hdr = list_to_text(csp->headers);
1986                   if (hdr == NULL)
1987                   {
1988                      /* 
1989                       * Memory is too tight to even generate the header.
1990                       * Send our static "Out-of-memory" page.
1991                       */
1992                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
1993                      rsp = cgi_error_memory();
1994                      send_crunch_response(csp, rsp);
1995                      mark_server_socket_tainted(csp);
1996                      return;
1997                   }
1998                   hdrlen = strlen(hdr);
1999
2000                   if (write_socket(csp->cfd, hdr, hdrlen)
2001                    || ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
2002                    || (write_socket(csp->cfd, buf, (size_t)len)))
2003                   {
2004                      log_error(LOG_LEVEL_CONNECT,
2005                         "Flush header and buffers to client failed: %E");
2006                      freez(hdr);
2007                      mark_server_socket_tainted(csp);
2008                      return;
2009                   }
2010
2011                   /*
2012                    * Reset the byte_count to the amount of bytes
2013                    * we just flushed. len will be added a few lines below,
2014                    * hdrlen doesn't matter for LOG_LEVEL_CLF.
2015                    */
2016                   byte_count = (unsigned long long)flushed;
2017                   freez(hdr);
2018                   content_filter = NULL;
2019                   server_body = 1;
2020                }
2021             }
2022             else
2023             {
2024                if (write_socket(csp->cfd, buf, (size_t)len))
2025                {
2026                   log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
2027                   mark_server_socket_tainted(csp);
2028                   return;
2029                }
2030             }
2031             byte_count += (unsigned long long)len;
2032             continue;
2033          }
2034          else
2035          {
2036             const char *header_start;
2037             /*
2038              * We're still looking for the end of the server's header.
2039              * Buffer up the data we just read.  If that fails, there's
2040              * little we can do but send our static out-of-memory page.
2041              */
2042             if (add_to_iob(csp, buf, len))
2043             {
2044                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
2045                rsp = cgi_error_memory();
2046                send_crunch_response(csp, rsp);               
2047                mark_server_socket_tainted(csp);
2048                return;
2049             }
2050
2051             header_start = csp->iob->cur;
2052
2053             /* Convert iob into something sed() can digest */
2054             if (JB_ERR_PARSE == get_server_headers(csp))
2055             {
2056                if (ms_iis5_hack)
2057                {
2058                   /*
2059                    * Well, we tried our MS IIS/5 hack and it didn't work.
2060                    * The header is incomplete and there isn't anything
2061                    * we can do about it.
2062                    */
2063                   log_error(LOG_LEVEL_ERROR, "Invalid server headers. "
2064                      "Applying the MS IIS5 hack didn't help.");
2065                   log_error(LOG_LEVEL_CLF,
2066                      "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
2067                   write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
2068                      strlen(INVALID_SERVER_HEADERS_RESPONSE));
2069                   mark_server_socket_tainted(csp);
2070                   return;
2071                }
2072                else
2073                {
2074                   /*
2075                    * Since we have to wait for more from the server before
2076                    * we can parse the headers we just continue here.
2077                    */
2078                   long header_offset = csp->iob->cur - header_start;
2079                   assert(csp->iob->cur >= header_start);
2080                   byte_count += (unsigned long long)(len - header_offset);
2081                   log_error(LOG_LEVEL_CONNECT, "Continuing buffering headers. "
2082                      "byte_count: %llu. header_offset: %d. len: %d.",
2083                      byte_count, header_offset, len);
2084                   continue;
2085                }
2086             }
2087
2088             /* Did we actually get anything? */
2089             if (NULL == csp->headers->first)
2090             {
2091                log_error(LOG_LEVEL_ERROR, "Empty server or forwarder response.");
2092                log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
2093                send_crunch_response(csp, error_response(csp, "no-server-data"));
2094                free_http_request(http);
2095                mark_server_socket_tainted(csp);
2096                return;
2097             }
2098
2099             assert(csp->headers->first->str);
2100             assert(!http->ssl);
2101             if (strncmpic(csp->headers->first->str, "HTTP", 4) &&
2102                 strncmpic(csp->headers->first->str, "ICY", 3))
2103             {
2104                /*
2105                 * It doesn't look like a HTTP (or Shoutcast) response:
2106                 * tell the client and log the problem.
2107                 */
2108                if (strlen(csp->headers->first->str) > 30)
2109                {
2110                   csp->headers->first->str[30] = '\0';
2111                }
2112                log_error(LOG_LEVEL_ERROR,
2113                   "Invalid server or forwarder response. Starts with: %s",
2114                   csp->headers->first->str);
2115                log_error(LOG_LEVEL_CLF,
2116                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
2117                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
2118                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
2119                free_http_request(http);
2120                mark_server_socket_tainted(csp);
2121                return;
2122             }
2123
2124             /*
2125              * We have now received the entire server header,
2126              * filter it and send the result to the client
2127              */
2128             if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS))
2129             {
2130                log_error(LOG_LEVEL_FATAL, "Failed to parse server headers.");
2131             }
2132             hdr = list_to_text(csp->headers);
2133             if (hdr == NULL)
2134             {
2135                /* FIXME Should handle error properly */
2136                log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
2137             }
2138
2139             if (crunch_response_triggered(csp, crunchers_light))
2140             {
2141                /*
2142                 * One of the tags created by a server-header
2143                 * tagger triggered a crunch. We already
2144                 * delivered the crunch response to the client
2145                 * and are done here after cleaning up.
2146                 */
2147                 freez(hdr);
2148                 mark_server_socket_tainted(csp);
2149                 return;
2150             }
2151             /* Buffer and pcrs filter this if appropriate. */
2152
2153             if (!http->ssl) /* We talk plaintext */
2154             {
2155                content_filter = get_filter_function(csp);
2156             }
2157             /*
2158              * Only write if we're not buffering for content modification
2159              */
2160             if (!content_filter)
2161             {
2162                /*
2163                 * Write the server's (modified) header to
2164                 * the client (along with anything else that
2165                 * may be in the buffer)
2166                 */
2167
2168                if (write_socket(csp->cfd, hdr, strlen(hdr))
2169                 || ((len = flush_socket(csp->cfd, csp->iob)) < 0))
2170                {
2171                   log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
2172
2173                   /*
2174                    * The write failed, so don't bother mentioning it
2175                    * to the client... it probably can't hear us anyway.
2176                    */
2177                   freez(hdr);
2178                   mark_server_socket_tainted(csp);
2179                   return;
2180                }
2181
2182                byte_count += (unsigned long long)len;
2183             }
2184             else
2185             {
2186                /*
2187                 * XXX: the header lenght should probably
2188                 * be calculated by get_server_headers().
2189                 */
2190                long header_length = csp->iob->cur - header_start;
2191                assert(csp->iob->cur > header_start);
2192                byte_count += (unsigned long long)(len - header_length);
2193             }
2194
2195             /* we're finished with the server's header */
2196
2197             freez(hdr);
2198             server_body = 1;
2199
2200             /*
2201              * If this was a MS IIS/5 hack then it means the server
2202              * has already closed the connection. Nothing more to read.
2203              * Time to bail.
2204              */
2205             if (ms_iis5_hack)
2206             {
2207                log_error(LOG_LEVEL_ERROR,
2208                   "Closed server connection detected. "
2209                   "Applying the MS IIS5 hack didn't help.");
2210                log_error(LOG_LEVEL_CLF,
2211                   "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
2212                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
2213                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
2214                mark_server_socket_tainted(csp);
2215                return;
2216             }
2217          }
2218          continue;
2219       }
2220       mark_server_socket_tainted(csp);
2221       return; /* huh? we should never get here */
2222    }
2223
2224    if (csp->content_length == 0)
2225    {
2226       /*
2227        * If Privoxy didn't recalculate the Content-Lenght,
2228        * byte_count is still correct.
2229        */
2230       csp->content_length = byte_count;
2231    }
2232
2233 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2234    if ((csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
2235       && (csp->expected_content_length != byte_count))
2236    {
2237       log_error(LOG_LEVEL_CONNECT,
2238          "Received %llu bytes while expecting %llu.",
2239          byte_count, csp->expected_content_length);
2240       mark_server_socket_tainted(csp);
2241    }
2242 #endif
2243
2244    log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
2245       csp->ip_addr_str, http->ocmd, csp->content_length);
2246 }
2247
2248
2249 /*********************************************************************
2250  *
2251  * Function    :  serve
2252  *
2253  * Description :  This is little more than chat.  We only "serve" to
2254  *                to close (or remember) any socket that chat may have
2255  *                opened.
2256  *
2257  * Parameters  :
2258  *          1  :  csp = Current client state (buffers, headers, etc...)
2259  *
2260  * Returns     :  N/A
2261  *
2262  *********************************************************************/
2263 #ifdef AMIGA
2264 void serve(struct client_state *csp)
2265 #else /* ifndef AMIGA */
2266 static void serve(struct client_state *csp)
2267 #endif /* def AMIGA */
2268 {
2269 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2270    static int monitor_thread_running = 0;
2271    int continue_chatting = 0;
2272    do
2273    {
2274       chat(csp);
2275
2276       continue_chatting = (csp->config->feature_flags
2277          & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
2278          && (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
2279          && (csp->cfd != JB_INVALID_SOCKET)
2280          && (csp->sfd != JB_INVALID_SOCKET)
2281          && socket_is_still_usable(csp->sfd);
2282
2283       if (continue_chatting)
2284       {
2285          log_error(LOG_LEVEL_CONNECT,
2286             "Waiting for the next client request. "
2287             "Keeping the server socket %d to %s open.",
2288             csp->sfd, csp->server_connection.host);
2289
2290          if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
2291             && data_is_available(csp->cfd, (int)csp->server_connection.keep_alive_timeout)
2292             && socket_is_still_usable(csp->cfd))
2293          {
2294             log_error(LOG_LEVEL_CONNECT, "Client request arrived in "
2295                "time or the client closed the connection.");
2296             /*
2297              * Get the csp in a mostly vergin state again.
2298              * XXX: Should be done elsewhere.
2299              */
2300             csp->content_type = 0;
2301             csp->content_length = 0;
2302             csp->expected_content_length = 0;
2303             list_remove_all(csp->headers);
2304             freez(csp->iob->buf);
2305             memset(csp->iob, 0, sizeof(csp->iob));
2306             freez(csp->error_message);
2307             free_http_request(csp->http);
2308             destroy_list(csp->headers);
2309             destroy_list(csp->tags);
2310             free_current_action(csp->action);
2311             if (NULL != csp->fwd)
2312             {
2313                unload_forward_spec(csp->fwd);
2314                csp->fwd = NULL;
2315             }
2316
2317             /* XXX: Store per-connection flags someplace else. */
2318             csp->flags = CSP_FLAG_ACTIVE | (csp->flags & CSP_FLAG_TOGGLED_ON);
2319          }
2320          else
2321          {
2322             log_error(LOG_LEVEL_CONNECT,
2323                "No additional client request received in time.");
2324             if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
2325             {
2326                remember_connection(csp->sfd, csp->http,
2327                   forward_url(csp, csp->http),
2328                   csp->server_connection.keep_alive_timeout);
2329                csp->sfd = JB_INVALID_SOCKET;
2330                close_socket(csp->cfd);
2331                csp->cfd = JB_INVALID_SOCKET;
2332                privoxy_mutex_lock(&connection_reuse_mutex);
2333                if (!monitor_thread_running)
2334                {
2335                   monitor_thread_running = 1;
2336                   privoxy_mutex_unlock(&connection_reuse_mutex);
2337                   wait_for_alive_connections();
2338                   privoxy_mutex_lock(&connection_reuse_mutex);
2339                   monitor_thread_running = 0;
2340                }
2341                privoxy_mutex_unlock(&connection_reuse_mutex);
2342             }
2343             break;
2344          }
2345       }
2346       else if (csp->sfd != JB_INVALID_SOCKET)
2347       {
2348          log_error(LOG_LEVEL_CONNECT,
2349             "The connection on server socket %d to %s isn't reusable. "
2350             "Closing.", csp->sfd, csp->server_connection.host);
2351       }
2352    } while (continue_chatting);
2353
2354    mark_connection_closed(&csp->server_connection);
2355 #else
2356    chat(csp);
2357 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2358
2359    if (csp->sfd != JB_INVALID_SOCKET)
2360    {
2361 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2362       forget_connection(csp->sfd);
2363 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2364       close_socket(csp->sfd);
2365    }
2366
2367    if (csp->cfd != JB_INVALID_SOCKET)
2368    {
2369       close_socket(csp->cfd);
2370    }
2371
2372    csp->flags &= ~CSP_FLAG_ACTIVE;
2373
2374 }
2375
2376
2377 #ifdef __BEOS__
2378 /*********************************************************************
2379  *
2380  * Function    :  server_thread
2381  *
2382  * Description :  We only exist to call `serve' in a threaded environment.
2383  *
2384  * Parameters  :
2385  *          1  :  data = Current client state (buffers, headers, etc...)
2386  *
2387  * Returns     :  Always 0.
2388  *
2389  *********************************************************************/
2390 static int32 server_thread(void *data)
2391 {
2392    serve((struct client_state *) data);
2393    return 0;
2394
2395 }
2396 #endif
2397
2398
2399 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
2400 /*********************************************************************
2401  *
2402  * Function    :  usage
2403  *
2404  * Description :  Print usage info & exit.
2405  *
2406  * Parameters  :  Pointer to argv[0] for identifying ourselves
2407  *
2408  * Returns     :  No. ,-)
2409  *
2410  *********************************************************************/
2411 static void usage(const char *myname)
2412 {
2413    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
2414           "Usage: %s "
2415 #if defined(unix)
2416           "[--chroot] "
2417 #endif /* defined(unix) */
2418           "[--help] "
2419 #if defined(unix)
2420           "[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
2421 #endif /* defined(unix) */
2422           "[--version] [configfile]\n"
2423           "Aborting\n", myname);
2424
2425    exit(2);
2426
2427 }
2428 #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */
2429
2430
2431 #ifdef MUTEX_LOCKS_AVAILABLE
2432 /*********************************************************************
2433  *
2434  * Function    :  privoxy_mutex_lock
2435  *
2436  * Description :  Locks a mutex.
2437  *
2438  * Parameters  :
2439  *          1  :  mutex = The mutex to lock.
2440  *
2441  * Returns     :  Void. May exit in case of errors.
2442  *
2443  *********************************************************************/
2444 void privoxy_mutex_lock(privoxy_mutex_t *mutex)
2445 {
2446 #ifdef FEATURE_PTHREAD
2447    int err = pthread_mutex_lock(mutex);
2448    if (err)
2449    {
2450       if (mutex != &log_mutex)
2451       {
2452          log_error(LOG_LEVEL_FATAL,
2453             "Mutex locking failed: %s.\n", strerror(err));
2454       }
2455       exit(1);
2456    }
2457 #else
2458    EnterCriticalSection(mutex);
2459 #endif /* def FEATURE_PTHREAD */
2460 }
2461
2462
2463 /*********************************************************************
2464  *
2465  * Function    :  privoxy_mutex_unlock
2466  *
2467  * Description :  Unlocks a mutex.
2468  *
2469  * Parameters  :
2470  *          1  :  mutex = The mutex to unlock.
2471  *
2472  * Returns     :  Void. May exit in case of errors.
2473  *
2474  *********************************************************************/
2475 void privoxy_mutex_unlock(privoxy_mutex_t *mutex)
2476 {
2477 #ifdef FEATURE_PTHREAD
2478    int err = pthread_mutex_unlock(mutex);
2479    if (err)
2480    {
2481       if (mutex != &log_mutex)
2482       {
2483          log_error(LOG_LEVEL_FATAL,
2484             "Mutex unlocking failed: %s.\n", strerror(err));
2485       }
2486       exit(1);
2487    }
2488 #else
2489    LeaveCriticalSection(mutex);
2490 #endif /* def FEATURE_PTHREAD */
2491 }
2492
2493
2494 /*********************************************************************
2495  *
2496  * Function    :  privoxy_mutex_init
2497  *
2498  * Description :  Prepares a mutex.
2499  *
2500  * Parameters  :
2501  *          1  :  mutex = The mutex to initialize.
2502  *
2503  * Returns     :  Void. May exit in case of errors.
2504  *
2505  *********************************************************************/
2506 static void privoxy_mutex_init(privoxy_mutex_t *mutex)
2507 {
2508 #ifdef FEATURE_PTHREAD
2509    int err = pthread_mutex_init(mutex, 0);
2510    if (err)
2511    {
2512       printf("Fatal error. Mutex initialization failed: %s.\n",
2513          strerror(err));
2514       exit(1);
2515    }
2516 #else
2517    InitializeCriticalSection(mutex);
2518 #endif /* def FEATURE_PTHREAD */
2519 }
2520 #endif /* def MUTEX_LOCKS_AVAILABLE */
2521
2522 /*********************************************************************
2523  *
2524  * Function    :  initialize_mutexes
2525  *
2526  * Description :  Prepares mutexes if mutex support is available.
2527  *
2528  * Parameters  :  None
2529  *
2530  * Returns     :  Void, exits in case of errors.
2531  *
2532  *********************************************************************/
2533 static void initialize_mutexes(void)
2534 {
2535 #ifdef MUTEX_LOCKS_AVAILABLE
2536    /*
2537     * Prepare global mutex semaphores
2538     */
2539    privoxy_mutex_init(&log_mutex);
2540    privoxy_mutex_init(&log_init_mutex);
2541    privoxy_mutex_init(&connection_reuse_mutex);
2542
2543    /*
2544     * XXX: The assumptions below are a bit naive
2545     * and can cause locks that aren't necessary.
2546     *
2547     * For example older FreeBSD versions (< 6.x?)
2548     * have no gethostbyname_r, but gethostbyname is
2549     * thread safe.
2550     */
2551 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
2552    privoxy_mutex_init(&resolver_mutex);
2553 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
2554    /*
2555     * XXX: should we use a single mutex for
2556     * localtime() and gmtime() as well?
2557     */
2558 #ifndef HAVE_GMTIME_R
2559    privoxy_mutex_init(&gmtime_mutex);
2560 #endif /* ndef HAVE_GMTIME_R */
2561
2562 #ifndef HAVE_LOCALTIME_R
2563    privoxy_mutex_init(&localtime_mutex);
2564 #endif /* ndef HAVE_GMTIME_R */
2565
2566 #ifndef HAVE_RANDOM
2567    privoxy_mutex_init(&rand_mutex);
2568 #endif /* ndef HAVE_RANDOM */
2569 #endif /* def MUTEX_LOCKS_AVAILABLE */
2570 }
2571
2572
2573 /*********************************************************************
2574  *
2575  * Function    :  main
2576  *
2577  * Description :  Load the config file and start the listen loop.
2578  *                This function is a lot more *sane* with the `load_config'
2579  *                and `listen_loop' functions; although it stills does
2580  *                a *little* too much for my taste.
2581  *
2582  * Parameters  :
2583  *          1  :  argc = Number of parameters (including $0).
2584  *          2  :  argv = Array of (char *)'s to the parameters.
2585  *
2586  * Returns     :  1 if : can't open config file, unrecognized directive,
2587  *                stats requested in multi-thread mode, can't open the
2588  *                log file, can't open the jar file, listen port is invalid,
2589  *                any load fails, and can't bind port.
2590  *
2591  *                Else main never returns, the process must be signaled
2592  *                to terminate execution.  Or, on Windows, use the
2593  *                "File", "Exit" menu option.
2594  *
2595  *********************************************************************/
2596 #ifdef __MINGW32__
2597 int real_main(int argc, const char *argv[])
2598 #else
2599 int main(int argc, const char *argv[])
2600 #endif
2601 {
2602    int argc_pos = 0;
2603    unsigned int random_seed;
2604 #ifdef unix
2605    struct passwd *pw = NULL;
2606    struct group *grp = NULL;
2607    char *p;
2608    int do_chroot = 0;
2609    char *pre_chroot_nslookup_to_load_resolver = NULL;
2610 #endif
2611
2612    Argc = argc;
2613    Argv = argv;
2614
2615    configfile =
2616 #if !defined(_WIN32)
2617    "config"
2618 #else
2619    "config.txt"
2620 #endif
2621       ;
2622
2623    /* Prepare mutexes if supported and necessary. */
2624    initialize_mutexes();
2625
2626    /* Enable logging until further notice. */
2627    init_log_module();
2628
2629    /*
2630     * Parse the command line arguments
2631     *
2632     * XXX: simply printing usage information in case of
2633     * invalid arguments isn't particularly user friendly.
2634     */
2635    while (++argc_pos < argc)
2636    {
2637 #ifdef _WIN32
2638       /* Check to see if the service must be installed or uninstalled */
2639       if (strncmp(argv[argc_pos], "--install", 9) == 0)
2640       {
2641          const char *pName = argv[argc_pos] + 9;
2642          if (*pName == ':')
2643             pName++;
2644          exit( (install_service(pName)) ? 0 : 1 );
2645       }
2646       else if (strncmp(argv[argc_pos], "--uninstall", + 11) == 0)
2647       {
2648          const char *pName = argv[argc_pos] + 11;
2649          if (*pName == ':')
2650             pName++;
2651          exit((uninstall_service(pName)) ? 0 : 1);
2652       }
2653       else if (strcmp(argv[argc_pos], "--service" ) == 0)
2654       {
2655          bRunAsService = TRUE;
2656          w32_set_service_cwd();
2657          atexit(w32_service_exit_notify);
2658       }
2659       else
2660 #endif /* defined(_WIN32) */
2661
2662
2663 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
2664
2665       if (strcmp(argv[argc_pos], "--help") == 0)
2666       {
2667          usage(argv[0]);
2668       }
2669
2670       else if(strcmp(argv[argc_pos], "--version") == 0)
2671       {
2672          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
2673          exit(0);
2674       }
2675
2676 #if defined(unix)
2677
2678       else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
2679       {
2680          set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
2681          no_daemon = 1;
2682       }
2683
2684       else if (strcmp(argv[argc_pos], "--pidfile" ) == 0)
2685       {
2686          if (++argc_pos == argc) usage(argv[0]);
2687          pidfile = strdup(argv[argc_pos]);
2688       }
2689
2690       else if (strcmp(argv[argc_pos], "--user" ) == 0)
2691       {
2692          if (++argc_pos == argc) usage(argv[argc_pos]);
2693
2694          if ((NULL != (p = strchr(argv[argc_pos], '.'))) && *(p + 1) != '0')
2695          {
2696             *p++ = '\0';
2697             if (NULL == (grp = getgrnam(p)))
2698             {
2699                log_error(LOG_LEVEL_FATAL, "Group %s not found.", p);
2700             }
2701          }
2702
2703          if (NULL == (pw = getpwnam(argv[argc_pos])))
2704          {
2705             log_error(LOG_LEVEL_FATAL, "User %s not found.", argv[argc_pos]);
2706          }
2707
2708          if (p != NULL) *--p = '\0';
2709       }
2710
2711       else if (strcmp(argv[argc_pos], "--pre-chroot-nslookup" ) == 0)
2712       {
2713          if (++argc_pos == argc) usage(argv[0]);
2714          pre_chroot_nslookup_to_load_resolver = strdup(argv[argc_pos]);
2715       }
2716
2717       else if (strcmp(argv[argc_pos], "--chroot" ) == 0)
2718       {
2719          do_chroot = 1;
2720       }
2721 #endif /* defined(unix) */
2722
2723       else if (argc_pos + 1 != argc)
2724       {
2725          /*
2726           * This is neither the last command line
2727           * option, nor was it recognized before,
2728           * therefore it must be invalid.
2729           */
2730          usage(argv[0]);
2731       }
2732       else
2733
2734 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
2735       {
2736          configfile = argv[argc_pos];
2737       }
2738
2739    } /* -END- while (more arguments) */
2740
2741    show_version(Argv[0]);
2742
2743 #if defined(unix)
2744    if ( *configfile != '/' )
2745    {
2746       char cwd[BUFFER_SIZE];
2747       char *abs_file;
2748       size_t abs_file_size; 
2749
2750       /* make config-filename absolute here */
2751       if (NULL == getcwd(cwd, sizeof(cwd)))
2752       {
2753          perror("failed to get current working directory");
2754          exit( 1 );
2755       }
2756
2757       /* XXX: why + 5? */
2758       abs_file_size = strlen(cwd) + strlen(configfile) + 5;
2759       basedir = strdup(cwd);
2760
2761       if (NULL == basedir ||
2762           NULL == (abs_file = malloc(abs_file_size)))
2763       {
2764          perror("malloc failed");
2765          exit( 1 );
2766       }
2767       strlcpy(abs_file, basedir, abs_file_size);
2768       strlcat(abs_file, "/", abs_file_size );
2769       strlcat(abs_file, configfile, abs_file_size);
2770       configfile = abs_file;
2771    }
2772 #endif /* defined unix */
2773
2774
2775    files->next = NULL;
2776    clients->next = NULL;
2777
2778    /* XXX: factor out initialising after the next stable release. */
2779 #ifdef AMIGA
2780    InitAmiga();
2781 #elif defined(_WIN32)
2782    InitWin32();
2783 #endif
2784
2785    random_seed = (unsigned int)time(NULL);
2786 #ifdef HAVE_RANDOM
2787    srandom(random_seed);
2788 #else
2789    srand(random_seed);
2790 #endif /* ifdef HAVE_RANDOM */
2791
2792    /*
2793     * Unix signal handling
2794     *
2795     * Catch the abort, interrupt and terminate signals for a graceful exit
2796     * Catch the hangup signal so the errlog can be reopened.
2797     * Ignore the broken pipe signals (FIXME: Why?)
2798     */
2799 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
2800 {
2801    int idx;
2802    const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP, 0 };
2803    const int ignored_signals[] = { SIGPIPE, 0 };
2804
2805    for (idx = 0; catched_signals[idx] != 0; idx++)
2806    {
2807 #ifdef sun /* FIXME: Is it safe to check for HAVE_SIGSET instead? */ 
2808       if (sigset(catched_signals[idx], sig_handler) == SIG_ERR)
2809 #else
2810       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
2811 #endif /* ifdef sun */
2812       {
2813          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
2814       }
2815    }
2816
2817    for (idx = 0; ignored_signals[idx] != 0; idx++)
2818    {
2819       if (signal(ignored_signals[idx], SIG_IGN) == SIG_ERR)
2820       {
2821          log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for signal %d: %E", ignored_signals[idx]);
2822       }
2823    }
2824
2825 }
2826 #else /* ifdef _WIN32 */
2827 # ifdef _WIN_CONSOLE
2828    /*
2829     * We *are* in a windows console app.
2830     * Print a verbose messages about FAQ's and such
2831     */
2832    printf("%s", win32_blurb);
2833 # endif /* def _WIN_CONSOLE */
2834 #endif /* def _WIN32 */
2835
2836
2837    /* Initialize the CGI subsystem */
2838    cgi_init_error_messages();
2839
2840    /*
2841     * If runnig on unix and without the --nodaemon
2842     * option, become a daemon. I.e. fork, detach
2843     * from tty and get process group leadership
2844     */
2845 #if defined(unix)
2846 {
2847    pid_t pid = 0;
2848 #if 0
2849    int   fd;
2850 #endif
2851
2852    if (!no_daemon)
2853    {
2854       pid  = fork();
2855
2856       if ( pid < 0 ) /* error */
2857       {
2858          perror("fork");
2859          exit( 3 );
2860       }
2861       else if ( pid != 0 ) /* parent */
2862       {
2863          int status;
2864          pid_t wpid;
2865          /*
2866           * must check for errors
2867           * child died due to missing files aso
2868           */
2869          sleep( 1 );
2870          wpid = waitpid( pid, &status, WNOHANG );
2871          if ( wpid != 0 )
2872          {
2873             exit( 1 );
2874          }
2875          exit( 0 );
2876       }
2877       /* child */
2878 #if 1
2879       /* Should be more portable, but not as well tested */
2880       setsid();
2881 #else /* !1 */
2882 #ifdef __FreeBSD__
2883       setpgrp(0,0);
2884 #else /* ndef __FreeBSD__ */
2885       setpgrp();
2886 #endif /* ndef __FreeBSD__ */
2887       fd = open("/dev/tty", O_RDONLY);
2888       if ( fd )
2889       {
2890          /* no error check here */
2891          ioctl( fd, TIOCNOTTY,0 );
2892          close ( fd );
2893       }
2894 #endif /* 1 */
2895       /*
2896        * stderr (fd 2) will be closed later on,
2897        * when the config file has been parsed.
2898        */
2899
2900       close( 0 );
2901       close( 1 );
2902       chdir("/");
2903
2904    } /* -END- if (!no_daemon) */
2905
2906    /*
2907     * As soon as we have written the PID file, we can switch
2908     * to the user and group ID indicated by the --user option
2909     */
2910    write_pid_file();
2911
2912    if (NULL != pw)
2913    {
2914       if (setgid((NULL != grp) ? grp->gr_gid : pw->pw_gid))
2915       {
2916          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
2917       }
2918       if (NULL != grp)
2919       {
2920          if (setgroups(1, &grp->gr_gid))
2921          {
2922             log_error(LOG_LEVEL_FATAL, "setgroups() failed: %E");
2923          }
2924       }
2925       else if (initgroups(pw->pw_name, pw->pw_gid))
2926       {
2927          log_error(LOG_LEVEL_FATAL, "initgroups() failed: %E");
2928       }
2929       if (do_chroot)
2930       {
2931          if (!pw->pw_dir)
2932          {
2933             log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
2934          }
2935          /* Read the time zone file from /etc before doing chroot. */
2936          tzset();
2937          if (NULL != pre_chroot_nslookup_to_load_resolver
2938              && '\0' != pre_chroot_nslookup_to_load_resolver[0])
2939          {
2940             /* Initialize resolver library. */
2941             (void) resolve_hostname_to_ip(pre_chroot_nslookup_to_load_resolver);
2942          }
2943          if (chroot(pw->pw_dir) < 0)
2944          {
2945             log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
2946          }
2947          if (chdir ("/"))
2948          {
2949             log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
2950          }
2951       }
2952       if (setuid(pw->pw_uid))
2953       {
2954          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
2955       }
2956       if (do_chroot)
2957       {
2958          char putenv_dummy[64];
2959
2960          strlcpy(putenv_dummy, "HOME=/", sizeof(putenv_dummy));
2961          if (putenv(putenv_dummy) != 0)
2962          {
2963             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
2964          }                
2965
2966          snprintf(putenv_dummy, sizeof(putenv_dummy), "USER=%s", pw->pw_name);
2967          if (putenv(putenv_dummy) != 0)
2968          {
2969             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
2970          }
2971       }
2972    }
2973    else if (do_chroot)
2974    {
2975       log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
2976    }
2977 }
2978 #endif /* defined unix */
2979
2980 #ifdef _WIN32
2981    /* This will be FALSE unless the command line specified --service
2982     */
2983    if (bRunAsService)
2984    {
2985       /* Yup, so now we must attempt to establish a connection 
2986        * with the service dispatcher. This will only work if this
2987        * process was launched by the service control manager to
2988        * actually run as a service. If this isn't the case, i've
2989        * known it take around 30 seconds or so for the call to return.
2990        */
2991
2992       /* The StartServiceCtrlDispatcher won't return until the service is stopping */
2993       if (w32_start_service_ctrl_dispatcher(w32ServiceDispatchTable))
2994       {
2995          /* Service has run, and at this point is now being stopped, so just return */
2996          return 0;
2997       }
2998
2999 #ifdef _WIN_CONSOLE
3000       printf("Warning: Failed to connect to Service Control Dispatcher\nwhen starting as a service!\n");
3001 #endif
3002       /* An error occurred. Usually it's because --service was wrongly specified
3003        * and we were unable to connect to the Service Control Dispatcher because
3004        * it wasn't expecting us and is therefore not listening.
3005        *
3006        * For now, just continue below to call the listen_loop function.
3007        */
3008    }
3009 #endif /* def _WIN32 */
3010
3011    listen_loop();
3012
3013    /* NOTREACHED */
3014    return(-1);
3015
3016 }
3017
3018
3019 /*********************************************************************
3020  *
3021  * Function    :  bind_port_helper
3022  *
3023  * Description :  Bind the listen port.  Handles logging, and aborts
3024  *                on failure.
3025  *
3026  * Parameters  :
3027  *          1  :  config = Privoxy configuration.  Specifies port
3028  *                         to bind to.
3029  *
3030  * Returns     :  Port that was opened.
3031  *
3032  *********************************************************************/
3033 static jb_socket bind_port_helper(struct configuration_spec * config)
3034 {
3035    int result;
3036    jb_socket bfd;
3037
3038    if (config->haddr == NULL)
3039    {
3040       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
3041                 config->hport);
3042    }
3043    else
3044    {
3045       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
3046                 config->hport, config->haddr);
3047    }
3048
3049    result = bind_port(config->haddr, config->hport, &bfd);
3050
3051    if (result < 0)
3052    {
3053       switch(result)
3054       {
3055          case -3 :
3056             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: "
3057                "There may be another Privoxy or some other "
3058                "proxy running on port %d",
3059                (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
3060                       config->hport, config->hport);
3061
3062          case -2 :
3063             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " 
3064                "The hostname is not resolvable",
3065                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
3066
3067          default :
3068             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E",
3069                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
3070       }
3071
3072       /* shouldn't get here */
3073       return JB_INVALID_SOCKET;
3074    }
3075
3076    config->need_bind = 0;
3077
3078    return bfd;
3079 }
3080
3081
3082 #ifdef _WIN32
3083 /* Without this simple workaround we get this compiler warning from _beginthread
3084  *     warning C4028: formal parameter 1 different from declaration
3085  */
3086 void w32_service_listen_loop(void *p)
3087 {
3088    listen_loop();
3089 }
3090 #endif /* def _WIN32 */
3091
3092
3093 /*********************************************************************
3094  *
3095  * Function    :  listen_loop
3096  *
3097  * Description :  bind the listen port and enter a "FOREVER" listening loop.
3098  *
3099  * Parameters  :  N/A
3100  *
3101  * Returns     :  Never.
3102  *
3103  *********************************************************************/
3104 static void listen_loop(void)
3105 {
3106    struct client_state *csp = NULL;
3107    jb_socket bfd;
3108    struct configuration_spec *config;
3109    unsigned int active_threads = 0;
3110
3111    config = load_config();
3112
3113 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3114    /*
3115     * XXX: Should be relocated once it no
3116     * longer needs to emit log messages.
3117     */
3118    initialize_reusable_connections();
3119 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
3120
3121    bfd = bind_port_helper(config);
3122
3123 #ifdef FEATURE_GRACEFUL_TERMINATION
3124    while (!g_terminate)
3125 #else
3126    for (;;)
3127 #endif
3128    {
3129 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
3130       while (waitpid(-1, NULL, WNOHANG) > 0)
3131       {
3132          /* zombie children */
3133       }
3134 #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
3135
3136       /*
3137        * Free data that was used by died threads
3138        */
3139       active_threads = sweep();
3140
3141 #if defined(unix)
3142       /*
3143        * Re-open the errlog after HUP signal
3144        */
3145       if (received_hup_signal)
3146       {
3147          if (NULL != config->logfile)
3148          {
3149             init_error_log(Argv[0], config->logfile);
3150          }
3151          received_hup_signal = 0;
3152       }
3153 #endif
3154
3155       if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) )
3156       {
3157          log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp));
3158          continue;
3159       }
3160
3161       csp->flags |= CSP_FLAG_ACTIVE;
3162       csp->sfd    = JB_INVALID_SOCKET;
3163
3164       csp->config = config = load_config();
3165
3166       if ( config->need_bind )
3167       {
3168          /*
3169           * Since we were listening to the "old port", we will not see
3170           * a "listen" param change until the next request.  So, at
3171           * least 1 more request must be made for us to find the new
3172           * setting.  I am simply closing the old socket and binding the
3173           * new one.
3174           *
3175           * Which-ever is correct, we will serve 1 more page via the
3176           * old settings.  This should probably be a "show-proxy-args"
3177           * request.  This should not be a so common of an operation
3178           * that this will hurt people's feelings.
3179           */
3180
3181          close_socket(bfd);
3182
3183          bfd = bind_port_helper(config);
3184       }
3185
3186       log_error(LOG_LEVEL_CONNECT, "Listening for new connections ... ");
3187
3188       if (!accept_connection(csp, bfd))
3189       {
3190          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
3191
3192 #ifdef AMIGA
3193          if(!childs)
3194          {
3195             exit(1);
3196          }
3197 #endif
3198          freez(csp);
3199          continue;
3200       }
3201       else
3202       {
3203          log_error(LOG_LEVEL_CONNECT, "accepted connection from %s", csp->ip_addr_str);
3204       }
3205
3206 #ifdef FEATURE_TOGGLE
3207       if (global_toggle_state)
3208 #endif /* def FEATURE_TOGGLE */
3209       {
3210          csp->flags |= CSP_FLAG_TOGGLED_ON;
3211       }
3212
3213       if (run_loader(csp))
3214       {
3215          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
3216          /* Never get here - LOG_LEVEL_FATAL causes program exit */
3217       }
3218
3219 #ifdef FEATURE_ACL
3220       if (block_acl(NULL,csp))
3221       {
3222          log_error(LOG_LEVEL_CONNECT, "Connection from %s dropped due to ACL", csp->ip_addr_str);
3223          close_socket(csp->cfd);
3224          freez(csp->ip_addr_str);
3225          freez(csp);
3226          continue;
3227       }
3228 #endif /* def FEATURE_ACL */
3229
3230       if ((0 != config->max_client_connections)
3231          && (active_threads >= config->max_client_connections))
3232       {
3233          log_error(LOG_LEVEL_CONNECT,
3234             "Rejecting connection from %s. Maximum number of connections reached.",
3235             csp->ip_addr_str);
3236          write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
3237             strlen(TOO_MANY_CONNECTIONS_RESPONSE));
3238          close_socket(csp->cfd);
3239          freez(csp->ip_addr_str);
3240          freez(csp);
3241          continue;
3242       }
3243
3244       /* add it to the list of clients */
3245       csp->next = clients->next;
3246       clients->next = csp;
3247
3248       if (config->multi_threaded)
3249       {
3250          int child_id;
3251
3252 /* this is a switch () statment in the C preprocessor - ugh */
3253 #undef SELECTED_ONE_OPTION
3254
3255 /* Use Pthreads in preference to native code */
3256 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
3257 #define SELECTED_ONE_OPTION
3258          {
3259             pthread_t the_thread;
3260             pthread_attr_t attrs;
3261
3262             pthread_attr_init(&attrs);
3263             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
3264             errno = pthread_create(&the_thread, &attrs,
3265                (void * (*)(void *))serve, csp);
3266             child_id = errno ? -1 : 0;
3267             pthread_attr_destroy(&attrs);
3268          }
3269 #endif
3270
3271 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
3272 #define SELECTED_ONE_OPTION
3273          child_id = _beginthread(
3274             (void (*)(void *))serve,
3275             64 * 1024,
3276             csp);
3277 #endif
3278
3279 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
3280 #define SELECTED_ONE_OPTION
3281          child_id = _beginthread(
3282             (void(* _Optlink)(void*))serve,
3283             NULL,
3284             64 * 1024,
3285             csp);
3286 #endif
3287
3288 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
3289 #define SELECTED_ONE_OPTION
3290          {
3291             thread_id tid = spawn_thread
3292                (server_thread, "server", B_NORMAL_PRIORITY, csp);
3293
3294             if ((tid >= 0) && (resume_thread(tid) == B_OK))
3295             {
3296                child_id = (int) tid;
3297             }
3298             else
3299             {
3300                child_id = -1;
3301             }
3302          }
3303 #endif
3304
3305 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
3306 #define SELECTED_ONE_OPTION
3307          csp->cfd = ReleaseSocket(csp->cfd, -1);
3308          
3309 #ifdef __amigaos4__
3310          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
3311                                            NP_Output, Output(),
3312                                            NP_CloseOutput, FALSE,
3313                                            NP_Name, (ULONG)"privoxy child",
3314                                            NP_Child, TRUE,
3315                                            TAG_DONE);
3316 #else
3317          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
3318                                            NP_Output, Output(),
3319                                            NP_CloseOutput, FALSE,
3320                                            NP_Name, (ULONG)"privoxy child",
3321                                            NP_StackSize, 200*1024,
3322                                            TAG_DONE);
3323 #endif
3324          if(0 != child_id)
3325          {
3326             childs++;
3327             ((struct Task *)child_id)->tc_UserData = csp;
3328             Signal((struct Task *)child_id, SIGF_SINGLE);
3329             Wait(SIGF_SINGLE);
3330          }
3331 #endif
3332
3333 #if !defined(SELECTED_ONE_OPTION)
3334          child_id = fork();
3335
3336          /* This block is only needed when using fork().
3337           * When using threads, the server thread was
3338           * created and run by the call to _beginthread().
3339           */
3340          if (child_id == 0)   /* child */
3341          {
3342             int rc = 0;
3343 #ifdef FEATURE_TOGGLE
3344             int inherited_toggle_state = global_toggle_state;
3345 #endif /* def FEATURE_TOGGLE */
3346
3347             serve(csp);
3348
3349             /* 
3350              * If we've been toggled or we've blocked the request, tell Mom
3351              */
3352
3353 #ifdef FEATURE_TOGGLE
3354             if (inherited_toggle_state != global_toggle_state)
3355             {
3356                rc |= RC_FLAG_TOGGLED;
3357             }
3358 #endif /* def FEATURE_TOGGLE */
3359
3360 #ifdef FEATURE_STATISTICS  
3361             if (csp->flags & CSP_FLAG_REJECTED)
3362             {
3363                rc |= RC_FLAG_BLOCKED;
3364             }
3365 #endif /* ndef FEATURE_STATISTICS */
3366
3367             _exit(rc);
3368          }
3369          else if (child_id > 0) /* parent */
3370          {
3371             /* in a fork()'d environment, the parent's
3372              * copy of the client socket and the CSP
3373              * are not used.
3374              */
3375             int child_status;
3376 #if !defined(_WIN32) && !defined(__CYGWIN__)
3377
3378             wait( &child_status );
3379
3380             /* 
3381              * Evaluate child's return code: If the child has
3382              *  - been toggled, toggle ourselves
3383              *  - blocked its request, bump up the stats counter
3384              */
3385
3386 #ifdef FEATURE_TOGGLE
3387             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
3388             {
3389                global_toggle_state = !global_toggle_state;
3390             }
3391 #endif /* def FEATURE_TOGGLE */
3392
3393 #ifdef FEATURE_STATISTICS
3394             urls_read++;
3395             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
3396             {
3397                urls_rejected++;
3398             }
3399 #endif /* def FEATURE_STATISTICS */ 
3400
3401 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
3402             close_socket(csp->cfd);
3403             csp->flags &= ~CSP_FLAG_ACTIVE;
3404          }
3405 #endif
3406
3407 #undef SELECTED_ONE_OPTION
3408 /* end of cpp switch () */
3409
3410          if (child_id < 0)
3411          {
3412             /*
3413              * Spawning the child failed, assume it's because
3414              * there are too many children running already.
3415              * XXX: If you assume ...
3416              */
3417             log_error(LOG_LEVEL_ERROR,
3418                "Unable to take any additional connections: %E");
3419             write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
3420                strlen(TOO_MANY_CONNECTIONS_RESPONSE));
3421             close_socket(csp->cfd);
3422             csp->flags &= ~CSP_FLAG_ACTIVE;
3423          }
3424       }
3425       else
3426       {
3427          serve(csp);
3428       }
3429    }
3430
3431    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
3432
3433    /* Clean up.  Aim: free all memory (no leaks) */
3434 #ifdef FEATURE_GRACEFUL_TERMINATION
3435
3436    log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
3437
3438    unload_current_config_file();
3439    unload_current_actions_file();
3440    unload_current_re_filterfile();
3441 #ifdef FEATURE_TRUST
3442    unload_current_trust_file();
3443 #endif
3444
3445    if (config->multi_threaded)
3446    {
3447       int i = 60;
3448       do
3449       {
3450          sleep(1);
3451          sweep();
3452       } while ((clients->next != NULL) && (--i > 0));
3453
3454       if (i <= 0)
3455       {
3456          log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
3457       }
3458    }
3459    sweep();
3460    sweep();
3461
3462 #if defined(unix)
3463    freez(basedir);
3464 #endif
3465    freez(configfile);
3466
3467 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
3468    /* Cleanup - remove taskbar icon etc. */
3469    TermLogWindow();
3470 #endif
3471
3472    exit(0);
3473 #endif /* FEATURE_GRACEFUL_TERMINATION */
3474
3475 }
3476
3477
3478 /*
3479   Local Variables:
3480   tab-width: 3
3481   end:
3482 */