Fix byte_count calculation in case of flushes
[privoxy.git] / jcc.c
1 const char jcc_rcs[] = "$Id: jcc.c,v 1.145 2007/08/19 13:13:31 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-2007 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  * Revisions   :
35  *    $Log: jcc.c,v $
36  *    Revision 1.145  2007/08/19 13:13:31  fabiankeil
37  *    - If there's a connection problem after we already forwarded
38  *      parts of the original content, just hang up. Fixes BR#1776724.
39  *    - Fix warnings about unused code on mingw32.
40  *    - In case of flushes, calculate the byte count
41  *      less incorrectly (I think).
42  *
43  *    Revision 1.144  2007/08/11 14:43:22  fabiankeil
44  *    Add some more prototypes for static functions.
45  *
46  *    Revision 1.143  2007/08/05 13:58:19  fabiankeil
47  *    Comment out request_contains_null_bytes() until it's used again.
48  *
49  *    Revision 1.142  2007/08/05 13:50:26  fabiankeil
50  *    #1763173 from Stefan Huehner: s@const static@static const@
51  *    and declare some more functions static.
52  *
53  *    Revision 1.141  2007/08/04 09:56:23  fabiankeil
54  *    - Log rejected CONNECT requests with LOG_LEVEL_INFO
55  *      and explain why they were rejected in the first place.
56  *    - Fix the LOG_LEVEL_CLF message for crunches of unallowed
57  *      CONNECT requests. The request line was missing.
58  *    - Add two more XXX reminders as we don't have enough already.
59  *
60  *    Revision 1.140  2007/07/21 11:51:36  fabiankeil
61  *    As Hal noticed, checking dispatch_cgi() as the last cruncher
62  *    looks like a bug if CGI requests are blocked unintentionally,
63  *    so don't do it unless the user enabled the new config option
64  *    "allow-cgi-request-crunching".
65  *
66  *    Revision 1.139  2007/07/14 07:46:41  fabiankeil
67  *    - Allow to rewrite the request destination behind the client's back.
68  *    - Turn the weird-looking unconditional for loop that
69  *      reads the client request into a conditional while loop.
70  *      Move the stuff that only runs once out of the loop.
71  *    - Move parts of chat(), server_content_type() and the
72  *      necessary stuff to fix BR#1750917 into get_filter_function().
73  *
74  *    Revision 1.138  2007/06/03 18:45:18  fabiankeil
75  *    Temporary workaround for BR#1730105.
76  *
77  *    Revision 1.137  2007/06/01 18:16:36  fabiankeil
78  *    Use the same mutex for gethostbyname() and gethostbyaddr() to prevent
79  *    deadlocks and crashes on OpenBSD and possibly other OS with neither
80  *    gethostbyname_r() nor gethostaddr_r(). Closes BR#1729174.
81  *    Thanks to Ralf Horstmann for report and solution.
82  *
83  *    Revision 1.136  2007/06/01 16:41:11  fabiankeil
84  *    Add forward-override{} to change the forwarding settings through
85  *    action sections. This is mainly interesting to forward different
86  *    clients differently (for example based on User-Agent or request
87  *    origin).
88  *
89  *    Revision 1.135  2007/05/24 17:03:50  fabiankeil
90  *    - Let usage() mention the --chroot parameter.
91  *    - Use read_socket() consistently and always leave
92  *      the last buffer byte alone, even in cases where
93  *      null termination (currently) doesn't matter.
94  *
95  *    Revision 1.134  2007/05/16 14:59:46  fabiankeil
96  *    - Fix config file loading on Unix if no config file is specified.
97  *      Since r1.97 Privoxy would always interpret the last argument as
98  *      config file, even if it's a valid command line option.
99  *    - Abort in case of unrecognized command line options. Closes #1719696.
100  *    - Remove a bunch of unnecessary strcpy() calls (yay for c&p without thinking).
101  *    - Replace the remaining strcpy() and strcat() calls with strlcpy() and strcat().
102  *
103  *    Revision 1.133  2007/05/04 11:23:19  fabiankeil
104  *    - Don't rerun crunchers that only depend on the request URL.
105  *    - Don't count redirects and CGI requests as "blocked requests".
106  *
107  *    Revision 1.132  2007/04/25 15:15:17  fabiankeil
108  *    Support crunching based on tags created by server-header taggers.
109  *
110  *    Revision 1.131  2007/04/22 13:24:50  fabiankeil
111  *    Make HTTP snippets static (again). Add a Content-Type for those
112  *    with content so the browser doesn't guess it based on the URL.
113  *
114  *    Revision 1.130  2007/04/19 13:47:34  fabiankeil
115  *    Move crunching and request line rebuilding out of chat().
116  *
117  *    Revision 1.129  2007/04/15 16:39:20  fabiankeil
118  *    Introduce tags as alternative way to specify which
119  *    actions apply to a request. At the moment tags can be
120  *    created based on client and server headers.
121  *
122  *    Revision 1.128  2007/03/25 16:55:54  fabiankeil
123  *    Don't CLF-log CONNECT requests twice.
124  *
125  *    Revision 1.127  2007/03/20 13:53:17  fabiankeil
126  *    Log the source address for ACL-related connection drops.
127  *
128  *    Revision 1.126  2007/03/17 15:20:05  fabiankeil
129  *    New config option: enforce-blocks.
130  *
131  *    Revision 1.125  2007/03/09 14:12:00  fabiankeil
132  *    - Move null byte check into separate function.
133  *    - Don't confuse the client with error pages
134  *      if a CONNECT request was already confirmed.
135  *
136  *    Revision 1.124  2007/02/23 14:59:54  fabiankeil
137  *    Speed up NULL byte escaping and only log the complete
138  *    NULL byte requests with header debugging enabled.
139  *
140  *    Revision 1.123  2007/02/21 18:42:10  fabiankeil
141  *    Answer requests that contain NULL bytes with
142  *    a custom response instead of waiting for more
143  *    data until the client eventually hangs up.
144  *
145  *    Revision 1.122  2007/02/07 11:12:02  fabiankeil
146  *    - Move delivery and logging of crunched responses
147  *      from chat() into send_crunch_response().
148  *    - Display the reason for generating http_responses.
149  *    - Log the content length for LOG_LEVEL_CLF correctly
150  *      (still incorrect for some fixed responses).
151  *    - Reword an incorrect comment about
152  *      treat-forbidden-connects-like-blocks violating
153  *      the specs.
154  *    - Add some log messages.
155  *
156  *    Revision 1.121  2007/01/27 10:52:56  fabiankeil
157  *    Move mutex initialization into separate
158  *    function and exit in case of errors.
159  *
160  *    Revision 1.120  2007/01/26 14:18:42  fabiankeil
161  *    - Start to reduce chat()'s line count and move
162  *      parts of it into separate functions.
163  *    - Add "HTTP/1.1 100 Continue" hack for BR 756734.
164  *
165  *    Revision 1.119  2007/01/25 14:02:30  fabiankeil
166  *    - Add Proxy-Agent header to HTTP snippets that are
167  *      supposed to reach HTTP clients only.
168  *    - Made a few CONNECT log messages more descriptive.
169  *    - Catch completely empty server responses (as seen
170  *      with Tor's fake ".noconnect" top level domain).
171  *    - Use shiny new "forwarding-failed" template for socks errors.
172  *
173  *    Revision 1.118  2007/01/07 07:43:43  joergs
174  *    AmigaOS4 support added.
175  *
176  *    Revision 1.117  2006/12/31 17:56:37  fabiankeil
177  *    Added config option accept-intercepted-requests
178  *    and disabled it by default.
179  *
180  *    Revision 1.116  2006/12/29 19:08:22  fabiankeil
181  *    Reverted parts of my last commit
182  *    to keep error handling working.
183  *
184  *    Revision 1.115  2006/12/29 17:38:57  fabiankeil
185  *    Fixed gcc43 conversion warnings.
186  *
187  *    Revision 1.114  2006/12/27 18:52:02  fabiankeil
188  *    Fix -pedantic ISO C warning about converting
189  *    from function pointer to object pointer.
190  *
191  *    Revision 1.113  2006/12/26 17:38:50  fabiankeil
192  *    Silence compiler warning I introduced with my last commit.
193  *
194  *    Revision 1.112  2006/12/26 17:31:41  fabiankeil
195  *    Mutex protect rand() if POSIX threading
196  *    is used, warn the user if that's not possible
197  *    and stop using it on _WIN32 where it could
198  *    cause crashes.
199  *
200  *    Revision 1.111  2006/12/23 16:15:06  fabiankeil
201  *    Don't prevent core dumps by catching SIGABRT.
202  *    It's rude and makes debugging unreasonable painful.
203  *
204  *    Revision 1.110  2006/12/13 14:52:53  etresoft
205  *    Fix build failure on MacOS X. Global symbols can be either static or extern, but not both.
206  *
207  *    Revision 1.109  2006/12/06 19:41:40  fabiankeil
208  *    Privoxy is now able to run as intercepting
209  *    proxy in combination with any packet filter
210  *    that does the port redirection. The destination
211  *    is extracted from the "Host:" header which
212  *    should be available for nearly all requests.
213  *
214  *    Moved HTTP snipplets into jcc.c.
215  *    Added error message for gopher proxy requests.
216  *
217  *    Revision 1.108  2006/11/28 15:38:51  fabiankeil
218  *    Only unlink the pidfile if it's actually used.
219  *
220  *    Change order of interception checks to make
221  *    it possible to block or redirect requests for
222  *    the cgi pages.
223  *
224  *    Revision 1.107  2006/11/13 19:05:51  fabiankeil
225  *    Make pthread mutex locking more generic. Instead of
226  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
227  *    and use mutex locking unless there is an _r function
228  *    available. Better safe than sorry.
229  *
230  *    Fixes "./configure --disable-pthread" and should result
231  *    in less threading-related problems on pthread-using platforms,
232  *    but it still doesn't fix BR#1122404.
233  *
234  *    Revision 1.106  2006/11/06 19:58:23  fabiankeil
235  *    Move pthread.h inclusion from jcc.c to jcc.h.
236  *    Fixes build on x86-freebsd1 (FreeBSD 5.4-RELEASE).
237  *
238  *    Revision 1.105  2006/11/06 14:26:02  fabiankeil
239  *    Don't exit after receiving the second SIGHUP on Solaris.
240  *
241  *    Fixes BR 1052235, but the same problem may exist on other
242  *    systems. Once 3.0.6 is out we should use sigset()
243  *    where available and see if it breaks anything.
244  *
245  *    Revision 1.104  2006/09/23 13:26:38  roro
246  *    Replace TABs by spaces in source code.
247  *
248  *    Revision 1.103  2006/09/21 12:54:43  fabiankeil
249  *    Fix +redirect{}. Didn't work with -fast-redirects.
250  *
251  *    Revision 1.102  2006/09/06 13:03:04  fabiankeil
252  *    Respond with 400 and a short text message
253  *    if the client tries to use Privoxy as FTP proxy.
254  *
255  *    Revision 1.101  2006/09/06 09:23:37  fabiankeil
256  *    Make number of retries in case of forwarded-connect problems
257  *    a config file option (forwarded-connect-retries) and use 0 as
258  *    default.
259  *
260  *    Revision 1.100  2006/09/03 19:42:59  fabiankeil
261  *    Set random(3) seed.
262  *
263  *    Revision 1.99  2006/09/02 15:36:42  fabiankeil
264  *    Follow the OpenBSD port's lead and protect the resolve
265  *    functions on OpenBSD as well.
266  *
267  *    Revision 1.98  2006/08/24 11:01:34  fabiankeil
268  *    --user fix. Only use the user as group if no group is specified.
269  *    Solves BR 1492612. Thanks to Spinor S. and David Laight.
270  *
271  *    Revision 1.97  2006/08/18 15:23:17  david__schmidt
272  *    Windows service (re-)integration
273  *
274  *    The new args are:
275  *
276  *    --install[:service_name]
277  *    --uninstall[:service_name]
278  *    --service
279  *
280  *    They work as follows:
281  *    --install will create a service for you and then terminate.
282  *    By default the service name will be "privoxy" (without the quotes).
283  *    However you can run multiple services if you wish, just by adding
284  *    a colon and then a name (no spaces).
285  *
286  *    --uninstall follows the exact same rules a --install.
287  *
288  *    --service is used when the program is executed by the service
289  *    control manager, and in normal circumstances would never be
290  *    used as a command line argument.
291  *
292  *    Revision 1.96  2006/08/15 20:12:36  david__schmidt
293  *    Windows service integration
294  *
295  *    Revision 1.95  2006/08/03 02:46:41  david__schmidt
296  *    Incorporate Fabian Keil's patch work:
297 http://www.fabiankeil.de/sourcecode/privoxy/
298  *
299  *    Revision 1.94  2006/07/18 14:48:46  david__schmidt
300  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
301  *    with what was really the latest development (the v_3_0_branch branch)
302  *
303  *    Revision 1.92.2.16  2005/04/03 20:10:50  david__schmidt
304  *    Thanks to Jindrich Makovicka for a race condition fix for the log
305  *    file.  The race condition remains for non-pthread implementations.
306  *    Reference patch #1175720.
307  *
308  *    Revision 1.92.2.15  2004/10/03 12:53:32  david__schmidt
309  *    Add the ability to check jpeg images for invalid
310  *    lengths of comment blocks.  Defensive strategy
311  *    against the exploit:
312  *       Microsoft Security Bulletin MS04-028
313  *       Buffer Overrun in JPEG Processing (GDI+) Could
314  *       Allow Code Execution (833987)
315  *    Enabled with +inspect-jpegs in actions files.
316  *
317  *    Revision 1.92.2.14  2003/12/12 12:52:53  oes
318  *    - Fixed usage info for non-unix platforms
319  *    - Fixed small cmdline parsing bug
320  *
321  *    Revision 1.92.2.13  2003/11/27 19:20:27  oes
322  *    Diagnostics: Now preserve the returncode of pthread_create
323  *    in errno. Closes BR #775721. Thanks to Geoffrey Hausheer.
324  *
325  *    Revision 1.92.2.12  2003/07/11 11:34:19  oes
326  *    No longer ignore SIGCHLD. Fixes bug #769381
327  *
328  *    Revision 1.92.2.11  2003/05/14 12:32:02  oes
329  *    Close jarfile on graceful exit, remove stray line
330  *
331  *    Revision 1.92.2.10  2003/05/08 15:13:46  oes
332  *    Cosmetics: Killed a warning, a typo and an allocation left at exit
333  *
334  *    Revision 1.92.2.9  2003/04/03 15:08:42  oes
335  *    No longer rely on non-POSIX.1 extensions of getcwd().
336  *    Fixes bug #711001
337  *
338  *    Revision 1.92.2.8  2003/03/31 13:12:32  oes
339  *    Replaced setenv() by posix-compliant putenv()
340  *    Thanks to Neil McCalden (nmcc AT users.sf.net).
341  *
342  *    Revision 1.92.2.7  2003/03/17 16:48:59  oes
343  *    Added chroot ability, thanks to patch by Sviatoslav Sviridov
344  *
345  *    Revision 1.92.2.6  2003/03/11 11:55:00  oes
346  *    Clean-up and extension of improvements for forked mode:
347  *     - Child's return code now consists of flags RC_FLAG_*
348  *     - Reporting toggle to parent now properly #ifdef'ed
349  *     - Children now report blocking to parent. This enables
350  *       statistics in forked mode
351  *
352  *    Revision 1.92.2.5  2003/03/10 23:45:32  oes
353  *    Fixed bug #700381: Non-Threaded version now capable of being toggled.
354  *    Children now report having been toggled through _exit(17), parents
355  *    watch for that code and toggle themselves if found.
356  *
357  *    Revision 1.92.2.4  2003/03/07 03:41:04  david__schmidt
358  *    Wrapping all *_r functions (the non-_r versions of them) with 
359  *    mutex semaphores for OSX.  Hopefully this will take care of all 
360  *    of those pesky crash reports.
361  *
362  *    Revision 1.92.2.3  2003/02/28 12:53:06  oes
363  *    Fixed two mostly harmless mem leaks
364  *
365  *    Revision 1.92.2.2  2002/11/20 14:37:47  oes
366  *    Fix: Head of global clients list now initialized to NULL
367  *
368  *    Revision 1.92.2.1  2002/09/25 14:52:24  oes
369  *    Added basic support for OPTIONS and TRACE HTTP methods:
370  *     - New interceptor direct_response() added in chat().
371  *     - sed() moved to earlier in the process, so that the
372  *       Host: header is evaluated before actions and forwarding
373  *       are decided on.
374  *
375  *    Revision 1.92  2002/05/08 16:00:46  oes
376  *    Chat's buffer handling:
377  *     - Fixed bug with unchecked out-of-mem conditions
378  *       while reading client request & server headers
379  *     - No longer predict if the buffer limit will be exceeded
380  *       in the next read -- check add_to_iob's new
381  *       return code. If buffer couldn't be extended
382  *       (policy or out-of-mem) while
383  *       - reading from client: abort
384  *       - reading server headers: send error page
385  *       - buffering server body for filter: flush,
386  *         and if that fails: send error page
387  *
388  *    Revision 1.91  2002/04/08 20:35:58  swa
389  *    fixed JB spelling
390  *
391  *    Revision 1.90  2002/04/02 14:57:28  oes
392  *    Made sending wafers independent of FEATURE_COOKIE_JAR
393  *
394  *    Revision 1.89  2002/03/31 17:18:59  jongfoster
395  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
396  *
397  *    Revision 1.88  2002/03/27 14:32:43  david__schmidt
398  *    More compiler warning message maintenance
399  *
400  *    Revision 1.87  2002/03/26 22:29:54  swa
401  *    we have a new homepage!
402  *
403  *    Revision 1.86  2002/03/25 17:04:55  david__schmidt
404  *    Workaround for closing the jarfile before load_config() comes around again
405  *
406  *    Revision 1.85  2002/03/24 15:23:33  jongfoster
407  *    Name changes
408  *
409  *    Revision 1.84  2002/03/24 13:25:43  swa
410  *    name change related issues
411  *
412  *    Revision 1.83  2002/03/16 23:54:06  jongfoster
413  *    Adding graceful termination feature, to help look for memory leaks.
414  *    If you enable this (which, by design, has to be done by hand
415  *    editing config.h) and then go to http://i.j.b/die, then the program
416  *    will exit cleanly after the *next* request.  It should free all the
417  *    memory that was used.
418  *
419  *    Revision 1.82  2002/03/13 00:27:05  jongfoster
420  *    Killing warnings
421  *
422  *    Revision 1.81  2002/03/12 01:42:50  oes
423  *    Introduced modular filters
424  *
425  *    Revision 1.80  2002/03/11 22:07:05  david__schmidt
426  *    OS/2 port maintenance:
427  *    - Fixed EMX build - it had decayed a little
428  *    - Fixed inexplicable crash during FD_ZERO - must be due to a bad macro.
429  *      substituted a memset for now.
430  *
431  *    Revision 1.79  2002/03/09 20:03:52  jongfoster
432  *    - Making various functions return int rather than size_t.
433  *      (Undoing a recent change).  Since size_t is unsigned on
434  *      Windows, functions like read_socket that return -1 on
435  *      error cannot return a size_t.
436  *
437  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
438  *      crashes, and also frequently caused JB to jump to 100%
439  *      CPU and stay there.  (Because it thought it had just
440  *      read ((unsigned)-1) == 4Gb of data...)
441  *
442  *    - The signature of write_socket has changed, it now simply
443  *      returns success=0/failure=nonzero.
444  *
445  *    - Trying to get rid of a few warnings --with-debug on
446  *      Windows, I've introduced a new type "jb_socket".  This is
447  *      used for the socket file descriptors.  On Windows, this
448  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
449  *      an int.  The error value can't be -1 any more, so it's
450  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
451  *      Windows it maps to the #define INVALID_SOCKET.)
452  *
453  *    - The signature of bind_port has changed.
454  *
455  *    Revision 1.78  2002/03/08 21:35:04  oes
456  *    Added optional group supplement to --user option. Will now use default group of user if no group given
457  *
458  *    Revision 1.77  2002/03/07 03:52:06  oes
459  *     - Fixed compiler warnings etc
460  *     - Improved handling of failed DNS lookups
461  *
462  *    Revision 1.76  2002/03/06 22:54:35  jongfoster
463  *    Automated function-comment nitpicking.
464  *
465  *    Revision 1.75  2002/03/06 10:02:19  oes
466  *    Fixed stupid bug when --user was not given
467  *
468  *    Revision 1.74  2002/03/06 00:49:31  jongfoster
469  *    Fixing warning on Windows
470  *    Making #ifdefs that refer to the same variable consistently
471  *    use #ifdef unix rather than mixing #ifdef unix & #ifndef OS2
472  *
473  *    Revision 1.73  2002/03/05 23:57:30  hal9
474  *    Stray character 's' on line 1618 was breaking build.
475  *
476  *    Revision 1.72  2002/03/05 21:33:45  david__schmidt
477  *    - Re-enable OS/2 building after new parms were added
478  *    - Fix false out of memory report when resolving CGI templates when no IP
479  *      address is available of failed attempt (a la no such domain)
480  *
481  *    Revision 1.71  2002/03/05 18:13:56  oes
482  *    Added --user option
483  *
484  *    Revision 1.70  2002/03/05 04:52:42  oes
485  *    Deleted non-errlog debugging code
486  *
487  *    Revision 1.69  2002/03/04 23:50:00  jongfoster
488  *    Splitting off bind_port() call into bind_port_helper(), with
489  *    improved logging.
490  *
491  *    Revision 1.68  2002/03/04 20:17:32  oes
492  *    Fixed usage info
493  *
494  *    Revision 1.67  2002/03/04 18:18:57  oes
495  *    - Removed _DEBUG mode
496  *    - Cleand up cmdline parsing
497  *    - Introduced --no-daemon, --pidfile options
498  *    - Cleaned up signal handling:
499  *      - Terminate cleanly on INT, TERM and ABRT
500  *      - Schedule logfile for re-opening on HUP
501  *      - Ignore CHLD and PIPE
502  *      - Leave the rest with their default handlers
503  *      - Uniform handler registration
504  *    - Added usage() function
505  *    - Played styleguide police
506  *
507  *    Revision 1.66  2002/03/03 15:06:55  oes
508  *    Re-enabled automatic config reloading
509  *
510  *    Revision 1.65  2002/03/03 14:49:11  oes
511  *    Fixed CLF logging: Now uses client's original HTTP request
512  *
513  *    Revision 1.64  2002/03/03 09:18:03  joergs
514  *    Made jumbjuster work on AmigaOS again.
515  *
516  *    Revision 1.63  2002/03/02 04:14:50  david__schmidt
517  *    Clean up a little CRLF unpleasantness that suddenly appeared
518  *
519  *    Revision 1.62  2002/02/20 23:17:23  jongfoster
520  *    Detecting some out-of memory conditions and exiting with a log message.
521  *
522  *    Revision 1.61  2002/01/17 21:01:52  jongfoster
523  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
524  *
525  *    Revision 1.60  2001/12/30 14:07:32  steudten
526  *    - Add signal handling (unix)
527  *    - Add SIGHUP handler (unix)
528  *    - Add creation of pidfile (unix)
529  *    - Add action 'top' in rc file (RH)
530  *    - Add entry 'SIGNALS' to manpage
531  *    - Add exit message to logfile (unix)
532  *
533  *    Revision 1.59  2001/12/13 14:07:18  oes
534  *    Fixed Bug: 503 error page now sent OK
535  *
536  *    Revision 1.58  2001/11/30 23:37:24  jongfoster
537  *    Renaming the Win32 config file to config.txt - this is almost the
538  *    same as the corresponding UNIX name "config"
539  *
540  *    Revision 1.57  2001/11/16 00:47:43  jongfoster
541  *    Changing the tty-disconnection code to use setsid().
542  *
543  *    Revision 1.56  2001/11/13 20:20:54  jongfoster
544  *    Tabs->spaces, fixing a bug with missing {} around an if()
545  *
546  *    Revision 1.55  2001/11/13 20:14:53  jongfoster
547  *    Patch for FreeBSD setpgrp() as suggested by Alexander Lazic
548  *
549  *    Revision 1.54  2001/11/07 00:03:14  steudten
550  *    Give reliable return value if an error
551  *    occurs not just 0 with new daemon mode.
552  *
553  *    Revision 1.53  2001/11/05 21:41:43  steudten
554  *    Add changes to be a real daemon just for unix os.
555  *    (change cwd to /, detach from controlling tty, set
556  *    process group and session leader to the own process.
557  *    Add DBG() Macro.
558  *    Add some fatal-error log message for failed malloc().
559  *    Add '-d' if compiled with 'configure --with-debug' to
560  *    enable debug output.
561  *
562  *    Revision 1.52  2001/10/26 20:11:20  jongfoster
563  *    Fixing type mismatch
564  *
565  *    Revision 1.51  2001/10/26 17:38:28  oes
566  *    Cosmetics
567  *
568  *    Revision 1.50  2001/10/25 03:40:48  david__schmidt
569  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
570  *    threads to call select() simultaneously.  So, it's time to do a real, live,
571  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
572  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
573  *
574  *    Revision 1.49  2001/10/23 21:41:35  jongfoster
575  *    Added call to initialize the (statically-allocated of course)
576  *    "out of memory" CGI response.
577  *
578  *    Revision 1.48  2001/10/10 19:56:46  jongfoster
579  *    Moving some code that wasn't cookie-related out of an #ifdef
580  *    FEATURE_COOKIE_JAR
581  *
582  *    Revision 1.47  2001/10/10 16:44:36  oes
583  *    Added CONNECT destination port limitation check
584  *
585  *    Revision 1.46  2001/10/08 15:17:41  oes
586  *    Re-enabled SSL forwarding
587  *
588  *    Revision 1.45  2001/10/07 15:42:11  oes
589  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
590  *
591  *    Moved downgrading of the HTTP version from parse_http_request to
592  *      chat(), since we can't decide if it is necessary before we have
593  *      determined the actions for the URL. The HTTP command is now
594  *      *always* re-built so the repairs need no longer be special-cased.
595  *
596  *    filter_popups now gets a csp pointer so it can raise the new
597  *      CSP_FLAG_MODIFIED flag.
598  *
599  *    Bugfix
600  *
601  *    Added configurable size limit for the IOB. If the IOB grows so
602  *      large that the next read would exceed the limit, the header
603  *      is generated, and the header & unfiltered buffer are flushed
604  *      to the client. Chat then continues in non-buffering,
605  *      non-filtering body mode.
606  *
607  *    Revision 1.44  2001/10/02 18:13:57  oes
608  *    Ooops
609  *
610  *    Revision 1.43  2001/10/02 15:32:13  oes
611  *    Moved generation of hdr
612  *
613  *    Revision 1.42  2001/09/21 23:02:02  david__schmidt
614  *    Cleaning up 2 compiler warnings on OS/2.
615  *
616  *    Revision 1.41  2001/09/16 17:05:14  jongfoster
617  *    Removing unused #include showarg.h
618  *
619  *    Revision 1.40  2001/09/16 15:41:45  jongfoster
620  *    Fixing signed/unsigned comparison warning.
621  *
622  *    Revision 1.39  2001/09/16 13:21:27  jongfoster
623  *    Changes to use new list functions.
624  *
625  *    Revision 1.38  2001/09/16 13:01:46  jongfoster
626  *    Removing redundant function call that zeroed zalloc()'d memory.
627  *
628  *    Revision 1.37  2001/09/10 11:12:24  oes
629  *    Deleted unused variable
630  *
631  *    Revision 1.36  2001/09/10 10:56:15  oes
632  *    Silenced compiler warnings
633  *
634  *    Revision 1.35  2001/07/31 14:44:22  oes
635  *    Deleted unused size parameter from filter_popups()
636  *
637  *    Revision 1.34  2001/07/30 22:08:36  jongfoster
638  *    Tidying up #defines:
639  *    - All feature #defines are now of the form FEATURE_xxx
640  *    - Permanently turned off WIN_GUI_EDIT
641  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
642  *
643  *    Revision 1.33  2001/07/29 19:32:00  jongfoster
644  *    Renaming _main() [mingw32 only] to real_main(), for ANSI compliance.
645  *
646  *    Revision 1.32  2001/07/29 18:47:05  jongfoster
647  *    Adding missing #include "loadcfg.h"
648  *
649  *    Revision 1.31  2001/07/29 12:17:48  oes
650  *    Applied pthread fix by Paul Lieverse
651  *
652  *    Revision 1.30  2001/07/25 22:57:13  jongfoster
653  *    __BEOS__ no longer overrides FEATURE_PTHREAD.
654  *    This is because FEATURE_PTHREAD will soon be widely used, so I
655  *    want to keep it simple.
656  *
657  *    Revision 1.29  2001/07/24 12:47:06  oes
658  *    Applied BeOS support update by Eugenia
659  *
660  *    Revision 1.28  2001/07/23 13:26:12  oes
661  *    Fixed bug in popup-killing for the first read that caused binary garbage to be sent between headers and body
662  *
663  *    Revision 1.27  2001/07/19 19:09:47  haroon
664  *    - Added code to take care of the situation where while processing the first
665  *      server response (which includes the server header), after finding the end
666  *      of the headers we were not looking past the end of the headers for
667  *      content modification. I enabled it for filter_popups.
668  *      Someone else should look to see if other similar operations should be
669  *      done to the discarded portion of the buffer.
670  *
671  *      Note 2001/07/20: No, the other content modification mechanisms will process
672  *                       the whole iob later anyway. --oes
673  *
674  *    Revision 1.26  2001/07/18 12:31:36  oes
675  *    cosmetics
676  *
677  *    Revision 1.25  2001/07/15 19:43:49  jongfoster
678  *    Supports POSIX threads.
679  *    Also removed some unused #includes.
680  *
681  *    Revision 1.24  2001/07/13 14:00:40  oes
682  *     - Generic content modification scheme:
683  *       Each feature has its own applicability flag that is set
684  *       from csp->action->flags.
685  *       Replaced the "filtering" int flag , by a function pointer
686  *       "content_filter" to the function that will do the content
687  *       modification. If it is != NULL, the document will be buffered
688  *       and processed through *content_filter, which must set
689  *       csp->content_length and return a modified copy of the body
690  *       or return NULL (on failiure).
691  *     - Changed csp->is_text to the more generic bitmap csp->content_type
692  *       which can currently take the valued CT_TEXT or CT_GIF
693  *     - Reformatting etc
694  *     - Removed all #ifdef PCRS
695  *
696  *    Revision 1.23  2001/07/02 02:28:25  iwanttokeepanon
697  *    Added "#ifdef ACL_FILES" conditional compilation to line 1291 to exclude
698  *    the `block_acl' call.  This prevents a compilation error when the user
699  *    does not wish to use the "ACL" feature.
700  *
701  *    Revision 1.22  2001/06/29 21:45:41  oes
702  *    Indentation, CRLF->LF, Tab-> Space
703  *
704  *    Revision 1.21  2001/06/29 13:29:36  oes
705  *    - Cleaned up, improved comments
706  *    - Unified all possible interceptors (CGI,
707  *      block, trust, fast_redirect) in one
708  *      place, with one (CGI) answer generation
709  *      mechansim. Much clearer now.
710  *    - Removed the GIF image generation, which
711  *      is now done in filters.c:block_url()
712  *    - Made error conditions like domain lookup
713  *      failiure or (various) problems while talking
714  *      to the server use cgi.c:error_response()
715  *      instead of generating HTML/HTTP in chat() (yuck!)
716  *    - Removed logentry from cancelled commit
717  *
718  *    Revision 1.20  2001/06/09 10:55:28  jongfoster
719  *    Changing BUFSIZ ==> BUFFER_SIZE
720  *
721  *    Revision 1.19  2001/06/07 23:12:52  jongfoster
722  *    Replacing function pointer in struct gateway with a directly
723  *    called function forwarded_connect().
724  *    Replacing struct gateway with struct forward_spec
725  *
726  *    Revision 1.18  2001/06/03 19:12:16  oes
727  *    introduced new cgi handling
728  *
729  *    Revision 1.17  2001/06/01 20:07:23  jongfoster
730  *    Now uses action +image-blocker{} rather than config->tinygif
731  *
732  *    Revision 1.16  2001/06/01 18:49:17  jongfoster
733  *    Replaced "list_share" with "list" - the tiny memory gain was not
734  *    worth the extra complexity.
735  *
736  *    Revision 1.15  2001/05/31 21:24:47  jongfoster
737  *    Changed "permission" to "action" throughout.
738  *    Removed DEFAULT_USER_AGENT - it must now be specified manually.
739  *    Moved vanilla wafer check into chat(), since we must now
740  *    decide whether or not to add it based on the URL.
741  *
742  *    Revision 1.14  2001/05/29 20:14:01  joergs
743  *    AmigaOS bugfix: PCRS needs a lot of stack, stacksize for child threads
744  *    increased.
745  *
746  *    Revision 1.13  2001/05/29 09:50:24  jongfoster
747  *    Unified blocklist/imagelist/permissionslist.
748  *    File format is still under discussion, but the internal changes
749  *    are (mostly) done.
750  *
751  *    Also modified interceptor behaviour:
752  *    - We now intercept all URLs beginning with one of the following
753  *      prefixes (and *only* these prefixes):
754  *        * http://i.j.b/
755  *        * http://ijbswa.sf.net/config/
756  *        * http://ijbswa.sourceforge.net/config/
757  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
758  *    - Internal changes so that intercepted and fast redirect pages
759  *      are not replaced with an image.
760  *    - Interceptors now have the option to send a binary page direct
761  *      to the client. (i.e. ijb-send-banner uses this)
762  *    - Implemented show-url-info interceptor.  (Which is why I needed
763  *      the above interceptors changes - a typical URL is
764  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
765  *      The previous mechanism would not have intercepted that, and
766  *      if it had been intercepted then it then it would have replaced
767  *      it with an image.)
768  *
769  *    Revision 1.12  2001/05/27 22:17:04  oes
770  *
771  *    - re_process_buffer no longer writes the modified buffer
772  *      to the client, which was very ugly. It now returns the
773  *      buffer, which it is then written by chat.
774  *
775  *    - content_length now adjusts the Content-Length: header
776  *      for modified documents rather than crunch()ing it.
777  *      (Length info in csp->content_length, which is 0 for
778  *      unmodified documents)
779  *
780  *    - For this to work, sed() is called twice when filtering.
781  *
782  *    Revision 1.11  2001/05/26 17:27:53  jongfoster
783  *    Added support for CLF and fixed LOG_LEVEL_LOG.
784  *    Also did CRLF->LF fix of my previous patch.
785  *
786  *    Revision 1.10  2001/05/26 15:26:15  jongfoster
787  *    ACL feature now provides more security by immediately dropping
788  *    connections from untrusted hosts.
789  *
790  *    Revision 1.9  2001/05/26 00:28:36  jongfoster
791  *    Automatic reloading of config file.
792  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
793  *    Most of the global variables have been moved to a new
794  *    struct configuration_spec, accessed through csp->config->globalname
795  *    Most of the globals remaining are used by the Win32 GUI.
796  *
797  *    Revision 1.8  2001/05/25 22:43:18  jongfoster
798  *    Fixing minor memory leak and buffer overflow.
799  *
800  *    Revision 1.7  2001/05/25 22:34:30  jongfoster
801  *    Hard tabs->Spaces
802  *
803  *    Revision 1.6  2001/05/23 00:13:58  joergs
804  *    AmigaOS support fixed.
805  *
806  *    Revision 1.5  2001/05/22 18:46:04  oes
807  *
808  *    - Enabled filtering banners by size rather than URL
809  *      by adding patterns that replace all standard banner
810  *      sizes with the "Junkbuster" gif to the re_filterfile
811  *
812  *    - Enabled filtering WebBugs by providing a pattern
813  *      which kills all 1x1 images
814  *
815  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
816  *      which is selected by the (nonstandard and therefore
817  *      capital) letter 'U' in the option string.
818  *      It causes the quantifiers to be ungreedy by default.
819  *      Appending a ? turns back to greedy (!).
820  *
821  *    - Added a new interceptor ijb-send-banner, which
822  *      sends back the "Junkbuster" gif. Without imagelist or
823  *      MSIE detection support, or if tinygif = 1, or the
824  *      URL isn't recognized as an imageurl, a lame HTML
825  *      explanation is sent instead.
826  *
827  *    - Added new feature, which permits blocking remote
828  *      script redirects and firing back a local redirect
829  *      to the browser.
830  *      The feature is conditionally compiled, i.e. it
831  *      can be disabled with --disable-fast-redirects,
832  *      plus it must be activated by a "fast-redirects"
833  *      line in the config file, has its own log level
834  *      and of course wants to be displayed by show-proxy-args
835  *      Note: Boy, all the #ifdefs in 1001 locations and
836  *      all the fumbling with configure.in and acconfig.h
837  *      were *way* more work than the feature itself :-(
838  *
839  *    - Because a generic redirect template was needed for
840  *      this, tinygif = 3 now uses the same.
841  *
842  *    - Moved GIFs, and other static HTTP response templates
843  *      to project.h
844  *
845  *    - Some minor fixes
846  *
847  *    - Removed some >400 CRs again (Jon, you really worked
848  *      a lot! ;-)
849  *
850  *    Revision 1.4  2001/05/21 19:34:01  jongfoster
851  *    Made failure to bind() a fatal error.
852  *
853  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
854  *    Version 2.9.4 checkin.
855  *    - Merged popupfile and cookiefile, and added control over PCRS
856  *      filtering, in new "permissionsfile".
857  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
858  *      file error you now get a message box (in the Win32 GUI) rather
859  *      than the program exiting with no explanation.
860  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
861  *      skipping.
862  *    - Removed tabs from "config"
863  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
864  *    - Bumped up version number.
865  *
866  *    Revision 1.2  2001/05/17 22:34:44  oes
867  *     - Added hint on GIF char array generation to jcc.c
868  *     - Cleaned CRLF's from the sources and related files
869  *     - Repaired logging for REF and FRC
870  *
871  *    Revision 1.1.1.1  2001/05/15 13:58:56  oes
872  *    Initial import of version 2.9.3 source tree
873  *
874  *
875  *********************************************************************/
876 \f
877
878 #include "config.h"
879
880 #include <stdio.h>
881 #include <sys/types.h>
882 #include <stdlib.h>
883 #include <string.h>
884 #include <signal.h>
885 #include <fcntl.h>
886 #include <errno.h>
887 #include <assert.h>
888
889 #ifdef _WIN32
890 # ifndef FEATURE_PTHREAD
891 #  ifndef STRICT
892 #   define STRICT
893 #  endif
894 #  include <windows.h>
895 #  include <process.h>
896 # endif /* ndef FEATURE_PTHREAD */
897
898 # include "win32.h"
899 # ifndef _WIN_CONSOLE
900 #  include "w32log.h"
901 # endif /* ndef _WIN_CONSOLE */
902 # include "w32svrapi.h"
903
904 #else /* ifndef _WIN32 */
905
906 # if !defined (__OS2__)
907 # include <unistd.h>
908 # include <sys/wait.h>
909 # endif /* ndef __OS2__ */
910 # include <sys/time.h>
911 # include <sys/stat.h>
912 # include <sys/ioctl.h>
913
914 #ifdef sun
915 #include <sys/termios.h>
916 #endif /* sun */
917
918 #ifdef unix
919 #include <pwd.h>
920 #include <grp.h>
921 #endif
922
923 # include <signal.h>
924
925 # ifdef __BEOS__
926 #  include <socket.h>  /* BeOS has select() for sockets only. */
927 #  include <OS.h>      /* declarations for threads and stuff. */
928 # endif
929
930 # if defined(__EMX__) || defined(__OS2__)
931 #  include <sys/select.h>  /* OS/2/EMX needs a little help with select */
932 # endif
933 # ifdef __OS2__
934 #define INCL_DOS
935 # include <os2.h>
936 #define bzero(B,N) memset(B,0x00,n)
937 # endif
938
939 # ifndef FD_ZERO
940 #  include <select.h>
941 # endif
942
943 #endif
944
945 #include "project.h"
946 #include "list.h"
947 #include "jcc.h"
948 #include "filters.h"
949 #include "loaders.h"
950 #include "parsers.h"
951 #include "killpopup.h"
952 #include "miscutil.h"
953 #include "errlog.h"
954 #include "jbsockets.h"
955 #include "gateway.h"
956 #include "actions.h"
957 #include "cgi.h"
958 #include "loadcfg.h"
959 #include "urlmatch.h"
960
961 const char jcc_h_rcs[] = JCC_H_VERSION;
962 const char project_h_rcs[] = PROJECT_H_VERSION;
963
964 int no_daemon = 0;
965 struct client_state  clients[1];
966 struct file_list     files[1];
967
968 #ifdef FEATURE_STATISTICS
969 int urls_read     = 0;     /* total nr of urls read inc rejected */
970 int urls_rejected = 0;     /* total nr of urls rejected */
971 #endif /* def FEATURE_STATISTICS */
972
973 #ifdef FEATURE_GRACEFUL_TERMINATION
974 int g_terminate = 0;
975 #endif
976
977 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
978 static void sig_handler(int the_signal);
979 #endif
980 static int client_protocol_is_unsupported(const struct client_state *csp, char *req);
981 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
982 static jb_err get_server_headers(struct client_state *csp);
983 static const char *crunch_reason(const struct http_response *rsp);
984 static void send_crunch_response(struct client_state *csp, struct http_response *rsp);
985 /*
986  * static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len);
987  */
988 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line);
989 static jb_err change_request_destination(struct client_state *csp);
990 static void chat(struct client_state *csp);
991 static void serve(struct client_state *csp);
992 #if defined(unix)
993 static void usage(const char *myname);
994 #endif
995 static void initialize_mutexes(void);
996 static jb_socket bind_port_helper(struct configuration_spec *config);
997 static void listen_loop(void);
998
999 #ifdef AMIGA
1000 void serve(struct client_state *csp);
1001 #else /* ifndef AMIGA */
1002 static void serve(struct client_state *csp);
1003 #endif /* def AMIGA */
1004
1005 #ifdef __BEOS__
1006 static int32 server_thread(void *data);
1007 #endif /* def __BEOS__ */
1008
1009 #ifdef _WIN32
1010 #define sleep(N)  Sleep(((N) * 1000))
1011 #endif
1012
1013 #ifdef __OS2__
1014 #define sleep(N)  DosSleep(((N) * 100))
1015 #endif
1016
1017 #ifdef FEATURE_PTHREAD
1018 pthread_mutex_t log_mutex;
1019 pthread_mutex_t log_init_mutex;
1020
1021 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
1022 pthread_mutex_t resolver_mutex;
1023 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
1024
1025 #ifndef HAVE_GMTIME_R
1026 pthread_mutex_t gmtime_mutex;
1027 #endif /* ndef HAVE_GMTIME_R */
1028
1029 #ifndef HAVE_LOCALTIME_R
1030 pthread_mutex_t localtime_mutex;
1031 #endif /* ndef HAVE_GMTIME_R */
1032
1033 #ifndef HAVE_RANDOM
1034 pthread_mutex_t rand_mutex;
1035 #endif /* ndef HAVE_RANDOM */
1036
1037 #endif /* FEATURE_PTHREAD */
1038
1039 #if defined(unix) || defined(__EMX__)
1040 const char *basedir = NULL;
1041 const char *pidfile = NULL;
1042 int received_hup_signal = 0;
1043 #endif /* defined unix */
1044
1045 /* The vanilla wafer. */
1046 static const char VANILLA_WAFER[] =
1047    "NOTICE=TO_WHOM_IT_MAY_CONCERN_"
1048    "Do_not_send_me_any_copyrighted_information_other_than_the_"
1049    "document_that_I_am_requesting_or_any_of_its_necessary_components._"
1050    "In_particular_do_not_send_me_any_cookies_that_"
1051    "are_subject_to_a_claim_of_copyright_by_anybody._"
1052    "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_"
1053    "(copyright_or_otherwise)_applying_to_any_cookie._";
1054
1055 /* HTTP snipplets. */
1056 static const char CSUCCEED[] =
1057    "HTTP/1.0 200 Connection established\n"
1058    "Proxy-Agent: Privoxy/" VERSION "\r\n\r\n";
1059
1060 static const char CHEADER[] =
1061    "HTTP/1.0 400 Invalid header received from browser\r\n"
1062    "Proxy-Agent: Privoxy " VERSION "\r\n"
1063    "Content-Type: text/plain\r\n"
1064    "Connection: close\r\n\r\n"
1065    "Invalid header received from browser.\r\n";
1066
1067 static const char CFORBIDDEN[] =
1068    "HTTP/1.0 403 Connection not allowable\r\n"
1069    "Proxy-Agent: Privoxy " VERSION "\r\n"
1070    "X-Hint: If you read this message interactively, then you know why this happens ,-)\r\n"
1071    "Connection: close\r\n\r\n";
1072
1073 static const char FTP_RESPONSE[] =
1074    "HTTP/1.0 400 Invalid request received from browser\r\n"
1075    "Content-Type: text/plain\r\n"
1076    "Connection: close\r\n\r\n"
1077    "Invalid request. Privoxy doesn't support FTP.\r\n";
1078
1079 static const char GOPHER_RESPONSE[] =
1080    "HTTP/1.0 400 Invalid request received from browser\r\n"
1081    "Content-Type: text/plain\r\n"
1082    "Connection: close\r\n\r\n"
1083    "Invalid request. Privoxy doesn't support gopher.\r\n";
1084
1085 /* XXX: should be a template */
1086 static const char MISSING_DESTINATION_RESPONSE[] =
1087    "HTTP/1.0 400 Bad request received from browser\r\n"
1088    "Proxy-Agent: Privoxy " VERSION "\r\n"
1089    "Content-Type: text/plain\r\n"
1090    "Connection: close\r\n\r\n"
1091    "Bad request. Privoxy was unable to extract the destination.\r\n";
1092
1093 /* XXX: should be a template */
1094 static const char NO_SERVER_DATA_RESPONSE[] =
1095    "HTTP/1.0 502 Server or forwarder response empty\r\n"
1096    "Proxy-Agent: Privoxy " VERSION "\r\n"
1097    "Content-Type: text/plain\r\n"
1098    "Connection: close\r\n\r\n"
1099    "Empty server or forwarder response.\r\n"
1100    "The connection was closed without sending any data.\r\n";
1101
1102 /* XXX: should be a template */
1103 static const char NULL_BYTE_RESPONSE[] =
1104    "HTTP/1.0 400 Bad request received from browser\r\n"
1105    "Proxy-Agent: Privoxy " VERSION "\r\n"
1106    "Content-Type: text/plain\r\n"
1107    "Connection: close\r\n\r\n"
1108    "Bad request. Null byte(s) before end of request.\r\n";
1109
1110 /* XXX: should be a template */
1111 static const char MESSED_UP_REQUEST_RESPONSE[] =
1112    "HTTP/1.0 400 Malformed request after rewriting\r\n"
1113    "Proxy-Agent: Privoxy " VERSION "\r\n"
1114    "Content-Type: text/plain\r\n"
1115    "Connection: close\r\n\r\n"
1116    "Bad request. Messed up with header filters.\r\n";
1117
1118 /* A function to crunch a response */
1119 typedef struct http_response *(*crunch_func_ptr)(struct client_state *);
1120
1121 typedef char *(*filter_function_ptr)();
1122
1123 /* Crunch function flags */
1124 #define CF_NO_FLAGS        0
1125 /* Cruncher applies to forced requests as well */
1126 #define CF_IGNORE_FORCE    1
1127 /* Crunched requests are counted for the block statistics */
1128 #define CF_COUNT_AS_REJECT 2
1129
1130 /* A crunch function and its flags */
1131 struct cruncher
1132 {
1133    const crunch_func_ptr cruncher;
1134    const int flags;
1135 };
1136
1137 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]);
1138 static filter_function_ptr get_filter_function(struct client_state *csp);
1139
1140 /* Complete list of cruncher functions */
1141 static const struct cruncher crunchers_all[] = {
1142    { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE},
1143    { block_url,       CF_COUNT_AS_REJECT },
1144 #ifdef FEATURE_TRUST
1145    { trust_url,       CF_COUNT_AS_REJECT },
1146 #endif /* def FEATURE_TRUST */
1147    { redirect_url,    CF_NO_FLAGS  },
1148    { dispatch_cgi,    CF_IGNORE_FORCE},
1149    { NULL,            0 }
1150 };
1151
1152 /* Light version, used after tags are applied */
1153 static const struct cruncher crunchers_light[] = {
1154    { block_url,       CF_COUNT_AS_REJECT },
1155    { redirect_url,    CF_NO_FLAGS },
1156    { NULL,            0 }
1157 };
1158
1159
1160 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
1161 /*********************************************************************
1162  *
1163  * Function    :  sig_handler 
1164  *
1165  * Description :  Signal handler for different signals.
1166  *                Exit gracefully on TERM and INT
1167  *                or set a flag that will cause the errlog
1168  *                to be reopened by the main thread on HUP.
1169  *
1170  * Parameters  :
1171  *          1  :  the_signal = the signal cause this function to call
1172  *
1173  * Returns     :  - 
1174  *
1175  *********************************************************************/
1176 static void sig_handler(int the_signal)
1177 {
1178    switch(the_signal)
1179    {
1180       case SIGTERM:
1181       case SIGINT:
1182          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
1183 #if defined(unix)
1184          if(pidfile)
1185          {
1186             unlink(pidfile);
1187          }
1188 #endif /* unix */
1189          exit(the_signal);
1190          break;
1191
1192       case SIGHUP:
1193          received_hup_signal = 1;
1194          break;         
1195
1196       default:
1197          /* 
1198           * We shouldn't be here, unless we catch signals
1199           * in main() that we can't handle here!
1200           */
1201          log_error(LOG_LEVEL_FATAL, "sig_handler: exiting on unexpected signal %d", the_signal);
1202    }
1203    return;
1204
1205 }
1206 #endif
1207
1208
1209 /*********************************************************************
1210  *
1211  * Function    :  client_protocol_is_unsupported
1212  *
1213  * Description :  Checks if the client used a known unsupported
1214  *                protocol and deals with it by sending an error
1215  *                response.
1216  *
1217  * Parameters  :
1218  *          1  :  csp = Current client state (buffers, headers, etc...)
1219  *          2  :  req = the first request line send by the client
1220  *
1221  * Returns     :  TRUE if an error response has been generated, or
1222  *                FALSE if the request doesn't look invalid.
1223  *
1224  *********************************************************************/
1225 static int client_protocol_is_unsupported(const struct client_state *csp, char *req)
1226 {
1227    char buf[BUFFER_SIZE];
1228
1229    /*
1230     * If it's a FTP or gopher request, we don't support it.
1231     *
1232     * These checks are better than nothing, but they might
1233     * not work in all configurations and some clients might
1234     * have problems digesting the answer.
1235     *
1236     * They should, however, never cause more problems than
1237     * Privoxy's old behaviour (returning the misleading HTML
1238     * error message:
1239     *
1240     * "Could not resolve http://(ftp|gopher)://example.org").
1241     */
1242    if (!strncmpic(req, "GET ftp://", 10) || !strncmpic(req, "GET gopher://", 13))
1243    {
1244       if (!strncmpic(req, "GET ftp://", 10))
1245       {
1246          strlcpy(buf, FTP_RESPONSE, sizeof(buf));
1247          log_error(LOG_LEVEL_ERROR, "%s tried to use Privoxy as FTP proxy: %s",
1248             csp->ip_addr_str, req);
1249       }
1250       else
1251       {
1252          strlcpy(buf, GOPHER_RESPONSE, sizeof(buf));
1253          log_error(LOG_LEVEL_ERROR, "%s tried to use Privoxy as gopher proxy: %s",
1254             csp->ip_addr_str, req);
1255       }
1256       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
1257       freez(req);
1258       write_socket(csp->cfd, buf, strlen(buf));
1259
1260       return TRUE;
1261    }
1262
1263    return FALSE;
1264 }
1265
1266
1267 /*********************************************************************
1268  *
1269  * Function    :  get_request_destination_elsewhere
1270  *
1271  * Description :  If the client's request was redirected into
1272  *                Privoxy without the client's knowledge,
1273  *                the request line lacks the destination host.
1274  *
1275  *                This function tries to get it elsewhere,
1276  *                provided accept-intercepted-requests is enabled.
1277  *
1278  *                "Elsewhere" currently only means "Host: header",
1279  *                but in the future we may ask the redirecting
1280  *                packet filter to look the destination up.
1281  *
1282  *                If the destination stays unknown, an error
1283  *                response is send to the client and headers
1284  *                are freed so that chat() can return directly.
1285  *
1286  * Parameters  :
1287  *          1  :  csp = Current client state (buffers, headers, etc...)
1288  *          2  :  headers = a header list
1289  *
1290  * Returns     :  JB_ERR_OK if the destination is now known, or
1291  *                JB_ERR_PARSE if it isn't.
1292  *
1293  *********************************************************************/
1294 static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
1295 {
1296    char *req;
1297
1298    if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
1299    {
1300       log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
1301          " Privoxy isn't configured to accept intercepted requests.",
1302          csp->ip_addr_str, csp->http->cmd);
1303       /* XXX: Use correct size */
1304       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
1305          csp->ip_addr_str, csp->http->cmd);
1306
1307       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
1308       destroy_list(headers);
1309
1310       return JB_ERR_PARSE;
1311    }
1312    else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http))
1313    {
1314       /* Split the domain we just got for pattern matching */
1315       init_domain_components(csp->http);
1316
1317       return JB_ERR_OK;
1318    }
1319    else
1320    {
1321       /* We can't work without destination. Go spread the news.*/
1322
1323       req = list_to_text(headers);
1324       chomp(req);
1325       /* XXX: Use correct size */
1326       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
1327          csp->ip_addr_str, csp->http->cmd);
1328       log_error(LOG_LEVEL_ERROR,
1329          "Privoxy was unable to get the destination for %s's request:\n%s\n%s",
1330          csp->ip_addr_str, csp->http->cmd, req);
1331       freez(req);
1332
1333       write_socket(csp->cfd, MISSING_DESTINATION_RESPONSE, strlen(MISSING_DESTINATION_RESPONSE));
1334       destroy_list(headers);
1335
1336       return JB_ERR_PARSE;
1337    }
1338    /*
1339     * TODO: If available, use PF's ioctl DIOCNATLOOK as last resort
1340     * to get the destination IP address, use it as host directly
1341     * or do a reverse DNS lookup first.
1342     */
1343 }
1344
1345
1346 /*********************************************************************
1347  *
1348  * Function    :  get_server_headers
1349  *
1350  * Description :  Parses server headers in iob and fills them
1351  *                into csp->headers so that they can later be
1352  *                handled by sed().
1353  *
1354  * Parameters  :
1355  *          1  :  csp = Current client state (buffers, headers, etc...)
1356  *
1357  * Returns     :  JB_ERR_OK if everything went fine, or
1358  *                JB_ERR_PARSE if the headers were incomplete.
1359  *
1360  *********************************************************************/
1361 static jb_err get_server_headers(struct client_state *csp)
1362 {
1363    int continue_hack_in_da_house = 0;
1364    char * header;
1365
1366    while (((header = get_header(csp)) != NULL) || continue_hack_in_da_house)
1367    {
1368       if (header == NULL)
1369       {
1370          /*
1371           * continue hack in da house. Ignore the ending of
1372           * this head and continue enlisting header lines.
1373           * The reason is described below.
1374           */
1375          enlist(csp->headers, "");
1376          continue_hack_in_da_house = 0;
1377          continue;
1378       }
1379       else if (0 == strncmpic(header, "HTTP/1.1 100", 12))
1380       {
1381          /*
1382           * It's a bodyless continue response, don't
1383           * stop header parsing after reaching it's end.
1384           *
1385           * As a result Privoxy will concatenate the
1386           * next response's head and parse and deliver
1387           * the headers as if they belonged to one request.
1388           *
1389           * The client will separate them because of the
1390           * empty line between them.
1391           *
1392           * XXX: What we're doing here is clearly against
1393           * the intended purpose of the continue header,
1394           * and under some conditions (HTTP/1.0 client request)
1395           * it's a standard violation.
1396           *
1397           * Anyway, "sort of against the spec" is preferable
1398           * to "always getting confused by Continue responses"
1399           * (Privoxy's behaviour before this hack was added)
1400           */
1401          log_error(LOG_LEVEL_HEADER, "Continue hack in da house.");
1402          continue_hack_in_da_house = 1;
1403       }
1404       else if (*header == '\0') 
1405       {
1406          /*
1407           * If the header is empty, but the Continue hack
1408           * isn't active, we can assume that we reached the
1409           * end of the buffer before we hit the end of the
1410           * head.
1411           *
1412           * Inform the caller an let it decide how to handle it.
1413           */
1414          return JB_ERR_PARSE;
1415       }
1416
1417       /* Enlist header */
1418       if (JB_ERR_MEMORY == enlist(csp->headers, header))
1419       {
1420          /*
1421           * XXX: Should we quit the request and return a
1422           * out of memory error page instead?
1423           */
1424          log_error(LOG_LEVEL_ERROR,
1425             "Out of memory while enlisting server headers. %s lost.",
1426             header);
1427       }
1428       freez(header);
1429    }
1430
1431    return JB_ERR_OK;
1432 }
1433
1434
1435 /*********************************************************************
1436  *
1437  * Function    :  crunch_reason
1438  *
1439  * Description :  Translates the crunch reason code into a string.
1440  *
1441  * Parameters  :
1442  *          1  :  rsp = a http_response
1443  *
1444  * Returns     :  A string with the crunch reason or an error description.
1445  *
1446  *********************************************************************/
1447 static const char *crunch_reason(const struct http_response *rsp)
1448 {
1449    char * reason = NULL;
1450
1451    assert(rsp != NULL);
1452    if (rsp == NULL)
1453    {
1454       return "Internal error while searching for crunch reason";
1455    }
1456
1457    switch (rsp->reason)
1458    {
1459       case RSP_REASON_UNSUPPORTED:
1460          reason = "Unsupported HTTP feature";
1461          break;
1462       case RSP_REASON_BLOCKED:
1463          reason = "Blocked";
1464          break;
1465       case RSP_REASON_UNTRUSTED:
1466          reason = "Untrusted";
1467          break;
1468       case RSP_REASON_REDIRECTED:
1469          reason = "Redirected";
1470          break;
1471       case RSP_REASON_CGI_CALL:
1472          reason = "CGI Call";
1473          break;
1474       case RSP_REASON_NO_SUCH_DOMAIN:
1475          reason = "DNS failure";
1476          break;
1477       case RSP_REASON_FORWARDING_FAILED:
1478          reason = "Forwarding failed";
1479          break;
1480       case RSP_REASON_CONNECT_FAILED:
1481          reason = "Connection failure";
1482          break;
1483       case RSP_REASON_OUT_OF_MEMORY:
1484          reason = "Out of memory (may mask other reasons)";
1485          break;
1486       default:
1487          reason = "No reason recorded";
1488          break;
1489    }
1490
1491    return reason;
1492 }
1493
1494
1495 /*********************************************************************
1496  *
1497  * Function    :  send_crunch_response
1498  *
1499  * Description :  Delivers already prepared response for
1500  *                intercepted requests, logs the interception
1501  *                and frees the response.
1502  *
1503  * Parameters  :
1504  *          1  :  csp = Current client state (buffers, headers, etc...)
1505  *          1  :  rsp = Fully prepared response. Will be freed on exit.
1506  *
1507  * Returns     :  Nothing.
1508  *
1509  *********************************************************************/
1510 static void send_crunch_response(struct client_state *csp, struct http_response *rsp)
1511 {
1512       const struct http_request *http = csp->http;
1513       char status_code[4];
1514
1515       assert(rsp != NULL);
1516       assert(rsp->head != NULL);
1517
1518       if (rsp == NULL)
1519       {
1520          /*
1521           * Not supposed to happen. If it does
1522           * anyway, treat it as an unknown error.
1523           */
1524          cgi_error_unknown(csp, rsp, RSP_REASON_INTERNAL_ERROR);
1525          /* return code doesn't matter */
1526       }
1527
1528       if (rsp == NULL)
1529       {
1530          /* If rsp is still NULL, we have serious internal problems. */
1531          log_error(LOG_LEVEL_FATAL,
1532             "NULL response in send_crunch_response and cgi_error_unknown failed as well.");
1533       }
1534
1535       /*
1536        * Extract the status code from the actual head
1537        * that was send to the client. It is the only
1538        * way to get it right for all requests, including
1539        * the fixed ones for out-of-memory problems.
1540        *
1541        * A head starts like this: 'HTTP/1.1 200...'
1542        *                           0123456789|11
1543        *                                     10
1544        */
1545       status_code[0] = rsp->head[9];
1546       status_code[1] = rsp->head[10];
1547       status_code[2] = rsp->head[11];
1548       status_code[3] = '\0';
1549
1550       /* Write the answer to the client */
1551       if (write_socket(csp->cfd, rsp->head, rsp->head_length)
1552        || write_socket(csp->cfd, rsp->body, rsp->content_length))
1553       {
1554          /* There is nothing we can do about it. */
1555          log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", csp->http->host);
1556       }
1557
1558       /* Log that the request was crunched and why. */
1559       log_error(LOG_LEVEL_GPC, "%s%s crunch! (%s)",
1560          http->hostport, http->path, crunch_reason(rsp));
1561       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %d",
1562          csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
1563
1564       /* Clean up and return */
1565       if (cgi_error_memory() != rsp)
1566       {
1567          free_http_response(rsp);
1568       } 
1569       return;
1570 }
1571
1572
1573 #if 0
1574 /*********************************************************************
1575  *
1576  * Function    :  request_contains_null_bytes
1577  *
1578  * Description :  Checks for NULL bytes in the request and sends
1579  *                an error message to the client if any were found.
1580  *
1581  *                XXX: currently not used, see comment in chat().
1582  *
1583  * Parameters  :
1584  *          1  :  csp = Current client state (buffers, headers, etc...)
1585  *          2  :  buf = Data from the client's request to check.
1586  *          3  :  len = The data length.
1587  *
1588  * Returns     :  TRUE if the request contained one or more NULL bytes, or
1589  *                FALSE otherwise.
1590  *
1591  *********************************************************************/
1592 static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len)
1593 {
1594    size_t c_len; /* Request lenght when treated as C string */
1595
1596    c_len = strlen(buf);
1597
1598    if (c_len < len)
1599    {
1600       /*
1601        * Null byte(s) found. Log the request,
1602        * return an error response and hang up.
1603        */
1604       size_t tmp_len = c_len;
1605
1606       do
1607       {
1608         /*
1609          * Replace NULL byte(s) with '°' characters
1610          * so the request can be logged as string.
1611          * XXX: Is there a better replacement character?
1612          */
1613          buf[tmp_len]='°';
1614          tmp_len += strlen(buf+tmp_len);
1615       } while (tmp_len < len);
1616
1617       log_error(LOG_LEVEL_ERROR, "%s\'s request contains at least one NULL byte "
1618          "(length=%d, strlen=%d).", csp->ip_addr_str, len, c_len);
1619       log_error(LOG_LEVEL_HEADER, 
1620          "Offending request data with NULL bytes turned into \'°\' characters: %s", buf);
1621
1622       write_socket(csp->cfd, NULL_BYTE_RESPONSE, strlen(NULL_BYTE_RESPONSE));
1623
1624       /* XXX: Log correct size */
1625       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
1626
1627       return TRUE;
1628    }
1629
1630    return FALSE;
1631 }
1632 #endif
1633
1634
1635 /*********************************************************************
1636  *
1637  * Function    :  crunch_response_triggered
1638  *
1639  * Description :  Checks if the request has to be crunched,
1640  *                and delivers the crunch response if necessary.
1641  *
1642  * Parameters  :
1643  *          1  :  csp = Current client state (buffers, headers, etc...)
1644  *          2  :  crunchers = list of cruncher functions to run
1645  *
1646  * Returns     :  TRUE if the request was answered with a crunch response
1647  *                FALSE otherwise.
1648  *
1649  *********************************************************************/
1650 static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[])
1651 {
1652    struct http_response *rsp = NULL;
1653    const struct cruncher *c;
1654
1655    /*
1656     * If CGI request crunching is disabled,
1657     * check the CGI dispatcher out of order to
1658     * prevent unintentional blocks or redirects. 
1659     */
1660    if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING)
1661        && (NULL != (rsp = dispatch_cgi(csp))))
1662    {
1663       /* Deliver, log and free the interception response. */
1664       send_crunch_response(csp, rsp);
1665       return TRUE;
1666    }
1667
1668    for (c = crunchers; c->cruncher != NULL; c++)
1669    {
1670       /*
1671        * Check the cruncher if either Privoxy is toggled
1672        * on and the request isn't forced, or if the cruncher
1673        * applies to forced requests as well.
1674        */
1675       if (((csp->flags & CSP_FLAG_TOGGLED_ON) &&
1676           !(csp->flags & CSP_FLAG_FORCED)) ||
1677           (c->flags & CF_IGNORE_FORCE))
1678       {
1679          rsp = c->cruncher(csp);
1680          if (NULL != rsp)
1681          {
1682             /* Deliver, log and free the interception response. */
1683             send_crunch_response(csp, rsp);
1684 #ifdef FEATURE_STATISTICS
1685             if (c->flags & CF_COUNT_AS_REJECT)
1686             {
1687                csp->flags |= CSP_FLAG_REJECTED;
1688             }
1689 #endif /* def FEATURE_STATISTICS */
1690
1691             return TRUE;
1692          }
1693       }
1694    }
1695
1696    return FALSE;
1697 }
1698
1699
1700 /*********************************************************************
1701  *
1702  * Function    :  build_request_line
1703  *
1704  * Description :  Builds the HTTP request line.
1705  *
1706  *                If a HTTP forwarder is used it expects the whole URL,
1707  *                web servers only get the path.
1708  *
1709  * Parameters  :
1710  *          1  :  csp = Current client state (buffers, headers, etc...)
1711  *          2  :  fwd = The forwarding spec used for the request
1712  *                XXX: Should use http->fwd instead.
1713  *          3  :  request_line = The old request line which will be replaced.
1714  *
1715  * Returns     :  Nothing. Terminates in case of memory problems.
1716  *
1717  *********************************************************************/
1718 static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line)
1719 {
1720    struct http_request *http = csp->http;
1721
1722    assert(http->ssl == 0);
1723
1724    /*
1725     * Downgrade http version from 1.1 to 1.0
1726     * if +downgrade action applies.
1727     */
1728    if ( (csp->action->flags & ACTION_DOWNGRADE)
1729      && (!strcmpic(http->ver, "HTTP/1.1")))
1730    {
1731       freez(http->ver);
1732       http->ver = strdup("HTTP/1.0");
1733
1734       if (http->ver == NULL)
1735       {
1736          log_error(LOG_LEVEL_FATAL, "Out of memory downgrading HTTP version");
1737       }
1738    }
1739
1740    /*
1741     * Rebuild the request line.
1742     */
1743    freez(*request_line);
1744    *request_line = strdup(http->gpc);
1745    string_append(request_line, " ");
1746
1747    if (fwd->forward_host)
1748    {
1749       string_append(request_line, http->url);
1750    }
1751    else
1752    {
1753       string_append(request_line, http->path);
1754    }
1755    string_append(request_line, " ");
1756    string_append(request_line, http->ver);
1757
1758    if (*request_line == NULL)
1759    {
1760       log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
1761    }
1762    log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line);
1763 }
1764
1765
1766 /*********************************************************************
1767  *
1768  * Function    :  change_request_destination
1769  *
1770  * Description :  Parse a (rewritten) request line and regenerate
1771  *                the http request data.
1772  *
1773  * Parameters  :
1774  *          1  :  csp = Current client state (buffers, headers, etc...)
1775  *
1776  * Returns     :  Forwards the parse_http_request() return code.
1777  *                Terminates in case of memory problems.
1778  *
1779  *********************************************************************/
1780 static jb_err change_request_destination(struct client_state *csp)
1781 {
1782    struct http_request *http = csp->http;
1783    jb_err err;
1784
1785    log_error(LOG_LEVEL_INFO, "Rewrite detected: %s", csp->headers->first->str);
1786    free_http_request(http);
1787    err = parse_http_request(csp->headers->first->str, http, csp);
1788    if (JB_ERR_OK != err)
1789    {
1790       log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
1791          jb_err_to_string(err));
1792    }
1793    http->ocmd = strdup(http->cmd); /* XXX: ocmd is a misleading name */
1794    if (http->ocmd == NULL)
1795    {
1796       log_error(LOG_LEVEL_FATAL, "Out of memory copying rewritten HTTP request line");
1797    }
1798
1799    return err;
1800 }
1801
1802
1803 /*********************************************************************
1804  *
1805  * Function    :  get_filter_function
1806  *
1807  * Description :  Decides which content filter function has
1808  *                to be applied (if any).
1809  *
1810  *                XXX: Doesn't handle filter_popups()
1811  *                because of the different prototype. Probably
1812  *                we should ditch filter_popups() anyway, it's
1813  *                even less reliable than popup blocking based
1814  *                on pcrs filters.
1815  *
1816  * Parameters  :
1817  *          1  :  csp = Current client state (buffers, headers, etc...)
1818  *
1819  * Returns     :  The content filter function to run, or
1820  *                NULL if no content filter is active
1821  *
1822  *********************************************************************/
1823 static filter_function_ptr get_filter_function(struct client_state *csp)
1824 {
1825    filter_function_ptr filter_function = NULL;
1826
1827    /*
1828     * Are we enabling text mode by force?
1829     */
1830    if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
1831    {
1832       /*
1833        * Do we really have to?
1834        */
1835       if (csp->content_type & CT_TEXT)
1836       {
1837          log_error(LOG_LEVEL_HEADER, "Text mode is already enabled.");   
1838       }
1839       else
1840       {
1841          csp->content_type |= CT_TEXT;
1842          log_error(LOG_LEVEL_HEADER, "Text mode enabled by force. Take cover!");   
1843       }
1844    }
1845
1846    if (!(csp->content_type & CT_DECLARED))
1847    {
1848       /*
1849        * The server didn't bother to declare a MIME-Type.
1850        * Assume it's text that can be filtered.
1851        *
1852        * This also regulary happens with 304 responses,
1853        * therefore logging anything here would cause
1854        * too much noise.
1855        */
1856       csp->content_type |= CT_TEXT;
1857    }
1858
1859
1860    /*
1861     * Choose the applying filter function based on
1862     * the content type and action settings.
1863     */
1864    if ((csp->content_type & CT_TEXT) &&
1865        (csp->rlist != NULL) &&
1866        (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
1867    {
1868       filter_function = pcrs_filter_response;
1869    }
1870    else if ((csp->content_type & CT_GIF)  &&
1871             (csp->action->flags & ACTION_DEANIMATE))
1872    {
1873       filter_function = gif_deanimate_response;
1874    }
1875    else if ((csp->content_type & CT_JPEG)  &&
1876             (csp->action->flags & ACTION_JPEG_INSPECT))
1877    {
1878       filter_function = jpeg_inspect_response;
1879    }
1880
1881    return filter_function;
1882 }
1883
1884 /*********************************************************************
1885  *
1886  * Function    :  chat
1887  *
1888  * Description :  Once a connection to the client has been accepted,
1889  *                this function is called (via serve()) to handle the
1890  *                main business of the communication.  When this
1891  *                function returns, the caller must close the client
1892  *                socket handle.
1893  *
1894  *                FIXME: chat is nearly thousand lines long.
1895  *                Ridiculous.
1896  *
1897  * Parameters  :
1898  *          1  :  csp = Current client state (buffers, headers, etc...)
1899  *
1900  * Returns     :  Nothing.
1901  *
1902  *********************************************************************/
1903 static void chat(struct client_state *csp)
1904 {
1905    char buf[BUFFER_SIZE];
1906    char *hdr;
1907    char *p;
1908    char *req;
1909    fd_set rfds;
1910    int n;
1911    jb_socket maxfd;
1912    int server_body;
1913    int ms_iis5_hack = 0;
1914    size_t byte_count = 0;
1915    int forwarded_connect_retries = 0;
1916    int max_forwarded_connect_retries = csp->config->forwarded_connect_retries;
1917    const struct forward_spec * fwd;
1918    struct http_request *http;
1919    int len; /* for buffer sizes (and negative error codes) */
1920    jb_err err;
1921 #ifdef FEATURE_KILL_POPUPS
1922    int block_popups_now = 0; /* bool, 1==currently blocking popups */
1923 #endif /* def FEATURE_KILL_POPUPS */
1924
1925    /* Function that does the content filtering for the current request */
1926    filter_function_ptr content_filter = NULL;
1927
1928    /* Skeleton for HTTP response, if we should intercept the request */
1929    struct http_response *rsp;
1930
1931    /* Temporary copy of the client's headers before they get enlisted in csp->headers */
1932    struct list header_list;
1933    struct list *headers = &header_list;
1934
1935    http = csp->http;
1936
1937    memset(buf, 0, sizeof(buf));
1938
1939    /*
1940     * Read the client's request.  Note that since we're not using select() we
1941     * could get blocked here if a client connected, then didn't say anything!
1942     */
1943
1944    do
1945    {
1946       len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1947
1948       if (len <= 0) break;      /* error! */
1949
1950       /*
1951        * If there is no memory left for buffering the
1952        * request, there is nothing we can do but hang up
1953        */
1954       if (add_to_iob(csp, buf, len))
1955       {
1956          return;
1957       }
1958
1959       req = get_header(csp);
1960
1961    } while ((NULL != req) && ('\0' == *req));
1962
1963    if (NULL != req)
1964    {
1965       /* Request received. Validate and parse it. */
1966
1967 #if 0
1968       /*
1969        * XXX: Temporary disabled to prevent problems
1970        * with POST requests whose bodies are allowed to
1971        * contain NULL bytes. BR#1730105.
1972        *
1973        * The main purpose of this check is to properly
1974        * log stuff like BitTorrent traffic and other junk
1975        * that hits public proxies. It's not required for
1976        * Privoxy to functions as those requests are discarded
1977        * later on anyway.
1978        *
1979        * It probably should be rewritten to only check
1980        * the head of the request. Another option would
1981        * be to let all POST requests pass, although that
1982        * may not be good enough.
1983        */
1984       if (request_contains_null_bytes(csp, buf, len))
1985       {
1986          /* NULL bytes found and dealt with, just hang up. */
1987          return;
1988       }
1989 #endif
1990
1991       /* Does the request line look invalid? */
1992       if (client_protocol_is_unsupported(csp, req))
1993       {
1994          /* 
1995           * Yes. The request has already been
1996           * answered with a error response, the buffers
1997           * were freed and we're done with chatting.
1998           */
1999          return;
2000       }
2001
2002 #ifdef FEATURE_FORCE_LOAD
2003       /*
2004        * If this request contains the FORCE_PREFIX and blocks
2005        * aren't enforced, get rid of it and set the force flag.
2006        */
2007       if (strstr(req, FORCE_PREFIX))
2008       {
2009          if (csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS)
2010          {
2011             log_error(LOG_LEVEL_FORCE,
2012                "Ignored force prefix in request: \"%s\".", req);
2013          }
2014          else
2015          {
2016             strclean(req, FORCE_PREFIX);
2017             log_error(LOG_LEVEL_FORCE, "Enforcing request: \"%s\".", req);
2018             csp->flags |= CSP_FLAG_FORCED;
2019          }
2020       }
2021
2022 #endif /* def FEATURE_FORCE_LOAD */
2023       err = parse_http_request(req, http, csp);
2024       if (JB_ERR_OK != err)
2025       {
2026          log_error(LOG_LEVEL_ERROR, "Couldn't parse request: %s.", jb_err_to_string(err));
2027       }
2028
2029       freez(req);
2030    }
2031
2032    if (http->cmd == NULL)
2033    {
2034       write_socket(csp->cfd, CHEADER, strlen(CHEADER));
2035       /* XXX: Use correct size */
2036       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
2037       log_error(LOG_LEVEL_ERROR, "Invalid header received from %s.", csp->ip_addr_str);
2038
2039       free_http_request(http);
2040       return;
2041    }
2042
2043    /* grab the rest of the client's headers */
2044    init_list(headers);
2045    for (;;)
2046    {
2047       if ( ( ( p = get_header(csp) ) != NULL) && ( *p == '\0' ) )
2048       {
2049          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
2050          if (len <= 0)
2051          {
2052             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
2053             return;
2054          }
2055          
2056          /*
2057           * If there is no memory left for buffering the
2058           * request, there is nothing we can do but hang up
2059           */
2060          if (add_to_iob(csp, buf, len))
2061          {
2062             return;
2063          }
2064          continue;
2065       }
2066
2067       if (p == NULL) break;
2068
2069       enlist(headers, p);
2070       freez(p);
2071
2072    }
2073
2074    if (http->host == NULL)
2075    {
2076       /*
2077        * If we still don't know the request destination,
2078        * the request is invalid or the client uses
2079        * Privoxy without its knowledge.
2080        */
2081       if (JB_ERR_OK != get_request_destination_elsewhere(csp, headers))
2082       {
2083          /*
2084           * Our attempts to get the request destination
2085           * elsewhere failed or Privoxy is configured
2086           * to only accept proxy requests.
2087           *
2088           * An error response has already been send
2089           * and we're done here.
2090           */
2091           return;
2092       }
2093    }
2094
2095    /*
2096     * Determine the actions for this URL
2097     */
2098 #ifdef FEATURE_TOGGLE
2099    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
2100    {
2101       /* Most compatible set of actions (i.e. none) */
2102       init_current_action(csp->action);
2103    }
2104    else
2105 #endif /* ndef FEATURE_TOGGLE */
2106    {
2107       url_actions(http, csp);
2108    }
2109
2110    /* 
2111     * Save a copy of the original request for logging
2112     */
2113    http->ocmd = strdup(http->cmd);
2114
2115    if (http->ocmd == NULL)
2116    {
2117       log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line");
2118    }
2119
2120    enlist(csp->headers, http->cmd);
2121
2122    /* Append the previously read headers */
2123    list_append_list_unique(csp->headers, headers);
2124    destroy_list(headers);
2125
2126    /*
2127     * If the user has not supplied any wafers, and the user has not
2128     * told us to suppress the vanilla wafer, then send the vanilla wafer.
2129     */
2130    if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER])
2131        && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0))
2132    {
2133       enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER);
2134    }
2135
2136    err = sed(client_patterns, add_client_headers, csp);
2137    if (JB_ERR_OK != err)
2138    {
2139       assert(err == JB_ERR_PARSE);
2140       log_error(LOG_LEVEL_FATAL, "Failed to parse client headers");
2141    }
2142    csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
2143
2144    if (strcmp(http->cmd, csp->headers->first->str))
2145    {
2146       /*
2147        * A header filter rewrote the request line,
2148        * modify the http request accordingly.
2149        */
2150       if (JB_ERR_OK != change_request_destination(csp))
2151       {
2152          write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE));
2153          /* XXX: Use correct size */
2154          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str);
2155          log_error(LOG_LEVEL_ERROR, "Invalid request line after applying header filters.");
2156
2157          free_http_request(http);
2158          return;
2159       }
2160    }
2161
2162    /* decide how to route the HTTP request */
2163    if (NULL == (fwd = forward_url(http, csp)))
2164    {
2165       log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
2166       /* Never get here - LOG_LEVEL_FATAL causes program exit */
2167    }
2168
2169    /* build the http request to send to the server
2170     * we have to do one of the following:
2171     *
2172     * create = use the original HTTP request to create a new
2173     *          HTTP request that has either the path component
2174     *          without the http://domainspec (w/path) or the
2175     *          full orininal URL (w/url)
2176     *          Note that the path and/or the HTTP version may
2177     *          have been altered by now.
2178     *
2179     * connect = Open a socket to the host:port of the server
2180     *           and short-circuit server and client socket.
2181     *
2182     * pass =  Pass the request unchanged if forwarding a CONNECT
2183     *         request to a parent proxy. Note that we'll be sending
2184     *         the CFAIL message ourselves if connecting to the parent
2185     *         fails, but we won't send a CSUCCEED message if it works,
2186     *         since that would result in a double message (ours and the
2187     *         parent's). After sending the request to the parent, we simply
2188     *         tunnel.
2189     *
2190     * here's the matrix:
2191     *                        SSL
2192     *                    0        1
2193     *                +--------+--------+
2194     *                |        |        |
2195     *             0  | create | connect|
2196     *                | w/path |        |
2197     *  Forwarding    +--------+--------+
2198     *                |        |        |
2199     *             1  | create | pass   |
2200     *                | w/url  |        |
2201     *                +--------+--------+
2202     *
2203     */
2204
2205    /*
2206     * Check if a CONNECT request is allowable:
2207     * In the absence of a +limit-connect action, allow only port 443.
2208     * If there is an action, allow whatever matches the specificaton.
2209     */
2210    if(http->ssl)
2211    {
2212       if(  ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443)
2213            || (csp->action->flags & ACTION_LIMIT_CONNECT
2214               && !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) )
2215       {
2216          if (csp->action->flags & ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS)
2217          {
2218             /*
2219              * The response may confuse some clients,
2220              * but makes unblocking easier.
2221              *
2222              * XXX: It seems to work with all major browsers,
2223              * so we should consider returning a body by default someday ... 
2224              */
2225             log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
2226                "limit-connect{%s} doesn't allow CONNECT requests to port %d.",
2227                csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT],
2228                csp->http->port);
2229             csp->action->flags |= ACTION_BLOCK;
2230             http->ssl = 0;
2231          }
2232          else
2233          {
2234             write_socket(csp->cfd, CFORBIDDEN, strlen(CFORBIDDEN));
2235             log_error(LOG_LEVEL_INFO, "Request from %s denied. "
2236                "limit-connect{%s} doesn't allow CONNECT requests to port %d.",
2237                csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT],
2238                csp->http->port);
2239             assert(NULL != csp->http->ocmd);
2240             log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 403 0", csp->ip_addr_str, csp->http->ocmd);
2241
2242             list_remove_all(csp->headers);
2243             /*
2244              * XXX: For consistency we might want to log a crunch message here.
2245              */
2246             return;
2247          }
2248       }
2249    }
2250
2251    if (http->ssl == 0)
2252    {
2253       freez(csp->headers->first->str);
2254       build_request_line(csp, fwd, &csp->headers->first->str);
2255    }
2256
2257    hdr = list_to_text(csp->headers);
2258    if (hdr == NULL)
2259    {
2260       /* FIXME Should handle error properly */
2261       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
2262    }
2263
2264    /*
2265     * We have a request. Check if one of the crunchers wants it.
2266     */
2267    if (crunch_response_triggered(csp, crunchers_all))
2268    {
2269       /*
2270        * Yes. The client got the crunch response
2271        * and we are done here after cleaning up.
2272        */
2273       freez(hdr);
2274       list_remove_all(csp->headers);
2275
2276       return;
2277    }
2278
2279    /*
2280     * The headers can't be removed earlier because
2281     * they were still needed for the referrer check
2282     * in case of CGI crunches.
2283     *
2284     * XXX: Would it be worth to move the referrer check
2285     * into client_referrer() and set a flag if it's trusted?
2286     */
2287    list_remove_all(csp->headers);
2288
2289    log_error(LOG_LEVEL_GPC, "%s%s", http->hostport, http->path);
2290
2291    if (fwd->forward_host)
2292    {
2293       log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
2294                fwd->forward_host, fwd->forward_port, http->hostport);
2295    }
2296    else
2297    {
2298       log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
2299    }
2300
2301    /* here we connect to the server, gateway, or the forwarder */
2302
2303    while ( (csp->sfd = forwarded_connect(fwd, http, csp))
2304          && (errno == EINVAL) && (forwarded_connect_retries++ < max_forwarded_connect_retries))
2305    {
2306       log_error(LOG_LEVEL_ERROR, "failed request #%u to connect to %s. Trying again.",
2307                 forwarded_connect_retries, http->hostport);
2308    }
2309
2310    if (csp->sfd == JB_INVALID_SOCKET)
2311    {
2312       if (fwd->type != SOCKS_NONE)
2313       {
2314          /* Socks error. */
2315          rsp = error_response(csp, "forwarding-failed", errno);
2316       }
2317       else if (errno == EINVAL)
2318       {
2319          rsp = error_response(csp, "no-such-domain", errno);
2320       }
2321       else
2322       {
2323          rsp = error_response(csp, "connect-failed", errno);
2324          log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E",
2325                 http->hostport);
2326       }
2327
2328
2329       /* Write the answer to the client */
2330       if (rsp != NULL)
2331       {
2332          send_crunch_response(csp, rsp);
2333       }
2334
2335       freez(hdr);
2336       return;
2337    }
2338
2339    if (fwd->forward_host || (http->ssl == 0))
2340    {
2341       /* write the client's (modified) header to the server
2342        * (along with anything else that may be in the buffer)
2343        */
2344
2345       if (write_socket(csp->sfd, hdr, strlen(hdr))
2346        || (flush_socket(csp->sfd, csp) <  0))
2347       {
2348          log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
2349                     http->hostport);
2350
2351          rsp = error_response(csp, "connect-failed", errno);
2352
2353          if(rsp)
2354          {
2355             send_crunch_response(csp, rsp);
2356          }
2357
2358          freez(hdr);
2359          return;
2360       }
2361    }
2362    else
2363    {
2364       /*
2365        * We're running an SSL tunnel and we're not forwarding,
2366        * so just send the "connect succeeded" message to the
2367        * client, flush the rest, and get out of the way.
2368        */
2369       if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
2370       {
2371          freez(hdr);
2372          return;
2373       }
2374       IOB_RESET(csp);
2375    }
2376
2377    log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
2378
2379    /* we're finished with the client's header */
2380    freez(hdr);
2381
2382    maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
2383
2384    /* pass data between the client and server
2385     * until one or the other shuts down the connection.
2386     */
2387
2388    server_body = 0;
2389
2390    for (;;)
2391    {
2392 #ifdef __OS2__
2393       /*
2394        * FD_ZERO here seems to point to an errant macro which crashes.
2395        * So do this by hand for now...
2396        */
2397       memset(&rfds,0x00,sizeof(fd_set));
2398 #else
2399       FD_ZERO(&rfds);
2400 #endif
2401       FD_SET(csp->cfd, &rfds);
2402       FD_SET(csp->sfd, &rfds);
2403
2404       n = select((int)maxfd+1, &rfds, NULL, NULL, NULL);
2405
2406       if (n < 0)
2407       {
2408          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
2409          return;
2410       }
2411
2412       /* this is the body of the browser's request
2413        * just read it and write it.
2414        */
2415
2416       if (FD_ISSET(csp->cfd, &rfds))
2417       {
2418          len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
2419
2420          if (len <= 0)
2421          {
2422             break; /* "game over, man" */
2423          }
2424
2425          if (write_socket(csp->sfd, buf, (size_t)len))
2426          {
2427             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
2428             return;
2429          }
2430          continue;
2431       }
2432
2433       /*
2434        * The server wants to talk.  It could be the header or the body.
2435        * If `hdr' is null, then it's the header otherwise it's the body.
2436        * FIXME: Does `hdr' really mean `host'? No.
2437        */
2438
2439
2440       if (FD_ISSET(csp->sfd, &rfds))
2441       {
2442          fflush( 0 );
2443          len = read_socket(csp->sfd, buf, sizeof(buf) - 1);
2444
2445          if (len < 0)
2446          {
2447             log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
2448
2449             if (http->ssl && (fwd->forward_host == NULL))
2450             {
2451                /*
2452                 * Just hang up. We already confirmed the client's CONNECT
2453                 * request with status code 200 and unencrypted content is
2454                 * no longer welcome.
2455                 */
2456                log_error(LOG_LEVEL_ERROR,
2457                   "CONNECT already confirmed. Unable to tell the client about the problem.");
2458                return;
2459             }
2460             else if (byte_count)
2461             {
2462                /*
2463                 * Just hang up. We already transmitted the original headers
2464                 * and parts of the original content and therefore missed the
2465                 * chance to send an error message (without risking data corruption).
2466                 *
2467                 * XXX: we could retry with a fancy range request here.
2468                 */
2469                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
2470                   "Unable to tell the client about the problem.");
2471                return;
2472             }
2473
2474             rsp = error_response(csp, "connect-failed", errno);
2475
2476             if (rsp)
2477             {
2478                send_crunch_response(csp, rsp);
2479             }
2480
2481             return;
2482          }
2483
2484          /* Add a trailing zero.  This lets filter_popups
2485           * use string operations.
2486           */
2487          buf[len] = '\0';
2488
2489 #ifdef FEATURE_KILL_POPUPS
2490          /* Filter the popups on this read. */
2491          if (block_popups_now)
2492          {
2493             filter_popups(buf, csp);
2494          }
2495 #endif /* def FEATURE_KILL_POPUPS */
2496
2497          /* Normally, this would indicate that we've read
2498           * as much as the server has sent us and we can
2499           * close the client connection.  However, Microsoft
2500           * in its wisdom has released IIS/5 with a bug that
2501           * prevents it from sending the trailing \r\n in
2502           * a 302 redirect header (and possibly other headers).
2503           * To work around this if we've haven't parsed
2504           * a full header we'll append a trailing \r\n
2505           * and see if this now generates a valid one.
2506           *
2507           * This hack shouldn't have any impacts.  If we've
2508           * already transmitted the header or if this is a
2509           * SSL connection, then we won't bother with this
2510           * hack.  So we only work on partially received
2511           * headers.  If we append a \r\n and this still
2512           * doesn't generate a valid header, then we won't
2513           * transmit anything to the client.
2514           */
2515          if (len == 0)
2516          {
2517
2518             if (server_body || http->ssl)
2519             {
2520                /*
2521                 * If we have been buffering up the document,
2522                 * now is the time to apply content modification
2523                 * and send the result to the client.
2524                 */
2525                if (content_filter)
2526                {
2527                   /*
2528                    * If the content filter fails, use the original
2529                    * buffer and length.
2530                    * (see p != NULL ? p : csp->iob->cur below)
2531                    */
2532                   if (NULL == (p = (*content_filter)(csp)))
2533                   {
2534                      csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur);
2535                   }
2536
2537                   if (JB_ERR_OK != sed(server_patterns_light, NULL, csp))
2538                   {
2539                      log_error(LOG_LEVEL_FATAL, "Failed to parse server headers.");
2540                   }
2541
2542                   hdr = list_to_text(csp->headers);
2543                   if (hdr == NULL)
2544                   {
2545                      /* FIXME Should handle error properly */
2546                      log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
2547                   }
2548
2549                   /*
2550                    * Shouldn't happen because this was the second sed run
2551                    * and tags are only created for the first one.
2552                    */
2553                   assert(!crunch_response_triggered(csp, crunchers_all));
2554
2555                   if (write_socket(csp->cfd, hdr, strlen(hdr))
2556                    || write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length))
2557                   {
2558                      log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
2559                      freez(hdr);
2560                      freez(p);
2561                      return;
2562                   }
2563
2564                   freez(hdr);
2565                   freez(p);
2566                }
2567
2568                break; /* "game over, man" */
2569             }
2570
2571             /*
2572              * This is NOT the body, so
2573              * Let's pretend the server just sent us a blank line.
2574              */
2575             snprintf(buf, sizeof(buf), "\r\n");
2576             len = (int)strlen(buf);
2577
2578             /*
2579              * Now, let the normal header parsing algorithm below do its
2580              * job.  If it fails, we'll exit instead of continuing.
2581              */
2582
2583             ms_iis5_hack = 1;
2584          }
2585
2586          /*
2587           * If this is an SSL connection or we're in the body
2588           * of the server document, just write it to the client,
2589           * unless we need to buffer the body for later content-filtering
2590           */
2591
2592          if (server_body || http->ssl)
2593          {
2594             if (content_filter)
2595             {
2596                /*
2597                 * If there is no memory left for buffering the content, or the buffer limit
2598                 * has been reached, switch to non-filtering mode, i.e. make & write the
2599                 * header, flush the iob and buf, and get out of the way.
2600                 */
2601                if (add_to_iob(csp, buf, len))
2602                {
2603                   size_t hdrlen;
2604                   int flushed;
2605
2606                   log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering.");
2607
2608                   hdr = list_to_text(csp->headers);
2609                   if (hdr == NULL)
2610                   {
2611                      /* 
2612                       * Memory is too tight to even generate the header.
2613                       * Send our static "Out-of-memory" page.
2614                       */
2615                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
2616                      rsp = cgi_error_memory();
2617                      send_crunch_response(csp, rsp);
2618
2619                      return;
2620                   }
2621                   hdrlen = strlen(hdr);
2622
2623                   if (write_socket(csp->cfd, hdr, hdrlen)
2624                    || ((flushed = flush_socket(csp->cfd, csp)) < 0)
2625                    || (write_socket(csp->cfd, buf, (size_t)len)))
2626                   {
2627                      log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E");
2628
2629                      freez(hdr);
2630                      return;
2631                   }
2632
2633                   /*
2634                    * Reset the byte_count to the amount of bytes
2635                    * we just flushed. len will be added a few lines below,
2636                    * hdrlen doesn't matter for LOG_LEVEL_CLF.
2637                    */
2638                   byte_count = (size_t)flushed;
2639                   freez(hdr);
2640                   content_filter = NULL;
2641                   server_body = 1;
2642                }
2643             }
2644             else
2645             {
2646                if (write_socket(csp->cfd, buf, (size_t)len))
2647                {
2648                   log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
2649                   return;
2650                }
2651             }
2652             byte_count += (size_t)len;
2653             continue;
2654          }
2655          else
2656          {
2657             /* we're still looking for the end of the
2658              * server's header ... (does that make header
2659              * parsing an "out of body experience" ?
2660              */
2661
2662             /* 
2663              * buffer up the data we just read.  If that fails, 
2664              * there's little we can do but send our static
2665              * out-of-memory page.
2666              */
2667             if (add_to_iob(csp, buf, len))
2668             {
2669                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
2670                rsp = cgi_error_memory();
2671                send_crunch_response(csp, rsp);               
2672
2673                return;
2674             }
2675
2676             /* Convert iob into something sed() can digest */
2677             if (JB_ERR_PARSE == get_server_headers(csp))
2678             {
2679                if (ms_iis5_hack)
2680                {
2681                   /* Well, we tried our MS IIS/5
2682                    * hack and it didn't work.
2683                    * The header is incomplete
2684                    * and there isn't anything
2685                    * we can do about it.
2686                    */
2687                   break;
2688                }
2689                else
2690                {
2691                   /* Since we have to wait for
2692                    * more from the server before
2693                    * we can parse the headers
2694                    * we just continue here.
2695                    */
2696                   continue;
2697                }
2698             }
2699
2700             /* Did we actually get anything? */
2701             if (NULL == csp->headers->first)
2702             {
2703                log_error(LOG_LEVEL_ERROR, "Empty server or forwarder response.");
2704                log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
2705                write_socket(csp->cfd, NO_SERVER_DATA_RESPONSE, strlen(NO_SERVER_DATA_RESPONSE));
2706                free_http_request(http);
2707                return;
2708             }
2709
2710             /* we have now received the entire header.
2711              * filter it and send the result to the client
2712              */
2713             if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp))
2714             {
2715                log_error(LOG_LEVEL_FATAL, "Failed to parse server headers.");
2716             }
2717             hdr = list_to_text(csp->headers);
2718             if (hdr == NULL)
2719             {
2720                /* FIXME Should handle error properly */
2721                log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
2722             }
2723
2724             if (crunch_response_triggered(csp, crunchers_light))
2725             {
2726                /*
2727                 * One of the tags created by a server-header
2728                 * tagger triggered a crunch. We already
2729                 * delivered the crunch response to the client
2730                 * and are done here after cleaning up.
2731                 */
2732                 freez(hdr);
2733                 return;
2734             }
2735             /* Buffer and pcrs filter this if appropriate. */
2736
2737             if (!http->ssl) /* We talk plaintext */
2738             {
2739
2740 #ifdef FEATURE_KILL_POPUPS
2741                /* Start blocking popups if appropriate. */
2742                if ((csp->content_type & CT_TEXT) &&               /* It's a text / * MIME-Type */
2743                    (csp->action->flags & ACTION_NO_POPUPS) != 0)  /* Policy allows */
2744                {
2745                   block_popups_now = 1;
2746                   /*
2747                    * Filter the part of the body that came in the same read
2748                    * as the last headers:
2749                    */
2750                   filter_popups(csp->iob->cur, csp);
2751                }
2752 #endif /* def FEATURE_KILL_POPUPS */
2753                content_filter = get_filter_function(csp);
2754             }
2755             /*
2756              * Only write if we're not buffering for content modification
2757              */
2758             if (!content_filter)
2759             {
2760                /* write the server's (modified) header to
2761                 * the client (along with anything else that
2762                 * may be in the buffer)
2763                 */
2764
2765                if (write_socket(csp->cfd, hdr, strlen(hdr))
2766                 || ((len = flush_socket(csp->cfd, csp)) < 0))
2767                {
2768                   log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
2769
2770                   /* the write failed, so don't bother
2771                    * mentioning it to the client...
2772                    * it probably can't hear us anyway.
2773                    */
2774                   freez(hdr);
2775                   return;
2776                }
2777
2778                byte_count += (size_t)len;
2779             }
2780
2781             /* we're finished with the server's header */
2782
2783             freez(hdr);
2784             server_body = 1;
2785
2786             /* If this was a MS IIS/5 hack then it means
2787              * the server has already closed the
2788              * connection.  Nothing more to read.  Time
2789              * to bail.
2790              */
2791             if (ms_iis5_hack)
2792             {
2793                break;
2794             }
2795          }
2796          continue;
2797       }
2798
2799       return; /* huh? we should never get here */
2800    }
2801
2802    if (csp->content_length == 0)
2803    {
2804       /*
2805        * If Privoxy didn't recalculate the
2806        * Content-Lenght, byte_count is still
2807        * correct.
2808        */
2809       csp->content_length = byte_count;
2810    }
2811
2812    log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
2813       csp->ip_addr_str, http->ocmd, csp->content_length);
2814 }
2815
2816
2817 /*********************************************************************
2818  *
2819  * Function    :  serve
2820  *
2821  * Description :  This is little more than chat.  We only "serve" to
2822  *                to close any socket that chat may have opened.
2823  *
2824  * Parameters  :
2825  *          1  :  csp = Current client state (buffers, headers, etc...)
2826  *
2827  * Returns     :  N/A
2828  *
2829  *********************************************************************/
2830 #ifdef AMIGA
2831 void serve(struct client_state *csp)
2832 #else /* ifndef AMIGA */
2833 static void serve(struct client_state *csp)
2834 #endif /* def AMIGA */
2835 {
2836    chat(csp);
2837    close_socket(csp->cfd);
2838
2839    if (csp->sfd != JB_INVALID_SOCKET)
2840    {
2841       close_socket(csp->sfd);
2842    }
2843
2844    csp->flags &= ~CSP_FLAG_ACTIVE;
2845
2846 }
2847
2848
2849 #ifdef __BEOS__
2850 /*********************************************************************
2851  *
2852  * Function    :  server_thread
2853  *
2854  * Description :  We only exist to call `serve' in a threaded environment.
2855  *
2856  * Parameters  :
2857  *          1  :  data = Current client state (buffers, headers, etc...)
2858  *
2859  * Returns     :  Always 0.
2860  *
2861  *********************************************************************/
2862 static int32 server_thread(void *data)
2863 {
2864    serve((struct client_state *) data);
2865    return 0;
2866
2867 }
2868 #endif
2869
2870
2871 #if defined(unix)
2872 /*********************************************************************
2873  *
2874  * Function    :  usage
2875  *
2876  * Description :  Print usage info & exit.
2877  *
2878  * Parameters  :  Pointer to argv[0] for identifying ourselves
2879  *
2880  * Returns     :  No. ,-)
2881  *
2882  *********************************************************************/
2883 static void usage(const char *myname)
2884 {
2885    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
2886           "Usage: %s "
2887 #if defined(unix)
2888           "[--chroot] "
2889 #endif /* defined(unix) */
2890           "[--help] "
2891 #if defined(unix)
2892           "[--no-daemon] [--pidfile pidfile] [--user user[.group]] "
2893 #endif /* defined(unix) */
2894           "[--version] [configfile]\n"
2895           "Aborting\n", myname);
2896
2897    exit(2);
2898
2899 }
2900 #endif /* defined(unix) */
2901
2902
2903 /*********************************************************************
2904  *
2905  * Function    :  initialize_mutexes
2906  *
2907  * Description :  Prepares mutexes if mutex support is available.
2908  *
2909  * Parameters  :  None
2910  *
2911  * Returns     :  Void, exits in case of errors.
2912  *
2913  *********************************************************************/
2914 static void initialize_mutexes(void)
2915 {
2916    int err = 0;
2917
2918 #ifdef FEATURE_PTHREAD
2919    /*
2920     * Prepare global mutex semaphores
2921     */
2922    err = pthread_mutex_init(&log_mutex, 0);
2923
2924    if (!err) err = pthread_mutex_init(&log_init_mutex, 0);
2925
2926    /*
2927     * XXX: The assumptions below are a bit naive
2928     * and can cause locks that aren't necessary.
2929     *
2930     * For example older FreeBSD versions (< 6.x?)
2931     * have no gethostbyname_r, but gethostbyname is
2932     * thread safe.
2933     */
2934 #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
2935    if (!err) err = pthread_mutex_init(&resolver_mutex, 0);
2936 #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
2937    /*
2938     * XXX: should we use a single mutex for
2939     * localtime() and gmtime() as well?
2940     */
2941 #ifndef HAVE_GMTIME_R
2942    if (!err) err = pthread_mutex_init(&gmtime_mutex, 0);
2943 #endif /* ndef HAVE_GMTIME_R */
2944
2945 #ifndef HAVE_LOCALTIME_R
2946    if (!err) err = pthread_mutex_init(&localtime_mutex, 0);
2947 #endif /* ndef HAVE_GMTIME_R */
2948
2949 #ifndef HAVE_RANDOM
2950    if (!err) err = pthread_mutex_init(&rand_mutex, 0);
2951 #endif /* ndef HAVE_RANDOM */
2952 #endif /* FEATURE_PTHREAD */
2953
2954    /*
2955     * TODO: mutex support for mingw32 would be swell.
2956     */
2957
2958    if (err)
2959    {
2960       printf("Fatal error. Mutex initialization failed: %s.\n",
2961          strerror(err));
2962       exit(1);
2963    }
2964
2965    return;
2966 }
2967
2968
2969 /*********************************************************************
2970  *
2971  * Function    :  main
2972  *
2973  * Description :  Load the config file and start the listen loop.
2974  *                This function is a lot more *sane* with the `load_config'
2975  *                and `listen_loop' functions; although it stills does
2976  *                a *little* too much for my taste.
2977  *
2978  * Parameters  :
2979  *          1  :  argc = Number of parameters (including $0).
2980  *          2  :  argv = Array of (char *)'s to the parameters.
2981  *
2982  * Returns     :  1 if : can't open config file, unrecognized directive,
2983  *                stats requested in multi-thread mode, can't open the
2984  *                log file, can't open the jar file, listen port is invalid,
2985  *                any load fails, and can't bind port.
2986  *
2987  *                Else main never returns, the process must be signaled
2988  *                to terminate execution.  Or, on Windows, use the
2989  *                "File", "Exit" menu option.
2990  *
2991  *********************************************************************/
2992 #ifdef __MINGW32__
2993 int real_main(int argc, const char *argv[])
2994 #else
2995 int main(int argc, const char *argv[])
2996 #endif
2997 {
2998    int argc_pos = 0;
2999    unsigned int random_seed;
3000 #ifdef unix
3001    struct passwd *pw = NULL;
3002    struct group *grp = NULL;
3003    char *p;
3004    int do_chroot = 0;
3005 #endif
3006
3007    Argc = argc;
3008    Argv = argv;
3009
3010    configfile =
3011 #if !defined(_WIN32)
3012    "config"
3013 #else
3014    "config.txt"
3015 #endif
3016       ;
3017
3018    /*
3019     * Parse the command line arguments
3020     *
3021     * XXX: simply printing usage information in case of
3022     * invalid arguments isn't particular user friendly.
3023     */
3024    while (++argc_pos < argc)
3025    {
3026 #ifdef _WIN32
3027       /* Check to see if the service must be installed or uninstalled */
3028       if (strncmp(argv[argc_pos], "--install", 9) == 0)
3029       {
3030          const char *pName = argv[argc_pos] + 9;
3031          if (*pName == ':')
3032             pName++;
3033          exit( (install_service(pName)) ? 0 : 1 );
3034       }
3035       else if (strncmp(argv[argc_pos], "--uninstall", + 11) == 0)
3036       {
3037          const char *pName = argv[argc_pos] + 11;
3038          if (*pName == ':')
3039             pName++;
3040          exit((uninstall_service(pName)) ? 0 : 1);
3041       }
3042       else if (strcmp(argv[argc_pos], "--service" ) == 0)
3043       {
3044          bRunAsService = TRUE;
3045          w32_set_service_cwd();
3046          atexit(w32_service_exit_notify);
3047       }
3048       else
3049 #endif /* defined(_WIN32) */
3050
3051
3052 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
3053
3054       if (strcmp(argv[argc_pos], "--help") == 0)
3055       {
3056          usage(argv[0]);
3057       }
3058
3059       else if(strcmp(argv[argc_pos], "--version") == 0)
3060       {
3061          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
3062          exit(0);
3063       }
3064
3065 #if defined(unix)
3066
3067       else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
3068       {
3069          no_daemon = 1;
3070       }
3071
3072       else if (strcmp(argv[argc_pos], "--pidfile" ) == 0)
3073       {
3074          if (++argc_pos == argc) usage(argv[0]);
3075          pidfile = strdup(argv[argc_pos]);
3076       }
3077
3078       else if (strcmp(argv[argc_pos], "--user" ) == 0)
3079       {
3080          if (++argc_pos == argc) usage(argv[argc_pos]);
3081
3082          if ((NULL != (p = strchr(argv[argc_pos], '.'))) && *(p + 1) != '0')
3083          {
3084             *p++ = '\0';
3085             if (NULL == (grp = getgrnam(p)))
3086             {
3087                log_error(LOG_LEVEL_FATAL, "Group %s not found.", p);
3088             }
3089          }
3090
3091          if (NULL == (pw = getpwnam(argv[argc_pos])))
3092          {
3093             log_error(LOG_LEVEL_FATAL, "User %s not found.", argv[argc_pos]);
3094          }
3095
3096          if (p != NULL) *--p = '\0';
3097       }
3098
3099       else if (strcmp(argv[argc_pos], "--chroot" ) == 0)
3100       {
3101          do_chroot = 1;
3102       }
3103 #endif /* defined(unix) */
3104
3105       else if (argc_pos + 1 != argc)
3106       {
3107          /*
3108           * This is neither the last command line
3109           * option, nor was it recognized before,
3110           * therefore it must be invalid.
3111           */
3112          usage(argv[0]);
3113       }
3114       else
3115
3116 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
3117       {
3118          configfile = argv[argc_pos];
3119       }
3120
3121    } /* -END- while (more arguments) */
3122
3123 #if defined(unix)
3124    if ( *configfile != '/' )
3125    {
3126       char cwd[BUFFER_SIZE];
3127       char *abs_file;
3128       size_t abs_file_size; 
3129
3130       /* make config-filename absolute here */
3131       if (NULL == getcwd(cwd, sizeof(cwd)))
3132       {
3133          perror("failed to get current working directory");
3134          exit( 1 );
3135       }
3136
3137       /* XXX: why + 5? */
3138       abs_file_size = strlen(cwd) + strlen(configfile) + 5;
3139       basedir = strdup(cwd);
3140
3141       if (NULL == basedir ||
3142           NULL == (abs_file = malloc(abs_file_size)))
3143       {
3144          perror("malloc failed");
3145          exit( 1 );
3146       }
3147       strlcpy(abs_file, basedir, abs_file_size);
3148       strlcat(abs_file, "/", abs_file_size );
3149       strlcat(abs_file, configfile, abs_file_size);
3150       configfile = abs_file;
3151    }
3152 #endif /* defined unix */
3153
3154
3155    files->next = NULL;
3156    clients->next = NULL;
3157
3158 #ifdef AMIGA
3159    InitAmiga();
3160 #elif defined(_WIN32)
3161    InitWin32();
3162 #endif
3163
3164    /* Prepare mutexes if supported and necessary. */
3165    initialize_mutexes();
3166
3167    random_seed = (unsigned int)time(NULL);
3168 #ifdef HAVE_RANDOM
3169    srandom(random_seed);
3170 #else
3171    srand(random_seed);
3172 #endif /* ifdef HAVE_RANDOM */
3173
3174    /*
3175     * Unix signal handling
3176     *
3177     * Catch the abort, interrupt and terminate signals for a graceful exit
3178     * Catch the hangup signal so the errlog can be reopened.
3179     * Ignore the broken pipe signals (FIXME: Why?)
3180     */
3181 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
3182 {
3183    int idx;
3184    const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP, 0 };
3185    const int ignored_signals[] = { SIGPIPE, 0 };
3186
3187    for (idx = 0; catched_signals[idx] != 0; idx++)
3188    {
3189 #ifdef sun /* FIXME: Is it safe to check for HAVE_SIGSET instead? */ 
3190       if (sigset(catched_signals[idx], sig_handler) == SIG_ERR)
3191 #else
3192       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
3193 #endif /* ifdef sun */
3194       {
3195          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
3196       }
3197    }
3198
3199    for (idx = 0; ignored_signals[idx] != 0; idx++)
3200    {
3201       if (signal(ignored_signals[idx], SIG_IGN) == SIG_ERR)
3202       {
3203          log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for signal %d: %E", ignored_signals[idx]);
3204       }
3205    }
3206
3207 }
3208 #else /* ifdef _WIN32 */
3209 # ifdef _WIN_CONSOLE
3210    /*
3211     * We *are* in a windows console app.
3212     * Print a verbose messages about FAQ's and such
3213     */
3214    printf("%s", win32_blurb);
3215 # endif /* def _WIN_CONSOLE */
3216 #endif /* def _WIN32 */
3217
3218
3219    /* Initialize the CGI subsystem */
3220    cgi_init_error_messages();
3221
3222    /*
3223     * If runnig on unix and without the --nodaemon
3224     * option, become a daemon. I.e. fork, detach
3225     * from tty and get process group leadership
3226     */
3227 #if defined(unix)
3228 {
3229    pid_t pid = 0;
3230 #if 0
3231    int   fd;
3232 #endif
3233
3234    if (!no_daemon)
3235    {
3236       pid  = fork();
3237
3238       if ( pid < 0 ) /* error */
3239       {
3240          perror("fork");
3241          exit( 3 );
3242       }
3243       else if ( pid != 0 ) /* parent */
3244       {
3245          int status;
3246          pid_t wpid;
3247          /*
3248           * must check for errors
3249           * child died due to missing files aso
3250           */
3251          sleep( 1 );
3252          wpid = waitpid( pid, &status, WNOHANG );
3253          if ( wpid != 0 )
3254          {
3255             exit( 1 );
3256          }
3257          exit( 0 );
3258       }
3259       /* child */
3260 #if 1
3261       /* Should be more portable, but not as well tested */
3262       setsid();
3263 #else /* !1 */
3264 #ifdef __FreeBSD__
3265       setpgrp(0,0);
3266 #else /* ndef __FreeBSD__ */
3267       setpgrp();
3268 #endif /* ndef __FreeBSD__ */
3269       fd = open("/dev/tty", O_RDONLY);
3270       if ( fd )
3271       {
3272          /* no error check here */
3273          ioctl( fd, TIOCNOTTY,0 );
3274          close ( fd );
3275       }
3276 #endif /* 1 */
3277       /* FIXME: should close stderr (fd 2) here too, but the test
3278        * for existence
3279        * and load config file is done in listen_loop() and puts
3280        * some messages on stderr there.
3281        */
3282
3283       close( 0 );
3284       close( 1 );
3285       chdir("/");
3286
3287    } /* -END- if (!no_daemon) */
3288
3289    /*
3290     * As soon as we have written the PID file, we can switch
3291     * to the user and group ID indicated by the --user option
3292     */
3293    write_pid_file();
3294
3295    if (NULL != pw)
3296    {
3297       if (setgid((NULL != grp) ? grp->gr_gid : pw->pw_gid))
3298       {
3299          log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
3300       }
3301       if (do_chroot)
3302       {
3303          if (!pw->pw_dir)
3304          {
3305             log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
3306          }
3307          if (chroot(pw->pw_dir) < 0)
3308          {
3309             log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
3310          }
3311          if (chdir ("/"))
3312          {
3313             log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
3314          }
3315       }
3316       if (setuid(pw->pw_uid))
3317       {
3318          log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
3319       }
3320       if (do_chroot)
3321       {
3322          char putenv_dummy[64];
3323
3324          strlcpy(putenv_dummy, "HOME=/", sizeof(putenv_dummy));
3325          if (putenv(putenv_dummy) != 0)
3326          {
3327             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
3328          }                
3329
3330          snprintf(putenv_dummy, sizeof(putenv_dummy), "USER=%s", pw->pw_name);
3331          if (putenv(putenv_dummy) != 0)
3332          {
3333             log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
3334          }
3335       }
3336    }
3337    else if (do_chroot)
3338    {
3339       log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
3340    }
3341 }
3342 #endif /* defined unix */
3343
3344 #ifdef _WIN32
3345    /* This will be FALSE unless the command line specified --service
3346     */
3347    if (bRunAsService)
3348    {
3349       /* Yup, so now we must attempt to establish a connection 
3350        * with the service dispatcher. This will only work if this
3351        * process was launched by the service control manager to
3352        * actually run as a service. If this isn't the case, i've
3353        * known it take around 30 seconds or so for the call to return.
3354        */
3355
3356       /* The StartServiceCtrlDispatcher won't return until the service is stopping */
3357       if (w32_start_service_ctrl_dispatcher(w32ServiceDispatchTable))
3358       {
3359          /* Service has run, and at this point is now being stopped, so just return */
3360          return 0;
3361       }
3362
3363 #ifdef _WIN_CONSOLE
3364       printf("Warning: Failed to connect to Service Control Dispatcher\nwhen starting as a service!\n");
3365 #endif
3366       /* An error occurred. Usually it's because --service was wrongly specified
3367        * and we were unable to connect to the Service Control Dispatcher because
3368        * it wasn't expecting us and is therefore not listening.
3369        *
3370        * For now, just continue below to call the listen_loop function.
3371        */
3372    }
3373 #endif /* def _WIN32 */
3374
3375    listen_loop();
3376
3377    /* NOTREACHED */
3378    return(-1);
3379
3380 }
3381
3382
3383 /*********************************************************************
3384  *
3385  * Function    :  bind_port_helper
3386  *
3387  * Description :  Bind the listen port.  Handles logging, and aborts
3388  *                on failure.
3389  *
3390  * Parameters  :
3391  *          1  :  config = Privoxy configuration.  Specifies port
3392  *                         to bind to.
3393  *
3394  * Returns     :  Port that was opened.
3395  *
3396  *********************************************************************/
3397 static jb_socket bind_port_helper(struct configuration_spec * config)
3398 {
3399    int result;
3400    jb_socket bfd;
3401
3402    if ( (config->haddr != NULL)
3403      && (config->haddr[0] == '1')
3404      && (config->haddr[1] == '2')
3405      && (config->haddr[2] == '7')
3406      && (config->haddr[3] == '.') )
3407    {
3408       log_error(LOG_LEVEL_INFO, "Listening on port %d for local connections only",
3409                 config->hport);
3410    }
3411    else if (config->haddr == NULL)
3412    {
3413       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
3414                 config->hport);
3415    }
3416    else
3417    {
3418       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
3419                 config->hport, config->haddr);
3420    }
3421
3422    result = bind_port(config->haddr, config->hport, &bfd);
3423
3424    if (result < 0)
3425    {
3426       switch(result)
3427       {
3428          case -3 :
3429             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: "
3430                "There may be another Privoxy or some other "
3431                "proxy running on port %d",
3432                (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
3433                       config->hport, config->hport);
3434
3435          case -2 :
3436             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " 
3437                "The hostname is not resolvable",
3438                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
3439
3440          default :
3441             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E",
3442                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
3443       }
3444
3445       /* shouldn't get here */
3446       return JB_INVALID_SOCKET;
3447    }
3448
3449    config->need_bind = 0;
3450
3451    return bfd;
3452 }
3453
3454
3455 #ifdef _WIN32
3456 /* Without this simple workaround we get this compiler warning from _beginthread
3457  *     warning C4028: formal parameter 1 different from declaration
3458  */
3459 void w32_service_listen_loop(void *p)
3460 {
3461    listen_loop();
3462 }
3463 #endif /* def _WIN32 */
3464
3465
3466 /*********************************************************************
3467  *
3468  * Function    :  listen_loop
3469  *
3470  * Description :  bind the listen port and enter a "FOREVER" listening loop.
3471  *
3472  * Parameters  :  N/A
3473  *
3474  * Returns     :  Never.
3475  *
3476  *********************************************************************/
3477 static void listen_loop(void)
3478 {
3479    struct client_state *csp = NULL;
3480    jb_socket bfd;
3481    struct configuration_spec * config;
3482
3483    config = load_config();
3484
3485    bfd = bind_port_helper(config);
3486
3487 #ifdef FEATURE_GRACEFUL_TERMINATION
3488    while (!g_terminate)
3489 #else
3490    for (;;)
3491 #endif
3492    {
3493 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
3494       while (waitpid(-1, NULL, WNOHANG) > 0)
3495       {
3496          /* zombie children */
3497       }
3498 #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
3499
3500       /*
3501        * Free data that was used by died threads
3502        */
3503       sweep();
3504
3505 #if defined(unix)
3506       /*
3507        * Re-open the errlog after HUP signal
3508        */
3509       if (received_hup_signal)
3510       {
3511          init_error_log(Argv[0], config->logfile, config->debug);
3512          received_hup_signal = 0;
3513       }
3514 #endif
3515
3516 #ifdef __OS2__
3517 #ifdef FEATURE_COOKIE_JAR
3518       /*
3519        * Need a workaround here: we have to fclose() the jarfile, or we die because it's
3520        * already open.  I think unload_configfile() is not being run, which should do
3521        * this work.  Until that can get resolved, we'll use this workaround.
3522        */
3523        if (csp)
3524          if(csp->config)
3525            if (csp->config->jar)
3526            {
3527              fclose(csp->config->jar);
3528              csp->config->jar = NULL;
3529            }
3530 #endif /* FEATURE_COOKIE_JAR */
3531 #endif /* __OS2__ */
3532
3533       if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) )
3534       {
3535          log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp));
3536          continue;
3537       }
3538
3539       csp->flags |= CSP_FLAG_ACTIVE;
3540       csp->sfd    = JB_INVALID_SOCKET;
3541
3542       csp->config = config = load_config();
3543
3544       if ( config->need_bind )
3545       {
3546          /*
3547           * Since we were listening to the "old port", we will not see
3548           * a "listen" param change until the next IJB request.  So, at
3549           * least 1 more request must be made for us to find the new
3550           * setting.  I am simply closing the old socket and binding the
3551           * new one.
3552           *
3553           * Which-ever is correct, we will serve 1 more page via the
3554           * old settings.  This should probably be a "show-proxy-args"
3555           * request.  This should not be a so common of an operation
3556           * that this will hurt people's feelings.
3557           */
3558
3559          close_socket(bfd);
3560
3561          bfd = bind_port_helper(config);
3562       }
3563
3564       log_error(LOG_LEVEL_CONNECT, "Listening for new connections ... ");
3565
3566       if (!accept_connection(csp, bfd))
3567       {
3568          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
3569
3570 #ifdef AMIGA
3571          if(!childs)
3572          {
3573             exit(1);
3574          }
3575 #endif
3576          freez(csp);
3577          continue;
3578       }
3579       else
3580       {
3581          log_error(LOG_LEVEL_CONNECT, "accepted connection from %s", csp->ip_addr_str);
3582       }
3583
3584 #ifdef FEATURE_TOGGLE
3585       if (global_toggle_state)
3586       {
3587          csp->flags |= CSP_FLAG_TOGGLED_ON;
3588       }
3589 #endif /* def FEATURE_TOGGLE */
3590
3591       if (run_loader(csp))
3592       {
3593          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
3594          /* Never get here - LOG_LEVEL_FATAL causes program exit */
3595       }
3596
3597 #ifdef FEATURE_ACL
3598       if (block_acl(NULL,csp))
3599       {
3600          log_error(LOG_LEVEL_CONNECT, "Connection from %s dropped due to ACL", csp->ip_addr_str);
3601          close_socket(csp->cfd);
3602          freez(csp);
3603          continue;
3604       }
3605 #endif /* def FEATURE_ACL */
3606
3607       /* add it to the list of clients */
3608       csp->next = clients->next;
3609       clients->next = csp;
3610
3611       if (config->multi_threaded)
3612       {
3613          int child_id;
3614
3615 /* this is a switch () statment in the C preprocessor - ugh */
3616 #undef SELECTED_ONE_OPTION
3617
3618 /* Use Pthreads in preference to native code */
3619 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
3620 #define SELECTED_ONE_OPTION
3621          {
3622             pthread_t the_thread;
3623             pthread_attr_t attrs;
3624
3625             pthread_attr_init(&attrs);
3626             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
3627             errno = pthread_create(&the_thread, &attrs,
3628                (void * (*)(void *))serve, csp);
3629             child_id = errno ? -1 : 0;
3630             pthread_attr_destroy(&attrs);
3631          }
3632 #endif
3633
3634 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
3635 #define SELECTED_ONE_OPTION
3636          child_id = _beginthread(
3637             (void (*)(void *))serve,
3638             64 * 1024,
3639             csp);
3640 #endif
3641
3642 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
3643 #define SELECTED_ONE_OPTION
3644          child_id = _beginthread(
3645             (void(* _Optlink)(void*))serve,
3646             NULL,
3647             64 * 1024,
3648             csp);
3649 #endif
3650
3651 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
3652 #define SELECTED_ONE_OPTION
3653          {
3654             thread_id tid = spawn_thread
3655                (server_thread, "server", B_NORMAL_PRIORITY, csp);
3656
3657             if ((tid >= 0) && (resume_thread(tid) == B_OK))
3658             {
3659                child_id = (int) tid;
3660             }
3661             else
3662             {
3663                child_id = -1;
3664             }
3665          }
3666 #endif
3667
3668 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
3669 #define SELECTED_ONE_OPTION
3670          csp->cfd = ReleaseSocket(csp->cfd, -1);
3671          
3672 #ifdef __amigaos4__
3673          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
3674                                            NP_Output, Output(),
3675                                            NP_CloseOutput, FALSE,
3676                                            NP_Name, (ULONG)"privoxy child",
3677                                            NP_Child, TRUE,
3678                                            TAG_DONE);
3679 #else
3680          child_id = (int)CreateNewProcTags(NP_Entry, (ULONG)server_thread,
3681                                            NP_Output, Output(),
3682                                            NP_CloseOutput, FALSE,
3683                                            NP_Name, (ULONG)"privoxy child",
3684                                            NP_StackSize, 200*1024,
3685                                            TAG_DONE);
3686 #endif
3687          if(0 != child_id)
3688          {
3689             childs++;
3690             ((struct Task *)child_id)->tc_UserData = csp;
3691             Signal((struct Task *)child_id, SIGF_SINGLE);
3692             Wait(SIGF_SINGLE);
3693          }
3694 #endif
3695
3696 #if !defined(SELECTED_ONE_OPTION)
3697          child_id = fork();
3698
3699          /* This block is only needed when using fork().
3700           * When using threads, the server thread was
3701           * created and run by the call to _beginthread().
3702           */
3703          if (child_id == 0)   /* child */
3704          {
3705             int rc = 0;
3706 #ifdef FEATURE_TOGGLE
3707             int inherited_toggle_state = global_toggle_state;
3708 #endif /* def FEATURE_TOGGLE */
3709
3710             serve(csp);
3711
3712             /* 
3713              * If we've been toggled or we've blocked the request, tell Mom
3714              */
3715
3716 #ifdef FEATURE_TOGGLE
3717             if (inherited_toggle_state != global_toggle_state)
3718             {
3719                rc |= RC_FLAG_TOGGLED;
3720             }
3721 #endif /* def FEATURE_TOGGLE */
3722
3723 #ifdef FEATURE_STATISTICS  
3724             if (csp->flags & CSP_FLAG_REJECTED)
3725             {
3726                rc |= RC_FLAG_BLOCKED;
3727             }
3728 #endif /* ndef FEATURE_STATISTICS */
3729
3730             _exit(rc);
3731          }
3732          else if (child_id > 0) /* parent */
3733          {
3734             /* in a fork()'d environment, the parent's
3735              * copy of the client socket and the CSP
3736              * are not used.
3737              */
3738             int child_status;
3739 #if !defined(_WIN32) && !defined(__CYGWIN__)
3740
3741             wait( &child_status );
3742
3743             /* 
3744              * Evaluate child's return code: If the child has
3745              *  - been toggled, toggle ourselves
3746              *  - blocked its request, bump up the stats counter
3747              */
3748
3749 #ifdef FEATURE_TOGGLE
3750             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
3751             {
3752                global_toggle_state = !global_toggle_state;
3753             }
3754 #endif /* def FEATURE_TOGGLE */
3755
3756 #ifdef FEATURE_STATISTICS
3757             urls_read++;
3758             if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
3759             {
3760                urls_rejected++;
3761             }
3762 #endif /* def FEATURE_STATISTICS */ 
3763
3764 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
3765             close_socket(csp->cfd);
3766             csp->flags &= ~CSP_FLAG_ACTIVE;
3767          }
3768 #endif
3769
3770 #undef SELECTED_ONE_OPTION
3771 /* end of cpp switch () */
3772
3773          if (child_id < 0) /* failed */
3774          {
3775             char buf[BUFFER_SIZE];
3776
3777             log_error(LOG_LEVEL_ERROR, "can't fork: %E");
3778
3779             snprintf(buf , sizeof(buf), "Privoxy: can't fork: errno = %d", errno);
3780
3781             write_socket(csp->cfd, buf, strlen(buf));
3782             close_socket(csp->cfd);
3783             csp->flags &= ~CSP_FLAG_ACTIVE;
3784             sleep(5);
3785             continue;
3786          }
3787       }
3788       else
3789       {
3790          serve(csp);
3791       }
3792    }
3793
3794    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
3795
3796    /* Clean up.  Aim: free all memory (no leaks) */
3797 #ifdef FEATURE_GRACEFUL_TERMINATION
3798
3799    log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
3800
3801    unload_current_config_file();
3802    unload_current_actions_file();
3803    unload_current_re_filterfile();
3804 #ifdef FEATURE_TRUST
3805    unload_current_trust_file();
3806 #endif
3807
3808    if (config->multi_threaded)
3809    {
3810       int i = 60;
3811       do
3812       {
3813          sleep(1);
3814          sweep();
3815       } while ((clients->next != NULL) && (--i > 0));
3816
3817       if (i <= 0)
3818       {
3819          log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
3820       }
3821    }
3822    sweep();
3823    sweep();
3824
3825 #if defined(unix)
3826    freez(basedir);
3827 #endif
3828    freez(configfile);
3829
3830 #ifdef FEATURE_COOKIE_JAR
3831    if (NULL != config->jar)
3832    {
3833       fclose(config->jar);
3834    }
3835 #endif
3836
3837 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
3838    /* Cleanup - remove taskbar icon etc. */
3839    TermLogWindow();
3840 #endif
3841
3842    exit(0);
3843 #endif /* FEATURE_GRACEFUL_TERMINATION */
3844
3845 }
3846
3847
3848 /*
3849   Local Variables:
3850   tab-width: 3
3851   end:
3852 */