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