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