Trivial formatting changes
[privoxy.git] / src / jcc.c
1 const char jcc_rcs[] = "$Id: jcc.c,v 2.2 2002/07/12 04:26:17 agotneja Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/src/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 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 2.2  2002/07/12 04:26:17  agotneja
37  *    Re-factored 'chat()' to become understandable and maintainable as
38  *    a first step in adding Transparent Proxy functionality.
39  *
40  *    Added several new static functions in jcc.c, and moved some data
41  *    parameters up into project.h to allow them to be passed between
42  *    the new functions.
43  *
44  *    Revision 1.91  2002/04/08 20:35:58  swa
45  *    fixed JB spelling
46  *
47  *    Revision 1.90  2002/04/02 14:57:28  oes
48  *    Made sending wafers independent of FEATURE_COOKIE_JAR
49  *
50  *    Revision 1.89  2002/03/31 17:18:59  jongfoster
51  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
52  *
53  *    Revision 1.88  2002/03/27 14:32:43  david__schmidt
54  *    More compiler warning message maintenance
55  *
56  *    Revision 1.87  2002/03/26 22:29:54  swa
57  *    we have a new homepage!
58  *
59  *    Revision 1.86  2002/03/25 17:04:55  david__schmidt
60  *    Workaround for closing the jarfile before load_config() comes around again
61  *
62  *    Revision 1.85  2002/03/24 15:23:33  jongfoster
63  *    Name changes
64  *
65  *    Revision 1.84  2002/03/24 13:25:43  swa
66  *    name change related issues
67  *
68  *    Revision 1.83  2002/03/16 23:54:06  jongfoster
69  *    Adding graceful termination feature, to help look for memory leaks.
70  *    If you enable this (which, by design, has to be done by hand
71  *    editing config.h) and then go to http://i.j.b/die, then the program
72  *    will exit cleanly after the *next* request.  It should free all the
73  *    memory that was used.
74  *
75  *    Revision 1.82  2002/03/13 00:27:05  jongfoster
76  *    Killing warnings
77  *
78  *    Revision 1.81  2002/03/12 01:42:50  oes
79  *    Introduced modular filters
80  *
81  *    Revision 1.80  2002/03/11 22:07:05  david__schmidt
82  *    OS/2 port maintenance:
83  *    - Fixed EMX build - it had decayed a little
84  *    - Fixed inexplicable crash during FD_ZERO - must be due to a bad macro.
85  *      substituted a memset for now.
86  *
87  *    Revision 1.79  2002/03/09 20:03:52  jongfoster
88  *    - Making various functions return int rather than size_t.
89  *      (Undoing a recent change).  Since size_t is unsigned on
90  *      Windows, functions like read_socket that return -1 on
91  *      error cannot return a size_t.
92  *
93  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
94  *      crashes, and also frequently caused JB to jump to 100%
95  *      CPU and stay there.  (Because it thought it had just
96  *      read ((unsigned)-1) == 4Gb of data...)
97  *
98  *    - The signature of write_socket has changed, it now simply
99  *      returns success=0/failure=nonzero.
100  *
101  *    - Trying to get rid of a few warnings --with-debug on
102  *      Windows, I've introduced a new type "jb_socket".  This is
103  *      used for the socket file descriptors.  On Windows, this
104  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
105  *      an int.  The error value can't be -1 any more, so it's
106  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
107  *      Windows it maps to the #define INVALID_SOCKET.)
108  *
109  *    - The signature of bind_port has changed.
110  *
111  *    Revision 1.78  2002/03/08 21:35:04  oes
112  *    Added optional group supplement to --user option. Will now use default group of user if no group given
113  *
114  *    Revision 1.77  2002/03/07 03:52:06  oes
115  *     - Fixed compiler warnings etc
116  *     - Improved handling of failed DNS lookups
117  *
118  *    Revision 1.76  2002/03/06 22:54:35  jongfoster
119  *    Automated function-comment nitpicking.
120  *
121  *    Revision 1.75  2002/03/06 10:02:19  oes
122  *    Fixed stupid bug when --user was not given
123  *
124  *    Revision 1.74  2002/03/06 00:49:31  jongfoster
125  *    Fixing warning on Windows
126  *    Making #ifdefs that refer to the same variable consistently
127  *    use #ifdef unix rather than mixing #ifdef unix & #ifndef OS2
128  *
129  *    Revision 1.73  2002/03/05 23:57:30  hal9
130  *    Stray character 's' on line 1618 was breaking build.
131  *
132  *    Revision 1.72  2002/03/05 21:33:45  david__schmidt
133  *    - Re-enable OS/2 building after new parms were added
134  *    - Fix false out of memory report when resolving CGI templates when no IP
135  *      address is available of failed attempt (a la no such domain)
136  *
137  *    Revision 1.71  2002/03/05 18:13:56  oes
138  *    Added --user option
139  *
140  *    Revision 1.70  2002/03/05 04:52:42  oes
141  *    Deleted non-errlog debugging code
142  *
143  *    Revision 1.69  2002/03/04 23:50:00  jongfoster
144  *    Splitting off bind_port() call into bind_port_helper(), with
145  *    improved logging.
146  *
147  *    Revision 1.68  2002/03/04 20:17:32  oes
148  *    Fixed usage info
149  *
150  *    Revision 1.67  2002/03/04 18:18:57  oes
151  *    - Removed _DEBUG mode
152  *    - Cleand up cmdline parsing
153  *    - Introduced --no-daemon, --pidfile options
154  *    - Cleaned up signal handling:
155  *      - Terminate cleanly on INT, TERM and ABRT
156  *      - Schedule logfile for re-opening on HUP
157  *      - Ignore CHLD and PIPE
158  *      - Leave the rest with their default handlers
159  *      - Uniform handler registration
160  *    - Added usage() function
161  *    - Played styleguide police
162  *
163  *    Revision 1.66  2002/03/03 15:06:55  oes
164  *    Re-enabled automatic config reloading
165  *
166  *    Revision 1.65  2002/03/03 14:49:11  oes
167  *    Fixed CLF logging: Now uses client's original HTTP request
168  *
169  *    Revision 1.64  2002/03/03 09:18:03  joergs
170  *    Made jumbjuster work on AmigaOS again.
171  *
172  *    Revision 1.63  2002/03/02 04:14:50  david__schmidt
173  *    Clean up a little CRLF unpleasantness that suddenly appeared
174  *
175  *    Revision 1.62  2002/02/20 23:17:23  jongfoster
176  *    Detecting some out-of memory conditions and exiting with a log message.
177  *
178  *    Revision 1.61  2002/01/17 21:01:52  jongfoster
179  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
180  *
181  *    Revision 1.60  2001/12/30 14:07:32  steudten
182  *    - Add signal handling (unix)
183  *    - Add SIGHUP handler (unix)
184  *    - Add creation of pidfile (unix)
185  *    - Add action 'top' in rc file (RH)
186  *    - Add entry 'SIGNALS' to manpage
187  *    - Add exit message to logfile (unix)
188  *
189  *    Revision 1.59  2001/12/13 14:07:18  oes
190  *    Fixed Bug: 503 error page now sent OK
191  *
192  *    Revision 1.58  2001/11/30 23:37:24  jongfoster
193  *    Renaming the Win32 config file to config.txt - this is almost the
194  *    same as the corresponding UNIX name "config"
195  *
196  *    Revision 1.57  2001/11/16 00:47:43  jongfoster
197  *    Changing the tty-disconnection code to use setsid().
198  *
199  *    Revision 1.56  2001/11/13 20:20:54  jongfoster
200  *    Tabs->spaces, fixing a bug with missing {} around an if()
201  *
202  *    Revision 1.55  2001/11/13 20:14:53  jongfoster
203  *    Patch for FreeBSD setpgrp() as suggested by Alexander Lazic
204  *
205  *    Revision 1.54  2001/11/07 00:03:14  steudten
206  *    Give reliable return value if an error
207  *    occurs not just 0 with new daemon mode.
208  *
209  *    Revision 1.53  2001/11/05 21:41:43  steudten
210  *    Add changes to be a real daemon just for unix os.
211  *    (change cwd to /, detach from controlling tty, set
212  *    process group and session leader to the own process.
213  *    Add DBG() Macro.
214  *    Add some fatal-error log message for failed malloc().
215  *    Add '-d' if compiled with 'configure --with-debug' to
216  *    enable debug output.
217  *
218  *    Revision 1.52  2001/10/26 20:11:20  jongfoster
219  *    Fixing type mismatch
220  *
221  *    Revision 1.51  2001/10/26 17:38:28  oes
222  *    Cosmetics
223  *
224  *    Revision 1.50  2001/10/25 03:40:48  david__schmidt
225  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
226  *    threads to call select() simultaneously.  So, it's time to do a real, live,
227  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
228  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
229  *
230  *    Revision 1.49  2001/10/23 21:41:35  jongfoster
231  *    Added call to initialize the (statically-allocated of course)
232  *    "out of memory" CGI response.
233  *
234  *    Revision 1.48  2001/10/10 19:56:46  jongfoster
235  *    Moving some code that wasn't cookie-related out of an #ifdef
236  *    FEATURE_COOKIE_JAR
237  *
238  *    Revision 1.47  2001/10/10 16:44:36  oes
239  *    Added CONNECT destination port limitation check
240  *
241  *    Revision 1.46  2001/10/08 15:17:41  oes
242  *    Re-enabled SSL forwarding
243  *
244  *    Revision 1.45  2001/10/07 15:42:11  oes
245  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
246  *
247  *    Moved downgrading of the HTTP version from parse_http_request to
248  *      chat(), since we can't decide if it is necessary before we have
249  *      determined the actions for the URL. The HTTP command is now
250  *      *always* re-built so the repairs need no longer be special-cased.
251  *
252  *    filter_popups now gets a csp pointer so it can raise the new
253  *      CSP_FLAG_MODIFIED flag.
254  *
255  *    Bugfix
256  *
257  *    Added configurable size limit for the IOB. If the IOB grows so
258  *      large that the next read would exceed the limit, the header
259  *      is generated, and the header & unfiltered buffer are flushed
260  *      to the client. Chat then continues in non-buffering,
261  *      non-filtering body mode.
262  *
263  *    Revision 1.44  2001/10/02 18:13:57  oes
264  *    Ooops
265  *
266  *    Revision 1.43  2001/10/02 15:32:13  oes
267  *    Moved generation of hdr
268  *
269  *    Revision 1.42  2001/09/21 23:02:02  david__schmidt
270  *    Cleaning up 2 compiler warnings on OS/2.
271  *
272  *    Revision 1.41  2001/09/16 17:05:14  jongfoster
273  *    Removing unused #include showarg.h
274  *
275  *    Revision 1.40  2001/09/16 15:41:45  jongfoster
276  *    Fixing signed/unsigned comparison warning.
277  *
278  *    Revision 1.39  2001/09/16 13:21:27  jongfoster
279  *    Changes to use new list functions.
280  *
281  *    Revision 1.38  2001/09/16 13:01:46  jongfoster
282  *    Removing redundant function call that zeroed zalloc()'d memory.
283  *
284  *    Revision 1.37  2001/09/10 11:12:24  oes
285  *    Deleted unused variable
286  *
287  *    Revision 1.36  2001/09/10 10:56:15  oes
288  *    Silenced compiler warnings
289  *
290  *    Revision 1.35  2001/07/31 14:44:22  oes
291  *    Deleted unused size parameter from filter_popups()
292  *
293  *    Revision 1.34  2001/07/30 22:08:36  jongfoster
294  *    Tidying up #defines:
295  *    - All feature #defines are now of the form FEATURE_xxx
296  *    - Permanently turned off WIN_GUI_EDIT
297  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
298  *
299  *    Revision 1.33  2001/07/29 19:32:00  jongfoster
300  *    Renaming _main() [mingw32 only] to real_main(), for ANSI compliance.
301  *
302  *    Revision 1.32  2001/07/29 18:47:05  jongfoster
303  *    Adding missing #include "loadcfg.h"
304  *
305  *    Revision 1.31  2001/07/29 12:17:48  oes
306  *    Applied pthread fix by Paul Lieverse
307  *
308  *    Revision 1.30  2001/07/25 22:57:13  jongfoster
309  *    __BEOS__ no longer overrides FEATURE_PTHREAD.
310  *    This is because FEATURE_PTHREAD will soon be widely used, so I
311  *    want to keep it simple.
312  *
313  *    Revision 1.29  2001/07/24 12:47:06  oes
314  *    Applied BeOS support update by Eugenia
315  *
316  *    Revision 1.28  2001/07/23 13:26:12  oes
317  *    Fixed bug in popup-killing for the first read that caused binary garbage to be sent between headers and body
318  *
319  *    Revision 1.27  2001/07/19 19:09:47  haroon
320  *    - Added code to take care of the situation where while processing the first
321  *      server response (which includes the server header), after finding the end
322  *      of the headers we were not looking past the end of the headers for
323  *      content modification. I enabled it for filter_popups.
324  *      Someone else should look to see if other similar operations should be
325  *      done to the discarded portion of the buffer.
326  *
327  *      Note 2001/07/20: No, the other content modification mechanisms will process
328  *                       the whole iob later anyway. --oes
329  *
330  *    Revision 1.26  2001/07/18 12:31:36  oes
331  *    cosmetics
332  *
333  *    Revision 1.25  2001/07/15 19:43:49  jongfoster
334  *    Supports POSIX threads.
335  *    Also removed some unused #includes.
336  *
337  *    Revision 1.24  2001/07/13 14:00:40  oes
338  *     - Generic content modification scheme:
339  *       Each feature has its own applicability flag that is set
340  *       from csp->action->flags.
341  *       Replaced the "filtering" int flag , by a function pointer
342  *       "content_filter" to the function that will do the content
343  *       modification. If it is != NULL, the document will be buffered
344  *       and processed through *content_filter, which must set
345  *       csp->content_length and return a modified copy of the body
346  *       or return NULL (on failiure).
347  *     - Changed csp->is_text to the more generic bitmap csp->content_type
348  *       which can currently take the valued CT_TEXT or CT_GIF
349  *     - Reformatting etc
350  *     - Removed all #ifdef PCRS
351  *
352  *    Revision 1.23  2001/07/02 02:28:25  iwanttokeepanon
353  *    Added "#ifdef ACL_FILES" conditional compilation to line 1291 to exclude
354  *    the `block_acl' call.  This prevents a compilation error when the user
355  *    does not wish to use the "ACL" feature.
356  *
357  *    Revision 1.22  2001/06/29 21:45:41  oes
358  *    Indentation, CRLF->LF, Tab-> Space
359  *
360  *    Revision 1.21  2001/06/29 13:29:36  oes
361  *    - Cleaned up, improved comments
362  *    - Unified all possible interceptors (CGI,
363  *      block, trust, fast_redirect) in one
364  *      place, with one (CGI) answer generation
365  *      mechansim. Much clearer now.
366  *    - Removed the GIF image generation, which
367  *      is now done in filters.c:block_url()
368  *    - Made error conditions like domain lookup
369  *      failiure or (various) problems while talking
370  *      to the server use cgi.c:error_response()
371  *      instead of generating HTML/HTTP in chat() (yuck!)
372  *    - Removed logentry from cancelled commit
373  *
374  *    Revision 1.20  2001/06/09 10:55:28  jongfoster
375  *    Changing BUFSIZ ==> BUFFER_SIZE
376  *
377  *    Revision 1.19  2001/06/07 23:12:52  jongfoster
378  *    Replacing function pointer in struct gateway with a directly
379  *    called function forwarded_connect().
380  *    Replacing struct gateway with struct forward_spec
381  *
382  *    Revision 1.18  2001/06/03 19:12:16  oes
383  *    introduced new cgi handling
384  *
385  *    Revision 1.17  2001/06/01 20:07:23  jongfoster
386  *    Now uses action +image-blocker{} rather than config->tinygif
387  *
388  *    Revision 1.16  2001/06/01 18:49:17  jongfoster
389  *    Replaced "list_share" with "list" - the tiny memory gain was not
390  *    worth the extra complexity.
391  *
392  *    Revision 1.15  2001/05/31 21:24:47  jongfoster
393  *    Changed "permission" to "action" throughout.
394  *    Removed DEFAULT_USER_AGENT - it must now be specified manually.
395  *    Moved vanilla wafer check into chat(), since we must now
396  *    decide whether or not to add it based on the URL.
397  *
398  *    Revision 1.14  2001/05/29 20:14:01  joergs
399  *    AmigaOS bugfix: PCRS needs a lot of stack, stacksize for child threads
400  *    increased.
401  *
402  *    Revision 1.13  2001/05/29 09:50:24  jongfoster
403  *    Unified blocklist/imagelist/permissionslist.
404  *    File format is still under discussion, but the internal changes
405  *    are (mostly) done.
406  *
407  *    Also modified interceptor behaviour:
408  *    - We now intercept all URLs beginning with one of the following
409  *      prefixes (and *only* these prefixes):
410  *        * http://i.j.b/
411  *        * http://ijbswa.sf.net/config/
412  *        * http://ijbswa.sourceforge.net/config/
413  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
414  *    - Internal changes so that intercepted and fast redirect pages
415  *      are not replaced with an image.
416  *    - Interceptors now have the option to send a binary page direct
417  *      to the client. (i.e. ijb-send-banner uses this)
418  *    - Implemented show-url-info interceptor.  (Which is why I needed
419  *      the above interceptors changes - a typical URL is
420  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
421  *      The previous mechanism would not have intercepted that, and
422  *      if it had been intercepted then it then it would have replaced
423  *      it with an image.)
424  *
425  *    Revision 1.12  2001/05/27 22:17:04  oes
426  *
427  *    - re_process_buffer no longer writes the modified buffer
428  *      to the client, which was very ugly. It now returns the
429  *      buffer, which it is then written by chat.
430  *
431  *    - content_length now adjusts the Content-Length: header
432  *      for modified documents rather than crunch()ing it.
433  *      (Length info in csp->content_length, which is 0 for
434  *      unmodified documents)
435  *
436  *    - For this to work, sed() is called twice when filtering.
437  *
438  *    Revision 1.11  2001/05/26 17:27:53  jongfoster
439  *    Added support for CLF and fixed LOG_LEVEL_LOG.
440  *    Also did CRLF->LF fix of my previous patch.
441  *
442  *    Revision 1.10  2001/05/26 15:26:15  jongfoster
443  *    ACL feature now provides more security by immediately dropping
444  *    connections from untrusted hosts.
445  *
446  *    Revision 1.9  2001/05/26 00:28:36  jongfoster
447  *    Automatic reloading of config file.
448  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
449  *    Most of the global variables have been moved to a new
450  *    struct configuration_spec, accessed through csp->config->globalname
451  *    Most of the globals remaining are used by the Win32 GUI.
452  *
453  *    Revision 1.8  2001/05/25 22:43:18  jongfoster
454  *    Fixing minor memory leak and buffer overflow.
455  *
456  *    Revision 1.7  2001/05/25 22:34:30  jongfoster
457  *    Hard tabs->Spaces
458  *
459  *    Revision 1.6  2001/05/23 00:13:58  joergs
460  *    AmigaOS support fixed.
461  *
462  *    Revision 1.5  2001/05/22 18:46:04  oes
463  *
464  *    - Enabled filtering banners by size rather than URL
465  *      by adding patterns that replace all standard banner
466  *      sizes with the "Junkbuster" gif to the re_filterfile
467  *
468  *    - Enabled filtering WebBugs by providing a pattern
469  *      which kills all 1x1 images
470  *
471  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
472  *      which is selected by the (nonstandard and therefore
473  *      capital) letter 'U' in the option string.
474  *      It causes the quantifiers to be ungreedy by default.
475  *      Appending a ? turns back to greedy (!).
476  *
477  *    - Added a new interceptor ijb-send-banner, which
478  *      sends back the "Junkbuster" gif. Without imagelist or
479  *      MSIE detection support, or if tinygif = 1, or the
480  *      URL isn't recognized as an imageurl, a lame HTML
481  *      explanation is sent instead.
482  *
483  *    - Added new feature, which permits blocking remote
484  *      script redirects and firing back a local redirect
485  *      to the browser.
486  *      The feature is conditionally compiled, i.e. it
487  *      can be disabled with --disable-fast-redirects,
488  *      plus it must be activated by a "fast-redirects"
489  *      line in the config file, has its own log level
490  *      and of course wants to be displayed by show-proxy-args
491  *      Note: Boy, all the #ifdefs in 1001 locations and
492  *      all the fumbling with configure.in and acconfig.h
493  *      were *way* more work than the feature itself :-(
494  *
495  *    - Because a generic redirect template was needed for
496  *      this, tinygif = 3 now uses the same.
497  *
498  *    - Moved GIFs, and other static HTTP response templates
499  *      to project.h
500  *
501  *    - Some minor fixes
502  *
503  *    - Removed some >400 CRs again (Jon, you really worked
504  *      a lot! ;-)
505  *
506  *    Revision 1.4  2001/05/21 19:34:01  jongfoster
507  *    Made failure to bind() a fatal error.
508  *
509  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
510  *    Version 2.9.4 checkin.
511  *    - Merged popupfile and cookiefile, and added control over PCRS
512  *      filtering, in new "permissionsfile".
513  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
514  *      file error you now get a message box (in the Win32 GUI) rather
515  *      than the program exiting with no explanation.
516  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
517  *      skipping.
518  *    - Removed tabs from "config"
519  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
520  *    - Bumped up version number.
521  *
522  *    Revision 1.2  2001/05/17 22:34:44  oes
523  *     - Added hint on GIF char array generation to jcc.c
524  *     - Cleaned CRLF's from the sources and related files
525  *     - Repaired logging for REF and FRC
526  *
527  *    Revision 1.1.1.1  2001/05/15 13:58:56  oes
528  *    Initial import of version 2.9.3 source tree
529  *
530  *
531  *********************************************************************/
532 \f
533
534 #include "config.h"
535
536 #include <stdio.h>
537 #include <sys/types.h>
538 #include <stdlib.h>
539 #include <string.h>
540 #include <signal.h>
541 #include <fcntl.h>
542 #include <errno.h>
543
544 #ifdef FEATURE_PTHREAD
545 #include <pthread.h>
546 #endif /* def FEATURE_PTHREAD */
547
548 #ifdef _WIN32
549 # ifndef FEATURE_PTHREAD
550 #  ifndef STRICT
551 #   define STRICT
552 #  endif
553 #  include <windows.h>
554 #  include <process.h>
555 # endif /* ndef FEATURE_PTHREAD */
556
557 # include "win32.h"
558 # ifndef _WIN_CONSOLE
559 #  include "w32log.h"
560 # endif /* ndef _WIN_CONSOLE */
561
562 #else /* ifndef _WIN32 */
563
564 # if !defined (__OS2__)
565 # include <unistd.h>
566 # include <sys/wait.h>
567 # endif /* ndef __OS2__ */
568 # include <sys/time.h>
569 # include <sys/stat.h>
570 # include <sys/ioctl.h>
571
572 #ifdef sun
573 #include <sys/termios.h>
574 #endif /* sun */
575
576 #ifdef unix
577 #include <pwd.h>
578 #include <grp.h>
579 #endif
580
581 # include <signal.h>
582
583 # ifdef __BEOS__
584 #  include <socket.h>  /* BeOS has select() for sockets only. */
585 #  include <OS.h>      /* declarations for threads and stuff. */
586 # endif
587
588 # if defined(__EMX__) || defined(__OS2__)
589 #  include <sys/select.h>  /* OS/2/EMX needs a little help with select */
590 # endif
591 # ifdef __OS2__
592 #define INCL_DOS
593 # include <os2.h>
594 #define bzero(B,N) memset(B,0x00,n)
595 # endif
596
597 # ifndef FD_ZERO
598 #  include <select.h>
599 # endif
600
601 #endif
602
603 #include "project.h"
604 #include "list.h"
605 #include "jcc.h"
606 #include "filters.h"
607 #include "loaders.h"
608 #include "parsers.h"
609 #include "killpopup.h"
610 #include "miscutil.h"
611 #include "errlog.h"
612 #include "jbsockets.h"
613 #include "gateway.h"
614 #include "actions.h"
615 #include "cgi.h"
616 #include "loadcfg.h"
617 #include "urlmatch.h"
618
619 const char jcc_h_rcs[] = JCC_H_VERSION;
620 const char project_h_rcs[] = PROJECT_H_VERSION;
621
622 int no_daemon = 0;
623 struct client_state  clients[1];
624 struct file_list     files[1];
625
626 #ifdef FEATURE_STATISTICS
627 int urls_read     = 0;     /* total nr of urls read inc rejected */
628 int urls_rejected = 0;     /* total nr of urls rejected */
629 #endif /* def FEATURE_STATISTICS */
630
631 #ifdef FEATURE_GRACEFUL_TERMINATION
632 int g_terminate = 0;
633 #endif
634
635 static void listen_loop(void);
636 static void chat(struct client_state *csp);
637 static jb_err relay_server_traffic( struct client_state *csp ) ;
638 static jb_err read_client_headers( struct client_state *csp, struct http_request *http ) ;
639 static jb_err process_client_headers( struct client_state *csp, struct http_request *http ) ;
640 static jb_err intercept_page( struct client_state *csp, struct http_request *http );
641 static jb_err open_forwarding_connection( struct client_state *csp );
642 static jb_err send_client_headers_to_server( struct client_state *csp, struct http_request *http,  char* hdr );
643 static jb_err is_connect_request_allowed( struct client_state *csp ) ;
644
645
646 #ifdef AMIGA
647 void serve(struct client_state *csp);
648 #else /* ifndef AMIGA */
649 static void serve(struct client_state *csp);
650 #endif /* def AMIGA */
651
652 #ifdef __BEOS__
653 static int32 server_thread(void *data);
654 #endif /* def __BEOS__ */
655
656 #ifdef _WIN32
657 #define sleep(N)  Sleep(((N) * 1000))
658 #endif
659
660 #ifdef __OS2__
661 #define sleep(N)  DosSleep(((N) * 100))
662 #endif
663
664 #if defined(unix) || defined(__EMX__)
665 const char *basedir;
666 const char *pidfile = NULL;
667 int received_hup_signal = 0;
668 #endif /* defined unix */
669
670 /* The vanilla wafer. */
671 static const char VANILLA_WAFER[] =
672    "NOTICE=TO_WHOM_IT_MAY_CONCERN_"
673    "Do_not_send_me_any_copyrighted_information_other_than_the_"
674    "document_that_I_am_requesting_or_any_of_its_necessary_components._"
675    "In_particular_do_not_send_me_any_cookies_that_"
676    "are_subject_to_a_claim_of_copyright_by_anybody._"
677    "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_"
678    "(copyright_or_otherwise)_applying_to_any_cookie._";
679
680 /**
681  * HTTP header sent when doing HTTPS tunnelling ("CONNECT" method).
682  */
683 static const char CSUCCEED[] =
684    "HTTP/1.0 200 Connection established\n"
685    "Proxy-Agent: Privoxy/" VERSION "\r\n\r\n";
686
687
688 /**
689  * HTTP reply sent when the browser sends something unintelligible.
690  */
691 static const char CHEADER[] =
692    "HTTP/1.0 400 Invalid header received from browser\r\n\r\n";
693
694
695 /**
696  * HTTP reply sent when the browser tries to tunnel ("CONNECT") to something
697  * other than a HTTPS port (as defined by +limit-connect).
698  */
699 static const char CFORBIDDEN[] =
700    "HTTP/1.0 403 Connection not allowable\r\nX-Hint: If you read this message interactively, then you know why this happens ,-)\r\n\r\n";
701
702 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
703 /*********************************************************************
704  *
705  * Function    :  sig_handler 
706  *
707  * Description :  Signal handler for different signals.
708  *                Exit gracefully on ABRT, TERM and  INT
709  *                or set a flag that will cause the errlog
710  *                to be reopened by the main thread on HUP.
711  *
712  * Parameters  :
713  *          1  :  the_signal = the signal cause this function to call
714  *
715  * Returns     :  - 
716  *
717  *********************************************************************/
718 static void sig_handler(int the_signal)
719 {
720    switch(the_signal)
721    {
722       case SIGABRT:
723       case SIGTERM:
724       case SIGINT:
725          log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
726 #if defined(unix)
727          unlink(pidfile);
728 #endif /* unix */
729          exit(the_signal);
730          break;
731
732       case SIGHUP:
733          received_hup_signal = 1;
734          break;         
735
736       default:
737          /* 
738           * We shouldn't be here, unless we catch signals
739           * in main() that we can't handle here!
740           */
741          log_error(LOG_LEVEL_FATAL, "sig_handler: exiting on unexpected signal %d", the_signal);
742    }
743    return;
744
745 }
746 #endif
747
748
749 /*********************************************************************
750  *
751  * Function    :  chat
752  *
753  * Description :  Once a connection to the client has been accepted,
754  *                this function is called (via serve()) to handle the
755  *                main business of the communication.  When this
756  *                function returns, the caller must close the client
757  *                socket handle.
758  *
759  * Parameters  :
760  *          1  :  csp = Current client state (buffers, headers, etc...)
761  *
762  * Returns     :  void
763  *
764  *********************************************************************/
765 static void chat(struct client_state *csp)
766 {
767
768
769    char buf[BUFFER_SIZE];
770    int len; /* for buffer sizes */
771    char *hdr; 
772    fd_set rfds;
773    int n;
774    jb_socket maxfd;
775    int byte_count = 0;
776    struct http_request *http;
777
778    http = csp->http;
779
780    if (read_client_headers(csp, http ) != JB_ERR_OK )
781       return;
782    
783
784    /* Process the client headers */
785    if (process_client_headers(csp, http) != JB_ERR_OK)
786       return;
787    
788
789    /* Check if this connection request is permitted */
790    if (is_connect_request_allowed(csp) != JB_ERR_OK)
791       return ;
792
793    /*
794     * We have a valid and legit request. Now, check to see if we need to
795     * intercept it.
796     */
797    if (intercept_page(csp, http) != JB_ERR_OK)
798       return;
799   
800    /* 
801     * The page passed the intercept routine, so open a forwarding
802     * connection for conversation
803     */
804    if (open_forwarding_connection(csp) != JB_ERR_OK )
805       return ;
806
807
808
809    hdr = sed(client_patterns, add_client_headers, csp);
810    if (hdr == NULL)
811    {
812       /* FIXME Should handle error properly */
813       log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
814    }
815
816    /* FIXME - where should this go, logically ? */
817    list_remove_all(csp->headers);
818
819
820    if (send_client_headers_to_server(csp, http, hdr) != JB_ERR_OK)
821       return ;
822
823
824    /* we're finished with the client's header */
825    freez(hdr);
826
827    maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
828
829    /* pass data between the client and server
830     * until one or the other shuts down the connection.
831     */
832
833    /* Set the flag for reading headers to False */
834    /* This is used in relay_server_traffic */
835    csp->all_headers_read = 0 ;
836
837    for (;;)
838    {
839       jb_err tmp_ret_val = JB_ERR_GENERIC ;
840
841 #ifdef __OS2__
842       /*
843        * FD_ZERO here seems to point to an errant macro which crashes.
844        * So do this by hand for now...
845        */
846       memset(&rfds,0x00,sizeof(fd_set));
847 #else
848       FD_ZERO(&rfds);
849 #endif
850       FD_SET(csp->cfd, &rfds);
851       FD_SET(csp->sfd, &rfds);
852
853       n = select((int)maxfd+1, &rfds, NULL, NULL, NULL);
854
855       if (n < 0)
856       {
857          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
858          return;
859       }
860
861       /*
862        * This is the body of the browser's request.
863        * Just read it and write it.
864        */
865
866       if (FD_ISSET(csp->cfd, &rfds))
867       {
868          len = read_socket(csp->cfd, buf, sizeof(buf));
869
870          if (len <= 0)
871          {
872             log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
873              csp->ip_addr_str, http->ocmd, byte_count);
874             return ;
875          }
876
877          if (write_socket(csp->sfd, buf, (size_t)len))
878          {
879             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
880             return;
881          }
882          continue;
883       }
884
885       /*
886        * Check if the server wants to talk, and if so, converse.
887        */
888
889       if (FD_ISSET(csp->sfd, &rfds))
890          tmp_ret_val = relay_server_traffic(csp) ;
891
892
893       if (tmp_ret_val == JB_ERR_OK)
894          continue ;
895       else
896          return; 
897    }
898    /* We should never get here! */
899    log_error(LOG_LEVEL_FATAL, "chat() : logic error in for() loop" ) ;
900 } /* END chat() */
901
902
903 /*********************************************************************
904  *
905  * Function    :  serve
906  *
907  * Description :  This is little more than chat.  We only "serve" to
908  *                to close any socket that chat may have opened.
909  *
910  * Parameters  :
911  *          1  :  csp = Current client state (buffers, headers, etc...)
912  *
913  * Returns     :  N/A
914  *
915  *********************************************************************/
916 #ifdef AMIGA
917 void serve(struct client_state *csp)
918 #else /* ifndef AMIGA */
919 static void serve(struct client_state *csp)
920 #endif /* def AMIGA */
921 {
922    chat(csp);
923    close_socket(csp->cfd);
924
925    if (csp->sfd != JB_INVALID_SOCKET)
926    {
927       close_socket(csp->sfd);
928    }
929
930    csp->flags &= ~CSP_FLAG_ACTIVE;
931
932 }
933
934
935 #ifdef __BEOS__
936 /*********************************************************************
937  *
938  * Function    :  server_thread
939  *
940  * Description :  We only exist to call `serve' in a threaded environment.
941  *
942  * Parameters  :
943  *          1  :  data = Current client state (buffers, headers, etc...)
944  *
945  * Returns     :  Always 0.
946  *
947  *********************************************************************/
948 static int32 server_thread(void *data)
949 {
950    serve((struct client_state *) data);
951    return 0;
952
953 }
954 #endif
955
956
957 /*********************************************************************
958  *
959  * Function    :  usage
960  *
961  * Description :  Print usage info & exit.
962  *
963  * Parameters  :  Pointer to argv[0] for identifying ourselves
964  *
965  * Returns     :  No. ,-)
966  *
967  *********************************************************************/
968 void usage(const char *myname)
969 {
970    printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
971            "Usage: %s [--help] [--version] [--no-daemon] [--pidfile pidfile] [--user user[.group]] [configfile]\n"
972            "Aborting.\n", myname);
973  
974    exit(2);
975
976 }
977
978
979 /*********************************************************************
980  *
981  * Function    :  main
982  *
983  * Description :  Load the config file and start the listen loop.
984  *                This function is a lot more *sane* with the `load_config'
985  *                and `listen_loop' functions; although it stills does
986  *                a *little* too much for my taste.
987  *
988  * Parameters  :
989  *          1  :  argc = Number of parameters (including $0).
990  *          2  :  argv = Array of (char *)'s to the parameters.
991  *
992  * Returns     :  1 if : can't open config file, unrecognized directive,
993  *                stats requested in multi-thread mode, can't open the
994  *                log file, can't open the jar file, listen port is invalid,
995  *                any load fails, and can't bind port.
996  *
997  *                Else main never returns, the process must be signaled
998  *                to terminate execution.  Or, on Windows, use the
999  *                "File", "Exit" menu option.
1000  *
1001  *********************************************************************/
1002 #ifdef __MINGW32__
1003 int real_main(int argc, const char *argv[])
1004 #else
1005 int main(int argc, const char *argv[])
1006 #endif
1007 {
1008    int argc_pos = 0;
1009 #ifdef unix
1010    struct passwd *pw = NULL;
1011    struct group *grp = NULL;
1012    char *p;
1013 #endif
1014
1015    Argc = argc;
1016    Argv = argv;
1017
1018    configfile =
1019 #if !defined(_WIN32)
1020    "config"
1021 #else
1022    "config.txt"
1023 #endif
1024       ;
1025
1026    /*
1027     * Parse the command line arguments
1028     */
1029    while (++argc_pos < argc)
1030    {
1031 #if !defined(_WIN32) || defined(_WIN_CONSOLE)
1032
1033       if (strcmp(argv[argc_pos], "--help") == 0)
1034       {
1035          usage(argv[0]);
1036       }
1037
1038       else if(strcmp(argv[argc_pos], "--version") == 0)
1039       {
1040          printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
1041          exit(0);
1042       }
1043
1044       else if (strcmp(argv[argc_pos], "--no-daemon" ) == 0)
1045       {
1046          no_daemon = 1;
1047       }
1048 #if defined(unix)
1049       else if (strcmp(argv[argc_pos], "--pidfile" ) == 0)
1050       {
1051          if (++argc_pos == argc) usage(argv[0]);
1052          pidfile = strdup(argv[argc_pos]);
1053       }
1054
1055       else if (strcmp(argv[argc_pos], "--user" ) == 0)
1056       {
1057          if (++argc_pos == argc) usage(argv[argc_pos]);
1058
1059          if ((NULL != (p = strchr(argv[argc_pos], '.'))) && *(p + 1) != '0')
1060          {
1061             *p++ = '\0';
1062             if (NULL == (grp = getgrnam(p)))
1063             {
1064                log_error(LOG_LEVEL_FATAL, "Group %s not found.", p);
1065             }
1066          }
1067
1068          if (NULL == (pw = getpwnam(argv[argc_pos])))
1069          {
1070             log_error(LOG_LEVEL_FATAL, "User %s not found.", argv[argc_pos]);
1071          }
1072
1073          if (p != NULL) *--p = '\0';
1074       }
1075 #endif /* defined(unix) */
1076       else
1077 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
1078       {
1079          configfile = argv[argc_pos];
1080       }
1081
1082    } /* -END- while (more arguments) */
1083
1084 #if defined(unix)
1085    if ( *configfile != '/' )
1086    {
1087       char *abs_file;
1088
1089       /* make config-filename absolute here */
1090       if ( !(basedir = getcwd( NULL, 1024 )))
1091       {
1092          perror("get working dir failed");
1093          exit( 1 );
1094       }
1095
1096       if ( !(abs_file = malloc( strlen( basedir ) + strlen( configfile ) + 5 )))
1097       {
1098          perror("malloc failed");
1099          exit( 1 );
1100       }
1101       strcpy( abs_file, basedir );
1102       strcat( abs_file, "/" );
1103       strcat( abs_file, configfile );
1104       configfile = abs_file;
1105    }
1106 #endif /* defined unix */
1107
1108
1109    files->next = NULL;
1110
1111 #ifdef AMIGA
1112    InitAmiga();
1113 #elif defined(_WIN32)
1114    InitWin32();
1115 #endif
1116
1117    /*
1118     * Unix signal handling
1119     *
1120     * Catch the abort, interrupt and terminate signals for a graceful exit
1121     * Catch the hangup signal so the errlog can be reopened.
1122     * Ignore the broken pipe and child signals
1123     *  FIXME: Isn't ignoring the default for SIGCHLD anyway and why ignore SIGPIPE? 
1124     */
1125 #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
1126 {
1127    int idx;
1128    const int catched_signals[] = { SIGABRT, SIGTERM, SIGINT, SIGHUP, 0 };
1129    const int ignored_signals[] = { SIGPIPE, SIGCHLD, 0 };
1130
1131    for (idx = 0; catched_signals[idx] != 0; idx++)
1132    {
1133       if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
1134       {
1135          log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
1136       }
1137    }
1138
1139    for (idx = 0; ignored_signals[idx] != 0; idx++)
1140    {
1141       if (signal(ignored_signals[idx], SIG_IGN) == SIG_ERR)
1142       {
1143          log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for signal %d: %E", ignored_signals[idx]);
1144       }
1145    }
1146
1147 }
1148 #else /* ifdef _WIN32 */
1149 # ifdef _WIN_CONSOLE
1150    /*
1151     * We *are* in a windows console app.
1152     * Print a verbose messages about FAQ's and such
1153     */
1154    printf(win32_blurb);
1155 # endif /* def _WIN_CONSOLE */
1156 #endif /* def _WIN32 */
1157
1158
1159    /* Initialize the CGI subsystem */
1160    cgi_init_error_messages();
1161
1162    /*
1163     * If runnig on unix and without the --nodaemon
1164     * option, become a daemon. I.e. fork, detach
1165     * from tty and get process group leadership
1166     */
1167 #if defined(unix)
1168    {
1169       pid_t pid = 0;
1170 #if 0
1171       int   fd;
1172 #endif
1173
1174       if (!no_daemon)
1175       {
1176          pid  = fork();
1177
1178          if ( pid < 0 ) /* error */
1179          {
1180             perror("fork");
1181             exit( 3 );
1182          }
1183          else if ( pid != 0 ) /* parent */
1184          {
1185             int status;
1186             pid_t wpid;
1187             /*
1188              * must check for errors
1189              * child died due to missing files aso
1190              */
1191             sleep( 1 );
1192             wpid = waitpid( pid, &status, WNOHANG );
1193             if ( wpid != 0 )
1194             {
1195                exit( 1 );
1196             }
1197             exit( 0 );
1198          }
1199          /* child */
1200 #if 1
1201          /* Should be more portable, but not as well tested */
1202          setsid();
1203 #else /* !1 */
1204 #ifdef __FreeBSD__
1205          setpgrp(0,0);
1206 #else /* ndef __FreeBSD__ */
1207          setpgrp();
1208 #endif /* ndef __FreeBSD__ */
1209          fd = open("/dev/tty", O_RDONLY);
1210          if ( fd )
1211          {
1212             /* no error check here */
1213             ioctl( fd, TIOCNOTTY,0 );
1214             close ( fd );
1215          }
1216 #endif /* 1 */
1217          /* FIXME: should close stderr (fd 2) here too, but the test
1218           * for existence
1219           * and load config file is done in listen_loop() and puts
1220           * some messages on stderr there.
1221           */
1222
1223          close( 0 );
1224          close( 1 );
1225          chdir("/");
1226
1227       } /* -END- if (!no_daemon) */
1228
1229       /*
1230        * As soon as we have written the PID file, we can switch
1231        * to the user and group ID indicated by the --user option
1232        */
1233       write_pid_file();
1234    
1235       if (NULL != pw)
1236       {
1237          if (((NULL != grp) && setgid(grp->gr_gid)) || (setgid(pw->pw_gid)))
1238          {
1239             log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
1240          }
1241          if (setuid(pw->pw_uid))
1242          {
1243             log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
1244          }
1245       }
1246    }
1247 #endif /* defined unix */
1248
1249    listen_loop();
1250
1251    /* NOTREACHED */
1252    return(-1);
1253
1254 }
1255
1256
1257 /*********************************************************************
1258  *
1259  * Function    :  bind_port_helper
1260  *
1261  * Description :  Bind the listen port.  Handles logging, and aborts
1262  *                on failure.
1263  *
1264  * Parameters  :
1265  *          1  :  config = Privoxy configuration.  Specifies port
1266  *                         to bind to.
1267  *
1268  * Returns     :  Port that was opened.
1269  *
1270  *********************************************************************/
1271 static jb_socket bind_port_helper(struct configuration_spec * config)
1272 {
1273    int result;
1274    jb_socket bfd;
1275
1276    if ( (config->haddr != NULL)
1277      && (config->haddr[0] == '1')
1278      && (config->haddr[1] == '2')
1279      && (config->haddr[2] == '7')
1280      && (config->haddr[3] == '.') )
1281    {
1282       log_error(LOG_LEVEL_INFO, "Listening on port %d for local connections only",
1283                 config->hport);
1284    }
1285    else if (config->haddr == NULL)
1286    {
1287       log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
1288                 config->hport);
1289    }
1290    else
1291    {
1292       log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
1293                 config->hport, config->haddr);
1294    }
1295
1296    result = bind_port(config->haddr, config->hport, &bfd);
1297
1298    if (result < 0)
1299    {
1300       switch(result)
1301       {
1302          case -3 :
1303             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: "
1304                "There may be another Privoxy or some other "
1305                "proxy running on port %d",
1306                (NULL != config->haddr) ? config->haddr : "INADDR_ANY",
1307                       config->hport, config->hport);
1308
1309          case -2 :
1310             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: " 
1311                "The hostname is not resolvable",
1312                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
1313
1314          default :
1315             log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E",
1316                (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport);
1317       }
1318
1319       /* shouldn't get here */
1320       return JB_INVALID_SOCKET;
1321    }
1322
1323    config->need_bind = 0;
1324
1325    return bfd;
1326 }
1327
1328
1329 /*********************************************************************
1330  *
1331  * Function    :  listen_loop
1332  *
1333  * Description :  bind the listen port and enter a "FOREVER" listening loop.
1334  *
1335  * Parameters  :  N/A
1336  *
1337  * Returns     :  Never.
1338  *
1339  *********************************************************************/
1340 static void listen_loop(void)
1341 {
1342    struct client_state *csp = NULL;
1343    jb_socket bfd;
1344    struct configuration_spec * config;
1345
1346    config = load_config();
1347
1348    bfd = bind_port_helper(config);
1349
1350 #ifdef FEATURE_GRACEFUL_TERMINATION
1351    while (!g_terminate)
1352 #else
1353    for (;;)
1354 #endif
1355    {
1356 #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
1357       while (waitpid(-1, NULL, WNOHANG) > 0)
1358       {
1359          /* zombie children */
1360       }
1361 #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
1362
1363       /*
1364        * Free data that was used by died threads
1365        */
1366       sweep();
1367
1368 #if defined(unix)
1369       /*
1370        * Re-open the errlog after HUP signal
1371        */
1372       if (received_hup_signal)
1373       {
1374          init_error_log(Argv[0], config->logfile, config->debug);
1375          received_hup_signal = 0;
1376       }
1377 #endif
1378
1379 #ifdef __OS2__
1380 #ifdef FEATURE_COOKIE_JAR
1381       /*
1382        * Need a workaround here: we have to fclose() the jarfile, or we die because it's
1383        * already open.  I think unload_configfile() is not being run, which should do
1384        * this work.  Until that can get resolved, we'll use this workaround.
1385        *
1386        * [Note from Jon: We don't unload_configfile() until all existing threads have
1387        * exited - they're likely to hang aroung transferring data to the browser.]
1388        */
1389        if (csp)
1390          if(csp->config)
1391            if (csp->config->jar)
1392            {
1393              fclose(csp->config->jar);
1394              csp->config->jar = NULL;
1395            }
1396 #endif /* FEATURE_COOKIE_JAR */
1397 #endif /* __OS2__ */
1398
1399       if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) )
1400       {
1401          log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp));
1402          continue;
1403       }
1404
1405       csp->flags |= CSP_FLAG_ACTIVE;
1406       csp->sfd    = JB_INVALID_SOCKET;
1407
1408       csp->config = config = load_config();
1409
1410       if ( config->need_bind )
1411       {
1412          /*
1413           * Since we were listening to the "old port", we will not see
1414           * a "listen" param change until the next IJB request.  So, at
1415           * least 1 more request must be made for us to find the new
1416           * setting.  I am simply closing the old socket and binding the
1417           * new one.
1418           *
1419           * Which-ever is correct, we will serve 1 more page via the
1420           * old settings.  This should probably be a "show-proxy-args"
1421           * request.  This should not be a so common of an operation
1422           * that this will hurt people's feelings.
1423           */
1424
1425          close_socket(bfd);
1426
1427          bfd = bind_port_helper(config);
1428       }
1429
1430       log_error(LOG_LEVEL_CONNECT, "accept connection ... ");
1431
1432       if (!accept_connection(csp, bfd))
1433       {
1434          log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
1435
1436 #ifdef AMIGA
1437          if(!childs)
1438          {
1439             exit(1);
1440          }
1441 #endif
1442          freez(csp);
1443          continue;
1444       }
1445       else
1446       {
1447          log_error(LOG_LEVEL_CONNECT, "OK");
1448       }
1449
1450 #ifdef FEATURE_TOGGLE
1451       if (g_bToggleIJB)
1452       {
1453          csp->flags |= CSP_FLAG_TOGGLED_ON;
1454       }
1455 #endif /* def FEATURE_TOGGLE */
1456
1457       if (run_loader(csp))
1458       {
1459          log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
1460          /* Never get here - LOG_LEVEL_FATAL causes program exit */
1461       }
1462
1463 #ifdef FEATURE_ACL
1464       if (block_acl(NULL,csp))
1465       {
1466          log_error(LOG_LEVEL_CONNECT, "Connection dropped due to ACL");
1467          close_socket(csp->cfd);
1468          freez(csp);
1469          continue;
1470       }
1471 #endif /* def FEATURE_ACL */
1472
1473       /* add it to the list of clients */
1474       csp->next = clients->next;
1475       clients->next = csp;
1476
1477       if (config->multi_threaded)
1478       {
1479          int child_id;
1480
1481 /* this is a switch () statment in the C preprocessor - ugh */
1482 #undef SELECTED_ONE_OPTION
1483
1484 /* Use Pthreads in preference to native code */
1485 #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
1486 #define SELECTED_ONE_OPTION
1487          {
1488             pthread_t the_thread;
1489             pthread_attr_t attrs;
1490
1491             pthread_attr_init(&attrs);
1492             pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
1493             child_id = (pthread_create(&the_thread, &attrs,
1494                (void*)serve, csp) ? -1 : 0);
1495             pthread_attr_destroy(&attrs);
1496          }
1497 #endif
1498
1499 #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
1500 #define SELECTED_ONE_OPTION
1501          child_id = _beginthread(
1502             (void (*)(void *))serve,
1503             64 * 1024,
1504             csp);
1505 #endif
1506
1507 #if defined(__OS2__) && !defined(SELECTED_ONE_OPTION)
1508 #define SELECTED_ONE_OPTION
1509          child_id = _beginthread(
1510             (void(* _Optlink)(void*))serve,
1511             NULL,
1512             64 * 1024,
1513             csp);
1514 #endif
1515
1516 #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
1517 #define SELECTED_ONE_OPTION
1518          {
1519             thread_id tid = spawn_thread
1520                (server_thread, "server", B_NORMAL_PRIORITY, csp);
1521
1522             if ((tid >= 0) && (resume_thread(tid) == B_OK))
1523             {
1524                child_id = (int) tid;
1525             }
1526             else
1527             {
1528                child_id = -1;
1529             }
1530          }
1531 #endif
1532
1533 #if defined(AMIGA) && !defined(SELECTED_ONE_OPTION)
1534 #define SELECTED_ONE_OPTION
1535          csp->cfd = ReleaseSocket(csp->cfd, -1);
1536          if((child_id = (int)CreateNewProcTags(
1537             NP_Entry, (ULONG)server_thread,
1538             NP_Output, Output(),
1539             NP_CloseOutput, FALSE,
1540             NP_Name, (ULONG)"privoxy child",
1541             NP_StackSize, 200*1024,
1542             TAG_DONE)))
1543          {
1544             childs++;
1545             ((struct Task *)child_id)->tc_UserData = csp;
1546             Signal((struct Task *)child_id, SIGF_SINGLE);
1547             Wait(SIGF_SINGLE);
1548          }
1549 #endif
1550
1551 #if !defined(SELECTED_ONE_OPTION)
1552          child_id = fork();
1553
1554          /* This block is only needed when using fork().
1555           * When using threads, the server thread was
1556           * created and run by the call to _beginthread().
1557           */
1558          if (child_id == 0)   /* child */
1559          {
1560             serve(csp);
1561             _exit(0);
1562
1563          }
1564          else if (child_id > 0) /* parent */
1565          {
1566             /* in a fork()'d environment, the parent's
1567              * copy of the client socket and the CSP
1568              * are not used.
1569              */
1570
1571 #if !defined(_WIN32) && defined(__CYGWIN__)
1572             wait( NULL );
1573 #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
1574             close_socket(csp->cfd);
1575             csp->flags &= ~CSP_FLAG_ACTIVE;
1576          }
1577 #endif
1578
1579 #undef SELECTED_ONE_OPTION
1580 /* end of cpp switch () */
1581
1582          if (child_id < 0) /* failed */
1583          {
1584             char buf[BUFFER_SIZE];
1585
1586             log_error(LOG_LEVEL_ERROR, "can't fork: %E");
1587
1588             sprintf(buf , "Privoxy: can't fork: errno = %d", errno);
1589
1590             write_socket(csp->cfd, buf, strlen(buf));
1591             close_socket(csp->cfd);
1592             csp->flags &= ~CSP_FLAG_ACTIVE;
1593             sleep(5);
1594             continue;
1595          }
1596       }
1597       else
1598       {
1599          serve(csp);
1600       }
1601    }
1602
1603    /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
1604
1605    /* Clean up.  Aim: free all memory (no leaks) */
1606 #ifdef FEATURE_GRACEFUL_TERMINATION
1607
1608    log_error(LOG_LEVEL_ERROR, "Graceful termination requested");
1609
1610    unload_current_config_file();
1611    unload_current_actions_file();
1612    unload_current_re_filterfile();
1613 #ifdef FEATURE_TRUST
1614    unload_current_trust_file();
1615 #endif
1616
1617    if (config->multi_threaded)
1618    {
1619       int i = 60;
1620       do
1621       {
1622          sleep(1);
1623          sweep();
1624       } while ((clients->next != NULL) && (--i > 0));
1625
1626       if (i <= 0)
1627       {
1628          log_error(LOG_LEVEL_ERROR, "Graceful termination failed - still some live clients after 1 minute wait.");
1629       }
1630    }
1631    sweep();
1632    sweep();
1633
1634 #if defined(unix)
1635    free(basedir);
1636 #endif
1637 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
1638    /* Cleanup - remove taskbar icon etc. */
1639    TermLogWindow();
1640 #endif
1641
1642    exit(0);
1643 #endif /* FEATURE_GRACEFUL_TERMINATION */
1644
1645 }
1646
1647 /*********************************************************************
1648  *
1649  * Function    :  relay_server_traffic
1650  *
1651  * Description :  receive traffic from the server and relay it
1652  *                to the client, with some processing
1653  *
1654  * Parameters  :
1655  *          1  :  client_state structure
1656  *                         
1657  *
1658  * Returns     :  JB_ERR_OK if there may be more work
1659  *             :  other values for errors
1660  *
1661  **********************************************************************/
1662
1663 static jb_err relay_server_traffic( struct client_state *csp )
1664 {
1665 #ifdef FEATURE_KILL_POPUPS
1666    int block_popups;         /* bool, 1==will block popups */
1667    int block_popups_now = 0; /* bool, 1==currently blocking popups */
1668 #endif /* def FEATURE_KILL_POPUPS */
1669    
1670    char buf[BUFFER_SIZE];
1671    int len; /* for buffer sizes */
1672    int ms_iis5_hack = 0;
1673    int byte_count = 0;
1674    char *hdr;
1675    char *p;
1676
1677    /* Skeleton for HTTP response, if we should intercept the request */
1678    struct http_response *rsp;
1679
1680    int pcrs_filter;        /* bool, 1==will filter through pcrs */
1681    int gif_deanimate;      /* bool, 1==will deanimate gifs */
1682
1683 #ifdef FEATURE_KILL_POPUPS
1684    block_popups               = ((csp->action->flags & ACTION_NO_POPUPS) != 0);
1685 #endif /* def FEATURE_KILL_POPUPS */
1686
1687    pcrs_filter                = (csp->rlist != NULL) &&  /* There are expressions to be used */
1688                                 (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER]));
1689
1690    gif_deanimate              = ((csp->action->flags & ACTION_DEANIMATE) != 0);
1691
1692
1693    fflush (0);
1694    len = read_socket (csp->sfd, buf, sizeof (buf) - 1);
1695
1696    if (len < 0)
1697    {
1698       log_error (LOG_LEVEL_ERROR, "read from: %s failed: %E", csp->http->host);
1699
1700       log_error (LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
1701          csp->ip_addr_str, csp->http->ocmd);
1702
1703       rsp = error_response (csp, "connect-failed", errno);
1704
1705       if (rsp)
1706       {
1707          if (write_socket (csp->cfd, rsp->head, rsp->head_length)
1708             || write_socket (csp->cfd, rsp->body, rsp->content_length))
1709          {
1710             log_error (LOG_LEVEL_ERROR, "write to: %s failed: %E",
1711                        csp->http->host);
1712          }
1713       }
1714
1715       free_http_response (rsp);
1716       return JB_ERR_GENERIC;
1717    }
1718
1719    /* Add a trailing zero.  This lets filter_popups
1720     * use string operations.
1721     */
1722    buf[len] = '\0';
1723
1724 #ifdef FEATURE_KILL_POPUPS
1725    /* Filter the popups on this read. */
1726    if (block_popups_now)
1727    {
1728       filter_popups (buf, csp);
1729    }
1730 #endif /* def FEATURE_KILL_POPUPS */
1731
1732
1733    /* Normally, this would indicate that we've read
1734     * as much as the server has sent us and we can
1735     * close the client connection.  However, Microsoft
1736     * in its wisdom has released IIS/5 with a bug that
1737     * prevents it from sending the trailing \r\n in
1738     * a 302 redirect header (and possibly other headers).
1739     * To work around this if we've haven't parsed
1740     * a full header we'll append a trailing \r\n
1741     * and see if this now generates a valid one.
1742     *
1743     * This hack shouldn't have any impacts.  If we've
1744     * already transmitted the header or if this is a
1745     * SSL connection, then we won't bother with this
1746     * hack.  So we only work on partially received
1747     * headers.  If we append a \r\n and this still
1748     * doesn't generate a valid header, then we won't
1749     * transmit anything to the client.
1750     */
1751    if (len == 0)
1752    {
1753
1754       if (csp->all_headers_read || csp->http->ssl)
1755       {
1756          /*
1757           * If we have been buffering up the document,
1758           * now is the time to apply content modification
1759           * and send the result to the client.
1760           */
1761          if (csp->content_filter)
1762          {
1763             /*
1764              * If the content filter fails, use the original
1765              * buffer and length.
1766              * (see p != NULL ? p : csp->iob->cur below)
1767              */
1768             if (NULL == (p = (*csp->content_filter) (csp)))
1769             {
1770                csp->content_length = csp->iob->eod - csp->iob->cur;
1771             }
1772
1773             hdr = sed (server_patterns, add_server_headers, csp);
1774             if (hdr == NULL)
1775             {
1776                /* FIXME Should handle error properly */
1777                log_error (LOG_LEVEL_FATAL,
1778                   "Out of memory parsing server header");
1779
1780             }
1781
1782             if (write_socket (csp->cfd, hdr, strlen (hdr))
1783                || write_socket (csp->cfd, p != NULL ? p : csp->iob->cur,
1784                           csp->content_length))
1785             {
1786                log_error (LOG_LEVEL_ERROR,
1787                   "write modified content to client failed: %E");
1788                return JB_ERR_GENERIC;
1789             }
1790
1791             freez (hdr);
1792             if (NULL != p)
1793             {
1794                freez (p);
1795             }
1796          }
1797          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
1798             csp->ip_addr_str, csp->http->ocmd, byte_count);
1799          return JB_ERR_GENERIC;
1800       }
1801
1802       /*
1803        * This is NOT the body, so
1804        * Let's pretend the server just sent us a blank line.
1805        */
1806       len = sprintf (buf, "\r\n");
1807
1808       /*
1809        * Now, let the normal header parsing algorithm below do its
1810        * job.  If it fails, we'll exit instead of continuing.
1811        */
1812
1813       ms_iis5_hack = 1;
1814    }
1815
1816    /*
1817     * If this is an SSL connection or we're in the body
1818     * of the server document, just write it to the client,
1819     * unless we need to buffer the body for later content-filtering
1820     */
1821
1822    if (csp->all_headers_read || csp->http->ssl)
1823    {
1824       if (csp->content_filter)
1825       {
1826          add_to_iob (csp, buf, len);
1827
1828          /*
1829           * If the buffer limit will be reached on the next read,
1830           * switch to non-filtering mode, i.e. make & write the
1831           * header, flush the socket and get out of the way.
1832           */
1833          if (((size_t) (csp->iob->eod - csp->iob->buf)) +
1834               (size_t) BUFFER_SIZE > csp->config->buffer_limit)
1835          {
1836             size_t hdrlen;
1837
1838             log_error (LOG_LEVEL_ERROR,
1839                         "Buffer size limit reached! Flushing and stepping back.");
1840
1841             hdr = sed (server_patterns, add_server_headers, csp);
1842             if (hdr == NULL)
1843             {
1844                /* FIXME Should handle error properly */
1845                log_error (LOG_LEVEL_FATAL,
1846                   "Out of memory parsing server header");
1847             }
1848
1849             hdrlen = strlen (hdr);
1850             byte_count += hdrlen;
1851
1852             if (write_socket (csp->cfd, hdr, hdrlen)
1853                || ((len = flush_socket (csp->cfd, csp)) < 0))
1854             {
1855                log_error (LOG_LEVEL_CONNECT,
1856                   "write header to client failed: %E");
1857
1858                freez (hdr);
1859                return JB_ERR_GENERIC;
1860             }
1861
1862             freez (hdr);
1863             byte_count += len;
1864
1865             csp->content_filter = NULL;
1866             csp->all_headers_read = 1;
1867
1868          }
1869       }
1870       else
1871       {
1872          if (write_socket (csp->cfd, buf, (size_t) len))
1873          {
1874             log_error (LOG_LEVEL_ERROR, "write to client failed: %E");
1875             return JB_ERR_GENERIC;
1876          }
1877       }
1878       byte_count += len;
1879       return JB_ERR_OK ;
1880    }
1881    else
1882    {
1883       /*
1884        * we're still looking for the end of the
1885        * server's header ... (does that make header
1886        * parsing an "out of body experience" ?
1887        */
1888
1889       /* buffer up the data we just read */
1890       add_to_iob (csp, buf, len);
1891
1892       /* get header lines from the iob */
1893
1894       while ((p = get_header (csp)) != NULL)
1895       {
1896          if (*p == '\0')
1897          {
1898             /* see following note */
1899             log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %d",
1900                csp->ip_addr_str, csp->http->ocmd, byte_count);
1901             return JB_ERR_GENERIC;
1902          }
1903          enlist (csp->headers, p);
1904          freez (p);
1905       }
1906
1907       /* NOTE: there are no "empty" headers so
1908        * if the pointer `p' is not NULL we must
1909        * assume that we reached the end of the
1910        * buffer before we hit the end of the header.
1911        */
1912
1913       if (p)
1914       {
1915          if (ms_iis5_hack)
1916          {
1917             /* Well, we tried our MS IIS/5
1918              * hack and it didn't work.
1919              * The header is incomplete
1920              * and there isn't anything
1921              * we can do about it.
1922              */
1923             log_error(LOG_LEVEL_CLF, "Incomplete Server Header: %s - - [%T] \"%s\" 200 %d",
1924                 csp->ip_addr_str, csp->http->ocmd, byte_count);
1925             return JB_ERR_GENERIC;
1926          }
1927          else
1928          {
1929             /* Since we have to wait for
1930              * more from the server before
1931              * we can parse the headers
1932              * we just continue here.
1933              */
1934             return JB_ERR_OK;
1935          }
1936       }      
1937       
1938       /* we have now received the entire header.
1939        * filter it and send the result to the client
1940        */
1941
1942       hdr = sed (server_patterns, add_server_headers, csp);
1943       if (hdr == NULL)
1944       {
1945          /* FIXME Should handle error properly */
1946          log_error (LOG_LEVEL_FATAL, "Out of memory parsing server header");
1947       }
1948
1949   
1950
1951 #ifdef FEATURE_KILL_POPUPS
1952       /* Start blocking popups if appropriate. */
1953
1954       if ((csp->content_type & CT_TEXT) &&   /* It's a text / * MIME-Type */
1955           !csp->http->ssl &&                 /* We talk plaintext */
1956           block_popups)                      /* Policy allows */
1957       {
1958          block_popups_now = 1;
1959          /*
1960           * Filter the part of the body that came in the same read
1961           * as the last headers:
1962           */
1963          filter_popups (csp->iob->cur, csp);
1964       }
1965
1966 #endif /* def FEATURE_KILL_POPUPS */
1967
1968         /* Buffer and pcrs filter this if appropriate. */
1969
1970       if ((csp->content_type & CT_TEXT) &&       /* It's a text / * MIME-Type */
1971           !csp->http->ssl &&                     /* We talk plaintext */
1972           pcrs_filter)                           /* Policy allows */
1973       {
1974          csp->content_filter = pcrs_filter_response;
1975       }
1976
1977       /* Buffer and gif_deanimate this if appropriate. */
1978
1979       if ((csp->content_type & CT_GIF) &&        /* It's a image/gif MIME-Type */
1980           !csp->http->ssl &&                     /* We talk plaintext */
1981           gif_deanimate)                         /* Policy allows */
1982       {
1983          csp->content_filter = gif_deanimate_response;
1984       }
1985       /*
1986        * Only write if we're not buffering for content modification
1987        */
1988       if (!csp->content_filter)
1989       {
1990          /* write the server's (modified) header to
1991           * the client (along with anything else that
1992           * may be in the buffer)
1993           */
1994          if (write_socket (csp->cfd, hdr, strlen (hdr))
1995              || ((len = flush_socket (csp->cfd, csp)) < 0))
1996          {
1997             log_error (LOG_LEVEL_CONNECT,
1998                "write header to client failed: %E");
1999
2000             /* the write failed, so don't bother
2001              * mentioning it to the client...
2002              * it probably can't hear us anyway.
2003              */
2004             freez (hdr);
2005             return JB_ERR_GENERIC;
2006          }
2007
2008          byte_count += len;
2009       }
2010
2011       /* we're finished with the server's header */
2012
2013       freez (hdr);
2014       csp->all_headers_read = 1;
2015
2016       /* If this was a MS IIS/5 hack then it means
2017        * the server has already closed the
2018        * connection.  Nothing more to read.  Time
2019        * to bail.
2020        */
2021       if (ms_iis5_hack)
2022       {
2023          return JB_ERR_GENERIC ;
2024       }
2025    }
2026    return JB_ERR_OK ;
2027 } /* END relay_server_traffic() */
2028
2029
2030 /*********************************************************************
2031  *
2032  * Function    :  read_client_headers
2033  *
2034  * Description :  read all the client headers, and fill in the
2035  *                http* structure
2036  *
2037  * Parameters  :
2038  *          1  :  client_state structure
2039  *          2  :  http_request structure
2040  *                         
2041  *
2042  * Returns     :  JB_ERR_OK  - headers read and parsed ok
2043  *             :  other values - an error occurred.
2044  *********************************************************************/
2045
2046 static jb_err read_client_headers( struct client_state *csp, struct http_request *http )
2047 {
2048
2049    char *p;
2050    char *req;
2051    char buf[BUFFER_SIZE];
2052    int len; /* for buffer sizes */
2053
2054    /*
2055     * Read the client's request.  Note that since we're not using select() we
2056     * could get blocked here if a client connected, then didn't say anything!
2057     *
2058     * This will read all the client headers.
2059     */
2060
2061    req = NULL ;
2062    for (;;)
2063    {
2064       len = read_socket(csp->cfd, buf, sizeof(buf));
2065
2066       if (len <= 0) break;      /* error! */
2067
2068       add_to_iob(csp, buf, len);
2069
2070       req = get_header(csp);
2071
2072       if (req == NULL)
2073       {
2074          break;    /* no HTTP request! */
2075       }
2076
2077       if (*req == '\0')
2078       {
2079          continue;   /* more to come! */
2080       }
2081
2082       /* When we get here we have read one header which is enough */
2083       /* to check whether the connection is allowed */
2084       break; 
2085    }
2086
2087
2088    for(;;) 
2089    {
2090
2091      if ( ( ( p = get_header(csp) ) != NULL) && ( *p == '\0' ) )
2092       {
2093          len = read_socket(csp->cfd, buf, sizeof(buf));
2094          if (len <= 0)
2095          {
2096             log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
2097             return JB_ERR_GENERIC;
2098          }
2099          add_to_iob(csp, buf, len);
2100          continue;
2101       }
2102
2103       if (p == NULL) break;
2104
2105       enlist(csp->headers, p);
2106       freez(p);
2107
2108    }
2109
2110    parse_http_request(req, http, csp);
2111    freez(req);
2112
2113    if (http->cmd == NULL)
2114    {
2115       strcpy(buf, CHEADER);
2116       write_socket(csp->cfd, buf, strlen(buf));
2117
2118       log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 400 0", csp->ip_addr_str);
2119
2120       return JB_ERR_GENERIC;
2121    }
2122
2123    return JB_ERR_OK ;
2124
2125
2126 } /* END read_client_headers */
2127
2128
2129 /*********************************************************************
2130  *
2131  * Function    :  process_client_headers
2132  *
2133  * Description :  Process client headers
2134  * FIXME: Add description of what we do here!
2135  *
2136  * Parameters  :
2137  *          1  :  client_state structure
2138  *          2  :  http_request structure
2139  *                         
2140  *
2141  * Returns     :  JB_ERR_OK  - headers processed ok
2142  *             :  other values - an error occurred.
2143  *********************************************************************/
2144
2145 static jb_err process_client_headers( struct client_state *csp, struct http_request *http )
2146 {
2147
2148
2149 #ifdef FEATURE_FORCE_LOAD
2150       /* If this request contains the FORCE_PREFIX,
2151        * better get rid of it now and set the force flag --oes
2152        * Changed to use the http structure rather than the req field --jaa
2153        */
2154
2155       if (strstr(http->url, FORCE_PREFIX))
2156       {
2157          strclean(http->url, FORCE_PREFIX);
2158          log_error(LOG_LEVEL_FORCE, "Enforcing request \"%s\".\n", http->url);
2159          csp->flags |= CSP_FLAG_FORCED;
2160       }
2161
2162 #endif /* def FEATURE_FORCE_LOAD */
2163
2164
2165    /* decide how to route the HTTP request */
2166
2167    if ((http->fwd = forward_url(http, csp)) == NULL)
2168    {
2169       log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!?  This can't happen!");
2170       /* Never get here - LOG_LEVEL_FATAL causes program exit */
2171    }
2172
2173    /* build the http request to send to the server
2174     * we have to do one of the following:
2175     *
2176     * create = use the original HTTP request to create a new
2177     *          HTTP request that has either the path component
2178     *          without the http://domainspec (w/path) or the
2179     *          full orininal URL (w/url)
2180     *          Note that the path and/or the HTTP version may
2181     *          have been altered by now.
2182     *
2183     * connect = Open a socket to the host:port of the server
2184     *           and short-circuit server and client socket.
2185     *
2186     * pass =  Pass the request unchanged if forwarding a CONNECT
2187     *         request to a parent proxy. Note that we'll be sending
2188     *         the CFAIL message ourselves if connecting to the parent
2189     *         fails, but we won't send a CSUCCEED message if it works,
2190     *         since that would result in a double message (ours and the
2191     *         parent's). After sending the request to the parent, we simply
2192     *         tunnel.
2193     *
2194     * here's the matrix:
2195     *                        SSL
2196     *                    0        1
2197     *                +--------+--------+
2198     *                |        |        |
2199     *             0  | create | connect|
2200     *                | w/path |        |
2201     *  Forwarding    +--------+--------+
2202     *                |        |        |
2203     *             1  | create | pass   |
2204     *                | w/url  |        |
2205     *                +--------+--------+
2206     *
2207     */
2208
2209    /*
2210     * Determine the actions for this URL
2211     */
2212 #ifdef FEATURE_TOGGLE
2213    if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
2214    {
2215       /* Most compatible set of actions (i.e. none) */
2216       init_current_action(csp->action);
2217    }
2218    else
2219 #endif /* ndef FEATURE_TOGGLE */
2220    {
2221       url_actions(http, csp);
2222    }
2223
2224
2225
2226
2227
2228    /*
2229     * Downgrade http version from 1.1 to 1.0 if +downgrade
2230     * action applies
2231     */
2232    if ( (http->ssl == 0)
2233      && (!strcmpic(http->ver, "HTTP/1.1"))
2234      && (csp->action->flags & ACTION_DOWNGRADE))
2235    {
2236       freez(http->ver);
2237       http->ver = strdup("HTTP/1.0");
2238
2239       if (http->ver == NULL)
2240       {
2241          log_error(LOG_LEVEL_FATAL, "Out of memory downgrading HTTP version");
2242       }
2243    }
2244
2245    /* 
2246     * Save a copy of the original request for logging
2247     */
2248    http->ocmd = strdup(http->cmd);
2249
2250    if (http->ocmd == NULL)
2251    {
2252       log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line");
2253    }
2254
2255    /*
2256     * (Re)build the HTTP request for non-SSL requests.
2257     * If forwarding, use the whole URL, else, use only the path.
2258     */
2259    if (http->ssl == 0)
2260    {
2261       freez(http->cmd);
2262
2263       http->cmd = strdup(http->gpc);
2264       string_append(&http->cmd, " ");
2265
2266       if (http->fwd->forward_host)
2267       {
2268          string_append(&http->cmd, http->url);
2269       }
2270       else
2271       {
2272          string_append(&http->cmd, http->path);
2273       }
2274
2275       string_append(&http->cmd, " ");
2276       string_append(&http->cmd, http->ver);
2277
2278       if (http->cmd == NULL)
2279       {
2280          log_error(LOG_LEVEL_FATAL, "Out of memory rewiting SSL command");
2281       }
2282    }
2283    enlist_first(csp->headers, http->cmd);
2284
2285
2286    /*
2287     * If the user has not supplied any wafers, and the user has not
2288     * told us to suppress the vanilla wafer, then send the vanilla wafer.
2289     */
2290    if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER])
2291        && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0))
2292    {
2293       enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER);
2294    }
2295
2296    return JB_ERR_OK ;
2297 } /* process_client_headers */
2298
2299 /*********************************************************************
2300  *
2301  * Function    :  intercept_page
2302  *
2303  * Description :  Check whether to intercept page
2304  *
2305  * Parameters  :
2306  *          1  :  client_state structure
2307  *          2  :  http_request structure
2308  *                         
2309  *
2310  * Returns     :  JB_ERR_OK  - Do NOT intercept this page
2311  *             :  JB_ERR_INTERCEPT - intercept this page
2312  *             :  all other values - an error occurred.  
2313  *********************************************************************/
2314 static jb_err intercept_page( struct client_state *csp, struct http_request *http )
2315 {
2316
2317    /* Skeleton for HTTP response, if we should intercept the request */
2318    struct http_response *rsp;
2319
2320
2321 /*
2322  * These next lines are a little ugly, but they simplifies the if statements
2323  * below.  Basically if TOGGLE, then we want the if to test if the
2324  * CSP_FLAG_TOGGLED_ON flag ist set, else we don't.  And if FEATURE_FORCE_LOAD,
2325  * then we want the if to test for CSP_FLAG_FORCED , else we don't
2326  */
2327 #ifdef FEATURE_TOGGLE
2328 #   define IS_TOGGLED_ON_AND (csp->flags & CSP_FLAG_TOGGLED_ON) &&
2329 #else /* ifndef FEATURE_TOGGLE */
2330 #   define IS_TOGGLED_ON_AND
2331 #endif /* ndef FEATURE_TOGGLE */
2332 #ifdef FEATURE_FORCE_LOAD
2333 #   define IS_NOT_FORCED_AND !(csp->flags & CSP_FLAG_FORCED) &&
2334 #else /* ifndef FEATURE_FORCE_LOAD */
2335 #   define IS_NOT_FORCED_AND
2336 #endif /* def FEATURE_FORCE_LOAD */
2337
2338 #define IS_ENABLED_AND   IS_TOGGLED_ON_AND IS_NOT_FORCED_AND
2339
2340    if (
2341        /* a CGI call was detected and answered */
2342        (NULL != (rsp = dispatch_cgi(csp)))
2343
2344        /* or we are enabled and... */
2345        || (IS_ENABLED_AND (
2346
2347             /* ..the request was blocked */
2348           ( NULL != (rsp = block_url(csp)))
2349
2350           /* ..or untrusted */
2351 #ifdef FEATURE_TRUST
2352           || ( NULL != (rsp = trust_url(csp)))
2353 #endif /* def FEATURE_TRUST */
2354
2355           /* ..or a fast redirect kicked in */
2356 #ifdef FEATURE_FAST_REDIRECTS
2357           || (((csp->action->flags & ACTION_FAST_REDIRECTS) != 0) &&
2358                 (NULL != (rsp = redirect_url(csp))))
2359 #endif /* def FEATURE_FAST_REDIRECTS */
2360           ))
2361       )
2362    {
2363       /* Write the answer to the client */
2364       if (write_socket(csp->cfd, rsp->head, rsp->head_length)
2365        || write_socket(csp->cfd, rsp->body, rsp->content_length))
2366       {
2367          log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
2368       }
2369
2370 #ifdef FEATURE_STATISTICS
2371       /* Count as a rejected request */
2372       csp->flags |= CSP_FLAG_REJECTED;
2373 #endif /* def FEATURE_STATISTICS */
2374
2375       /* Log (FIXME: All intercept reasons apprear as "crunch" with Status 200) */
2376       log_error(LOG_LEVEL_GPC, "%s%s crunch!", http->hostport, http->path);
2377       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 3", csp->ip_addr_str, http->ocmd);
2378
2379       /* Clean up and return */
2380       free_http_response(rsp);
2381       return JB_ERR_INTERCEPT;
2382    }
2383
2384    /* When we get here the request doesn't need to be intercepted */
2385    return JB_ERR_OK ;
2386 }
2387
2388 /*********************************************************************
2389  *
2390  * Function    :  open_forwarding_connection
2391  *
2392  * Description :  Check whether to intercept page
2393  *
2394  * Parameters  :
2395  *          1  :  client_state structure
2396  *          2  :  http_request structure
2397  *                         
2398  * Returns     :  JB_ERR_OK  - Connection opened ok
2399  *             :  all other values - an error occurred.  
2400  *********************************************************************/
2401 static jb_err open_forwarding_connection(struct client_state *csp )
2402 {
2403    struct http_response *rsp;
2404    
2405    log_error(LOG_LEVEL_GPC, "%s%s", csp->http->hostport, csp->http->path);
2406
2407    if (csp->http->fwd->forward_host)
2408    {
2409       log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
2410                csp->http->fwd->forward_host, csp->http->fwd->forward_port, 
2411                csp->http->hostport);
2412    }
2413    else
2414    {
2415       log_error(LOG_LEVEL_CONNECT, "to %s", csp->http->hostport);
2416    }
2417
2418    /* here we connect to the server, gateway, or the forwarder */
2419
2420    csp->sfd = forwarded_connect(csp->http->fwd, csp->http, csp);
2421
2422    if (csp->sfd == JB_INVALID_SOCKET)
2423    {
2424       log_error(LOG_LEVEL_CONNECT, "connect to: %s failed: %E",
2425                 csp->http->hostport);
2426
2427       if (errno == EINVAL)
2428       {
2429          rsp = error_response(csp, "no-such-domain", errno);
2430
2431          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 404 0",
2432                    csp->ip_addr_str, csp->http->ocmd);
2433       }
2434       else
2435       {
2436          rsp = error_response(csp, "connect-failed", errno);
2437
2438          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
2439                    csp->ip_addr_str, csp->http->ocmd);
2440       }
2441
2442
2443       /* Write the answer to the client */
2444       if(rsp)
2445       {
2446          if (write_socket(csp->cfd, rsp->head, rsp->head_length)
2447           || write_socket(csp->cfd, rsp->body, rsp->content_length))
2448          {
2449             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", csp->http->host);
2450          }
2451       }
2452
2453       free_http_response(rsp);
2454       return JB_ERR_GENERIC;
2455    }
2456
2457    log_error(LOG_LEVEL_CONNECT, "OK");
2458    return JB_ERR_OK ;
2459
2460 } /* END open_forwarding_connection() */
2461
2462
2463 /*********************************************************************
2464  *
2465  * Function    :  send_client_headers_to_server
2466  *
2467  * Description :  send the client headers (possibly modified) to the server
2468  *
2469  * Parameters  :
2470  *          1  :  client_state structure
2471  *          2  :  http_request structure
2472  *                         
2473  *
2474  * Returns     :  JB_ERR_OK  - headers sent ok
2475  *             :  other values - an error occurred.
2476  *********************************************************************/
2477
2478 static jb_err send_client_headers_to_server( struct client_state *csp, struct http_request *http, char *hdr )
2479 {
2480
2481    struct http_response *rsp;
2482
2483    if (http->fwd->forward_host || (http->ssl == 0))
2484    {
2485       /* write the client's (modified) header to the server
2486        * (along with anything else that may be in the buffer)
2487        */
2488
2489       if (write_socket(csp->sfd, hdr, strlen(hdr))
2490        || (flush_socket(csp->sfd, csp) <  0))
2491       {
2492          log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
2493                     http->hostport);
2494
2495          log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 503 0",
2496                    csp->ip_addr_str, http->ocmd);
2497
2498          rsp = error_response(csp, "connect-failed", errno);
2499
2500          if(rsp)
2501          {
2502             if (write_socket(csp->cfd, rsp->head, rsp->head_length)
2503              || write_socket(csp->cfd, rsp->body, rsp->content_length))
2504             {
2505                log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
2506             }
2507          }
2508
2509          free_http_response(rsp);
2510          return JB_ERR_GENERIC;
2511       }
2512    }
2513    else
2514    {
2515       /*
2516        * We're running an SSL tunnel and we're not forwarding,
2517        * so just send the "connect succeeded" message to the
2518        * client, flush the rest, and get out of the way.
2519        */
2520       log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 2\n",
2521                 csp->ip_addr_str, http->ocmd);
2522
2523       if (write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1))
2524       {
2525          return JB_ERR_OK;
2526       }
2527       IOB_RESET(csp);
2528    }
2529
2530    return JB_ERR_OK ;
2531 } /* END send_client_headers_to_server */
2532
2533
2534 /*********************************************************************
2535  *
2536  * Function    :  is_connect_request_allowed
2537  *
2538  * Description :  send the client headers (possibly modified) to the server
2539  *
2540  * Parameters  :
2541  *          1  :  client_state structure
2542  *
2543  *                         
2544  *
2545  * Returns     :  JB_ERR_OK  - connect request allowed
2546  *             :  other values - connect request not allowed
2547  *********************************************************************/
2548 static jb_err is_connect_request_allowed( struct client_state *csp )
2549 {
2550    /*
2551     * Check if a CONNECT request is allowable:
2552     * In the absence of a +limit-connect action, allow only port 443.
2553     * If there is an action, allow whatever matches the specificaton.
2554     */
2555
2556    if(csp->http->ssl)
2557    {
2558       if(  ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443)
2559            || (csp->action->flags & ACTION_LIMIT_CONNECT
2560               && !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) )
2561       {
2562          char buf[BUFFER_SIZE];
2563          strcpy(buf, CFORBIDDEN);
2564          write_socket(csp->cfd, buf, strlen(buf));
2565
2566          log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str);
2567          log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str);
2568
2569          return JB_ERR_GENERIC;
2570       }
2571    }
2572
2573    return JB_ERR_OK ;
2574 } /* END is_connect_request_allowed */
2575
2576 /*
2577   Local Variables:
2578   tab-width: 3
2579   end:
2580 */