Prepare for critical sections on Windows by adding a
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.138 2008/08/30 12:03:07 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
5  *
6  * Purpose     :  Declares functions to parse/crunch headers and pages.
7  *                Functions declared include:
8  *                   `add_to_iob', `client_cookie_adder', `client_from',
9  *                   `client_referrer', `client_send_cookie', `client_ua',
10  *                   `client_uagent', `client_x_forwarded',
11  *                   `client_x_forwarded_adder', `client_xtra_adder',
12  *                   `content_type', `crumble', `destroy_list', `enlist',
13  *                   `flush_socket', ``get_header', `sed', `filter_header'
14  *                   `server_content_encoding', `server_content_disposition',
15  *                   `server_last_modified', `client_accept_language',
16  *                   `crunch_client_header', `client_if_modified_since',
17  *                   `client_if_none_match', `get_destination_from_headers',
18  *                   `parse_header_time', `decompress_iob' and `server_set_cookie'.
19  *
20  * Copyright   :  Written by and Copyright (C) 2001-2008 the SourceForge
21  *                Privoxy team. http://www.privoxy.org/
22  *
23  *                Based on the Internet Junkbuster originally written
24  *                by and Copyright (C) 1997 Anonymous Coders and
25  *                Junkbusters Corporation.  http://www.junkbusters.com
26  *
27  *                This program is free software; you can redistribute it
28  *                and/or modify it under the terms of the GNU General
29  *                Public License as published by the Free Software
30  *                Foundation; either version 2 of the License, or (at
31  *                your option) any later version.
32  *
33  *                This program is distributed in the hope that it will
34  *                be useful, but WITHOUT ANY WARRANTY; without even the
35  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
36  *                PARTICULAR PURPOSE.  See the GNU General Public
37  *                License for more details.
38  *
39  *                The GNU General Public License should be included with
40  *                this file.  If not, you can view it at
41  *                http://www.gnu.org/copyleft/gpl.html
42  *                or write to the Free Software Foundation, Inc., 59
43  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
44  *
45  * Revisions   :
46  *    $Log: parsers.c,v $
47  *    Revision 1.138  2008/08/30 12:03:07  fabiankeil
48  *    Remove FEATURE_COOKIE_JAR.
49  *
50  *    Revision 1.137  2008/05/30 15:50:08  fabiankeil
51  *    Remove questionable micro-optimizations
52  *    whose usefulness has never been measured.
53  *
54  *    Revision 1.136  2008/05/26 16:02:24  fabiankeil
55  *    s@Insufficent@Insufficient@
56  *
57  *    Revision 1.135  2008/05/21 20:12:10  fabiankeil
58  *    The whole point of strclean() is to modify the
59  *    first parameter, so don't mark it immutable,
60  *    even though the compiler lets us get away with it.
61  *
62  *    Revision 1.134  2008/05/21 19:27:25  fabiankeil
63  *    As the wafer actions are gone, we can stop including encode.h.
64  *
65  *    Revision 1.133  2008/05/21 15:50:47  fabiankeil
66  *    Ditch cast from (char **) to (char **).
67  *
68  *    Revision 1.132  2008/05/21 15:47:14  fabiankeil
69  *    Streamline sed()'s prototype and declare
70  *    the header parse and add structures static.
71  *
72  *    Revision 1.131  2008/05/20 20:13:30  fabiankeil
73  *    Factor update_server_headers() out of sed(), ditch the
74  *    first_run hack and make server_patterns_light static.
75  *
76  *    Revision 1.130  2008/05/19 17:18:04  fabiankeil
77  *    Wrap memmove() calls in string_move()
78  *    to document the purpose in one place.
79  *
80  *    Revision 1.129  2008/05/17 14:02:07  fabiankeil
81  *    Normalize linear header white space.
82  *
83  *    Revision 1.128  2008/05/16 16:39:03  fabiankeil
84  *    If a header is split across multiple lines,
85  *    merge them to a single line before parsing them.
86  *
87  *    Revision 1.127  2008/05/10 13:23:38  fabiankeil
88  *    Don't provide get_header() with the whole client state
89  *    structure when it only needs access to csp->iob.
90  *
91  *    Revision 1.126  2008/05/03 16:40:45  fabiankeil
92  *    Change content_filters_enabled()'s parameter from
93  *    csp->action to action so it can be also used in the
94  *    CGI code. Don't bother checking if there are filters
95  *    loaded, as that's somewhat besides the point.
96  *
97  *    Revision 1.125  2008/04/17 14:40:49  fabiankeil
98  *    Provide get_http_time() with the buffer size so it doesn't
99  *    have to blindly assume that the buffer is big enough.
100  *
101  *    Revision 1.124  2008/04/16 16:38:21  fabiankeil
102  *    Don't pass the whole csp structure to flush_socket()
103  *    when it only needs a file descriptor and a buffer.
104  *
105  *    Revision 1.123  2008/03/29 12:13:46  fabiankeil
106  *    Remove send-wafer and send-vanilla-wafer actions.
107  *
108  *    Revision 1.122  2008/03/28 15:13:39  fabiankeil
109  *    Remove inspect-jpegs action.
110  *
111  *    Revision 1.121  2008/01/05 21:37:03  fabiankeil
112  *    Let client_range() also handle Request-Range headers
113  *    which apparently are still supported by many servers.
114  *
115  *    Revision 1.120  2008/01/04 17:43:45  fabiankeil
116  *    Improve the warning messages that get logged if the action files
117  *    "enable" filters but no filters of that type have been loaded.
118  *
119  *    Revision 1.119  2007/12/28 18:32:51  fabiankeil
120  *    In server_content_type():
121  *    - Don't require leading white space when detecting image content types.
122  *    - Change '... not replaced ...' message to sound less crazy if the text
123  *      type actually is 'text/plain'.
124  *    - Mark the 'text/plain == binary data' assumption for removal.
125  *    - Remove a bunch of trailing white space.
126  *
127  *    Revision 1.118  2007/12/28 16:56:35  fabiankeil
128  *    Minor server_content_disposition() changes:
129  *    - Don't regenerate the header name all lower-case.
130  *    - Some white space fixes.
131  *    - Remove useless log message in case of ENOMEM.
132  *
133  *    Revision 1.117  2007/12/06 18:11:50  fabiankeil
134  *    Garbage-collect the code to add a X-Forwarded-For
135  *    header as it seems to be mostly used by accident.
136  *
137  *    Revision 1.116  2007/12/01 13:04:22  fabiankeil
138  *    Fix a crash on mingw32 with some Last Modified times in the future.
139  *
140  *    Revision 1.115  2007/11/02 16:52:50  fabiankeil
141  *    Remove a "can't happen" error block which, over
142  *    time, mutated into a "guaranteed to happen" block.
143  *
144  *    Revision 1.114  2007/10/19 16:56:26  fabiankeil
145  *    - Downgrade "Buffer limit reached" message to LOG_LEVEL_INFO.
146  *    - Use shiny new content_filters_enabled() in client_range().
147  *
148  *    Revision 1.113  2007/10/10 17:29:57  fabiankeil
149  *    I forgot about Poland.
150  *
151  *    Revision 1.112  2007/10/09 16:38:40  fabiankeil
152  *    Remove Range and If-Range headers if content filtering is enabled.
153  *
154  *    Revision 1.111  2007/10/04 18:07:00  fabiankeil
155  *    Move ACTION_VANILLA_WAFER handling from jcc's chat() into
156  *    client_cookie_adder() to make sure send-vanilla-wafer can be
157  *    controlled through tags (and thus regression-tested).
158  *
159  *    Revision 1.110  2007/09/29 10:42:37  fabiankeil
160  *    - Remove "scanning headers for" log message again.
161  *    - Some more whitespace fixes.
162  *
163  *    Revision 1.109  2007/09/08 14:25:48  fabiankeil
164  *    Refactor client_referrer() and add conditional-forge parameter.
165  *
166  *    Revision 1.108  2007/08/28 18:21:03  fabiankeil
167  *    A bunch of whitespace fixes, pointy hat to me.
168  *
169  *    Revision 1.107  2007/08/28 18:16:32  fabiankeil
170  *    Fix possible memory corruption in server_http, make sure it's not
171  *    executed for ordinary server headers and mark some problems for later.
172  *
173  *    Revision 1.106  2007/08/18 14:30:32  fabiankeil
174  *    Let content-type-overwrite{} honour force-text-mode again.
175  *
176  *    Revision 1.105  2007/08/11 14:49:49  fabiankeil
177  *    - Add prototpyes for the header parsers and make them static.
178  *    - Comment out client_accept_encoding_adder() which isn't used right now.
179  *
180  *    Revision 1.104  2007/07/14 07:38:19  fabiankeil
181  *    Move the ACTION_FORCE_TEXT_MODE check out of
182  *    server_content_type(). Signal other functions
183  *    whether or not a content type has been declared.
184  *    Part of the fix for BR#1750917.
185  *
186  *    Revision 1.103  2007/06/01 16:31:54  fabiankeil
187  *    Change sed() to return a jb_err in preparation for forward-override{}.
188  *
189  *    Revision 1.102  2007/05/27 12:39:32  fabiankeil
190  *    Adjust "X-Filter: No" to disable dedicated header filters.
191  *
192  *    Revision 1.101  2007/05/14 10:16:41  fabiankeil
193  *    Streamline client_cookie_adder().
194  *
195  *    Revision 1.100  2007/04/30 15:53:11  fabiankeil
196  *    Make sure filters with dynamic jobs actually use them.
197  *
198  *    Revision 1.99  2007/04/30 15:06:26  fabiankeil
199  *    - Introduce dynamic pcrs jobs that can resolve variables.
200  *    - Remove unnecessary update_action_bits_for_all_tags() call.
201  *
202  *    Revision 1.98  2007/04/17 18:32:10  fabiankeil
203  *    - Make tagging based on tags set by earlier taggers
204  *      of the same kind possible.
205  *    - Log whether or not new tags cause action bits updates
206  *      (in which case a matching tag-pattern section exists).
207  *    - Log if the user tries to set a tag that is already set.
208  *
209  *    Revision 1.97  2007/04/15 16:39:21  fabiankeil
210  *    Introduce tags as alternative way to specify which
211  *    actions apply to a request. At the moment tags can be
212  *    created based on client and server headers.
213  *
214  *    Revision 1.96  2007/04/12 12:53:58  fabiankeil
215  *    Log a warning if the content is compressed, filtering is
216  *    enabled and Privoxy was compiled without zlib support.
217  *    Closes FR#1673938.
218  *
219  *    Revision 1.95  2007/03/25 14:26:40  fabiankeil
220  *    - Fix warnings when compiled with glibc.
221  *    - Don't use crumble() for cookie crunching.
222  *    - Move cookie time parsing into parse_header_time().
223  *    - Let parse_header_time() return a jb_err code
224  *      instead of a pointer that can only be used to
225  *      check for NULL anyway.
226  *
227  *    Revision 1.94  2007/03/21 12:23:53  fabiankeil
228  *    - Add better protection against malicious gzip headers.
229  *    - Stop logging the first hundred bytes of decompressed content.
230  *      It looks like it's working and there is always debug 16.
231  *    - Log the content size after decompression in decompress_iob()
232  *      instead of pcrs_filter_response().
233  *
234  *    Revision 1.93  2007/03/20 15:21:44  fabiankeil
235  *    - Use dedicated header filter actions instead of abusing "filter".
236  *      Replace "filter-client-headers" and "filter-client-headers"
237  *      with "server-header-filter" and "client-header-filter".
238  *    - Remove filter_client_header() and filter_client_header(),
239  *      filter_header() now checks the shiny new
240  *      CSP_FLAG_CLIENT_HEADER_PARSING_DONE flag instead.
241  *
242  *    Revision 1.92  2007/03/05 13:25:32  fabiankeil
243  *    - Cosmetical changes for LOG_LEVEL_RE_FILTER messages.
244  *    - Handle "Cookie:" and "Connection:" headers a bit smarter
245  *      (don't crunch them just to recreate them later on).
246  *    - Add another non-standard time format for the cookie
247  *      expiration date detection.
248  *    - Fix a valgrind warning.
249  *
250  *    Revision 1.91  2007/02/24 12:27:32  fabiankeil
251  *    Improve cookie expiration date detection.
252  *
253  *    Revision 1.90  2007/02/08 19:12:35  fabiankeil
254  *    Don't run server_content_length() the first time
255  *    sed() parses server headers; only adjust the
256  *    Content-Length header if the page was modified.
257  *
258  *    Revision 1.89  2007/02/07 16:52:11  fabiankeil
259  *    Fix log messages regarding the cookie time format
260  *    (cookie and request URL were mixed up).
261  *
262  *    Revision 1.88  2007/02/07 11:27:12  fabiankeil
263  *    - Let decompress_iob()
264  *      - not corrupt the content if decompression fails
265  *        early. (the first byte(s) were lost).
266  *      - use pointer arithmetics with defined outcome for
267  *        a change.
268  *    - Use a different kludge to remember a failed decompression.
269  *
270  *    Revision 1.87  2007/01/31 16:21:38  fabiankeil
271  *    Search for Max-Forwards headers case-insensitive,
272  *    don't generate the "501 unsupported" message for invalid
273  *    Max-Forwards values and don't increase negative ones.
274  *
275  *    Revision 1.86  2007/01/30 13:05:26  fabiankeil
276  *    - Let server_set_cookie() check the expiration date
277  *      of cookies and don't touch the ones that are already
278  *      expired. Fixes problems with low quality web applications
279  *      as described in BR 932612.
280  *
281  *    - Adjust comment in client_max_forwards to reality;
282  *      remove invalid Max-Forwards headers.
283  *
284  *    Revision 1.85  2007/01/26 15:33:46  fabiankeil
285  *    Stop filter_header() from unintentionally removing
286  *    empty header lines that were enlisted by the continue
287  *    hack.
288  *
289  *    Revision 1.84  2007/01/24 12:56:52  fabiankeil
290  *    - Repeat the request URL before logging any headers.
291  *      Makes reading the log easier in case of simultaneous requests.
292  *    - If there are more than one Content-Type headers in one request,
293  *      use the first one and remove the others.
294  *    - Remove "newval" variable in server_content_type().
295  *      It's only used once.
296  *
297  *    Revision 1.83  2007/01/12 15:03:02  fabiankeil
298  *    Correct a cast, check inflateEnd() exit code
299  *    to see if we have to, replace sprintf calls
300  *    with snprintf.
301  *
302  *    Revision 1.82  2007/01/01 19:36:37  fabiankeil
303  *    Integrate a modified version of Wil Mahan's
304  *    zlib patch (PR #895531).
305  *
306  *    Revision 1.81  2006/12/31 22:21:33  fabiankeil
307  *    Skip empty filter files in filter_header()
308  *    but don't ignore the ones that come afterwards.
309  *    Fixes BR 1619208, this time for real.
310  *
311  *    Revision 1.80  2006/12/29 19:08:22  fabiankeil
312  *    Reverted parts of my last commit
313  *    to keep error handling working.
314  *
315  *    Revision 1.79  2006/12/29 18:04:40  fabiankeil
316  *    Fixed gcc43 conversion warnings.
317  *
318  *    Revision 1.78  2006/12/26 17:19:20  fabiankeil
319  *    Bringing back the "useless" localtime() call
320  *    I removed in revision 1.67. On some platforms
321  *    it's necessary to prevent time zone offsets.
322  *
323  *    Revision 1.77  2006/12/07 18:44:26  fabiankeil
324  *    Rebuild request URL in get_destination_from_headers()
325  *    to make sure redirect{pcrs command} works as expected
326  *    for intercepted requests.
327  *
328  *    Revision 1.76  2006/12/06 19:52:25  fabiankeil
329  *    Added get_destination_from_headers().
330  *
331  *    Revision 1.75  2006/11/13 19:05:51  fabiankeil
332  *    Make pthread mutex locking more generic. Instead of
333  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
334  *    and use mutex locking unless there is an _r function
335  *    available. Better safe than sorry.
336  *
337  *    Fixes "./configure --disable-pthread" and should result
338  *    in less threading-related problems on pthread-using platforms,
339  *    but it still doesn't fix BR#1122404.
340  *
341  *    Revision 1.74  2006/10/02 16:59:12  fabiankeil
342  *    The special header "X-Filter: No" now disables
343  *    header filtering as well.
344  *
345  *    Revision 1.73  2006/09/23 13:26:38  roro
346  *    Replace TABs by spaces in source code.
347  *
348  *    Revision 1.72  2006/09/23 12:37:21  fabiankeil
349  *    Don't print a log message every time filter_headers is
350  *    entered or left. It only creates noise without any real
351  *    information.
352  *
353  *    Revision 1.71  2006/09/21 19:55:17  fabiankeil
354  *    Fix +hide-if-modified-since{-n}.
355  *
356  *    Revision 1.70  2006/09/08 12:06:34  fabiankeil
357  *    Have hide-if-modified-since interpret the random
358  *    range value as minutes instead of hours. Allows
359  *    more fine-grained configuration.
360  *
361  *    Revision 1.69  2006/09/06 16:25:51  fabiankeil
362  *    Always have parse_header_time return a pointer
363  *    that actual makes sense, even though we currently
364  *    only need it to detect problems.
365  *
366  *    Revision 1.68  2006/09/06 10:43:32  fabiankeil
367  *    Added config option enable-remote-http-toggle
368  *    to specify if Privoxy should recognize special
369  *    headers (currently only X-Filter) to change its
370  *    behaviour. Disabled by default.
371  *
372  *    Revision 1.67  2006/09/04 11:01:26  fabiankeil
373  *    After filtering de-chunked instances, remove
374  *    "Transfer-Encoding" header entirely instead of changing
375  *    it to "Transfer-Encoding: identity", which is invalid.
376  *    Thanks Michael Shields <shields@msrl.com>. Fixes PR 1318658.
377  *
378  *    Don't use localtime in parse_header_time. An empty time struct
379  *    is good enough, it gets overwritten by strptime anyway.
380  *
381  *    Revision 1.66  2006/09/03 19:38:28  fabiankeil
382  *    Use gmtime_r if available, fallback to gmtime with mutex
383  *    protection for MacOSX and use vanilla gmtime for the rest.
384  *
385  *    Revision 1.65  2006/08/22 10:55:56  fabiankeil
386  *    Changed client_referrer to use the right type (size_t) for
387  *    hostlenght and to shorten the temporary referrer string with
388  *    '\0' instead of adding a useless line break.
389  *
390  *    Revision 1.64  2006/08/17 17:15:10  fabiankeil
391  *    - Back to timegm() using GnuPG's replacement if necessary.
392  *      Using mktime() and localtime() could add a on hour offset if
393  *      the randomize factor was big enough to lead to a summer/wintertime
394  *      switch.
395  *
396  *    - Removed now-useless Privoxy 3.0.3 compatibility glue.
397  *
398  *    - Moved randomization code into pick_from_range().
399  *
400  *    - Changed parse_header_time definition.
401  *      time_t isn't guaranteed to be signed and
402  *      if it isn't, -1 isn't available as error code.
403  *      Changed some variable types in client_if_modified_since()
404  *      because of the same reason.
405  *
406  *    Revision 1.63  2006/08/14 13:18:08  david__schmidt
407  *    OS/2 compilation compatibility fixups
408  *
409  *    Revision 1.62  2006/08/14 08:58:42  fabiankeil
410  *    Changed include from strptime.c to strptime.h
411  *
412  *    Revision 1.61  2006/08/14 08:25:19  fabiankeil
413  *    Split filter-headers{} into filter-client-headers{}
414  *    and filter-server-headers{}.
415  *    Added parse_header_time() to share some code.
416  *    Replaced timegm() with mktime().
417  *
418  *    Revision 1.60  2006/08/12 03:54:37  david__schmidt
419  *    Windows service integration
420  *
421  *    Revision 1.59  2006/08/03 02:46:41  david__schmidt
422  *    Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
423  *
424  *    Revision 1.58  2006/07/18 14:48:47  david__schmidt
425  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
426  *    with what was really the latest development (the v_3_0_branch branch)
427  *
428  *    Revision 1.56.2.10  2006/01/21 16:16:08  david__schmidt
429  *    Thanks to  Edward Carrel for his patch to modernize OSX's\rpthreads support.  See bug #1409623.
430  *
431  *    Revision 1.56.2.9  2004/10/03 12:53:45  david__schmidt
432  *    Add the ability to check jpeg images for invalid
433  *    lengths of comment blocks.  Defensive strategy
434  *    against the exploit:
435  *       Microsoft Security Bulletin MS04-028
436  *       Buffer Overrun in JPEG Processing (GDI+) Could
437  *       Allow Code Execution (833987)
438  *    Enabled with +inspect-jpegs in actions files.
439  *
440  *    Revision 1.56.2.8  2003/07/11 13:21:25  oes
441  *    Excluded text/plain objects from filtering. This fixes a
442  *    couple of client-crashing, download corruption and
443  *    Privoxy performance issues, whose root cause lies in
444  *    web servers labelling content of unknown type as text/plain.
445  *
446  *    Revision 1.56.2.7  2003/05/06 12:07:26  oes
447  *    Fixed bug #729900: Suspicious HOST: headers are now killed and regenerated if necessary
448  *
449  *    Revision 1.56.2.6  2003/04/14 21:28:30  oes
450  *    Completing the previous change
451  *
452  *    Revision 1.56.2.5  2003/04/14 12:08:16  oes
453  *    Added temporary workaround for bug in PHP < 4.2.3
454  *
455  *    Revision 1.56.2.4  2003/03/07 03:41:05  david__schmidt
456  *    Wrapping all *_r functions (the non-_r versions of them) with mutex semaphores for OSX.  Hopefully this will take care of all of those pesky crash reports.
457  *
458  *    Revision 1.56.2.3  2002/11/10 04:20:02  hal9
459  *    Fix typo: supressed -> suppressed
460  *
461  *    Revision 1.56.2.2  2002/09/25 14:59:53  oes
462  *    Improved cookie logging
463  *
464  *    Revision 1.56.2.1  2002/09/25 14:52:45  oes
465  *    Added basic support for OPTIONS and TRACE HTTP methods:
466  *     - New parser function client_max_forwards which decrements
467  *       the Max-Forwards HTTP header field of OPTIONS and TRACE
468  *       requests by one before forwarding
469  *     - New parser function client_host which extracts the host
470  *       and port information from the HTTP header field if the
471  *       request URI was not absolute
472  *     - Don't crumble and re-add the Host: header, but only generate
473  *       and append if missing
474  *
475  *    Revision 1.56  2002/05/12 15:34:22  jongfoster
476  *    Fixing typo in a comment
477  *
478  *    Revision 1.55  2002/05/08 16:01:07  oes
479  *    Optimized add_to_iob:
480  *     - Use realloc instead of malloc(), memcpy(), free()
481  *     - Expand to powers of two if possible, to get
482  *       O(log n) reallocs instead of O(n).
483  *     - Moved check for buffer limit here from chat
484  *     - Report failure via returncode
485  *
486  *    Revision 1.54  2002/04/02 15:03:16  oes
487  *    Tiny code cosmetics
488  *
489  *    Revision 1.53  2002/03/26 22:29:55  swa
490  *    we have a new homepage!
491  *
492  *    Revision 1.52  2002/03/24 13:25:43  swa
493  *    name change related issues
494  *
495  *    Revision 1.51  2002/03/13 00:27:05  jongfoster
496  *    Killing warnings
497  *
498  *    Revision 1.50  2002/03/12 01:45:35  oes
499  *    More verbose logging
500  *
501  *    Revision 1.49  2002/03/09 20:03:52  jongfoster
502  *    - Making various functions return int rather than size_t.
503  *      (Undoing a recent change).  Since size_t is unsigned on
504  *      Windows, functions like read_socket that return -1 on
505  *      error cannot return a size_t.
506  *
507  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
508  *      crashes, and also frequently caused JB to jump to 100%
509  *      CPU and stay there.  (Because it thought it had just
510  *      read ((unsigned)-1) == 4Gb of data...)
511  *
512  *    - The signature of write_socket has changed, it now simply
513  *      returns success=0/failure=nonzero.
514  *
515  *    - Trying to get rid of a few warnings --with-debug on
516  *      Windows, I've introduced a new type "jb_socket".  This is
517  *      used for the socket file descriptors.  On Windows, this
518  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
519  *      an int.  The error value can't be -1 any more, so it's
520  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
521  *      Windows it maps to the #define INVALID_SOCKET.)
522  *
523  *    - The signature of bind_port has changed.
524  *
525  *    Revision 1.48  2002/03/07 03:46:53  oes
526  *    Fixed compiler warnings etc
527  *
528  *    Revision 1.47  2002/02/20 23:15:13  jongfoster
529  *    Parsing functions now handle out-of-memory gracefully by returning
530  *    an error code.
531  *
532  *    Revision 1.46  2002/01/17 21:03:47  jongfoster
533  *    Moving all our URL and URL pattern parsing code to urlmatch.c.
534  *
535  *    Revision 1.45  2002/01/09 14:33:03  oes
536  *    Added support for localtime_r.
537  *
538  *    Revision 1.44  2001/12/14 01:22:54  steudten
539  *    Remove 'user:pass@' from 'proto://user:pass@host' for the
540  *    new added header 'Host: ..'. (See Req ID 491818)
541  *
542  *    Revision 1.43  2001/11/23 00:26:38  jongfoster
543  *    Fixing two really stupid errors in my previous commit
544  *
545  *    Revision 1.42  2001/11/22 21:59:30  jongfoster
546  *    Adding code to handle +no-cookies-keep
547  *
548  *    Revision 1.41  2001/11/05 23:43:05  steudten
549  *    Add time+date to log files.
550  *
551  *    Revision 1.40  2001/10/26 20:13:09  jongfoster
552  *    ctype.h is needed in Windows, too.
553  *
554  *    Revision 1.39  2001/10/26 17:40:04  oes
555  *    Introduced get_header_value()
556  *    Removed http->user_agent, csp->referrer and csp->accept_types
557  *    Removed client_accept()
558  *
559  *    Revision 1.38  2001/10/25 03:40:48  david__schmidt
560  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
561  *    threads to call select() simultaneously.  So, it's time to do a real, live,
562  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
563  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
564  *
565  *    Revision 1.37  2001/10/23 21:36:02  jongfoster
566  *    Documenting sed()'s error behaviou (doc change only)
567  *
568  *    Revision 1.36  2001/10/13 12:51:51  joergs
569  *    Removed client_host, (was only required for the old 2.0.2-11 http://noijb.
570  *    force-load), instead crumble Host: and add it (again) in client_host_adder
571  *    (in case we get a HTTP/1.0 request without Host: header and forward it to
572  *    a HTTP/1.1 server/proxy).
573  *
574  *    Revision 1.35  2001/10/09 22:39:21  jongfoster
575  *    assert.h is also required under Win32, so moving out of #ifndef _WIN32
576  *    block.
577  *
578  *    Revision 1.34  2001/10/07 18:50:55  oes
579  *    Added server_content_encoding, renamed server_transfer_encoding
580  *
581  *    Revision 1.33  2001/10/07 18:04:49  oes
582  *    Changed server_http11 to server_http and its pattern to "HTTP".
583  *      Additional functionality: it now saves the HTTP status into
584  *      csp->http->status and sets CT_TABOO for Status 206 (partial range)
585  *
586  *    Revision 1.32  2001/10/07 15:43:28  oes
587  *    Removed FEATURE_DENY_GZIP and replaced it with client_accept_encoding,
588  *       client_te and client_accept_encoding_adder, triggered by the new
589  *       +no-compression action. For HTTP/1.1 the Accept-Encoding header is
590  *       changed to allow only identity and chunked, and the TE header is
591  *       crunched. For HTTP/1.0, Accept-Encoding is crunched.
592  *
593  *    parse_http_request no longer does anything than parsing. The rewriting
594  *      of http->cmd and version mangling are gone. It now also recognizes
595  *      the put and delete methods and saves the url in http->url. Removed
596  *      unused variable.
597  *
598  *    renamed content_type and content_length to have the server_ prefix
599  *
600  *    server_content_type now only works if csp->content_type != CT_TABOO
601  *
602  *    added server_transfer_encoding, which
603  *      - Sets CT_TABOO to prohibit filtering if encoding compresses
604  *      - Raises the CSP_FLAG_CHUNKED flag if Encoding is "chunked"
605  *      - Change from "chunked" to "identity" if body was chunked
606  *        but has been de-chunked for filtering.
607  *
608  *    added server_content_md5 which crunches any Content-MD5 headers
609  *      if the body was modified.
610  *
611  *    made server_http11 conditional on +downgrade action
612  *
613  *    Replaced 6 boolean members of csp with one bitmap (csp->flags)
614  *
615  *    Revision 1.31  2001/10/05 14:25:02  oes
616  *    Crumble Keep-Alive from Server
617  *
618  *    Revision 1.30  2001/09/29 12:56:03  joergs
619  *    IJB now changes HTTP/1.1 to HTTP/1.0 in requests and answers.
620  *
621  *    Revision 1.29  2001/09/24 21:09:24  jongfoster
622  *    Fixing 2 memory leaks that Guy spotted, where the paramater to
623  *    enlist() was not being free()d.
624  *
625  *    Revision 1.28  2001/09/22 16:32:28  jongfoster
626  *    Removing unused #includes.
627  *
628  *    Revision 1.27  2001/09/20 15:45:25  steudten
629  *
630  *    add casting from size_t to int for printf()
631  *    remove local variable shadow s2
632  *
633  *    Revision 1.26  2001/09/16 17:05:14  jongfoster
634  *    Removing unused #include showarg.h
635  *
636  *    Revision 1.25  2001/09/16 13:21:27  jongfoster
637  *    Changes to use new list functions.
638  *
639  *    Revision 1.24  2001/09/13 23:05:50  jongfoster
640  *    Changing the string paramater to the header parsers a "const".
641  *
642  *    Revision 1.23  2001/09/12 18:08:19  steudten
643  *
644  *    In parse_http_request() header rewriting miss the host value, so
645  *    from http://www.mydomain.com the result was just " / " not
646  *    http://www.mydomain.com/ in case we forward.
647  *
648  *    Revision 1.22  2001/09/10 10:58:53  oes
649  *    Silenced compiler warnings
650  *
651  *    Revision 1.21  2001/07/31 14:46:00  oes
652  *     - Persistant connections now suppressed
653  *     - sed() no longer appends empty header to csp->headers
654  *
655  *    Revision 1.20  2001/07/30 22:08:36  jongfoster
656  *    Tidying up #defines:
657  *    - All feature #defines are now of the form FEATURE_xxx
658  *    - Permanently turned off WIN_GUI_EDIT
659  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
660  *
661  *    Revision 1.19  2001/07/25 17:21:54  oes
662  *    client_uagent now saves copy of User-Agent: header value
663  *
664  *    Revision 1.18  2001/07/13 14:02:46  oes
665  *     - Included fix to repair broken HTTP requests that
666  *       don't contain a path, not even '/'.
667  *     - Removed all #ifdef PCRS
668  *     - content_type now always inspected and classified as
669  *       text, gif or other.
670  *     - formatting / comments
671  *
672  *    Revision 1.17  2001/06/29 21:45:41  oes
673  *    Indentation, CRLF->LF, Tab-> Space
674  *
675  *    Revision 1.16  2001/06/29 13:32:42  oes
676  *    - Fixed a comment
677  *    - Adapted free_http_request
678  *    - Removed logentry from cancelled commit
679  *
680  *    Revision 1.15  2001/06/03 19:12:38  oes
681  *    deleted const struct interceptors
682  *
683  *    Revision 1.14  2001/06/01 18:49:17  jongfoster
684  *    Replaced "list_share" with "list" - the tiny memory gain was not
685  *    worth the extra complexity.
686  *
687  *    Revision 1.13  2001/05/31 21:30:33  jongfoster
688  *    Removed list code - it's now in list.[ch]
689  *    Renamed "permission" to "action", and changed many features
690  *    to use the actions file rather than the global config.
691  *
692  *    Revision 1.12  2001/05/31 17:33:13  oes
693  *
694  *    CRLF -> LF
695  *
696  *    Revision 1.11  2001/05/29 20:11:19  joergs
697  *    '/ * inside comment' warning removed.
698  *
699  *    Revision 1.10  2001/05/29 09:50:24  jongfoster
700  *    Unified blocklist/imagelist/permissionslist.
701  *    File format is still under discussion, but the internal changes
702  *    are (mostly) done.
703  *
704  *    Also modified interceptor behaviour:
705  *    - We now intercept all URLs beginning with one of the following
706  *      prefixes (and *only* these prefixes):
707  *        * http://i.j.b/
708  *        * http://ijbswa.sf.net/config/
709  *        * http://ijbswa.sourceforge.net/config/
710  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
711  *    - Internal changes so that intercepted and fast redirect pages
712  *      are not replaced with an image.
713  *    - Interceptors now have the option to send a binary page direct
714  *      to the client. (i.e. ijb-send-banner uses this)
715  *    - Implemented show-url-info interceptor.  (Which is why I needed
716  *      the above interceptors changes - a typical URL is
717  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
718  *      The previous mechanism would not have intercepted that, and
719  *      if it had been intercepted then it then it would have replaced
720  *      it with an image.)
721  *
722  *    Revision 1.9  2001/05/28 17:26:33  jongfoster
723  *    Fixing segfault if last header was crunched.
724  *    Fixing Windows build (snprintf() is _snprintf() under Win32, but we
725  *    can use the cross-platform sprintf() instead.)
726  *
727  *    Revision 1.8  2001/05/27 22:17:04  oes
728  *
729  *    - re_process_buffer no longer writes the modified buffer
730  *      to the client, which was very ugly. It now returns the
731  *      buffer, which it is then written by chat.
732  *
733  *    - content_length now adjusts the Content-Length: header
734  *      for modified documents rather than crunch()ing it.
735  *      (Length info in csp->content_length, which is 0 for
736  *      unmodified documents)
737  *
738  *    - For this to work, sed() is called twice when filtering.
739  *
740  *    Revision 1.7  2001/05/27 13:19:06  oes
741  *    Patched Joergs solution for the content-length in.
742  *
743  *    Revision 1.6  2001/05/26 13:39:32  jongfoster
744  *    Only crunches Content-Length header if applying RE filtering.
745  *    Without this fix, Microsoft Windows Update wouldn't work.
746  *
747  *    Revision 1.5  2001/05/26 00:28:36  jongfoster
748  *    Automatic reloading of config file.
749  *    Removed obsolete SIGHUP support (Unix) and Reload menu option (Win32).
750  *    Most of the global variables have been moved to a new
751  *    struct configuration_spec, accessed through csp->config->globalname
752  *    Most of the globals remaining are used by the Win32 GUI.
753  *
754  *    Revision 1.4  2001/05/22 18:46:04  oes
755  *
756  *    - Enabled filtering banners by size rather than URL
757  *      by adding patterns that replace all standard banner
758  *      sizes with the "Junkbuster" gif to the re_filterfile
759  *
760  *    - Enabled filtering WebBugs by providing a pattern
761  *      which kills all 1x1 images
762  *
763  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
764  *      which is selected by the (nonstandard and therefore
765  *      capital) letter 'U' in the option string.
766  *      It causes the quantifiers to be ungreedy by default.
767  *      Appending a ? turns back to greedy (!).
768  *
769  *    - Added a new interceptor ijb-send-banner, which
770  *      sends back the "Junkbuster" gif. Without imagelist or
771  *      MSIE detection support, or if tinygif = 1, or the
772  *      URL isn't recognized as an imageurl, a lame HTML
773  *      explanation is sent instead.
774  *
775  *    - Added new feature, which permits blocking remote
776  *      script redirects and firing back a local redirect
777  *      to the browser.
778  *      The feature is conditionally compiled, i.e. it
779  *      can be disabled with --disable-fast-redirects,
780  *      plus it must be activated by a "fast-redirects"
781  *      line in the config file, has its own log level
782  *      and of course wants to be displayed by show-proxy-args
783  *      Note: Boy, all the #ifdefs in 1001 locations and
784  *      all the fumbling with configure.in and acconfig.h
785  *      were *way* more work than the feature itself :-(
786  *
787  *    - Because a generic redirect template was needed for
788  *      this, tinygif = 3 now uses the same.
789  *
790  *    - Moved GIFs, and other static HTTP response templates
791  *      to project.h
792  *
793  *    - Some minor fixes
794  *
795  *    - Removed some >400 CRs again (Jon, you really worked
796  *      a lot! ;-)
797  *
798  *    Revision 1.3  2001/05/20 01:21:20  jongfoster
799  *    Version 2.9.4 checkin.
800  *    - Merged popupfile and cookiefile, and added control over PCRS
801  *      filtering, in new "permissionsfile".
802  *    - Implemented LOG_LEVEL_FATAL, so that if there is a configuration
803  *      file error you now get a message box (in the Win32 GUI) rather
804  *      than the program exiting with no explanation.
805  *    - Made killpopup use the PCRS MIME-type checking and HTTP-header
806  *      skipping.
807  *    - Removed tabs from "config"
808  *    - Moved duplicated url parsing code in "loaders.c" to a new funcition.
809  *    - Bumped up version number.
810  *
811  *    Revision 1.2  2001/05/17 23:02:36  oes
812  *     - Made referrer option accept 'L' as a substitute for '§'
813  *
814  *    Revision 1.1.1.1  2001/05/15 13:59:01  oes
815  *    Initial import of version 2.9.3 source tree
816  *
817  *
818  *********************************************************************/
819 \f
820
821 #include "config.h"
822
823 #ifndef _WIN32
824 #include <stdio.h>
825 #include <sys/types.h>
826 #endif
827
828 #include <stdlib.h>
829 #include <ctype.h>
830 #include <assert.h>
831 #include <string.h>
832
833 #ifdef __GLIBC__
834 /*
835  * Convince GNU's libc to provide a strptime prototype.
836  */
837 #define __USE_XOPEN
838 #endif /*__GLIBC__ */
839 #include <time.h>
840
841 #ifdef FEATURE_ZLIB
842 #include <zlib.h>
843 #endif
844
845 #if !defined(_WIN32) && !defined(__OS2__)
846 #include <unistd.h>
847 #endif
848
849 #include "project.h"
850
851 #ifdef FEATURE_PTHREAD
852 #include "jcc.h"
853 /* jcc.h is for mutex semapores only */
854 #endif /* def FEATURE_PTHREAD */
855 #include "list.h"
856 #include "parsers.h"
857 #include "ssplit.h"
858 #include "errlog.h"
859 #include "jbsockets.h"
860 #include "miscutil.h"
861 #include "list.h"
862 #include "actions.h"
863 #include "filters.h"
864
865 #ifndef HAVE_STRPTIME
866 #include "strptime.h"
867 #endif
868
869 const char parsers_h_rcs[] = PARSERS_H_VERSION;
870
871 /* Fix a problem with Solaris.  There should be no effect on other
872  * platforms.
873  * Solaris's isspace() is a macro which uses its argument directly
874  * as an array index.  Therefore we need to make sure that high-bit
875  * characters generate +ve values, and ideally we also want to make
876  * the argument match the declared parameter type of "int".
877  *
878  * Why did they write a character function that can't take a simple
879  * "char" argument?  Doh!
880  */
881 #define ijb_isupper(__X) isupper((int)(unsigned char)(__X))
882 #define ijb_tolower(__X) tolower((int)(unsigned char)(__X))
883
884 static char *get_header_line(struct iob *iob);
885 static jb_err scan_headers(struct client_state *csp);
886 static jb_err header_tagger(struct client_state *csp, char *header);
887 static jb_err parse_header_time(const char *header_time, time_t *result);
888
889 static jb_err crumble                   (struct client_state *csp, char **header);
890 static jb_err connection                (struct client_state *csp, char **header);
891 static jb_err filter_header             (struct client_state *csp, char **header);
892 static jb_err client_referrer           (struct client_state *csp, char **header);
893 static jb_err client_uagent             (struct client_state *csp, char **header);
894 static jb_err client_ua                 (struct client_state *csp, char **header);
895 static jb_err client_from               (struct client_state *csp, char **header);
896 static jb_err client_send_cookie        (struct client_state *csp, char **header);
897 static jb_err client_x_forwarded        (struct client_state *csp, char **header);
898 static jb_err client_accept_encoding    (struct client_state *csp, char **header);
899 static jb_err client_te                 (struct client_state *csp, char **header);
900 static jb_err client_max_forwards       (struct client_state *csp, char **header);
901 static jb_err client_host               (struct client_state *csp, char **header);
902 static jb_err client_if_modified_since  (struct client_state *csp, char **header);
903 static jb_err client_accept_language    (struct client_state *csp, char **header);
904 static jb_err client_if_none_match      (struct client_state *csp, char **header);
905 static jb_err crunch_client_header      (struct client_state *csp, char **header);
906 static jb_err client_x_filter           (struct client_state *csp, char **header);
907 static jb_err client_range              (struct client_state *csp, char **header);
908 static jb_err server_set_cookie         (struct client_state *csp, char **header);
909 static jb_err server_content_type       (struct client_state *csp, char **header);
910 static jb_err server_content_length     (struct client_state *csp, char **header);
911 static jb_err server_content_md5        (struct client_state *csp, char **header);
912 static jb_err server_content_encoding   (struct client_state *csp, char **header);
913 static jb_err server_transfer_coding    (struct client_state *csp, char **header);
914 static jb_err server_http               (struct client_state *csp, char **header);
915 static jb_err crunch_server_header      (struct client_state *csp, char **header);
916 static jb_err server_last_modified      (struct client_state *csp, char **header);
917 static jb_err server_content_disposition(struct client_state *csp, char **header);
918
919 static jb_err client_host_adder       (struct client_state *csp);
920 static jb_err client_xtra_adder       (struct client_state *csp);
921 static jb_err connection_close_adder  (struct client_state *csp); 
922
923 static jb_err create_forged_referrer(char **header, const char *hostport);
924 static jb_err create_fake_referrer(char **header, const char *fake_referrer);
925 static jb_err handle_conditional_hide_referrer_parameter(char **header,
926    const char *host, const int parameter_conditional_block);
927
928 /*
929  * List of functions to run on a list of headers.
930  */
931 struct parsers
932 {
933    /** The header prefix to match */
934    const char *str;
935    
936    /** The length of the prefix to match */
937    const size_t len;
938    
939    /** The function to apply to this line */
940    const parser_func_ptr parser;
941 };
942
943 static const struct parsers client_patterns[] = {
944    { "referer:",                  8,   client_referrer },
945    { "user-agent:",              11,   client_uagent },
946    { "ua-",                       3,   client_ua },
947    { "from:",                     5,   client_from },
948    { "cookie:",                   7,   client_send_cookie },
949    { "x-forwarded-for:",         16,   client_x_forwarded },
950    { "Accept-Encoding:",         16,   client_accept_encoding },
951    { "TE:",                       3,   client_te },
952    { "Host:",                     5,   client_host },
953    { "if-modified-since:",       18,   client_if_modified_since },
954    { "Keep-Alive:",              11,   crumble },
955    { "connection:",              11,   connection },
956    { "proxy-connection:",        17,   crumble },
957    { "max-forwards:",            13,   client_max_forwards },
958    { "Accept-Language:",         16,   client_accept_language },
959    { "if-none-match:",           14,   client_if_none_match },
960    { "Range:",                    6,   client_range },
961    { "Request-Range:",           14,   client_range },
962    { "If-Range:",                 9,   client_range },
963    { "X-Filter:",                 9,   client_x_filter },
964    { "*",                         0,   crunch_client_header },
965    { "*",                         0,   filter_header },
966    { NULL,                        0,   NULL }
967 };
968
969 static const struct parsers server_patterns[] = {
970    { "HTTP/",                     5, server_http },
971    { "set-cookie:",              11, server_set_cookie },
972    { "connection:",              11, connection },
973    { "Content-Type:",            13, server_content_type },
974    { "Content-MD5:",             12, server_content_md5 },
975    { "Content-Encoding:",        17, server_content_encoding },
976    { "Transfer-Encoding:",       18, server_transfer_coding },
977    { "Keep-Alive:",              11, crumble },
978    { "content-disposition:",     20, server_content_disposition },
979    { "Last-Modified:",           14, server_last_modified },
980    { "*",                         0, crunch_server_header },
981    { "*",                         0, filter_header },
982    { NULL, 0, NULL }
983 };
984
985 static const add_header_func_ptr add_client_headers[] = {
986    client_host_adder,
987    client_xtra_adder,
988    /* Temporarily disabled:    client_accept_encoding_adder, */
989    connection_close_adder,
990    NULL
991 };
992
993 static const add_header_func_ptr add_server_headers[] = {
994    connection_close_adder,
995    NULL
996 };
997
998 /*********************************************************************
999  *
1000  * Function    :  flush_socket
1001  *
1002  * Description :  Write any pending "buffered" content.
1003  *
1004  * Parameters  :
1005  *          1  :  fd = file descriptor of the socket to read
1006  *          2  :  iob = The I/O buffer to flush, usually csp->iob.
1007  *
1008  * Returns     :  On success, the number of bytes written are returned (zero
1009  *                indicates nothing was written).  On error, -1 is returned,
1010  *                and errno is set appropriately.  If count is zero and the
1011  *                file descriptor refers to a regular file, 0 will be
1012  *                returned without causing any other effect.  For a special
1013  *                file, the results are not portable.
1014  *
1015  *********************************************************************/
1016 int flush_socket(jb_socket fd, struct iob *iob)
1017 {
1018    int len = iob->eod - iob->cur;
1019
1020    if (len <= 0)
1021    {
1022       return(0);
1023    }
1024
1025    if (write_socket(fd, iob->cur, (size_t)len))
1026    {
1027       return(-1);
1028    }
1029    iob->eod = iob->cur = iob->buf;
1030    return(len);
1031
1032 }
1033
1034
1035 /*********************************************************************
1036  *
1037  * Function    :  add_to_iob
1038  *
1039  * Description :  Add content to the buffered page, expanding the
1040  *                buffer if necessary.
1041  *
1042  * Parameters  :
1043  *          1  :  csp = Current client state (buffers, headers, etc...)
1044  *          2  :  buf = holds the content to be added to the page
1045  *          3  :  n = number of bytes to be added
1046  *
1047  * Returns     :  JB_ERR_OK on success, JB_ERR_MEMORY if out-of-memory
1048  *                or buffer limit reached.
1049  *
1050  *********************************************************************/
1051 jb_err add_to_iob(struct client_state *csp, char *buf, int n)
1052 {
1053    struct iob *iob = csp->iob;
1054    size_t used, offset, need, want;
1055    char *p;
1056
1057    if (n <= 0) return JB_ERR_OK;
1058
1059    used   = (size_t)(iob->eod - iob->buf);
1060    offset = (size_t)(iob->cur - iob->buf);
1061    need   = used + (size_t)n + 1;
1062
1063    /*
1064     * If the buffer can't hold the new data, extend it first.
1065     * Use the next power of two if possible, else use the actual need.
1066     */
1067    if (need > csp->config->buffer_limit)
1068    {
1069       log_error(LOG_LEVEL_INFO, "Buffer limit reached while extending the buffer (iob)");
1070       return JB_ERR_MEMORY;
1071    }
1072
1073    if (need > iob->size)
1074    {
1075       for (want = csp->iob->size ? csp->iob->size : 512; want <= need;) want *= 2;
1076       
1077       if (want <= csp->config->buffer_limit && NULL != (p = (char *)realloc(iob->buf, want)))
1078       {
1079          iob->size = want;
1080       }
1081       else if (NULL != (p = (char *)realloc(iob->buf, need)))
1082       {
1083          iob->size = need;
1084       }
1085       else
1086       {
1087          log_error(LOG_LEVEL_ERROR, "Extending the buffer (iob) failed: %E");
1088          return JB_ERR_MEMORY;
1089       }
1090
1091       /* Update the iob pointers */
1092       iob->cur = p + offset;
1093       iob->eod = p + used;
1094       iob->buf = p;
1095    }
1096
1097    /* copy the new data into the iob buffer */
1098    memcpy(iob->eod, buf, (size_t)n);
1099
1100    /* point to the end of the data */
1101    iob->eod += n;
1102
1103    /* null terminate == cheap insurance */
1104    *iob->eod = '\0';
1105
1106    return JB_ERR_OK;
1107
1108 }
1109
1110
1111 #ifdef FEATURE_ZLIB
1112 /*********************************************************************
1113  *
1114  * Function    :  decompress_iob
1115  *
1116  * Description :  Decompress buffered page, expanding the
1117  *                buffer as necessary.  csp->iob->cur
1118  *                should point to the the beginning of the
1119  *                compressed data block.
1120  *
1121  * Parameters  :
1122  *          1  :  csp = Current client state (buffers, headers, etc...)
1123  *
1124  * Returns     :  JB_ERR_OK on success,
1125  *                JB_ERR_MEMORY if out-of-memory limit reached, and
1126  *                JB_ERR_COMPRESS if error decompressing buffer.
1127  *
1128  *********************************************************************/
1129 jb_err decompress_iob(struct client_state *csp)
1130 {
1131    char  *buf;       /* new, uncompressed buffer */
1132    char  *cur;       /* Current iob position (to keep the original 
1133                       * iob->cur unmodified if we return early) */
1134    size_t bufsize;   /* allocated size of the new buffer */
1135    size_t old_size;  /* Content size before decompression */
1136    size_t skip_size; /* Number of bytes at the beginning of the iob
1137                         that we should NOT decompress. */
1138    int status;       /* return status of the inflate() call */
1139    z_stream zstr;    /* used by calls to zlib */
1140
1141    assert(csp->iob->cur - csp->iob->buf > 0);
1142    assert(csp->iob->eod - csp->iob->cur > 0);
1143
1144    bufsize = csp->iob->size;
1145    skip_size = (size_t)(csp->iob->cur - csp->iob->buf);
1146    old_size = (size_t)(csp->iob->eod - csp->iob->cur);
1147
1148    cur = csp->iob->cur;
1149
1150    if (bufsize < 10)
1151    {
1152       /*
1153        * This is to protect the parsing of gzipped data,
1154        * but it should(?) be valid for deflated data also.
1155        */
1156       log_error(LOG_LEVEL_ERROR, "Buffer too small decompressing iob");
1157       return JB_ERR_COMPRESS;
1158    }
1159
1160    if (csp->content_type & CT_GZIP)
1161    {
1162       /*
1163        * Our task is slightly complicated by the facts that data
1164        * compressed by gzip does not include a zlib header, and
1165        * that there is no easily accessible interface in zlib to
1166        * handle a gzip header. We strip off the gzip header by
1167        * hand, and later inform zlib not to expect a header.
1168        */
1169
1170       /*
1171        * Strip off the gzip header. Please see RFC 1952 for more
1172        * explanation of the appropriate fields.
1173        */
1174       if ((*cur++ != (char)0x1f)
1175        || (*cur++ != (char)0x8b)
1176        || (*cur++ != Z_DEFLATED))
1177       {
1178          log_error(LOG_LEVEL_ERROR, "Invalid gzip header when decompressing");
1179          return JB_ERR_COMPRESS;
1180       }
1181       else
1182       {
1183          int flags = *cur++;
1184          /*
1185           * XXX: These magic numbers should be replaced
1186           * with macros to give a better idea what they do.
1187           */
1188          if (flags & 0xe0)
1189          {
1190             /* The gzip header has reserved bits set; bail out. */
1191             log_error(LOG_LEVEL_ERROR, "Invalid gzip header flags when decompressing");
1192             return JB_ERR_COMPRESS;
1193          }
1194          cur += 6;
1195
1196          /* Skip extra fields if necessary. */
1197          if (flags & 0x04)
1198          {
1199             /*
1200              * Skip a given number of bytes, specified
1201              * as a 16-bit little-endian value.
1202              */
1203             /*
1204              * XXX: This code used to be:
1205              * 
1206              * csp->iob->cur += *csp->iob->cur++ + (*csp->iob->cur++ << 8);
1207              *
1208              * which I had to change into:
1209              *
1210              * cur += *cur++ + (*cur++ << 8);
1211              *
1212              * at which point gcc43 finally noticed that the value
1213              * of cur is undefined (it depends on which of the
1214              * summands is evaluated first).
1215              *
1216              * I haven't come across a site where this
1217              * code is actually executed yet, but I hope
1218              * it works anyway.
1219              */
1220             int skip_bytes;
1221             skip_bytes = *cur++;
1222             skip_bytes = *cur++ << 8;
1223
1224             assert(skip_bytes == *csp->iob->cur - 2 + ((*csp->iob->cur - 1) << 8));
1225
1226             /*
1227              * The number of bytes to skip should be positive
1228              * and we'd like to stay in the buffer.
1229              */
1230             if ((skip_bytes < 0) || (skip_bytes >= (csp->iob->eod - cur)))
1231             {
1232                log_error(LOG_LEVEL_ERROR,
1233                   "Unreasonable amount of bytes to skip (%d). Stopping decompression",
1234                   skip_bytes);
1235                return JB_ERR_COMPRESS;
1236             }
1237             log_error(LOG_LEVEL_INFO,
1238                "Skipping %d bytes for gzip compression. Does this sound right?",
1239                skip_bytes);
1240             cur += skip_bytes;
1241          }
1242
1243          /* Skip the filename if necessary. */
1244          if (flags & 0x08)
1245          {
1246             /* A null-terminated string is supposed to follow. */
1247             while (*cur++ && (cur < csp->iob->eod));
1248
1249          }
1250
1251          /* Skip the comment if necessary. */
1252          if (flags & 0x10)
1253          {
1254             /* A null-terminated string is supposed to follow. */
1255             while (*cur++ && (cur < csp->iob->eod));
1256          }
1257
1258          /* Skip the CRC if necessary. */
1259          if (flags & 0x02)
1260          {
1261             cur += 2;
1262          }
1263
1264          if (cur >= csp->iob->eod)
1265          {
1266             /*
1267              * If the current position pointer reached or passed
1268              * the buffer end, we were obviously tricked to skip
1269              * too much.
1270              */
1271             log_error(LOG_LEVEL_ERROR,
1272                "Malformed gzip header detected. Aborting decompression.");
1273             return JB_ERR_COMPRESS;
1274          }
1275       }
1276    }
1277    else if (csp->content_type & CT_DEFLATE)
1278    {
1279       /*
1280        * XXX: The debug level should be lowered
1281        * before the next stable release.
1282        */
1283       log_error(LOG_LEVEL_INFO, "Decompressing deflated iob: %d", *cur);
1284       /*
1285        * In theory (that is, according to RFC 1950), deflate-compressed
1286        * data should begin with a two-byte zlib header and have an
1287        * adler32 checksum at the end. It seems that in practice only
1288        * the raw compressed data is sent. Note that this means that
1289        * we are not RFC 1950-compliant here, but the advantage is that
1290        * this actually works. :)
1291        *
1292        * We add a dummy null byte to tell zlib where the data ends,
1293        * and later inform it not to expect a header.
1294        *
1295        * Fortunately, add_to_iob() has thoughtfully null-terminated
1296        * the buffer; we can just increment the end pointer to include
1297        * the dummy byte.  
1298        */
1299       csp->iob->eod++;
1300    }
1301    else
1302    {
1303       log_error(LOG_LEVEL_ERROR,
1304          "Unable to determine compression format for decompression");
1305       return JB_ERR_COMPRESS;
1306    }
1307
1308    /* Set up the fields required by zlib. */
1309    zstr.next_in  = (Bytef *)cur;
1310    zstr.avail_in = (unsigned int)(csp->iob->eod - cur);
1311    zstr.zalloc   = Z_NULL;
1312    zstr.zfree    = Z_NULL;
1313    zstr.opaque   = Z_NULL;
1314
1315    /*
1316     * Passing -MAX_WBITS to inflateInit2 tells the library
1317     * that there is no zlib header.
1318     */
1319    if (inflateInit2 (&zstr, -MAX_WBITS) != Z_OK)
1320    {
1321       log_error(LOG_LEVEL_ERROR, "Error initializing decompression");
1322       return JB_ERR_COMPRESS;
1323    }
1324
1325    /*
1326     * Next, we allocate new storage for the inflated data.
1327     * We don't modify the existing iob yet, so in case there
1328     * is error in decompression we can recover gracefully.
1329     */
1330    buf = zalloc(bufsize);
1331    if (NULL == buf)
1332    {
1333       log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob");
1334       return JB_ERR_MEMORY;
1335    }
1336
1337    assert(bufsize >= skip_size);
1338    memcpy(buf, csp->iob->buf, skip_size);
1339    zstr.avail_out = bufsize - skip_size;
1340    zstr.next_out  = (Bytef *)buf + skip_size;
1341
1342    /* Try to decompress the whole stream in one shot. */
1343    while (Z_BUF_ERROR == (status = inflate(&zstr, Z_FINISH)))
1344    {
1345       /* We need to allocate more memory for the output buffer. */
1346
1347       char *tmpbuf;                /* used for realloc'ing the buffer */
1348       size_t oldbufsize = bufsize; /* keep track of the old bufsize */
1349
1350       /*
1351        * If zlib wants more data then there's a problem, because
1352        * the complete compressed file should have been buffered.
1353        */
1354       if (0 == zstr.avail_in)
1355       {
1356          log_error(LOG_LEVEL_ERROR, "Unexpected end of compressed iob");
1357          return JB_ERR_COMPRESS;
1358       }
1359
1360       /*
1361        * If we tried the limit and still didn't have enough
1362        * memory, just give up.
1363        */
1364       if (bufsize == csp->config->buffer_limit)
1365       {
1366          log_error(LOG_LEVEL_ERROR, "Buffer limit reached while decompressing iob");
1367          return JB_ERR_MEMORY;
1368       }
1369
1370       /* Try doubling the buffer size each time. */
1371       bufsize *= 2;
1372
1373       /* Don't exceed the buffer limit. */
1374       if (bufsize > csp->config->buffer_limit)
1375       {
1376          bufsize = csp->config->buffer_limit;
1377       }
1378     
1379       /* Try to allocate the new buffer. */
1380       tmpbuf = realloc(buf, bufsize);
1381       if (NULL == tmpbuf)
1382       {
1383          log_error(LOG_LEVEL_ERROR, "Out of memory decompressing iob");
1384          freez(buf);
1385          return JB_ERR_MEMORY;
1386       }
1387       else
1388       {
1389          char *oldnext_out = (char *)zstr.next_out;
1390
1391          /*
1392           * Update the fields for inflate() to use the new
1393           * buffer, which may be in a location different from
1394           * the old one.
1395           */
1396          zstr.avail_out += bufsize - oldbufsize;
1397          zstr.next_out   = (Bytef *)tmpbuf + bufsize - zstr.avail_out;
1398
1399          /*
1400           * Compare with an uglier method of calculating these values
1401           * that doesn't require the extra oldbufsize variable.
1402           */
1403          assert(zstr.avail_out == tmpbuf + bufsize - (char *)zstr.next_out);
1404          assert((char *)zstr.next_out == tmpbuf + ((char *)oldnext_out - buf));
1405          assert(zstr.avail_out > 0);
1406
1407          buf = tmpbuf;
1408       }
1409    }
1410
1411    if (Z_STREAM_ERROR == inflateEnd(&zstr))
1412    {
1413       log_error(LOG_LEVEL_ERROR,
1414          "Inconsistent stream state after decompression: %s", zstr.msg);
1415       /*
1416        * XXX: Intentionally no return.
1417        *
1418        * According to zlib.h, Z_STREAM_ERROR is returned
1419        * "if the stream state was inconsistent".
1420        *
1421        * I assume in this case inflate()'s status
1422        * would also be something different than Z_STREAM_END
1423        * so this check should be redundant, but lets see.
1424        */
1425    }
1426
1427    if (status != Z_STREAM_END)
1428    {
1429       /* We failed to decompress the stream. */
1430       log_error(LOG_LEVEL_ERROR,
1431          "Error in decompressing to the buffer (iob): %s", zstr.msg);
1432       return JB_ERR_COMPRESS;
1433    }
1434
1435    /*
1436     * Finally, we can actually update the iob, since the
1437     * decompression was successful. First, free the old
1438     * buffer.
1439     */
1440    freez(csp->iob->buf);
1441
1442    /* Now, update the iob to use the new buffer. */
1443    csp->iob->buf  = buf;
1444    csp->iob->cur  = csp->iob->buf + skip_size;
1445    csp->iob->eod  = (char *)zstr.next_out;
1446    csp->iob->size = bufsize;
1447   
1448    /*
1449     * Make sure the new uncompressed iob obeys some minimal
1450     * consistency conditions.
1451     */
1452    if ((csp->iob->buf <  csp->iob->cur)
1453     && (csp->iob->cur <= csp->iob->eod)
1454     && (csp->iob->eod <= csp->iob->buf + csp->iob->size))
1455    {
1456       const size_t new_size = (size_t)(csp->iob->eod - csp->iob->cur);
1457       if (new_size > 0)
1458       {
1459          log_error(LOG_LEVEL_RE_FILTER,
1460             "Decompression successful. Old size: %d, new size: %d.",
1461             old_size, new_size);
1462       }
1463       else
1464       {
1465          /* zlib thinks this is OK, so lets do the same. */
1466          log_error(LOG_LEVEL_INFO, "Decompression didn't result in any content.");
1467       }
1468    }
1469    else
1470    {
1471       /* It seems that zlib did something weird. */
1472       log_error(LOG_LEVEL_ERROR,
1473          "Unexpected error decompressing the buffer (iob): %d==%d, %d>%d, %d<%d",
1474          csp->iob->cur, csp->iob->buf + skip_size, csp->iob->eod, csp->iob->buf,
1475          csp->iob->eod, csp->iob->buf + csp->iob->size);
1476       return JB_ERR_COMPRESS;
1477    }
1478
1479    return JB_ERR_OK;
1480
1481 }
1482 #endif /* defined(FEATURE_ZLIB) */
1483
1484
1485 /*********************************************************************
1486  *
1487  * Function    :  string_move
1488  *
1489  * Description :  memmove wrapper to move the last part of a string
1490  *                towards the beginning, overwriting the part in
1491  *                the middle. strlcpy() can't be used here as the
1492  *                strings overlap.
1493  *
1494  * Parameters  :
1495  *          1  :  dst = Destination to overwrite
1496  *          2  :  src = Source to move.
1497  *
1498  * Returns     :  N/A
1499  *
1500  *********************************************************************/
1501 static void string_move(char *dst, char *src)
1502 {
1503    assert(dst < src);
1504
1505    /* +1 to copy the terminating nul as well. */
1506    memmove(dst, src, strlen(src)+1);
1507 }
1508
1509
1510 /*********************************************************************
1511  *
1512  * Function    :  normalize_lws
1513  *
1514  * Description :  Reduces unquoted linear white space in headers
1515  *                to a single space in accordance with RFC 2616 2.2.
1516  *                This simplifies parsing and filtering later on.
1517  *
1518  *                XXX: Remove log messages before
1519  *                     the next stable release?
1520  *
1521  * Parameters  :
1522  *          1  :  header = A header with linear white space to reduce.
1523  *
1524  * Returns     :  N/A
1525  *
1526  *********************************************************************/
1527 static void normalize_lws(char *header)
1528 {
1529    char *p = header;
1530
1531    while (*p != '\0')
1532    {
1533       if (ijb_isspace(*p) && ijb_isspace(*(p+1)))
1534       {
1535          char *q = p+1;
1536
1537          while (ijb_isspace(*q))
1538          {
1539             q++;
1540          }
1541          log_error(LOG_LEVEL_HEADER, "Reducing white space in '%s'", header);
1542          string_move(p+1, q);
1543       }
1544
1545       if (*p == '\t')
1546       {
1547          log_error(LOG_LEVEL_HEADER,
1548             "Converting tab to space in '%s'", header);
1549          *p = ' ';
1550       }
1551       else if (*p == '"')
1552       {
1553          char *end_of_token = strstr(p+1, "\"");
1554
1555          if (NULL != end_of_token)
1556          {
1557             /* Don't mess with quoted text. */
1558             p = end_of_token;
1559          }
1560          else
1561          {
1562             log_error(LOG_LEVEL_HEADER,
1563                "Ignoring single quote in '%s'", header);
1564          }
1565       }
1566       p++;
1567    }
1568
1569    p = strchr(header, ':');
1570    if ((p != NULL) && (p != header) && ijb_isspace(*(p-1)))
1571    {
1572       /*
1573        * There's still space before the colon.
1574        * We don't want it.
1575        */
1576       string_move(p-1, p);
1577    }
1578 }
1579
1580
1581 /*********************************************************************
1582  *
1583  * Function    :  get_header
1584  *
1585  * Description :  This (odd) routine will parse the csp->iob
1586  *                to get the next complete header.
1587  *
1588  * Parameters  :
1589  *          1  :  iob = The I/O buffer to parse, usually csp->iob.
1590  *
1591  * Returns     :  Any one of the following:
1592  *
1593  * 1) a pointer to a dynamically allocated string that contains a header line
1594  * 2) NULL  indicating that the end of the header was reached
1595  * 3) ""    indicating that the end of the iob was reached before finding
1596  *          a complete header line.
1597  *
1598  *********************************************************************/
1599 char *get_header(struct iob *iob)
1600 {
1601    char *header;
1602
1603    header = get_header_line(iob);
1604
1605    if ((header == NULL) || (*header == '\0'))
1606    {
1607       /*
1608        * No complete header read yet, tell the client.
1609        */
1610       return header;
1611    }
1612
1613    while ((iob->cur[0] == ' ') || (iob->cur[0] == '\t'))
1614    {
1615       /*
1616        * Header spans multiple lines, append the next one.
1617        */
1618       char *continued_header;
1619       
1620       continued_header = get_header_line(iob);
1621       if ((continued_header == NULL) || (*continued_header == '\0'))
1622       {
1623          /*
1624           * No complete header read yet, return what we got.
1625           * XXX: Should "unread" header instead.
1626           */
1627          log_error(LOG_LEVEL_INFO,
1628             "Failed to read a multi-line header properly: '%s'",
1629             header);
1630          break;
1631       }
1632
1633       if (JB_ERR_OK != string_join(&header, continued_header))
1634       {
1635          log_error(LOG_LEVEL_FATAL,
1636             "Out of memory while appending multiple headers.");
1637       }
1638       else
1639       {
1640          /* XXX: remove before next stable release. */
1641          log_error(LOG_LEVEL_HEADER,
1642             "Merged multiple header lines to: '%s'",
1643             header);
1644       }
1645    }
1646
1647    normalize_lws(header);
1648
1649    return header;
1650
1651 }
1652
1653
1654 /*********************************************************************
1655  *
1656  * Function    :  get_header_line
1657  *
1658  * Description :  This (odd) routine will parse the csp->iob
1659  *                to get the next header line.
1660  *
1661  * Parameters  :
1662  *          1  :  iob = The I/O buffer to parse, usually csp->iob.
1663  *
1664  * Returns     :  Any one of the following:
1665  *
1666  * 1) a pointer to a dynamically allocated string that contains a header line
1667  * 2) NULL  indicating that the end of the header was reached
1668  * 3) ""    indicating that the end of the iob was reached before finding
1669  *          a complete header line.
1670  *
1671  *********************************************************************/
1672 static char *get_header_line(struct iob *iob)
1673 {
1674    char *p, *q, *ret;
1675
1676    if ((iob->cur == NULL)
1677       || ((p = strchr(iob->cur, '\n')) == NULL))
1678    {
1679       return(""); /* couldn't find a complete header */
1680    }
1681
1682    *p = '\0';
1683
1684    ret = strdup(iob->cur);
1685    if (ret == NULL)
1686    {
1687       /* FIXME No way to handle error properly */
1688       log_error(LOG_LEVEL_FATAL, "Out of memory in get_header_line()");
1689    }
1690
1691    iob->cur = p+1;
1692
1693    if ((q = strchr(ret, '\r')) != NULL) *q = '\0';
1694
1695    /* is this a blank line (i.e. the end of the header) ? */
1696    if (*ret == '\0')
1697    {
1698       freez(ret);
1699       return(NULL);
1700    }
1701
1702    return(ret);
1703
1704 }
1705
1706
1707 /*********************************************************************
1708  *
1709  * Function    :  get_header_value
1710  *
1711  * Description :  Get the value of a given header from a chained list
1712  *                of header lines or return NULL if no such header is
1713  *                present in the list.
1714  *
1715  * Parameters  :
1716  *          1  :  header_list = pointer to list
1717  *          2  :  header_name = string with name of header to look for.
1718  *                              Trailing colon required, capitalization
1719  *                              doesn't matter.
1720  *
1721  * Returns     :  NULL if not found, else value of header
1722  *
1723  *********************************************************************/
1724 char *get_header_value(const struct list *header_list, const char *header_name)
1725 {
1726    struct list_entry *cur_entry;
1727    char *ret = NULL;
1728    size_t length = 0;
1729
1730    assert(header_list);
1731    assert(header_name);
1732    length = strlen(header_name);
1733
1734    for (cur_entry = header_list->first; cur_entry ; cur_entry = cur_entry->next)
1735    {
1736       if (cur_entry->str)
1737       {
1738          if (!strncmpic(cur_entry->str, header_name, length))
1739          {
1740             /*
1741              * Found: return pointer to start of value
1742              */
1743             ret = (char *) (cur_entry->str + length);
1744             while (*ret && ijb_isspace(*ret)) ret++;
1745             return(ret);
1746          }
1747       }
1748    }
1749
1750    /* 
1751     * Not found
1752     */
1753    return NULL;
1754
1755 }
1756
1757
1758 /*********************************************************************
1759  *
1760  * Function    :  scan_headers
1761  *
1762  * Description :  Scans headers, applies tags and updates action bits. 
1763  *
1764  * Parameters  :
1765  *          1  :  csp = Current client state (buffers, headers, etc...)
1766  *
1767  * Returns     :  JB_ERR_OK
1768  *
1769  *********************************************************************/
1770 static jb_err scan_headers(struct client_state *csp)
1771 {
1772    struct list_entry *h; /* Header */
1773    jb_err err = JB_ERR_OK;
1774
1775    for (h = csp->headers->first; (err == JB_ERR_OK) && (h != NULL) ; h = h->next)
1776    {
1777       /* Header crunch()ed in previous run? -> ignore */
1778       if (h->str == NULL) continue;
1779       log_error(LOG_LEVEL_HEADER, "scan: %s", h->str);
1780       err = header_tagger(csp, h->str);
1781    }
1782
1783    return err;
1784 }
1785
1786
1787 /*********************************************************************
1788  *
1789  * Function    :  sed
1790  *
1791  * Description :  add, delete or modify lines in the HTTP header streams.
1792  *                On entry, it receives a linked list of headers space
1793  *                that was allocated dynamically (both the list nodes
1794  *                and the header contents).
1795  *
1796  *                As a side effect it frees the space used by the original
1797  *                header lines.
1798  *
1799  * Parameters  :
1800  *          1  :  csp = Current client state (buffers, headers, etc...)
1801  *          2  :  filter_server_headers = Boolean to switch between
1802  *                                        server and header filtering.
1803  *
1804  * Returns     :  JB_ERR_OK in case off success, or
1805  *                JB_ERR_MEMORY on out-of-memory error.
1806  *
1807  *********************************************************************/
1808 jb_err sed(struct client_state *csp, int filter_server_headers)
1809 {
1810    /* XXX: use more descriptive names. */
1811    struct list_entry *p;
1812    const struct parsers *v;
1813    const add_header_func_ptr *f;
1814    jb_err err = JB_ERR_OK;
1815
1816    if (filter_server_headers)
1817    {
1818       v = server_patterns;
1819       f = add_server_headers;
1820    }
1821    else
1822    {
1823       v = client_patterns;
1824       f = add_client_headers;
1825    }
1826
1827    scan_headers(csp);
1828
1829    while ((err == JB_ERR_OK) && (v->str != NULL))
1830    {
1831       for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL); p = p->next)
1832       {
1833          /* Header crunch()ed in previous run? -> ignore */
1834          if (p->str == NULL) continue;
1835
1836          /* Does the current parser handle this header? */
1837          if ((strncmpic(p->str, v->str, v->len) == 0) ||
1838              (v->len == CHECK_EVERY_HEADER_REMAINING))
1839          {
1840             err = v->parser(csp, &(p->str));
1841          }
1842       }
1843       v++;
1844    }
1845
1846    /* place additional headers on the csp->headers list */
1847    while ((err == JB_ERR_OK) && (*f))
1848    {
1849       err = (*f)(csp);
1850       f++;
1851    }
1852
1853    return err;
1854 }
1855
1856
1857 /*********************************************************************
1858  *
1859  * Function    :  update_server_headers
1860  *
1861  * Description :  Updates server headers after the body has been modified.
1862  *
1863  * Parameters  :
1864  *          1  :  csp = Current client state (buffers, headers, etc...)
1865  *
1866  * Returns     :  JB_ERR_OK in case off success, or
1867  *                JB_ERR_MEMORY on out-of-memory error.
1868  *
1869  *********************************************************************/
1870 jb_err update_server_headers(struct client_state *csp)
1871 {
1872    jb_err err = JB_ERR_OK;
1873
1874    static const struct parsers server_patterns_light[] = {
1875       { "Content-Length:",    15, server_content_length },
1876       { "Transfer-Encoding:", 18, server_transfer_coding },
1877 #ifdef FEATURE_ZLIB
1878       { "Content-Encoding:",  17, server_content_encoding },
1879 #endif /* def FEATURE_ZLIB */
1880       { NULL, 0, NULL }
1881    };
1882
1883    if (strncmpic(csp->http->cmd, "HEAD", 4))
1884    {
1885       const struct parsers *v;
1886       struct list_entry *p;
1887
1888       for (v = server_patterns_light; (err == JB_ERR_OK) && (v->str != NULL); v++)
1889       {
1890          for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL); p = p->next)
1891          {
1892             /* Header crunch()ed in previous run? -> ignore */
1893             if (p->str == NULL) continue;
1894
1895             /* Does the current parser handle this header? */
1896             if (strncmpic(p->str, v->str, v->len) == 0)
1897             {
1898                err = v->parser(csp, (char **)&(p->str));
1899             }
1900          }
1901       }
1902    }
1903
1904    return err;
1905 }
1906
1907
1908 /*********************************************************************
1909  *
1910  * Function    :  header_tagger
1911  *
1912  * Description :  Executes all text substitutions from applying
1913  *                tag actions and saves the result as tag.
1914  *
1915  *                XXX: Shares enough code with filter_header() and
1916  *                pcrs_filter_response() to warrant some helper functions.
1917  *
1918  * Parameters  :
1919  *          1  :  csp = Current client state (buffers, headers, etc...)
1920  *          2  :  header = Header that is used as tagger input
1921  *
1922  * Returns     :  JB_ERR_OK on success and always succeeds
1923  *
1924  *********************************************************************/
1925 static jb_err header_tagger(struct client_state *csp, char *header)
1926 {
1927    int wanted_filter_type;
1928    int multi_action_index;
1929    int i;
1930    pcrs_job *job;
1931
1932    struct file_list *fl;
1933    struct re_filterfile_spec *b;
1934    struct list_entry *tag_name;
1935
1936    int found_filters = 0;
1937    const size_t header_length = strlen(header);
1938
1939    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
1940    {
1941       wanted_filter_type = FT_SERVER_HEADER_TAGGER;
1942       multi_action_index = ACTION_MULTI_SERVER_HEADER_TAGGER;
1943    }
1944    else
1945    {
1946       wanted_filter_type = FT_CLIENT_HEADER_TAGGER;
1947       multi_action_index = ACTION_MULTI_CLIENT_HEADER_TAGGER;
1948    }
1949
1950    /* Check if there are any filters */
1951    for (i = 0; i < MAX_AF_FILES; i++)
1952    {
1953       fl = csp->rlist[i];
1954       if (NULL != fl)
1955       {
1956          if (NULL != fl->f)
1957          {
1958            found_filters = 1;
1959            break;
1960          }
1961       }
1962    }
1963
1964    if (0 == found_filters)
1965    {
1966       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
1967          "tagging enabled, but no taggers available.");
1968       return(JB_ERR_OK);
1969    }
1970
1971    for (i = 0; i < MAX_AF_FILES; i++)
1972    {
1973       fl = csp->rlist[i];
1974       if ((NULL == fl) || (NULL == fl->f))
1975       {
1976          /*
1977           * Either there are no filter files
1978           * left, or this filter file just
1979           * contains no valid filters.
1980           *
1981           * Continue to be sure we don't miss
1982           * valid filter files that are chained
1983           * after empty or invalid ones.
1984           */
1985          continue;
1986       }
1987
1988       /* For all filters, */
1989       for (b = fl->f; b; b = b->next)
1990       {
1991          if (b->type != wanted_filter_type)
1992          {
1993             /* skip the ones we don't care about, */
1994             continue;
1995          }
1996          /* leaving only taggers that could apply, of which we use the ones, */
1997          for (tag_name = csp->action->multi[multi_action_index]->first;
1998               NULL != tag_name; tag_name = tag_name->next)
1999          {
2000             /* that do apply, and */
2001             if (strcmp(b->name, tag_name->str) == 0)
2002             {
2003                char *modified_tag = NULL;
2004                char *tag = header;
2005                size_t size = header_length;
2006                pcrs_job *joblist = b->joblist;
2007
2008                if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
2009
2010                if (NULL == joblist)
2011                {
2012                   log_error(LOG_LEVEL_RE_FILTER,
2013                      "Tagger %s has empty joblist. Nothing to do.", b->name);
2014                   continue;
2015                }
2016
2017                /* execute their pcrs_joblist on the header. */
2018                for (job = joblist; NULL != job; job = job->next)
2019                {
2020                   const int hits = pcrs_execute(job, tag, size, &modified_tag, &size);
2021
2022                   if (0 < hits)
2023                   {
2024                      /* Success, continue with the modified version. */
2025                      if (tag != header)
2026                      {
2027                         freez(tag);
2028                      }
2029                      tag = modified_tag;
2030                   }
2031                   else
2032                   {
2033                      /* Tagger doesn't match */
2034                      if (0 > hits)
2035                      {
2036                         /* Regex failure, log it but continue anyway. */
2037                         log_error(LOG_LEVEL_ERROR,
2038                            "Problems with tagger \'%s\' and header \'%s\': %s",
2039                            b->name, *header, pcrs_strerror(hits));
2040                      }
2041                      freez(modified_tag);
2042                   }
2043                }
2044
2045                if (b->dynamic) pcrs_free_joblist(joblist);
2046
2047                /* If this tagger matched */
2048                if (tag != header)
2049                {
2050                   if (0 == size)
2051                   {
2052                      /*
2053                       * There is to technical limitation which makes
2054                       * it impossible to use empty tags, but I assume
2055                       * no one would do it intentionally.
2056                       */
2057                      freez(tag);
2058                      log_error(LOG_LEVEL_INFO,
2059                         "Tagger \'%s\' created an empty tag. Ignored.",
2060                         b->name);
2061                      continue;
2062                   }
2063  
2064                   if (!list_contains_item(csp->tags, tag))
2065                   {
2066                      if (JB_ERR_OK != enlist(csp->tags, tag))
2067                      {
2068                         log_error(LOG_LEVEL_ERROR,
2069                            "Insufficient memory to add tag \'%s\', "
2070                            "based on tagger \'%s\' and header \'%s\'",
2071                            tag, b->name, *header);
2072                      }
2073                      else
2074                      {
2075                         char *action_message;
2076                         /*
2077                          * update the action bits right away, to make
2078                          * tagging based on tags set by earlier taggers
2079                          * of the same kind possible.
2080                          */
2081                         if (update_action_bits_for_tag(csp, tag))
2082                         {
2083                            action_message = "Action bits updated accordingly.";
2084                         }
2085                         else
2086                         {
2087                            action_message = "No action bits update necessary.";
2088                         }
2089
2090                         log_error(LOG_LEVEL_HEADER,
2091                            "Tagger \'%s\' added tag \'%s\'. %s",
2092                            b->name, tag, action_message);
2093                      }
2094                   }
2095                   else
2096                   {
2097                      /* XXX: Is this log-worthy? */
2098                      log_error(LOG_LEVEL_HEADER,
2099                         "Tagger \'%s\' didn't add tag \'%s\'. "
2100                         "Tag already present", b->name, tag);
2101                   }
2102                   freez(tag);
2103                } /* if the tagger matched */
2104             } /* if the tagger applies */
2105          } /* for every tagger that could apply */
2106       } /* for all filters */
2107    } /* for all filter files */
2108
2109    return JB_ERR_OK;
2110 }
2111
2112 /* here begins the family of parser functions that reformat header lines */
2113
2114 /*********************************************************************
2115  *
2116  * Function    :  filter_header
2117  *
2118  * Description :  Executes all text substitutions from all applying
2119  *                +(server|client)-header-filter actions on the header.
2120  *                Most of the code was copied from pcrs_filter_response,
2121  *                including the rather short variable names
2122  *
2123  * Parameters  :
2124  *          1  :  csp = Current client state (buffers, headers, etc...)
2125  *          2  :  header = On input, pointer to header to modify.
2126  *                On output, pointer to the modified header, or NULL
2127  *                to remove the header.  This function frees the
2128  *                original string if necessary.
2129  *
2130  * Returns     :  JB_ERR_OK on success and always succeeds
2131  *
2132  *********************************************************************/
2133 static jb_err filter_header(struct client_state *csp, char **header)
2134 {
2135    int hits=0;
2136    int matches;
2137    size_t size = strlen(*header);
2138
2139    char *newheader = NULL;
2140    pcrs_job *job;
2141
2142    struct file_list *fl;
2143    struct re_filterfile_spec *b;
2144    struct list_entry *filtername;
2145
2146    int i, found_filters = 0;
2147    int wanted_filter_type;
2148    int multi_action_index;
2149
2150    if (csp->flags & CSP_FLAG_NO_FILTERING)
2151    {
2152       return JB_ERR_OK;
2153    }
2154
2155    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
2156    {
2157       wanted_filter_type = FT_SERVER_HEADER_FILTER;
2158       multi_action_index = ACTION_MULTI_SERVER_HEADER_FILTER;
2159    }
2160    else
2161    {
2162       wanted_filter_type = FT_CLIENT_HEADER_FILTER;
2163       multi_action_index = ACTION_MULTI_CLIENT_HEADER_FILTER;
2164    }
2165
2166    /*
2167     * Need to check the set of re_filterfiles...
2168     */
2169    for (i = 0; i < MAX_AF_FILES; i++)
2170    {
2171       fl = csp->rlist[i];
2172       if (NULL != fl)
2173       {
2174          if (NULL != fl->f)
2175          {
2176            found_filters = 1;
2177            break;
2178          }
2179       }
2180    }
2181
2182    if (0 == found_filters)
2183    {
2184       log_error(LOG_LEVEL_ERROR, "Inconsistent configuration: "
2185          "header filtering enabled, but no matching filters available.");
2186       return(JB_ERR_OK);
2187    }
2188
2189    for (i = 0; i < MAX_AF_FILES; i++)
2190    {
2191       fl = csp->rlist[i];
2192       if ((NULL == fl) || (NULL == fl->f))
2193       {
2194          /*
2195           * Either there are no filter files
2196           * left, or this filter file just
2197           * contains no valid filters.
2198           *
2199           * Continue to be sure we don't miss
2200           * valid filter files that are chained
2201           * after empty or invalid ones.
2202           */
2203          continue;
2204       }
2205       /*
2206        * For all applying +filter actions, look if a filter by that
2207        * name exists and if yes, execute its pcrs_joblist on the
2208        * buffer.
2209        */
2210       for (b = fl->f; b; b = b->next)
2211       {
2212          if (b->type != wanted_filter_type)
2213          {
2214             /* Skip other filter types */
2215             continue;
2216          }
2217
2218          for (filtername = csp->action->multi[multi_action_index]->first;
2219               filtername ; filtername = filtername->next)
2220          {
2221             if (strcmp(b->name, filtername->str) == 0)
2222             {
2223                int current_hits = 0;
2224                pcrs_job *joblist = b->joblist;
2225
2226                if (b->dynamic) joblist = compile_dynamic_pcrs_job_list(csp, b);
2227
2228                if (NULL == joblist)
2229                {
2230                   log_error(LOG_LEVEL_RE_FILTER, "Filter %s has empty joblist. Nothing to do.", b->name);
2231                   continue;
2232                }
2233
2234                log_error(LOG_LEVEL_RE_FILTER, "filtering \'%s\' (size %d) with \'%s\' ...",
2235                          *header, size, b->name);
2236
2237                /* Apply all jobs from the joblist */
2238                for (job = joblist; NULL != job; job = job->next)
2239                {
2240                   matches = pcrs_execute(job, *header, size, &newheader, &size);
2241                   if ( 0 < matches )
2242                   {
2243                      current_hits += matches; 
2244                      log_error(LOG_LEVEL_HEADER, "Transforming \"%s\" to \"%s\"", *header, newheader);
2245                      freez(*header);
2246                      *header = newheader;
2247                   }
2248                   else if ( 0 == matches )
2249                   {
2250                      /* Filter doesn't change header */
2251                      freez(newheader);
2252                   }
2253                   else
2254                   {
2255                      /* RegEx failure */
2256                      log_error(LOG_LEVEL_ERROR, "Filtering \'%s\' with \'%s\' didn't work out: %s",
2257                         *header, b->name, pcrs_strerror(matches));
2258                      if (newheader != NULL)
2259                      {
2260                         log_error(LOG_LEVEL_ERROR, "Freeing what's left: %s", newheader);
2261                         freez(newheader);
2262                      }
2263                   }
2264                }
2265
2266                if (b->dynamic) pcrs_free_joblist(joblist);
2267
2268                log_error(LOG_LEVEL_RE_FILTER, "... produced %d hits (new size %d).", current_hits, size);
2269                hits += current_hits;
2270             }
2271          }
2272       }
2273    }
2274
2275    /*
2276     * Additionally checking for hits is important because if
2277     * the continue hack is triggered, server headers can
2278     * arrive empty to separate multiple heads from each other.
2279     */
2280    if ((0 == size) && hits)
2281    {
2282       log_error(LOG_LEVEL_HEADER, "Removing empty header %s", *header);
2283       freez(*header);
2284    }
2285
2286    return(JB_ERR_OK);
2287 }
2288
2289
2290 /*********************************************************************
2291  *
2292  * Function    :  connection
2293  *
2294  * Description :  Makes sure that the value of the Connection: header
2295  *                is "close" and signals connection_close_adder 
2296  *                to do nothing.
2297  *
2298  * Parameters  :
2299  *          1  :  csp = Current client state (buffers, headers, etc...)
2300  *          2  :  header = On input, pointer to header to modify.
2301  *                On output, pointer to the modified header, or NULL
2302  *                to remove the header.  This function frees the
2303  *                original string if necessary.
2304  *
2305  * Returns     :  JB_ERR_OK on success, or
2306  *                JB_ERR_MEMORY on out-of-memory error.
2307  *
2308  *********************************************************************/
2309 static jb_err connection(struct client_state *csp, char **header)
2310 {
2311    char *old_header = *header;
2312
2313    /* Do we have a 'Connection: close' header? */
2314    if (strcmpic(*header, "Connection: close"))
2315    {
2316       /* No, create one */
2317       *header = strdup("Connection: close");
2318       if (header == NULL)
2319       { 
2320          return JB_ERR_MEMORY;
2321       }
2322       log_error(LOG_LEVEL_HEADER, "Replaced: \'%s\' with \'%s\'", old_header, *header);
2323       freez(old_header);
2324    }
2325
2326    /* Signal connection_close_adder() to return early. */
2327    if (csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
2328    {
2329       csp->flags |= CSP_FLAG_SERVER_CONNECTION_CLOSE_SET;
2330    }
2331    else
2332    {
2333       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_CLOSE_SET;
2334    }
2335
2336    return JB_ERR_OK;
2337 }
2338
2339
2340 /*********************************************************************
2341  *
2342  * Function    :  crumble
2343  *
2344  * Description :  This is called if a header matches a pattern to "crunch"
2345  *
2346  * Parameters  :
2347  *          1  :  csp = Current client state (buffers, headers, etc...)
2348  *          2  :  header = On input, pointer to header to modify.
2349  *                On output, pointer to the modified header, or NULL
2350  *                to remove the header.  This function frees the
2351  *                original string if necessary.
2352  *
2353  * Returns     :  JB_ERR_OK on success, or
2354  *                JB_ERR_MEMORY on out-of-memory error.
2355  *
2356  *********************************************************************/
2357 static jb_err crumble(struct client_state *csp, char **header)
2358 {
2359    log_error(LOG_LEVEL_HEADER, "crumble crunched: %s!", *header);
2360    freez(*header);
2361    return JB_ERR_OK;
2362 }
2363
2364
2365 /*********************************************************************
2366  *
2367  * Function    :  crunch_server_header
2368  *
2369  * Description :  Crunch server header if it matches a string supplied by the
2370  *                user. Called from `sed'.
2371  *
2372  * Parameters  :
2373  *          1  :  csp = Current client state (buffers, headers, etc...)
2374  *          2  :  header = On input, pointer to header to modify.
2375  *                On output, pointer to the modified header, or NULL
2376  *                to remove the header.  This function frees the
2377  *                original string if necessary.
2378  *
2379  * Returns     :  JB_ERR_OK on success and always succeeds
2380  *
2381  *********************************************************************/
2382 static jb_err crunch_server_header(struct client_state *csp, char **header)
2383 {
2384    const char *crunch_pattern;
2385
2386    /* Do we feel like crunching? */
2387    if ((csp->action->flags & ACTION_CRUNCH_SERVER_HEADER))
2388    {
2389       crunch_pattern = csp->action->string[ACTION_STRING_SERVER_HEADER];
2390
2391       /* Is the current header the lucky one? */
2392       if (strstr(*header, crunch_pattern))
2393       {
2394          log_error(LOG_LEVEL_HEADER, "Crunching server header: %s (contains: %s)", *header, crunch_pattern);  
2395          freez(*header);
2396       }
2397    }
2398
2399    return JB_ERR_OK;
2400 }
2401
2402
2403 /*********************************************************************
2404  *
2405  * Function    :  server_content_type
2406  *
2407  * Description :  Set the content-type for filterable types (text/.*,
2408  *                .*xml.*, javascript and image/gif) unless filtering has been
2409  *                forbidden (CT_TABOO) while parsing earlier headers.
2410  *                NOTE: Since text/plain is commonly used by web servers
2411  *                      for files whose correct type is unknown, we don't
2412  *                      set CT_TEXT for it.
2413  *
2414  * Parameters  :
2415  *          1  :  csp = Current client state (buffers, headers, etc...)
2416  *          2  :  header = On input, pointer to header to modify.
2417  *                On output, pointer to the modified header, or NULL
2418  *                to remove the header.  This function frees the
2419  *                original string if necessary.
2420  *
2421  * Returns     :  JB_ERR_OK on success, or
2422  *                JB_ERR_MEMORY on out-of-memory error.
2423  *
2424  *********************************************************************/
2425 static jb_err server_content_type(struct client_state *csp, char **header)
2426 {
2427    /* Remove header if it isn't the first Content-Type header */
2428    if ((csp->content_type & CT_DECLARED))
2429    {
2430      /*
2431       * Another, slightly slower, way to see if
2432       * we already parsed another Content-Type header.
2433       */
2434       assert(NULL != get_header_value(csp->headers, "Content-Type:"));
2435
2436       log_error(LOG_LEVEL_ERROR,
2437          "Multiple Content-Type headers. Removing and ignoring: \'%s\'",
2438          *header);
2439       freez(*header);
2440
2441       return JB_ERR_OK;
2442    }
2443
2444    /*
2445     * Signal that the Content-Type has been set.
2446     */
2447    csp->content_type |= CT_DECLARED;
2448
2449    if (!(csp->content_type & CT_TABOO))
2450    {
2451       /*
2452        * XXX: The assumption that text/plain is a sign of
2453        * binary data seems to be somewhat unreasonable nowadays
2454        * and should be dropped after 3.0.8 is out.
2455        */
2456       if ((strstr(*header, "text/") && !strstr(*header, "plain"))
2457         || strstr(*header, "xml")
2458         || strstr(*header, "application/x-javascript"))
2459       {
2460          csp->content_type |= CT_TEXT;
2461       }
2462       else if (strstr(*header, "image/gif"))
2463       {
2464          csp->content_type |= CT_GIF;
2465       }
2466    }
2467
2468    /*
2469     * Are we messing with the content type?
2470     */
2471    if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE)
2472    {
2473       /*
2474        * Make sure the user doesn't accidently
2475        * change the content type of binary documents. 
2476        */
2477       if ((csp->content_type & CT_TEXT) || (csp->action->flags & ACTION_FORCE_TEXT_MODE))
2478       {
2479          freez(*header);
2480          *header = strdup("Content-Type: ");
2481          string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]);
2482
2483          if (header == NULL)
2484          {
2485             log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!");
2486             return JB_ERR_MEMORY;
2487          }
2488          log_error(LOG_LEVEL_HEADER, "Modified: %s!", *header);
2489       }
2490       else
2491       {
2492          log_error(LOG_LEVEL_HEADER, "%s not replaced. "
2493             "It doesn't look like a content type that should be filtered. "
2494             "Enable force-text-mode if you know what you're doing.", *header);
2495       }
2496    }
2497
2498    return JB_ERR_OK;
2499 }
2500
2501
2502 /*********************************************************************
2503  *
2504  * Function    :  server_transfer_coding
2505  *
2506  * Description :  - Prohibit filtering (CT_TABOO) if transfer coding compresses
2507  *                - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
2508  *                - Remove header if body was chunked but has been
2509  *                  de-chunked for filtering.
2510  *
2511  * Parameters  :
2512  *          1  :  csp = Current client state (buffers, headers, etc...)
2513  *          2  :  header = On input, pointer to header to modify.
2514  *                On output, pointer to the modified header, or NULL
2515  *                to remove the header.  This function frees the
2516  *                original string if necessary.
2517  *
2518  * Returns     :  JB_ERR_OK on success, or
2519  *                JB_ERR_MEMORY on out-of-memory error.
2520  *
2521  *********************************************************************/
2522 static jb_err server_transfer_coding(struct client_state *csp, char **header)
2523 {
2524    /*
2525     * Turn off pcrs and gif filtering if body compressed
2526     */
2527    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
2528    {
2529 #ifdef FEATURE_ZLIB
2530       /*
2531        * XXX: Added to test if we could use CT_GZIP and CT_DEFLATE here.
2532        */
2533       log_error(LOG_LEVEL_INFO, "Marking content type for %s as CT_TABOO because of %s.",
2534          csp->http->cmd, *header);
2535 #endif /* def FEATURE_ZLIB */
2536       csp->content_type = CT_TABOO;
2537    }
2538
2539    /*
2540     * Raise flag if body chunked
2541     */
2542    if (strstr(*header, "chunked"))
2543    {
2544       csp->flags |= CSP_FLAG_CHUNKED;
2545
2546       /*
2547        * If the body was modified, it has been de-chunked first
2548        * and the header must be removed.
2549        *
2550        * FIXME: If there is more than one transfer encoding,
2551        * only the "chunked" part should be removed here.
2552        */
2553       if (csp->flags & CSP_FLAG_MODIFIED)
2554       {
2555          log_error(LOG_LEVEL_HEADER, "Removing: %s", *header);
2556          freez(*header);
2557       }
2558    }
2559
2560    return JB_ERR_OK;
2561 }
2562
2563
2564 /*********************************************************************
2565  *
2566  * Function    :  server_content_encoding
2567  *
2568  * Description :  This function is run twice for each request,
2569  *                unless FEATURE_ZLIB and filtering are disabled.
2570  *
2571  *                The first run is used to check if the content
2572  *                is compressed, if FEATURE_ZLIB is disabled
2573  *                filtering is then disabled as well, if FEATURE_ZLIB
2574  *                is enabled the content is marked for decompression.
2575  *                
2576  *                The second run is used to remove the Content-Encoding
2577  *                header if the decompression was successful.
2578  *
2579  * Parameters  :
2580  *          1  :  csp = Current client state (buffers, headers, etc...)
2581  *          2  :  header = On input, pointer to header to modify.
2582  *                On output, pointer to the modified header, or NULL
2583  *                to remove the header.  This function frees the
2584  *                original string if necessary.
2585  *
2586  * Returns     :  JB_ERR_OK on success, or
2587  *                JB_ERR_MEMORY on out-of-memory error.
2588  *
2589  *********************************************************************/
2590 static jb_err server_content_encoding(struct client_state *csp, char **header)
2591 {
2592 #ifdef FEATURE_ZLIB
2593    if ((csp->flags & CSP_FLAG_MODIFIED)
2594     && (csp->content_type & (CT_GZIP | CT_DEFLATE)))
2595    {
2596       /*
2597        * We successfully decompressed the content,
2598        * and have to clean the header now, so the
2599        * client no longer expects compressed data..
2600        *
2601        * XXX: There is a difference between cleaning
2602        * and removing it completely.
2603        */
2604       log_error(LOG_LEVEL_HEADER, "Crunching: %s", *header);
2605       freez(*header);
2606    }
2607    else if (strstr(*header, "gzip"))
2608    {
2609       /* Mark for gzip decompression */
2610       csp->content_type |= CT_GZIP;
2611    }
2612    else if (strstr(*header, "deflate"))
2613    {
2614       /* Mark for zlib decompression */
2615       csp->content_type |= CT_DEFLATE;
2616    }
2617    else if (strstr(*header, "compress"))
2618    {
2619       /*
2620        * We can't decompress this; therefore we can't filter
2621        * it either.
2622        */
2623       csp->content_type |= CT_TABOO;
2624    }
2625 #else /* !defined(FEATURE_ZLIB) */
2626    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
2627    {
2628       /*
2629        * Body is compressed, turn off pcrs and gif filtering.
2630        */
2631       csp->content_type |= CT_TABOO;
2632
2633       /*
2634        * Log a warning if the user expects the content to be filtered.
2635        */
2636       if ((csp->rlist != NULL) &&
2637          (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
2638       {
2639          log_error(LOG_LEVEL_INFO,
2640             "Compressed content detected, content filtering disabled. "
2641             "Consider recompiling Privoxy with zlib support or "
2642             "enable the prevent-compression action.");
2643       }
2644    }
2645 #endif /* defined(FEATURE_ZLIB) */
2646
2647    return JB_ERR_OK;
2648
2649 }
2650
2651
2652 /*********************************************************************
2653  *
2654  * Function    :  server_content_length
2655  *
2656  * Description :  Adjust Content-Length header if we modified
2657  *                the body.
2658  *
2659  * Parameters  :
2660  *          1  :  csp = Current client state (buffers, headers, etc...)
2661  *          2  :  header = On input, pointer to header to modify.
2662  *                On output, pointer to the modified header, or NULL
2663  *                to remove the header.  This function frees the
2664  *                original string if necessary.
2665  *
2666  * Returns     :  JB_ERR_OK on success, or
2667  *                JB_ERR_MEMORY on out-of-memory error.
2668  *
2669  *********************************************************************/
2670 static jb_err server_content_length(struct client_state *csp, char **header)
2671 {
2672    const size_t max_header_length = 80;
2673
2674    /* Regenerate header if the content was modified. */
2675    if (csp->flags & CSP_FLAG_MODIFIED)
2676    {
2677       freez(*header);
2678       *header = (char *) zalloc(max_header_length);
2679       if (*header == NULL)
2680       {
2681          return JB_ERR_MEMORY;
2682       }
2683
2684       snprintf(*header, max_header_length, "Content-Length: %d",
2685          (int)csp->content_length);
2686       log_error(LOG_LEVEL_HEADER, "Adjusted Content-Length to %d",
2687          (int)csp->content_length);
2688    }
2689
2690    return JB_ERR_OK;
2691 }
2692
2693
2694 /*********************************************************************
2695  *
2696  * Function    :  server_content_md5
2697  *
2698  * Description :  Crumble any Content-MD5 headers if the document was
2699  *                modified. FIXME: Should we re-compute instead?
2700  *
2701  * Parameters  :
2702  *          1  :  csp = Current client state (buffers, headers, etc...)
2703  *          2  :  header = On input, pointer to header to modify.
2704  *                On output, pointer to the modified header, or NULL
2705  *                to remove the header.  This function frees the
2706  *                original string if necessary.
2707  *
2708  * Returns     :  JB_ERR_OK on success, or
2709  *                JB_ERR_MEMORY on out-of-memory error.
2710  *
2711  *********************************************************************/
2712 static jb_err server_content_md5(struct client_state *csp, char **header)
2713 {
2714    if (csp->flags & CSP_FLAG_MODIFIED)
2715    {
2716       log_error(LOG_LEVEL_HEADER, "Crunching Content-MD5");
2717       freez(*header);
2718    }
2719
2720    return JB_ERR_OK;
2721 }
2722
2723
2724 /*********************************************************************
2725  *
2726  * Function    :  server_content_disposition
2727  *
2728  * Description :  If enabled, blocks or modifies the "Content-Disposition" header.
2729  *                Called from `sed'.
2730  *
2731  * Parameters  :
2732  *          1  :  csp = Current client state (buffers, headers, etc...)
2733  *          2  :  header = On input, pointer to header to modify.
2734  *                On output, pointer to the modified header, or NULL
2735  *                to remove the header.  This function frees the
2736  *                original string if necessary.
2737  *
2738  * Returns     :  JB_ERR_OK on success, or
2739  *                JB_ERR_MEMORY on out-of-memory error.
2740  *
2741  *********************************************************************/
2742 static jb_err server_content_disposition(struct client_state *csp, char **header)
2743 {
2744    const char *newval;
2745
2746    /*
2747     * Are we messing with the Content-Disposition header?
2748     */
2749    if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0)
2750    {
2751       /* Me tinks not */
2752       return JB_ERR_OK;
2753    }
2754
2755    newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION];
2756
2757    if ((newval == NULL) || (0 == strcmpic(newval, "block")))
2758    {
2759       /*
2760        * Blocking content-disposition header
2761        */
2762       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2763       freez(*header);
2764       return JB_ERR_OK;
2765    }
2766    else
2767    {  
2768       /*
2769        * Replacing Content-Disposition header
2770        */
2771       freez(*header);
2772       *header = strdup("Content-Disposition: ");
2773       string_append(header, newval);
2774
2775       if (*header != NULL)
2776       {
2777          log_error(LOG_LEVEL_HEADER,
2778             "Content-Disposition header crunched and replaced with: %s", *header);
2779       }
2780    }
2781    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2782 }
2783
2784
2785 /*********************************************************************
2786  *
2787  * Function    :  server_last_modified
2788  *
2789  * Description :  Changes Last-Modified header to the actual date
2790  *                to help hide-if-modified-since.
2791  *                Called from `sed'.
2792  *
2793  * Parameters  :
2794  *          1  :  csp = Current client state (buffers, headers, etc...)
2795  *          2  :  header = On input, pointer to header to modify.
2796  *                On output, pointer to the modified header, or NULL
2797  *                to remove the header.  This function frees the
2798  *                original string if necessary.
2799  *
2800  * Returns     :  JB_ERR_OK on success, or
2801  *                JB_ERR_MEMORY on out-of-memory error.
2802  *
2803  *********************************************************************/
2804 static jb_err server_last_modified(struct client_state *csp, char **header)
2805 {
2806    const char *newval;
2807    char buf[BUFFER_SIZE];
2808
2809    char newheader[50];
2810 #ifdef HAVE_GMTIME_R
2811    struct tm gmt;
2812 #endif
2813    struct tm *timeptr = NULL;
2814    time_t now, last_modified;                  
2815    long int rtime;
2816    long int days, hours, minutes, seconds;
2817    
2818    /*
2819     * Are we messing with the Last-Modified header?
2820     */
2821    if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
2822    {
2823       /*Nope*/
2824       return JB_ERR_OK;
2825    }
2826
2827    newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
2828
2829    if (0 == strcmpic(newval, "block") )
2830    {
2831       /*
2832        * Blocking Last-Modified header. Useless but why not.
2833        */
2834       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2835       freez(*header);
2836       return JB_ERR_OK;
2837    }
2838    else if (0 == strcmpic(newval, "reset-to-request-time"))
2839    {  
2840       /*
2841        * Setting Last-Modified Header to now.
2842        */
2843       get_http_time(0, buf, sizeof(buf));
2844       freez(*header);
2845       *header = strdup("Last-Modified: ");
2846       string_append(header, buf);   
2847
2848       if (*header == NULL)
2849       {
2850          log_error(LOG_LEVEL_HEADER, "Insufficient memory. Last-Modified header got lost, boohoo.");  
2851       }
2852       else
2853       {
2854          log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
2855       }
2856    }
2857    else if (0 == strcmpic(newval, "randomize"))
2858    {
2859       const char *header_time = *header + sizeof("Last-Modified:");
2860
2861       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
2862       now = time(NULL);
2863 #ifdef HAVE_GMTIME_R
2864       timeptr = gmtime_r(&now, &gmt);
2865 #elif FEATURE_PTHREAD
2866       privoxy_mutex_lock(&gmtime_mutex);
2867       timeptr = gmtime(&now);
2868       privoxy_mutex_unlock(&gmtime_mutex);
2869 #else
2870       timeptr = gmtime(&now);
2871 #endif
2872       if (JB_ERR_OK != parse_header_time(header_time, &last_modified))
2873       {
2874          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2875          freez(*header);
2876       }
2877       else
2878       {
2879          rtime = (long int)difftime(now, last_modified);
2880          if (rtime)
2881          {
2882             int negative = 0;
2883
2884             if (rtime < 0)
2885             {
2886                rtime *= -1; 
2887                negative = 1;
2888                log_error(LOG_LEVEL_HEADER, "Server time in the future.");
2889             }
2890             rtime = pick_from_range(rtime);
2891             if (negative) rtime *= -1;
2892             last_modified += rtime;
2893 #ifdef HAVE_GMTIME_R
2894             timeptr = gmtime_r(&last_modified, &gmt);
2895 #elif FEATURE_PTHREAD
2896             privoxy_mutex_lock(&gmtime_mutex);
2897             timeptr = gmtime(&last_modified);
2898             privoxy_mutex_unlock(&gmtime_mutex);
2899 #else
2900             timeptr = gmtime(&last_modified);
2901 #endif
2902             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
2903             freez(*header);
2904             *header = strdup("Last-Modified: ");
2905             string_append(header, newheader);
2906
2907             if (*header == NULL)
2908             {
2909                log_error(LOG_LEVEL_ERROR, "Insufficient memory, header crunched without replacement.");
2910                return JB_ERR_MEMORY;  
2911             }
2912
2913             days    = rtime / (3600 * 24);
2914             hours   = rtime / 3600 % 24;
2915             minutes = rtime / 60 % 60;
2916             seconds = rtime % 60;
2917
2918             log_error(LOG_LEVEL_HEADER,
2919                "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
2920                *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
2921                minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
2922          }
2923          else
2924          {
2925             log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
2926          }
2927       }
2928    }
2929
2930    return JB_ERR_OK;
2931 }
2932
2933
2934 /*********************************************************************
2935  *
2936  * Function    :  client_accept_encoding
2937  *
2938  * Description :  Rewrite the client's Accept-Encoding header so that
2939  *                if doesn't allow compression, if the action applies.
2940  *                Note: For HTTP/1.0 the absence of the header is enough.
2941  *
2942  * Parameters  :
2943  *          1  :  csp = Current client state (buffers, headers, etc...)
2944  *          2  :  header = On input, pointer to header to modify.
2945  *                On output, pointer to the modified header, or NULL
2946  *                to remove the header.  This function frees the
2947  *                original string if necessary.
2948  *
2949  * Returns     :  JB_ERR_OK on success, or
2950  *                JB_ERR_MEMORY on out-of-memory error.
2951  *
2952  *********************************************************************/
2953 static jb_err client_accept_encoding(struct client_state *csp, char **header)
2954 {
2955    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2956    {
2957       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress content");
2958
2959       freez(*header);
2960
2961       /* Temporarily disable the correct behaviour to
2962        * work around a PHP bug. 
2963        *
2964        * if (!strcmpic(csp->http->ver, "HTTP/1.1"))
2965        * {
2966        *    *header = strdup("Accept-Encoding: identity;q=1.0, *;q=0");
2967        *    if (*header == NULL)
2968        *    {
2969        *       return JB_ERR_MEMORY;
2970        *    }
2971        * }
2972        * 
2973        */
2974    }
2975
2976    return JB_ERR_OK;
2977 }
2978
2979
2980 /*********************************************************************
2981  *
2982  * Function    :  client_te
2983  *
2984  * Description :  Rewrite the client's TE header so that
2985  *                if doesn't allow compression, if the action applies.
2986  *
2987  * Parameters  :
2988  *          1  :  csp = Current client state (buffers, headers, etc...)
2989  *          2  :  header = On input, pointer to header to modify.
2990  *                On output, pointer to the modified header, or NULL
2991  *                to remove the header.  This function frees the
2992  *                original string if necessary.
2993  *
2994  * Returns     :  JB_ERR_OK on success, or
2995  *                JB_ERR_MEMORY on out-of-memory error.
2996  *
2997  *********************************************************************/
2998 static jb_err client_te(struct client_state *csp, char **header)
2999 {
3000    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
3001    {
3002       freez(*header);
3003       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress transfer");
3004    }
3005
3006    return JB_ERR_OK;
3007 }
3008
3009
3010 /*********************************************************************
3011  *
3012  * Function    :  client_referrer
3013  *
3014  * Description :  Handle the "referer" config setting properly.
3015  *                Called from `sed'.
3016  *
3017  * Parameters  :
3018  *          1  :  csp = Current client state (buffers, headers, etc...)
3019  *          2  :  header = On input, pointer to header to modify.
3020  *                On output, pointer to the modified header, or NULL
3021  *                to remove the header.  This function frees the
3022  *                original string if necessary.
3023  *
3024  * Returns     :  JB_ERR_OK on success, or
3025  *                JB_ERR_MEMORY on out-of-memory error.
3026  *
3027  *********************************************************************/
3028 static jb_err client_referrer(struct client_state *csp, char **header)
3029 {
3030    const char *parameter;
3031    /* booleans for parameters we have to check multiple times */
3032    int parameter_conditional_block;
3033    int parameter_conditional_forge;
3034  
3035 #ifdef FEATURE_FORCE_LOAD
3036    /*
3037     * Since the referrer can include the prefix even
3038     * if the request itself is non-forced, we must
3039     * clean it unconditionally.
3040     *
3041     * XXX: strclean is too broad
3042     */
3043    strclean(*header, FORCE_PREFIX);
3044 #endif /* def FEATURE_FORCE_LOAD */
3045
3046    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
3047    {
3048       /* Nothing left to do */
3049       return JB_ERR_OK;
3050    }
3051
3052    parameter = csp->action->string[ACTION_STRING_REFERER];
3053    assert(parameter != NULL);
3054    parameter_conditional_block = (0 == strcmpic(parameter, "conditional-block"));
3055    parameter_conditional_forge = (0 == strcmpic(parameter, "conditional-forge"));
3056
3057    if (!parameter_conditional_block && !parameter_conditional_forge)
3058    {
3059       /*
3060        * As conditional-block and conditional-forge are the only
3061        * parameters that rely on the original referrer, we can
3062        * remove it now for all the others.
3063        */
3064       freez(*header);
3065    }
3066
3067    if (0 == strcmpic(parameter, "block"))
3068    {
3069       log_error(LOG_LEVEL_HEADER, "Referer crunched!");
3070       return JB_ERR_OK;
3071    }
3072    else if (parameter_conditional_block || parameter_conditional_forge)
3073    {
3074       return handle_conditional_hide_referrer_parameter(header,
3075          csp->http->hostport, parameter_conditional_block);
3076    }
3077    else if (0 == strcmpic(parameter, "forge"))
3078    {
3079       return create_forged_referrer(header, csp->http->hostport);
3080    }
3081    else
3082    {
3083       /* interpret parameter as user-supplied referer to fake */
3084       return create_fake_referrer(header, parameter);
3085    }
3086 }
3087
3088
3089 /*********************************************************************
3090  *
3091  * Function    :  client_accept_language
3092  *
3093  * Description :  Handle the "Accept-Language" config setting properly.
3094  *                Called from `sed'.
3095  *
3096  * Parameters  :
3097  *          1  :  csp = Current client state (buffers, headers, etc...)
3098  *          2  :  header = On input, pointer to header to modify.
3099  *                On output, pointer to the modified header, or NULL
3100  *                to remove the header.  This function frees the
3101  *                original string if necessary.
3102  *
3103  * Returns     :  JB_ERR_OK on success, or
3104  *                JB_ERR_MEMORY on out-of-memory error.
3105  *
3106  *********************************************************************/
3107 static jb_err client_accept_language(struct client_state *csp, char **header)
3108 {
3109    const char *newval;
3110
3111    /*
3112     * Are we messing with the Accept-Language?
3113     */
3114    if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
3115    {
3116       /*I don't think so*/
3117       return JB_ERR_OK;
3118    }
3119
3120    newval = csp->action->string[ACTION_STRING_LANGUAGE];
3121
3122    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
3123    {
3124       /*
3125        * Blocking Accept-Language header
3126        */
3127       log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
3128       freez(*header);
3129       return JB_ERR_OK;
3130    }
3131    else
3132    {  
3133       /*
3134        * Replacing Accept-Language header
3135        */
3136       freez(*header);
3137       *header = strdup("Accept-Language: ");
3138       string_append(header, newval);   
3139
3140       if (*header == NULL)
3141       {
3142          log_error(LOG_LEVEL_ERROR,
3143             "Insufficient memory. Accept-Language header crunched without replacement.");  
3144       }
3145       else
3146       {
3147          log_error(LOG_LEVEL_HEADER,
3148             "Accept-Language header crunched and replaced with: %s", *header);
3149       }
3150    }
3151    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
3152 }
3153
3154
3155 /*********************************************************************
3156  *
3157  * Function    :  crunch_client_header
3158  *
3159  * Description :  Crunch client header if it matches a string supplied by the
3160  *                user. Called from `sed'.
3161  *
3162  * Parameters  :
3163  *          1  :  csp = Current client state (buffers, headers, etc...)
3164  *          2  :  header = On input, pointer to header to modify.
3165  *                On output, pointer to the modified header, or NULL
3166  *                to remove the header.  This function frees the
3167  *                original string if necessary.
3168  *
3169  * Returns     :  JB_ERR_OK on success and always succeeds
3170  *
3171  *********************************************************************/
3172 static jb_err crunch_client_header(struct client_state *csp, char **header)
3173 {
3174    const char *crunch_pattern;
3175
3176    /* Do we feel like crunching? */
3177    if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
3178    {
3179       crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
3180
3181       /* Is the current header the lucky one? */
3182       if (strstr(*header, crunch_pattern))
3183       {
3184          log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);  
3185          freez(*header);
3186       }
3187    }
3188    return JB_ERR_OK;
3189 }
3190
3191
3192 /*********************************************************************
3193  *
3194  * Function    :  client_uagent
3195  *
3196  * Description :  Handle the "user-agent" config setting properly
3197  *                and remember its original value to enable browser
3198  *                bug workarounds. Called from `sed'.
3199  *
3200  * Parameters  :
3201  *          1  :  csp = Current client state (buffers, headers, etc...)
3202  *          2  :  header = On input, pointer to header to modify.
3203  *                On output, pointer to the modified header, or NULL
3204  *                to remove the header.  This function frees the
3205  *                original string if necessary.
3206  *
3207  * Returns     :  JB_ERR_OK on success, or
3208  *                JB_ERR_MEMORY on out-of-memory error.
3209  *
3210  *********************************************************************/
3211 static jb_err client_uagent(struct client_state *csp, char **header)
3212 {
3213    const char *newval;
3214
3215    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
3216    {
3217       return JB_ERR_OK;
3218    }
3219
3220    newval = csp->action->string[ACTION_STRING_USER_AGENT];
3221    if (newval == NULL)
3222    {
3223       return JB_ERR_OK;
3224    }
3225
3226    freez(*header);
3227    *header = strdup("User-Agent: ");
3228    string_append(header, newval);
3229
3230    log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
3231
3232    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
3233 }
3234
3235
3236 /*********************************************************************
3237  *
3238  * Function    :  client_ua
3239  *
3240  * Description :  Handle "ua-" headers properly.  Called from `sed'.
3241  *
3242  * Parameters  :
3243  *          1  :  csp = Current client state (buffers, headers, etc...)
3244  *          2  :  header = On input, pointer to header to modify.
3245  *                On output, pointer to the modified header, or NULL
3246  *                to remove the header.  This function frees the
3247  *                original string if necessary.
3248  *
3249  * Returns     :  JB_ERR_OK on success, or
3250  *                JB_ERR_MEMORY on out-of-memory error.
3251  *
3252  *********************************************************************/
3253 static jb_err client_ua(struct client_state *csp, char **header)
3254 {
3255    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
3256    {
3257       log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
3258       freez(*header);
3259    }
3260
3261    return JB_ERR_OK;
3262 }
3263
3264
3265 /*********************************************************************
3266  *
3267  * Function    :  client_from
3268  *
3269  * Description :  Handle the "from" config setting properly.
3270  *                Called from `sed'.
3271  *
3272  * Parameters  :
3273  *          1  :  csp = Current client state (buffers, headers, etc...)
3274  *          2  :  header = On input, pointer to header to modify.
3275  *                On output, pointer to the modified header, or NULL
3276  *                to remove the header.  This function frees the
3277  *                original string if necessary.
3278  *
3279  * Returns     :  JB_ERR_OK on success, or
3280  *                JB_ERR_MEMORY on out-of-memory error.
3281  *
3282  *********************************************************************/
3283 static jb_err client_from(struct client_state *csp, char **header)
3284 {
3285    const char *newval;
3286
3287    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
3288    {
3289       return JB_ERR_OK;
3290    }
3291
3292    freez(*header);
3293
3294    newval = csp->action->string[ACTION_STRING_FROM];
3295
3296    /*
3297     * Are we blocking the e-mail address?
3298     */
3299    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
3300    {
3301       log_error(LOG_LEVEL_HEADER, "crunched From!");
3302       return JB_ERR_OK;
3303    }
3304
3305    log_error(LOG_LEVEL_HEADER, " modified");
3306
3307    *header = strdup("From: ");
3308    string_append(header, newval);
3309
3310    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
3311 }
3312
3313
3314 /*********************************************************************
3315  *
3316  * Function    :  client_send_cookie
3317  *
3318  * Description :  Crunches the "cookie" header if necessary.
3319  *                Called from `sed'.
3320  *
3321  *                XXX: Stupid name, doesn't send squat.
3322  *
3323  * Parameters  :
3324  *          1  :  csp = Current client state (buffers, headers, etc...)
3325  *          2  :  header = On input, pointer to header to modify.
3326  *                On output, pointer to the modified header, or NULL
3327  *                to remove the header.  This function frees the
3328  *                original string if necessary.
3329  *
3330  * Returns     :  JB_ERR_OK on success, or
3331  *                JB_ERR_MEMORY on out-of-memory error.
3332  *
3333  *********************************************************************/
3334 static jb_err client_send_cookie(struct client_state *csp, char **header)
3335 {
3336    if (csp->action->flags & ACTION_NO_COOKIE_READ)
3337    {
3338       log_error(LOG_LEVEL_HEADER, "Crunched outgoing cookie: %s", *header);
3339       freez(*header);
3340    }
3341
3342    return JB_ERR_OK;
3343 }
3344
3345
3346 /*********************************************************************
3347  *
3348  * Function    :  client_x_forwarded
3349  *
3350  * Description :  Handle the "x-forwarded-for" config setting properly,
3351  *                also used in the add_client_headers list.  Called from `sed'.
3352  *
3353  * Parameters  :
3354  *          1  :  csp = Current client state (buffers, headers, etc...)
3355  *          2  :  header = On input, pointer to header to modify.
3356  *                On output, pointer to the modified header, or NULL
3357  *                to remove the header.  This function frees the
3358  *                original string if necessary.
3359  *
3360  * Returns     :  JB_ERR_OK on success, or
3361  *                JB_ERR_MEMORY on out-of-memory error.
3362  *
3363  *********************************************************************/
3364 jb_err client_x_forwarded(struct client_state *csp, char **header)
3365 {
3366    if ((csp->action->flags & ACTION_HIDE_FORWARDED) != 0)
3367    {
3368       freez(*header);
3369       log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
3370    }
3371
3372    return JB_ERR_OK;
3373 }
3374
3375
3376 /*********************************************************************
3377  *
3378  * Function    :  client_max_forwards
3379  *
3380  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
3381  *                from the value of the Max-Forwards header field.
3382  *
3383  * Parameters  :
3384  *          1  :  csp = Current client state (buffers, headers, etc...)
3385  *          2  :  header = On input, pointer to header to modify.
3386  *                On output, pointer to the modified header, or NULL
3387  *                to remove the header.  This function frees the
3388  *                original string if necessary.
3389  *
3390  * Returns     :  JB_ERR_OK on success, or
3391  *                JB_ERR_MEMORY on out-of-memory error.
3392  *
3393  *********************************************************************/
3394 static jb_err client_max_forwards(struct client_state *csp, char **header)
3395 {
3396    int max_forwards;
3397
3398    if ((0 == strcmpic(csp->http->gpc, "trace")) ||
3399        (0 == strcmpic(csp->http->gpc, "options")))
3400    {
3401       assert(*(*header+12) == ':');
3402       if (1 == sscanf(*header+12, ": %u", &max_forwards))
3403       {
3404          if (max_forwards > 0)
3405          {
3406             snprintf(*header, strlen(*header)+1, "Max-Forwards: %u", --max_forwards);
3407             log_error(LOG_LEVEL_HEADER, "Max-Forwards value for %s request reduced to %u.",
3408                csp->http->gpc, max_forwards);
3409          }
3410          else if (max_forwards < 0)
3411          {
3412             log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3413             freez(*header);
3414          }
3415       }
3416       else
3417       {
3418          log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3419          freez(*header);
3420       }
3421    }
3422
3423    return JB_ERR_OK;
3424 }
3425
3426
3427 /*********************************************************************
3428  *
3429  * Function    :  client_host
3430  *
3431  * Description :  If the request URI did not contain host and
3432  *                port information, parse and evaluate the Host
3433  *                header field.
3434  *
3435  *                Also, kill ill-formed HOST: headers as sent by
3436  *                Apple's iTunes software when used with a proxy.
3437  *
3438  * Parameters  :
3439  *          1  :  csp = Current client state (buffers, headers, etc...)
3440  *          2  :  header = On input, pointer to header to modify.
3441  *                On output, pointer to the modified header, or NULL
3442  *                to remove the header.  This function frees the
3443  *                original string if necessary.
3444  *
3445  * Returns     :  JB_ERR_OK on success, or
3446  *                JB_ERR_MEMORY on out-of-memory error.
3447  *
3448  *********************************************************************/
3449 static jb_err client_host(struct client_state *csp, char **header)
3450 {
3451    char *p, *q;
3452
3453    /*
3454     * If the header field name is all upper-case, chances are that it's
3455     * an ill-formed one from iTunes. BTW, killing innocent headers here is
3456     * not a problem -- they are regenerated later.
3457     */
3458    if ((*header)[1] == 'O')
3459    {
3460       log_error(LOG_LEVEL_HEADER, "Killed all-caps Host header line: %s", *header);
3461       freez(*header);
3462       return JB_ERR_OK;
3463    }
3464
3465    if (!csp->http->hostport || (*csp->http->hostport == '*') ||  
3466        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
3467    {
3468       
3469       if (NULL == (p = strdup((*header)+6)))
3470       {
3471          return JB_ERR_MEMORY;
3472       }
3473       chomp(p);
3474       if (NULL == (q = strdup(p)))
3475       {
3476          freez(p);
3477          return JB_ERR_MEMORY;
3478       }
3479
3480       freez(csp->http->hostport);
3481       csp->http->hostport = p;
3482       freez(csp->http->host);
3483       csp->http->host = q;
3484       q = strchr(csp->http->host, ':');
3485       if (q != NULL)
3486       {
3487          /* Terminate hostname and evaluate port string */
3488          *q++ = '\0';
3489          csp->http->port = atoi(q);
3490       }
3491       else
3492       {
3493          csp->http->port = csp->http->ssl ? 443 : 80;
3494       }
3495
3496       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
3497                 csp->http->hostport, csp->http->host, csp->http->port);
3498    }
3499
3500    /* Signal client_host_adder() to return right away */
3501    csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
3502
3503    return JB_ERR_OK;
3504 }
3505
3506
3507 /*********************************************************************
3508  *
3509  * Function    :  client_if_modified_since
3510  *
3511  * Description :  Remove or modify the If-Modified-Since header.
3512  *
3513  * Parameters  :
3514  *          1  :  csp = Current client state (buffers, headers, etc...)
3515  *          2  :  header = On input, pointer to header to modify.
3516  *                On output, pointer to the modified header, or NULL
3517  *                to remove the header.  This function frees the
3518  *                original string if necessary.
3519  *
3520  * Returns     :  JB_ERR_OK on success, or
3521  *                JB_ERR_MEMORY on out-of-memory error.
3522  *
3523  *********************************************************************/
3524 static jb_err client_if_modified_since(struct client_state *csp, char **header)
3525 {
3526    char newheader[50];
3527 #ifdef HAVE_GMTIME_R
3528    struct tm gmt;
3529 #endif
3530    struct tm *timeptr = NULL;
3531    time_t tm = 0;                  
3532    const char *newval;
3533    long int rtime;
3534    long int hours, minutes, seconds;
3535    int negative = 0;
3536    char * endptr;
3537    
3538    if ( 0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
3539    {
3540       /* 
3541        * The client got an error message because of a temporary problem,
3542        * the problem is gone and the client now tries to revalidate our
3543        * error message on the real server. The revalidation would always
3544        * end with the transmission of the whole document and there is
3545        * no need to expose the bogus If-Modified-Since header.
3546        */
3547       log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
3548       freez(*header);
3549    }
3550    else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
3551    {
3552       newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
3553
3554       if ((0 == strcmpic(newval, "block")))
3555       {
3556          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3557          freez(*header);
3558       }
3559       else /* add random value */
3560       {
3561          const char *header_time = *header + sizeof("If-Modified-Since:");
3562
3563          if (JB_ERR_OK != parse_header_time(header_time, &tm))
3564          {
3565             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
3566             freez(*header);
3567          }
3568          else
3569          {
3570             rtime = strtol(newval, &endptr, 0);
3571             if (rtime)
3572             {
3573                log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
3574                   *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
3575                if (rtime < 0)
3576                {
3577                   rtime *= -1; 
3578                   negative = 1;
3579                }
3580                rtime *= 60;
3581                rtime = pick_from_range(rtime);
3582             }
3583             else
3584             {
3585                log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
3586                   *header);
3587             }
3588             tm += rtime * (negative ? -1 : 1);
3589 #ifdef HAVE_GMTIME_R
3590             timeptr = gmtime_r(&tm, &gmt);
3591 #elif FEATURE_PTHREAD
3592             privoxy_mutex_lock(&gmtime_mutex);
3593             timeptr = gmtime(&tm);
3594             privoxy_mutex_unlock(&gmtime_mutex);
3595 #else
3596             timeptr = gmtime(&tm);
3597 #endif
3598             strftime(newheader, sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr);
3599
3600             freez(*header);
3601             *header = strdup("If-Modified-Since: ");
3602             string_append(header, newheader);
3603
3604             if (*header == NULL)
3605             {
3606                log_error(LOG_LEVEL_HEADER, "Insufficient memory, header crunched without replacement.");
3607                return JB_ERR_MEMORY;  
3608             }
3609
3610             hours   = rtime / 3600;
3611             minutes = rtime / 60 % 60;
3612             seconds = rtime % 60;
3613
3614             log_error(LOG_LEVEL_HEADER,
3615                "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
3616                *header, (negative) ? "subtracted" : "added", hours,
3617                (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es",
3618                seconds, (seconds == 1) ? ")" : "s)");
3619          }
3620       }
3621    }
3622
3623    return JB_ERR_OK;
3624 }
3625
3626
3627 /*********************************************************************
3628  *
3629  * Function    :  client_if_none_match
3630  *
3631  * Description :  Remove the If-None-Match header.
3632  *
3633  * Parameters  :
3634  *          1  :  csp = Current client state (buffers, headers, etc...)
3635  *          2  :  header = On input, pointer to header to modify.
3636  *                On output, pointer to the modified header, or NULL
3637  *                to remove the header.  This function frees the
3638  *                original string if necessary.
3639  *
3640  * Returns     :  JB_ERR_OK on success, or
3641  *                JB_ERR_MEMORY on out-of-memory error.
3642  *
3643  *********************************************************************/
3644 static jb_err client_if_none_match(struct client_state *csp, char **header)
3645 {
3646    if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
3647    {  
3648       log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3649       freez(*header);
3650    }
3651
3652    return JB_ERR_OK;
3653 }
3654
3655
3656 /*********************************************************************
3657  *
3658  * Function    :  client_x_filter
3659  *
3660  * Description :  Disables filtering if the client set "X-Filter: No".
3661  *                Called from `sed'.
3662  *
3663  * Parameters  :
3664  *          1  :  csp = Current client state (buffers, headers, etc...)
3665  *          2  :  header = On input, pointer to header to modify.
3666  *                On output, pointer to the modified header, or NULL
3667  *                to remove the header.  This function frees the
3668  *                original string if necessary.
3669  *
3670  * Returns     :  JB_ERR_OK on success
3671  *
3672  *********************************************************************/
3673 jb_err client_x_filter(struct client_state *csp, char **header)
3674 {
3675    if ( 0 == strcmpic(*header, "X-Filter: No"))
3676    {
3677       if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
3678       {
3679          log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
3680       }
3681       else
3682       {
3683          if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
3684          {
3685             log_error(LOG_LEVEL_HEADER,
3686                "force-text-mode overruled the client's request to fetch without filtering!");
3687          }
3688          else
3689          {  
3690             csp->content_type = CT_TABOO; /* XXX: This hack shouldn't be necessary */
3691             csp->flags |= CSP_FLAG_NO_FILTERING;
3692             log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
3693          }
3694          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3695          freez(*header);
3696       }
3697    }
3698    return JB_ERR_OK; 
3699 }
3700
3701
3702 /*********************************************************************
3703  *
3704  * Function    :  client_range
3705  *
3706  * Description :  Removes Range, Request-Range and If-Range headers if
3707  *                content filtering is enabled. If the client's version
3708  *                of the document has been altered by Privoxy, the server
3709  *                could interpret the range differently than the client
3710  *                intended in which case the user could end up with
3711  *                corrupted content.
3712  *
3713  * Parameters  :
3714  *          1  :  csp = Current client state (buffers, headers, etc...)
3715  *          2  :  header = On input, pointer to header to modify.
3716  *                On output, pointer to the modified header, or NULL
3717  *                to remove the header.  This function frees the
3718  *                original string if necessary.
3719  *
3720  * Returns     :  JB_ERR_OK
3721  *
3722  *********************************************************************/
3723 static jb_err client_range(struct client_state *csp, char **header)
3724 {
3725    if (content_filters_enabled(csp->action))
3726    {
3727       log_error(LOG_LEVEL_HEADER, "Content filtering is enabled."
3728          " Crunching: \'%s\' to prevent range-mismatch problems.", *header);
3729       freez(*header);
3730    }
3731
3732    return JB_ERR_OK; 
3733 }
3734
3735 /* the following functions add headers directly to the header list */
3736
3737 /*********************************************************************
3738  *
3739  * Function    :  client_host_adder
3740  *
3741  * Description :  Adds the Host: header field if it is missing.
3742  *                Called from `sed'.
3743  *
3744  * Parameters  :
3745  *          1  :  csp = Current client state (buffers, headers, etc...)
3746  *
3747  * Returns     :  JB_ERR_OK on success, or
3748  *                JB_ERR_MEMORY on out-of-memory error.
3749  *
3750  *********************************************************************/
3751 static jb_err client_host_adder(struct client_state *csp)
3752 {
3753    char *p;
3754    jb_err err;
3755
3756    if (csp->flags & CSP_FLAG_HOST_HEADER_IS_SET)
3757    {
3758       /* Header already set by the client, nothing to do. */
3759       return JB_ERR_OK;
3760    }
3761
3762    if ( !csp->http->hostport || !*(csp->http->hostport))
3763    {
3764       /* XXX: When does this happen and why is it OK? */
3765       log_error(LOG_LEVEL_INFO, "Weirdness in client_host_adder detected and ignored.");
3766       return JB_ERR_OK;
3767    }
3768
3769    /*
3770     * remove 'user:pass@' from 'proto://user:pass@host'
3771     */
3772    if ( (p = strchr( csp->http->hostport, '@')) != NULL )
3773    {
3774       p++;
3775    }
3776    else
3777    {
3778       p = csp->http->hostport;
3779    }
3780
3781    /* XXX: Just add it, we already made sure that it will be unique */
3782    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
3783    err = enlist_unique_header(csp->headers, "Host", p);
3784    return err;
3785
3786 }
3787
3788
3789 #if 0
3790 /*********************************************************************
3791  *
3792  * Function    :  client_accept_encoding_adder
3793  *
3794  * Description :  Add an Accept-Encoding header to the client's request
3795  *                that disables compression if the action applies, and
3796  *                the header is not already there. Called from `sed'.
3797  *                Note: For HTTP/1.0, the absence of the header is enough.
3798  *
3799  * Parameters  :
3800  *          1  :  csp = Current client state (buffers, headers, etc...)
3801  *
3802  * Returns     :  JB_ERR_OK on success, or
3803  *                JB_ERR_MEMORY on out-of-memory error.
3804  *
3805  *********************************************************************/
3806 static jb_err client_accept_encoding_adder(struct client_state *csp)
3807 {
3808    if (   ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
3809        && (!strcmpic(csp->http->ver, "HTTP/1.1")) )
3810    {
3811       return enlist_unique(csp->headers, "Accept-Encoding: identity;q=1.0, *;q=0", 16);
3812    }
3813
3814    return JB_ERR_OK;
3815 }
3816 #endif
3817
3818
3819 /*********************************************************************
3820  *
3821  * Function    :  client_xtra_adder
3822  *
3823  * Description :  Used in the add_client_headers list.  Called from `sed'.
3824  *
3825  * Parameters  :
3826  *          1  :  csp = Current client state (buffers, headers, etc...)
3827  *
3828  * Returns     :  JB_ERR_OK on success, or
3829  *                JB_ERR_MEMORY on out-of-memory error.
3830  *
3831  *********************************************************************/
3832 static jb_err client_xtra_adder(struct client_state *csp)
3833 {
3834    struct list_entry *lst;
3835    jb_err err;
3836
3837    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
3838         lst ; lst = lst->next)
3839    {
3840       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
3841       err = enlist(csp->headers, lst->str);
3842       if (err)
3843       {
3844          return err;
3845       }
3846
3847    }
3848
3849    return JB_ERR_OK;
3850 }
3851
3852
3853 /*********************************************************************
3854  *
3855  * Function    :  connection_close_adder
3856  *
3857  * Description :  "Temporary" fix for the needed but missing HTTP/1.1
3858  *                support. Adds a "Connection: close" header to csp->headers
3859  *                unless the header was already present. Called from `sed'.
3860  *
3861  *                FIXME: This whole function shouldn't be neccessary!
3862  *
3863  * Parameters  :
3864  *          1  :  csp = Current client state (buffers, headers, etc...)
3865  *
3866  * Returns     :  JB_ERR_OK on success, or
3867  *                JB_ERR_MEMORY on out-of-memory error.
3868  *
3869  *********************************************************************/
3870 static jb_err connection_close_adder(struct client_state *csp)
3871 {
3872    const unsigned int flags = csp->flags;
3873
3874    /*
3875     * Return right away if
3876     *
3877     * - we're parsing server headers and the server header
3878     *   "Connection: close" is already set, or if
3879     *
3880     * - we're parsing client headers and the client header 
3881     *   "Connection: close" is already set.
3882     */
3883    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE
3884      && flags & CSP_FLAG_SERVER_CONNECTION_CLOSE_SET)
3885    ||(!(flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3886      && flags & CSP_FLAG_CLIENT_CONNECTION_CLOSE_SET))
3887    {
3888       return JB_ERR_OK;
3889    }
3890
3891    log_error(LOG_LEVEL_HEADER, "Adding: Connection: close");
3892
3893    return enlist(csp->headers, "Connection: close");
3894 }
3895
3896
3897 /*********************************************************************
3898  *
3899  * Function    :  server_http
3900  *
3901  * Description :  - Save the HTTP Status into csp->http->status
3902  *                - Set CT_TABOO to prevent filtering if the answer
3903  *                  is a partial range (HTTP status 206)
3904  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
3905  *                  action applies.
3906  *
3907  * Parameters  :
3908  *          1  :  csp = Current client state (buffers, headers, etc...)
3909  *          2  :  header = On input, pointer to header to modify.
3910  *                On output, pointer to the modified header, or NULL
3911  *                to remove the header.  This function frees the
3912  *                original string if necessary.
3913  *
3914  * Returns     :  JB_ERR_OK on success, or
3915  *                JB_ERR_MEMORY on out-of-memory error.
3916  *
3917  *********************************************************************/
3918 static jb_err server_http(struct client_state *csp, char **header)
3919 {
3920    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
3921    if (csp->http->status == 206)
3922    {
3923       csp->content_type = CT_TABOO;
3924    }
3925
3926    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
3927    {
3928       /* XXX: Should we do a real validity check here? */
3929       if (strlen(*header) > 8)
3930       {
3931          (*header)[7] = '0';
3932          log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
3933       }
3934       else
3935       {
3936          /*
3937           * XXX: Should we block the request or
3938           * enlist a valid status code line here?
3939           */
3940          log_error(LOG_LEVEL_INFO, "Malformed server response detected. "
3941             "Downgrading to HTTP/1.0 impossible.");
3942       }
3943    }
3944
3945    return JB_ERR_OK;
3946 }
3947
3948
3949 /*********************************************************************
3950  *
3951  * Function    :  server_set_cookie
3952  *
3953  * Description :  Handle the server "cookie" header properly.
3954  *                Log cookie to the jar file.  Then "crunch",
3955  *                accept or rewrite it to a session cookie.
3956  *                Called from `sed'.
3957  *
3958  *                TODO: Allow the user to specify a new expiration
3959  *                time to cause the cookie to expire even before the
3960  *                browser is closed.
3961  *
3962  * Parameters  :
3963  *          1  :  csp = Current client state (buffers, headers, etc...)
3964  *          2  :  header = On input, pointer to header to modify.
3965  *                On output, pointer to the modified header, or NULL
3966  *                to remove the header.  This function frees the
3967  *                original string if necessary.
3968  *
3969  * Returns     :  JB_ERR_OK on success, or
3970  *                JB_ERR_MEMORY on out-of-memory error.
3971  *
3972  *********************************************************************/
3973 static jb_err server_set_cookie(struct client_state *csp, char **header)
3974 {
3975    time_t now;
3976    time_t cookie_time; 
3977
3978    time(&now);
3979
3980    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
3981    {
3982       log_error(LOG_LEVEL_HEADER, "Crunching incoming cookie: %s", *header);
3983       freez(*header);
3984    }
3985    else if ((csp->action->flags & ACTION_NO_COOKIE_KEEP) != 0)
3986    {
3987       /* Flag whether or not to log a message */
3988       int changed = 0;
3989
3990       /* A variable to store the tag we're working on */
3991       char *cur_tag;
3992
3993       /* Skip "Set-Cookie:" (11 characters) in header */
3994       cur_tag = *header + 11;
3995
3996       /* skip whitespace between "Set-Cookie:" and value */
3997       while (*cur_tag && ijb_isspace(*cur_tag))
3998       {
3999          cur_tag++;
4000       }
4001
4002       /* Loop through each tag in the cookie */
4003       while (*cur_tag)
4004       {
4005          /* Find next tag */
4006          char *next_tag = strchr(cur_tag, ';');
4007          if (next_tag != NULL)
4008          {
4009             /* Skip the ';' character itself */
4010             next_tag++;
4011
4012             /* skip whitespace ";" and start of tag */
4013             while (*next_tag && ijb_isspace(*next_tag))
4014             {
4015                next_tag++;
4016             }
4017          }
4018          else
4019          {
4020             /* "Next tag" is the end of the string */
4021             next_tag = cur_tag + strlen(cur_tag);
4022          }
4023
4024          /*
4025           * Check the expiration date to see
4026           * if the cookie is still valid, if yes,
4027           * rewrite it to a session cookie.
4028           */
4029          if ((strncmpic(cur_tag, "expires=", 8) == 0) && *(cur_tag + 8))
4030          {
4031             char *expiration_date = cur_tag + 8; /* Skip "[Ee]xpires=" */
4032
4033             /* Did we detect the date properly? */
4034             if (JB_ERR_OK != parse_header_time(expiration_date, &cookie_time))
4035             {
4036                /*
4037                 * Nope, treat it as if it was still valid.
4038                 *
4039                 * XXX: Should we remove the whole cookie instead?
4040                 */
4041                log_error(LOG_LEVEL_ERROR,
4042                   "Can't parse \'%s\', send by %s. Unsupported time format?", cur_tag, csp->http->url);
4043                string_move(cur_tag, next_tag);
4044                changed = 1;
4045             }
4046             else
4047             {
4048                /*
4049                 * Yes. Check if the cookie is still valid.
4050                 *
4051                 * If the cookie is already expired it's probably
4052                 * a delete cookie and even if it isn't, the browser
4053                 * will discard it anyway.
4054                 */
4055
4056                /*
4057                 * XXX: timegm() isn't available on some AmigaOS
4058                 * versions and our replacement doesn't work.
4059                 *
4060                 * Our options are to either:
4061                 *
4062                 * - disable session-cookies-only completely if timegm
4063                 *   is missing,
4064                 *
4065                 * - to simply remove all expired tags, like it has
4066                 *   been done until Privoxy 3.0.6 and to live with
4067                 *    the consequence that it can cause login/logout
4068                 *   problems on servers that don't validate their
4069                 *   input properly, or
4070                 *
4071                 * - to replace it with mktime in which
4072                 *   case there is a slight chance of valid cookies
4073                 *   passing as already expired.
4074                 *
4075                 *   This is the way it's currently done and it's not
4076                 *   as bad as it sounds. If the missing GMT offset is
4077                 *   enough to change the result of the expiration check
4078                 *   the cookie will be only valid for a few hours
4079                 *   anyway, which in many cases will be shorter
4080                 *   than a browser session.
4081                 */
4082                if (cookie_time - now < 0)
4083                {
4084                   log_error(LOG_LEVEL_HEADER,
4085                      "Cookie \'%s\' is already expired and can pass unmodified.", *header);
4086                   /* Just in case some clown sets more then one expiration date */
4087                   cur_tag = next_tag;
4088                }
4089                else
4090                {
4091                   /*
4092                    * Still valid, delete expiration date by copying
4093                    * the rest of the string over it.
4094                    */
4095                   string_move(cur_tag, next_tag);
4096
4097                   /* That changed the header, need to issue a log message */
4098                   changed = 1;
4099
4100                   /*
4101                    * Note that the next tag has now been moved to *cur_tag,
4102                    * so we do not need to update the cur_tag pointer.
4103                    */
4104                }
4105             }
4106
4107          }
4108          else
4109          {
4110             /* Move on to next cookie tag */
4111             cur_tag = next_tag;
4112          }
4113       }
4114
4115       if (changed)
4116       {
4117          assert(NULL != *header);
4118          log_error(LOG_LEVEL_HEADER, "Cookie rewritten to a temporary one: %s",
4119             *header);
4120       }
4121    }
4122
4123    return JB_ERR_OK;
4124 }
4125
4126
4127 #ifdef FEATURE_FORCE_LOAD
4128 /*********************************************************************
4129  *
4130  * Function    :  strclean
4131  *
4132  * Description :  In-Situ-Eliminate all occurances of substring in
4133  *                string
4134  *
4135  * Parameters  :
4136  *          1  :  string = string to clean
4137  *          2  :  substring = substring to eliminate
4138  *
4139  * Returns     :  Number of eliminations
4140  *
4141  *********************************************************************/
4142 int strclean(char *string, const char *substring)
4143 {
4144    int hits = 0;
4145    size_t len;
4146    char *pos, *p;
4147
4148    len = strlen(substring);
4149
4150    while((pos = strstr(string, substring)) != NULL)
4151    {
4152       p = pos + len;
4153       do
4154       {
4155          *(p - len) = *p;
4156       }
4157       while (*p++ != '\0');
4158
4159       hits++;
4160    }
4161
4162    return(hits);
4163 }
4164 #endif /* def FEATURE_FORCE_LOAD */
4165
4166
4167 /*********************************************************************
4168  *
4169  * Function    :  parse_header_time
4170  *
4171  * Description :  Parses time formats used in HTTP header strings
4172  *                to get the numerical respresentation.
4173  *
4174  * Parameters  :
4175  *          1  :  header_time = HTTP header time as string. 
4176  *          2  :  result = storage for header_time in seconds
4177  *
4178  * Returns     :  JB_ERR_OK if the time format was recognized, or
4179  *                JB_ERR_PARSE otherwise.
4180  *
4181  *********************************************************************/
4182 static jb_err parse_header_time(const char *header_time, time_t *result)
4183 {
4184    struct tm gmt;
4185
4186    /*
4187     * Zero out gmt to prevent time zone offsets.
4188     *
4189     * While this is only necessary on some platforms
4190     * (mingw32 for example), I don't know how to
4191     * detect these automatically and doing it everywhere
4192     * shouldn't hurt.
4193     */
4194    memset(&gmt, 0, sizeof(gmt));
4195
4196                             /* Tue, 02 Jun 2037 20:00:00 */
4197    if ((NULL == strptime(header_time, "%a, %d %b %Y %H:%M:%S", &gmt))
4198                             /* Tue, 02-Jun-2037 20:00:00 */
4199     && (NULL == strptime(header_time, "%a, %d-%b-%Y %H:%M:%S", &gmt))
4200                             /* Tue, 02-Jun-37 20:00:00 */
4201     && (NULL == strptime(header_time, "%a, %d-%b-%y %H:%M:%S", &gmt))
4202                         /* Tuesday, 02-Jun-2037 20:00:00 */
4203     && (NULL == strptime(header_time, "%A, %d-%b-%Y %H:%M:%S", &gmt))
4204                         /* Tuesday Jun 02 20:00:00 2037 */
4205     && (NULL == strptime(header_time, "%A %b %d %H:%M:%S %Y", &gmt)))
4206    {
4207       return JB_ERR_PARSE;
4208    }
4209
4210    *result = timegm(&gmt);
4211
4212    return JB_ERR_OK;
4213
4214 }
4215
4216
4217 /*********************************************************************
4218  *
4219  * Function    :  get_destination_from_headers
4220  *
4221  * Description :  Parse the "Host:" header to get the request's destination.
4222  *                Only needed if the client's request was forcefully
4223  *                redirected into Privoxy.
4224  *
4225  *                Code mainly copied from client_host() which is currently
4226  *                run too late for this purpose.
4227  *
4228  * Parameters  :
4229  *          1  :  headers = List of headers (one of them hopefully being
4230  *                the "Host:" header)
4231  *          2  :  http = storage for the result (host, port and hostport). 
4232  *
4233  * Returns     :  JB_ERR_MEMORY in case of memory problems,
4234  *                JB_ERR_PARSE if the host header couldn't be found,
4235  *                JB_ERR_OK otherwise.
4236  *
4237  *********************************************************************/
4238 jb_err get_destination_from_headers(const struct list *headers, struct http_request *http)
4239 {
4240    char *q;
4241    char *p;
4242    char *host;
4243
4244    host = get_header_value(headers, "Host:");
4245
4246    if (NULL == host)
4247    {
4248       log_error(LOG_LEVEL_ERROR, "No \"Host:\" header found.");
4249       return JB_ERR_PARSE;
4250    }
4251
4252    if (NULL == (p = strdup((host))))
4253    {
4254       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
4255       return JB_ERR_MEMORY;
4256    }
4257    chomp(p);
4258    if (NULL == (q = strdup(p)))
4259    {
4260       freez(p);
4261       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
4262       return JB_ERR_MEMORY;
4263    }
4264
4265    freez(http->hostport);
4266    http->hostport = p;
4267    freez(http->host);
4268    http->host = q;
4269    q = strchr(http->host, ':');
4270    if (q != NULL)
4271    {
4272       /* Terminate hostname and evaluate port string */
4273       *q++ = '\0';
4274       http->port = atoi(q);
4275    }
4276    else
4277    {
4278       http->port = http->ssl ? 443 : 80;
4279    }
4280
4281    /* Rebuild request URL */
4282    freez(http->url);
4283    http->url = strdup(http->ssl ? "https://" : "http://");
4284    string_append(&http->url, http->hostport);
4285    string_append(&http->url, http->path);
4286    if (http->url == NULL)
4287    {
4288       return JB_ERR_MEMORY;
4289    }
4290
4291    log_error(LOG_LEVEL_HEADER, "Destination extracted from \"Host:\" header. New request URL: %s",
4292       http->url);
4293
4294    return JB_ERR_OK;
4295
4296 }
4297
4298
4299 /*********************************************************************
4300  *
4301  * Function    :  create_forged_referrer
4302  *
4303  * Description :  Helper for client_referrer to forge a referer as
4304  *                'http://[hostname:port/' to fool stupid
4305  *                checks for in-site links 
4306  *
4307  * Parameters  :
4308  *          1  :  header   = Pointer to header pointer
4309  *          2  :  hostport = Host and optionally port as string
4310  *
4311  * Returns     :  JB_ERR_OK in case of success, or
4312  *                JB_ERR_MEMORY in case of memory problems.
4313  *
4314  *********************************************************************/
4315 static jb_err create_forged_referrer(char **header, const char *hostport)
4316 {
4317     assert(NULL == *header);
4318
4319     *header = strdup("Referer: http://");
4320     string_append(header, hostport);
4321     string_append(header, "/");
4322
4323     if (NULL == *header)
4324     {
4325        return JB_ERR_MEMORY;
4326     }
4327
4328     log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
4329
4330     return JB_ERR_OK;
4331
4332 }
4333
4334
4335 /*********************************************************************
4336  *
4337  * Function    :  create_fake_referrer
4338  *
4339  * Description :  Helper for client_referrer to create a fake referrer
4340  *                based on a string supplied by the user.
4341  *
4342  * Parameters  :
4343  *          1  :  header   = Pointer to header pointer
4344  *          2  :  hosthost = Referrer to fake
4345  *
4346  * Returns     :  JB_ERR_OK in case of success, or
4347  *                JB_ERR_MEMORY in case of memory problems.
4348  *
4349  *********************************************************************/
4350 static jb_err create_fake_referrer(char **header, const char *fake_referrer)
4351 {
4352    assert(NULL == *header);
4353
4354    if ((0 != strncmpic(fake_referrer, "http://", 7)) && (0 != strncmpic(fake_referrer, "https://", 8)))
4355    {
4356       log_error(LOG_LEVEL_HEADER,
4357          "Parameter: +hide-referrer{%s} is a bad idea, but I don't care.", fake_referrer);
4358    }
4359    *header = strdup("Referer: ");
4360    string_append(header, fake_referrer);
4361
4362    if (NULL == *header)
4363    {
4364       return JB_ERR_MEMORY;
4365    }
4366
4367    log_error(LOG_LEVEL_HEADER, "Referer replaced with: %s", *header);
4368
4369    return JB_ERR_OK;
4370
4371 }
4372
4373
4374 /*********************************************************************
4375  *
4376  * Function    :  handle_conditional_hide_referrer_parameter
4377  *
4378  * Description :  Helper for client_referrer to crunch or forge
4379  *                the referrer header if the host has changed.
4380  *
4381  * Parameters  :
4382  *          1  :  header = Pointer to header pointer
4383  *          2  :  host   = The target host (may include the port)
4384  *          3  :  parameter_conditional_block = Boolean to signal
4385  *                if we're in conditional-block mode. If not set,
4386  *                we're in conditional-forge mode.
4387  *
4388  * Returns     :  JB_ERR_OK in case of success, or
4389  *                JB_ERR_MEMORY in case of memory problems.
4390  *
4391  *********************************************************************/
4392 static jb_err handle_conditional_hide_referrer_parameter(char **header,
4393    const char *host, const int parameter_conditional_block)
4394 {
4395    char *referer = strdup(*header);
4396    const size_t hostlenght = strlen(host);
4397
4398    if (NULL == referer)
4399    {
4400       freez(*header);
4401       return JB_ERR_MEMORY;
4402    }
4403
4404    /* referer begins with 'Referer: http[s]://' */
4405    if (hostlenght < (strlen(referer)-17))
4406    {
4407       /*
4408        * Shorten referer to make sure the referer is blocked
4409        * if www.example.org/www.example.com-shall-see-the-referer/
4410        * links to www.example.com/
4411        */
4412       referer[hostlenght+17] = '\0';
4413    }
4414    if (NULL == strstr(referer, host))
4415    {
4416       /* Host has changed */
4417       if (parameter_conditional_block)
4418       {
4419          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
4420          freez(*header);
4421       }
4422       else
4423       {
4424          freez(*header);
4425          freez(referer);
4426          return create_forged_referrer(header, host);
4427       }
4428    }
4429    freez(referer);
4430
4431    return JB_ERR_OK;
4432
4433 }
4434
4435 /*
4436   Local Variables:
4437   tab-width: 3
4438   end:
4439 */