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