In a fatal error message in load_one_actions_file(), cover both URL and TAG patterns
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.217 2011/01/22 12:30:22 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    time_t last_modified;
2398    char newheader[50];
2399
2400    /*
2401     * Are we messing with the Last-Modified header?
2402     */
2403    if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
2404    {
2405       /*Nope*/
2406       return JB_ERR_OK;
2407    }
2408
2409    newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
2410
2411    if (0 == strcmpic(newval, "block") )
2412    {
2413       /*
2414        * Blocking Last-Modified header. Useless but why not.
2415        */
2416       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2417       freez(*header);
2418       return JB_ERR_OK;
2419    }
2420    else if (0 == strcmpic(newval, "reset-to-request-time"))
2421    {  
2422       /*
2423        * Setting Last-Modified Header to now.
2424        */
2425       get_http_time(0, buf, sizeof(buf));
2426       freez(*header);
2427       *header = strdup("Last-Modified: ");
2428       string_append(header, buf);   
2429
2430       if (*header == NULL)
2431       {
2432          log_error(LOG_LEVEL_HEADER, "Insufficient memory. Last-Modified header got lost, boohoo.");  
2433       }
2434       else
2435       {
2436          log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
2437       }
2438    }
2439    else if (0 == strcmpic(newval, "randomize"))
2440    {
2441       const char *header_time = *header + sizeof("Last-Modified:");
2442
2443       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
2444
2445       if (JB_ERR_OK != parse_header_time(header_time, &last_modified))
2446       {
2447          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2448          freez(*header);
2449       }
2450       else
2451       {
2452          time_t now;
2453          struct tm *timeptr = NULL;
2454          long int rtime;
2455 #ifdef HAVE_GMTIME_R
2456          struct tm gmt;
2457 #endif
2458          now = time(NULL);
2459          rtime = (long int)difftime(now, last_modified);
2460          if (rtime)
2461          {
2462             long int days, hours, minutes, seconds;
2463             const int negative_delta = (rtime < 0);
2464
2465             if (negative_delta)
2466             {
2467                rtime *= -1; 
2468                log_error(LOG_LEVEL_HEADER, "Server time in the future.");
2469             }
2470             rtime = pick_from_range(rtime);
2471             if (negative_delta)
2472             {
2473                rtime *= -1;
2474             }
2475             last_modified += rtime;
2476 #ifdef HAVE_GMTIME_R
2477             timeptr = gmtime_r(&last_modified, &gmt);
2478 #elif defined(MUTEX_LOCKS_AVAILABLE)
2479             privoxy_mutex_lock(&gmtime_mutex);
2480             timeptr = gmtime(&last_modified);
2481             privoxy_mutex_unlock(&gmtime_mutex);
2482 #else
2483             timeptr = gmtime(&last_modified);
2484 #endif
2485             if ((NULL == timeptr) || !strftime(newheader,
2486                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
2487             {
2488                log_error(LOG_LEVEL_ERROR,
2489                   "Randomizing '%s' failed. Crunching the header without replacement.",
2490                   *header);
2491                freez(*header);
2492                return JB_ERR_OK;
2493             }
2494
2495             freez(*header);
2496             *header = strdup("Last-Modified: ");
2497             string_append(header, newheader);
2498
2499             if (*header == NULL)
2500             {
2501                log_error(LOG_LEVEL_ERROR, "Insufficient memory, header crunched without replacement.");
2502                return JB_ERR_MEMORY;  
2503             }
2504
2505             days    = rtime / (3600 * 24);
2506             hours   = rtime / 3600 % 24;
2507             minutes = rtime / 60 % 60;
2508             seconds = rtime % 60;
2509
2510             log_error(LOG_LEVEL_HEADER,
2511                "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
2512                *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
2513                minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
2514          }
2515          else
2516          {
2517             log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
2518          }
2519       }
2520    }
2521
2522    return JB_ERR_OK;
2523 }
2524
2525
2526 /*********************************************************************
2527  *
2528  * Function    :  client_accept_encoding
2529  *
2530  * Description :  Rewrite the client's Accept-Encoding header so that
2531  *                if doesn't allow compression, if the action applies.
2532  *                Note: For HTTP/1.0 the absence of the header is enough.
2533  *
2534  * Parameters  :
2535  *          1  :  csp = Current client state (buffers, headers, etc...)
2536  *          2  :  header = On input, pointer to header to modify.
2537  *                On output, pointer to the modified header, or NULL
2538  *                to remove the header.  This function frees the
2539  *                original string if necessary.
2540  *
2541  * Returns     :  JB_ERR_OK on success, or
2542  *                JB_ERR_MEMORY on out-of-memory error.
2543  *
2544  *********************************************************************/
2545 static jb_err client_accept_encoding(struct client_state *csp, char **header)
2546 {
2547    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2548    {
2549       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress content");
2550       freez(*header);
2551    }
2552
2553    return JB_ERR_OK;
2554 }
2555
2556
2557 /*********************************************************************
2558  *
2559  * Function    :  client_te
2560  *
2561  * Description :  Rewrite the client's TE header so that
2562  *                if doesn't allow compression, if the action applies.
2563  *
2564  * Parameters  :
2565  *          1  :  csp = Current client state (buffers, headers, etc...)
2566  *          2  :  header = On input, pointer to header to modify.
2567  *                On output, pointer to the modified header, or NULL
2568  *                to remove the header.  This function frees the
2569  *                original string if necessary.
2570  *
2571  * Returns     :  JB_ERR_OK on success, or
2572  *                JB_ERR_MEMORY on out-of-memory error.
2573  *
2574  *********************************************************************/
2575 static jb_err client_te(struct client_state *csp, char **header)
2576 {
2577    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2578    {
2579       freez(*header);
2580       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress transfer");
2581    }
2582
2583    return JB_ERR_OK;
2584 }
2585
2586
2587 /*********************************************************************
2588  *
2589  * Function    :  client_referrer
2590  *
2591  * Description :  Handle the "referer" config setting properly.
2592  *                Called from `sed'.
2593  *
2594  * Parameters  :
2595  *          1  :  csp = Current client state (buffers, headers, etc...)
2596  *          2  :  header = On input, pointer to header to modify.
2597  *                On output, pointer to the modified header, or NULL
2598  *                to remove the header.  This function frees the
2599  *                original string if necessary.
2600  *
2601  * Returns     :  JB_ERR_OK on success, or
2602  *                JB_ERR_MEMORY on out-of-memory error.
2603  *
2604  *********************************************************************/
2605 static jb_err client_referrer(struct client_state *csp, char **header)
2606 {
2607    const char *parameter;
2608    /* booleans for parameters we have to check multiple times */
2609    int parameter_conditional_block;
2610    int parameter_conditional_forge;
2611  
2612 #ifdef FEATURE_FORCE_LOAD
2613    /*
2614     * Since the referrer can include the prefix even
2615     * if the request itself is non-forced, we must
2616     * clean it unconditionally.
2617     *
2618     * XXX: strclean is too broad
2619     */
2620    strclean(*header, FORCE_PREFIX);
2621 #endif /* def FEATURE_FORCE_LOAD */
2622
2623    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
2624    {
2625       /* Nothing left to do */
2626       return JB_ERR_OK;
2627    }
2628
2629    parameter = csp->action->string[ACTION_STRING_REFERER];
2630    assert(parameter != NULL);
2631    parameter_conditional_block = (0 == strcmpic(parameter, "conditional-block"));
2632    parameter_conditional_forge = (0 == strcmpic(parameter, "conditional-forge"));
2633
2634    if (!parameter_conditional_block && !parameter_conditional_forge)
2635    {
2636       /*
2637        * As conditional-block and conditional-forge are the only
2638        * parameters that rely on the original referrer, we can
2639        * remove it now for all the others.
2640        */
2641       freez(*header);
2642    }
2643
2644    if (0 == strcmpic(parameter, "block"))
2645    {
2646       log_error(LOG_LEVEL_HEADER, "Referer crunched!");
2647       return JB_ERR_OK;
2648    }
2649    else if (parameter_conditional_block || parameter_conditional_forge)
2650    {
2651       return handle_conditional_hide_referrer_parameter(header,
2652          csp->http->hostport, parameter_conditional_block);
2653    }
2654    else if (0 == strcmpic(parameter, "forge"))
2655    {
2656       return create_forged_referrer(header, csp->http->hostport);
2657    }
2658    else
2659    {
2660       /* interpret parameter as user-supplied referer to fake */
2661       return create_fake_referrer(header, parameter);
2662    }
2663 }
2664
2665
2666 /*********************************************************************
2667  *
2668  * Function    :  client_accept_language
2669  *
2670  * Description :  Handle the "Accept-Language" config setting properly.
2671  *                Called from `sed'.
2672  *
2673  * Parameters  :
2674  *          1  :  csp = Current client state (buffers, headers, etc...)
2675  *          2  :  header = On input, pointer to header to modify.
2676  *                On output, pointer to the modified header, or NULL
2677  *                to remove the header.  This function frees the
2678  *                original string if necessary.
2679  *
2680  * Returns     :  JB_ERR_OK on success, or
2681  *                JB_ERR_MEMORY on out-of-memory error.
2682  *
2683  *********************************************************************/
2684 static jb_err client_accept_language(struct client_state *csp, char **header)
2685 {
2686    const char *newval;
2687
2688    /*
2689     * Are we messing with the Accept-Language?
2690     */
2691    if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
2692    {
2693       /*I don't think so*/
2694       return JB_ERR_OK;
2695    }
2696
2697    newval = csp->action->string[ACTION_STRING_LANGUAGE];
2698
2699    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2700    {
2701       /*
2702        * Blocking Accept-Language header
2703        */
2704       log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
2705       freez(*header);
2706       return JB_ERR_OK;
2707    }
2708    else
2709    {  
2710       /*
2711        * Replacing Accept-Language header
2712        */
2713       freez(*header);
2714       *header = strdup("Accept-Language: ");
2715       string_append(header, newval);   
2716
2717       if (*header == NULL)
2718       {
2719          log_error(LOG_LEVEL_ERROR,
2720             "Insufficient memory. Accept-Language header crunched without replacement.");  
2721       }
2722       else
2723       {
2724          log_error(LOG_LEVEL_HEADER,
2725             "Accept-Language header crunched and replaced with: %s", *header);
2726       }
2727    }
2728    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2729 }
2730
2731
2732 /*********************************************************************
2733  *
2734  * Function    :  crunch_client_header
2735  *
2736  * Description :  Crunch client header if it matches a string supplied by the
2737  *                user. Called from `sed'.
2738  *
2739  * Parameters  :
2740  *          1  :  csp = Current client state (buffers, headers, etc...)
2741  *          2  :  header = On input, pointer to header to modify.
2742  *                On output, pointer to the modified header, or NULL
2743  *                to remove the header.  This function frees the
2744  *                original string if necessary.
2745  *
2746  * Returns     :  JB_ERR_OK on success and always succeeds
2747  *
2748  *********************************************************************/
2749 static jb_err crunch_client_header(struct client_state *csp, char **header)
2750 {
2751    const char *crunch_pattern;
2752
2753    /* Do we feel like crunching? */
2754    if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
2755    {
2756       crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
2757
2758       /* Is the current header the lucky one? */
2759       if (strstr(*header, crunch_pattern))
2760       {
2761          log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);  
2762          freez(*header);
2763       }
2764    }
2765    return JB_ERR_OK;
2766 }
2767
2768
2769 /*********************************************************************
2770  *
2771  * Function    :  client_uagent
2772  *
2773  * Description :  Handle the "user-agent" config setting properly
2774  *                and remember its original value to enable browser
2775  *                bug workarounds. Called from `sed'.
2776  *
2777  * Parameters  :
2778  *          1  :  csp = Current client state (buffers, headers, etc...)
2779  *          2  :  header = On input, pointer to header to modify.
2780  *                On output, pointer to the modified header, or NULL
2781  *                to remove the header.  This function frees the
2782  *                original string if necessary.
2783  *
2784  * Returns     :  JB_ERR_OK on success, or
2785  *                JB_ERR_MEMORY on out-of-memory error.
2786  *
2787  *********************************************************************/
2788 static jb_err client_uagent(struct client_state *csp, char **header)
2789 {
2790    const char *newval;
2791
2792    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
2793    {
2794       return JB_ERR_OK;
2795    }
2796
2797    newval = csp->action->string[ACTION_STRING_USER_AGENT];
2798    if (newval == NULL)
2799    {
2800       return JB_ERR_OK;
2801    }
2802
2803    freez(*header);
2804    *header = strdup("User-Agent: ");
2805    string_append(header, newval);
2806
2807    log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
2808
2809    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2810 }
2811
2812
2813 /*********************************************************************
2814  *
2815  * Function    :  client_ua
2816  *
2817  * Description :  Handle "ua-" headers properly.  Called from `sed'.
2818  *
2819  * Parameters  :
2820  *          1  :  csp = Current client state (buffers, headers, etc...)
2821  *          2  :  header = On input, pointer to header to modify.
2822  *                On output, pointer to the modified header, or NULL
2823  *                to remove the header.  This function frees the
2824  *                original string if necessary.
2825  *
2826  * Returns     :  JB_ERR_OK on success, or
2827  *                JB_ERR_MEMORY on out-of-memory error.
2828  *
2829  *********************************************************************/
2830 static jb_err client_ua(struct client_state *csp, char **header)
2831 {
2832    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
2833    {
2834       log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
2835       freez(*header);
2836    }
2837
2838    return JB_ERR_OK;
2839 }
2840
2841
2842 /*********************************************************************
2843  *
2844  * Function    :  client_from
2845  *
2846  * Description :  Handle the "from" config setting properly.
2847  *                Called from `sed'.
2848  *
2849  * Parameters  :
2850  *          1  :  csp = Current client state (buffers, headers, etc...)
2851  *          2  :  header = On input, pointer to header to modify.
2852  *                On output, pointer to the modified header, or NULL
2853  *                to remove the header.  This function frees the
2854  *                original string if necessary.
2855  *
2856  * Returns     :  JB_ERR_OK on success, or
2857  *                JB_ERR_MEMORY on out-of-memory error.
2858  *
2859  *********************************************************************/
2860 static jb_err client_from(struct client_state *csp, char **header)
2861 {
2862    const char *newval;
2863
2864    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
2865    {
2866       return JB_ERR_OK;
2867    }
2868
2869    freez(*header);
2870
2871    newval = csp->action->string[ACTION_STRING_FROM];
2872
2873    /*
2874     * Are we blocking the e-mail address?
2875     */
2876    if ((newval == NULL) || (0 == strcmpic(newval, "block")) )
2877    {
2878       log_error(LOG_LEVEL_HEADER, "crunched From!");
2879       return JB_ERR_OK;
2880    }
2881
2882    log_error(LOG_LEVEL_HEADER, " modified");
2883
2884    *header = strdup("From: ");
2885    string_append(header, newval);
2886
2887    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2888 }
2889
2890
2891 /*********************************************************************
2892  *
2893  * Function    :  client_send_cookie
2894  *
2895  * Description :  Crunches the "cookie" header if necessary.
2896  *                Called from `sed'.
2897  *
2898  *                XXX: Stupid name, doesn't send squat.
2899  *
2900  * Parameters  :
2901  *          1  :  csp = Current client state (buffers, headers, etc...)
2902  *          2  :  header = On input, pointer to header to modify.
2903  *                On output, pointer to the modified header, or NULL
2904  *                to remove the header.  This function frees the
2905  *                original string if necessary.
2906  *
2907  * Returns     :  JB_ERR_OK on success, or
2908  *                JB_ERR_MEMORY on out-of-memory error.
2909  *
2910  *********************************************************************/
2911 static jb_err client_send_cookie(struct client_state *csp, char **header)
2912 {
2913    if (csp->action->flags & ACTION_NO_COOKIE_READ)
2914    {
2915       log_error(LOG_LEVEL_HEADER, "Crunched outgoing cookie: %s", *header);
2916       freez(*header);
2917    }
2918
2919    return JB_ERR_OK;
2920 }
2921
2922
2923 /*********************************************************************
2924  *
2925  * Function    :  client_x_forwarded
2926  *
2927  * Description :  Handle the "x-forwarded-for" config setting properly,
2928  *                also used in the add_client_headers list.  Called from `sed'.
2929  *
2930  * Parameters  :
2931  *          1  :  csp = Current client state (buffers, headers, etc...)
2932  *          2  :  header = On input, pointer to header to modify.
2933  *                On output, pointer to the modified header, or NULL
2934  *                to remove the header.  This function frees the
2935  *                original string if necessary.
2936  *
2937  * Returns     :  JB_ERR_OK on success, or
2938  *                JB_ERR_MEMORY on out-of-memory error.
2939  *
2940  *********************************************************************/
2941 jb_err client_x_forwarded(struct client_state *csp, char **header)
2942 {
2943    if (0 != (csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR))
2944    {
2945       const char *parameter = csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR];
2946
2947       if (0 == strcmpic(parameter, "block"))
2948       {
2949          freez(*header);
2950          log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
2951       }
2952       else if (0 == strcmpic(parameter, "add"))
2953       {
2954          string_append(header, ", ");
2955          string_append(header, csp->ip_addr_str);
2956
2957          if (*header == NULL)
2958          {
2959             return JB_ERR_MEMORY;
2960          }
2961          log_error(LOG_LEVEL_HEADER,
2962             "Appended client IP address to %s", *header);
2963          csp->flags |= CSP_FLAG_X_FORWARDED_FOR_APPENDED;
2964       }
2965       else
2966       {
2967          log_error(LOG_LEVEL_FATAL,
2968             "Invalid change-x-forwarded-for parameter: '%s'", parameter);
2969       }
2970    }
2971
2972    return JB_ERR_OK;
2973 }
2974
2975
2976 /*********************************************************************
2977  *
2978  * Function    :  client_max_forwards
2979  *
2980  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
2981  *                from the value of the Max-Forwards header field.
2982  *
2983  * Parameters  :
2984  *          1  :  csp = Current client state (buffers, headers, etc...)
2985  *          2  :  header = On input, pointer to header to modify.
2986  *                On output, pointer to the modified header, or NULL
2987  *                to remove the header.  This function frees the
2988  *                original string if necessary.
2989  *
2990  * Returns     :  JB_ERR_OK on success, or
2991  *                JB_ERR_MEMORY on out-of-memory error.
2992  *
2993  *********************************************************************/
2994 static jb_err client_max_forwards(struct client_state *csp, char **header)
2995 {
2996    int max_forwards;
2997
2998    if ((0 == strcmpic(csp->http->gpc, "trace")) ||
2999        (0 == strcmpic(csp->http->gpc, "options")))
3000    {
3001       assert(*(*header+12) == ':');
3002       if (1 == sscanf(*header+12, ": %d", &max_forwards))
3003       {
3004          if (max_forwards > 0)
3005          {
3006             snprintf(*header, strlen(*header)+1, "Max-Forwards: %d", --max_forwards);
3007             log_error(LOG_LEVEL_HEADER,
3008                "Max-Forwards value for %s request reduced to %d.",
3009                csp->http->gpc, max_forwards);
3010          }
3011          else if (max_forwards < 0)
3012          {
3013             log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3014             freez(*header);
3015          }
3016       }
3017       else
3018       {
3019          log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3020          freez(*header);
3021       }
3022    }
3023
3024    return JB_ERR_OK;
3025 }
3026
3027
3028 /*********************************************************************
3029  *
3030  * Function    :  client_host
3031  *
3032  * Description :  If the request URI did not contain host and
3033  *                port information, parse and evaluate the Host
3034  *                header field.
3035  *
3036  *                Also, kill ill-formed HOST: headers as sent by
3037  *                Apple's iTunes software when used with a proxy.
3038  *
3039  * Parameters  :
3040  *          1  :  csp = Current client state (buffers, headers, etc...)
3041  *          2  :  header = On input, pointer to header to modify.
3042  *                On output, pointer to the modified header, or NULL
3043  *                to remove the header.  This function frees the
3044  *                original string if necessary.
3045  *
3046  * Returns     :  JB_ERR_OK on success, or
3047  *                JB_ERR_MEMORY on out-of-memory error.
3048  *
3049  *********************************************************************/
3050 static jb_err client_host(struct client_state *csp, char **header)
3051 {
3052    char *p, *q;
3053
3054    /*
3055     * If the header field name is all upper-case, chances are that it's
3056     * an ill-formed one from iTunes. BTW, killing innocent headers here is
3057     * not a problem -- they are regenerated later.
3058     */
3059    if ((*header)[1] == 'O')
3060    {
3061       log_error(LOG_LEVEL_HEADER, "Killed all-caps Host header line: %s", *header);
3062       freez(*header);
3063       return JB_ERR_OK;
3064    }
3065
3066    if (!csp->http->hostport || (*csp->http->hostport == '*') ||  
3067        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
3068    {
3069       
3070       if (NULL == (p = strdup((*header)+6)))
3071       {
3072          return JB_ERR_MEMORY;
3073       }
3074       chomp(p);
3075       if (NULL == (q = strdup(p)))
3076       {
3077          freez(p);
3078          return JB_ERR_MEMORY;
3079       }
3080
3081       freez(csp->http->hostport);
3082       csp->http->hostport = p;
3083       freez(csp->http->host);
3084       csp->http->host = q;
3085       q = strchr(csp->http->host, ':');
3086       if (q != NULL)
3087       {
3088          /* Terminate hostname and evaluate port string */
3089          *q++ = '\0';
3090          csp->http->port = atoi(q);
3091       }
3092       else
3093       {
3094          csp->http->port = csp->http->ssl ? 443 : 80;
3095       }
3096
3097       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
3098                 csp->http->hostport, csp->http->host, csp->http->port);
3099    }
3100
3101    /* Signal client_host_adder() to return right away */
3102    csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
3103
3104    return JB_ERR_OK;
3105 }
3106
3107
3108 /*********************************************************************
3109  *
3110  * Function    :  client_if_modified_since
3111  *
3112  * Description :  Remove or modify the If-Modified-Since header.
3113  *
3114  * Parameters  :
3115  *          1  :  csp = Current client state (buffers, headers, etc...)
3116  *          2  :  header = On input, pointer to header to modify.
3117  *                On output, pointer to the modified header, or NULL
3118  *                to remove the header.  This function frees the
3119  *                original string if necessary.
3120  *
3121  * Returns     :  JB_ERR_OK on success, or
3122  *                JB_ERR_MEMORY on out-of-memory error.
3123  *
3124  *********************************************************************/
3125 static jb_err client_if_modified_since(struct client_state *csp, char **header)
3126 {
3127    char newheader[50];
3128 #ifdef HAVE_GMTIME_R
3129    struct tm gmt;
3130 #endif
3131    struct tm *timeptr = NULL;
3132    time_t tm = 0;                  
3133    const char *newval;
3134    char * endptr;
3135    
3136    if ( 0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
3137    {
3138       /* 
3139        * The client got an error message because of a temporary problem,
3140        * the problem is gone and the client now tries to revalidate our
3141        * error message on the real server. The revalidation would always
3142        * end with the transmission of the whole document and there is
3143        * no need to expose the bogus If-Modified-Since header.
3144        */
3145       log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
3146       freez(*header);
3147    }
3148    else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
3149    {
3150       newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
3151
3152       if ((0 == strcmpic(newval, "block")))
3153       {
3154          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3155          freez(*header);
3156       }
3157       else /* add random value */
3158       {
3159          const char *header_time = *header + sizeof("If-Modified-Since:");
3160
3161          if (JB_ERR_OK != parse_header_time(header_time, &tm))
3162          {
3163             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
3164             freez(*header);
3165          }
3166          else
3167          {
3168             long int hours, minutes, seconds;
3169             long int rtime = strtol(newval, &endptr, 0);
3170             const int negative_range = (rtime < 0);
3171
3172             if (rtime)
3173             {
3174                log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
3175                   *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
3176                if (negative_range)
3177                {
3178                   rtime *= -1; 
3179                }
3180                rtime *= 60;
3181                rtime = pick_from_range(rtime);
3182             }
3183             else
3184             {
3185                log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
3186                   *header);
3187             }
3188             tm += rtime * (negative_range ? -1 : 1);
3189 #ifdef HAVE_GMTIME_R
3190             timeptr = gmtime_r(&tm, &gmt);
3191 #elif defined(MUTEX_LOCKS_AVAILABLE)
3192             privoxy_mutex_lock(&gmtime_mutex);
3193             timeptr = gmtime(&tm);
3194             privoxy_mutex_unlock(&gmtime_mutex);
3195 #else
3196             timeptr = gmtime(&tm);
3197 #endif
3198             if ((NULL == timeptr) || !strftime(newheader,
3199                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
3200             {
3201                log_error(LOG_LEVEL_ERROR,
3202                   "Randomizing '%s' failed. Crunching the header without replacement.",
3203                   *header);
3204                freez(*header);
3205                return JB_ERR_OK;
3206             }
3207
3208             freez(*header);
3209             *header = strdup("If-Modified-Since: ");
3210             string_append(header, newheader);
3211
3212             if (*header == NULL)
3213             {
3214                log_error(LOG_LEVEL_HEADER, "Insufficient memory, header crunched without replacement.");
3215                return JB_ERR_MEMORY;  
3216             }
3217
3218             hours   = rtime / 3600;
3219             minutes = rtime / 60 % 60;
3220             seconds = rtime % 60;
3221
3222             log_error(LOG_LEVEL_HEADER,
3223                "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
3224                *header, (negative_range) ? "subtracted" : "added", hours,
3225                (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es",
3226                seconds, (seconds == 1) ? ")" : "s)");
3227          }
3228       }
3229    }
3230
3231    return JB_ERR_OK;
3232 }
3233
3234
3235 /*********************************************************************
3236  *
3237  * Function    :  client_if_none_match
3238  *
3239  * Description :  Remove the If-None-Match header.
3240  *
3241  * Parameters  :
3242  *          1  :  csp = Current client state (buffers, headers, etc...)
3243  *          2  :  header = On input, pointer to header to modify.
3244  *                On output, pointer to the modified header, or NULL
3245  *                to remove the header.  This function frees the
3246  *                original string if necessary.
3247  *
3248  * Returns     :  JB_ERR_OK on success, or
3249  *                JB_ERR_MEMORY on out-of-memory error.
3250  *
3251  *********************************************************************/
3252 static jb_err client_if_none_match(struct client_state *csp, char **header)
3253 {
3254    if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
3255    {  
3256       log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3257       freez(*header);
3258    }
3259
3260    return JB_ERR_OK;
3261 }
3262
3263
3264 /*********************************************************************
3265  *
3266  * Function    :  client_x_filter
3267  *
3268  * Description :  Disables filtering if the client set "X-Filter: No".
3269  *                Called from `sed'.
3270  *
3271  * Parameters  :
3272  *          1  :  csp = Current client state (buffers, headers, etc...)
3273  *          2  :  header = On input, pointer to header to modify.
3274  *                On output, pointer to the modified header, or NULL
3275  *                to remove the header.  This function frees the
3276  *                original string if necessary.
3277  *
3278  * Returns     :  JB_ERR_OK on success
3279  *
3280  *********************************************************************/
3281 jb_err client_x_filter(struct client_state *csp, char **header)
3282 {
3283    if ( 0 == strcmpic(*header, "X-Filter: No"))
3284    {
3285       if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
3286       {
3287          log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
3288       }
3289       else
3290       {
3291          if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
3292          {
3293             log_error(LOG_LEVEL_HEADER,
3294                "force-text-mode overruled the client's request to fetch without filtering!");
3295          }
3296          else
3297          {  
3298             csp->content_type = CT_TABOO; /* XXX: This hack shouldn't be necessary */
3299             csp->flags |= CSP_FLAG_NO_FILTERING;
3300             log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
3301          }
3302          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3303          freez(*header);
3304       }
3305    }
3306    return JB_ERR_OK; 
3307 }
3308
3309
3310 /*********************************************************************
3311  *
3312  * Function    :  client_range
3313  *
3314  * Description :  Removes Range, Request-Range and If-Range headers if
3315  *                content filtering is enabled. If the client's version
3316  *                of the document has been altered by Privoxy, the server
3317  *                could interpret the range differently than the client
3318  *                intended in which case the user could end up with
3319  *                corrupted content.
3320  *
3321  * Parameters  :
3322  *          1  :  csp = Current client state (buffers, headers, etc...)
3323  *          2  :  header = On input, pointer to header to modify.
3324  *                On output, pointer to the modified header, or NULL
3325  *                to remove the header.  This function frees the
3326  *                original string if necessary.
3327  *
3328  * Returns     :  JB_ERR_OK
3329  *
3330  *********************************************************************/
3331 static jb_err client_range(struct client_state *csp, char **header)
3332 {
3333    if (content_filters_enabled(csp->action))
3334    {
3335       log_error(LOG_LEVEL_HEADER, "Content filtering is enabled."
3336          " Crunching: \'%s\' to prevent range-mismatch problems.", *header);
3337       freez(*header);
3338    }
3339
3340    return JB_ERR_OK; 
3341 }
3342
3343 /* the following functions add headers directly to the header list */
3344
3345 /*********************************************************************
3346  *
3347  * Function    :  client_host_adder
3348  *
3349  * Description :  Adds the Host: header field if it is missing.
3350  *                Called from `sed'.
3351  *
3352  * Parameters  :
3353  *          1  :  csp = Current client state (buffers, headers, etc...)
3354  *
3355  * Returns     :  JB_ERR_OK on success, or
3356  *                JB_ERR_MEMORY on out-of-memory error.
3357  *
3358  *********************************************************************/
3359 static jb_err client_host_adder(struct client_state *csp)
3360 {
3361    char *p;
3362    jb_err err;
3363
3364    if (csp->flags & CSP_FLAG_HOST_HEADER_IS_SET)
3365    {
3366       /* Header already set by the client, nothing to do. */
3367       return JB_ERR_OK;
3368    }
3369
3370    if ( !csp->http->hostport || !*(csp->http->hostport))
3371    {
3372       /* XXX: When does this happen and why is it OK? */
3373       log_error(LOG_LEVEL_INFO, "Weirdness in client_host_adder detected and ignored.");
3374       return JB_ERR_OK;
3375    }
3376
3377    /*
3378     * remove 'user:pass@' from 'proto://user:pass@host'
3379     */
3380    if ( (p = strchr( csp->http->hostport, '@')) != NULL )
3381    {
3382       p++;
3383    }
3384    else
3385    {
3386       p = csp->http->hostport;
3387    }
3388
3389    /* XXX: Just add it, we already made sure that it will be unique */
3390    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
3391    err = enlist_unique_header(csp->headers, "Host", p);
3392    return err;
3393
3394 }
3395
3396
3397 #if 0
3398 /*********************************************************************
3399  *
3400  * Function    :  client_accept_encoding_adder
3401  *
3402  * Description :  Add an Accept-Encoding header to the client's request
3403  *                that disables compression if the action applies, and
3404  *                the header is not already there. Called from `sed'.
3405  *                Note: For HTTP/1.0, the absence of the header is enough.
3406  *
3407  * Parameters  :
3408  *          1  :  csp = Current client state (buffers, headers, etc...)
3409  *
3410  * Returns     :  JB_ERR_OK on success, or
3411  *                JB_ERR_MEMORY on out-of-memory error.
3412  *
3413  *********************************************************************/
3414 static jb_err client_accept_encoding_adder(struct client_state *csp)
3415 {
3416    if (   ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
3417        && (!strcmpic(csp->http->ver, "HTTP/1.1")) )
3418    {
3419       return enlist_unique(csp->headers, "Accept-Encoding: identity;q=1.0, *;q=0", 16);
3420    }
3421
3422    return JB_ERR_OK;
3423 }
3424 #endif
3425
3426
3427 /*********************************************************************
3428  *
3429  * Function    :  client_xtra_adder
3430  *
3431  * Description :  Used in the add_client_headers list.  Called from `sed'.
3432  *
3433  * Parameters  :
3434  *          1  :  csp = Current client state (buffers, headers, etc...)
3435  *
3436  * Returns     :  JB_ERR_OK on success, or
3437  *                JB_ERR_MEMORY on out-of-memory error.
3438  *
3439  *********************************************************************/
3440 static jb_err client_xtra_adder(struct client_state *csp)
3441 {
3442    struct list_entry *lst;
3443    jb_err err;
3444
3445    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
3446         lst ; lst = lst->next)
3447    {
3448       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
3449       err = enlist(csp->headers, lst->str);
3450       if (err)
3451       {
3452          return err;
3453       }
3454
3455    }
3456
3457    return JB_ERR_OK;
3458 }
3459
3460
3461 /*********************************************************************
3462  *
3463  * Function    :  client_x_forwarded_for_adder
3464  *
3465  * Description :  Used in the add_client_headers list.  Called from `sed'.
3466  *
3467  * Parameters  :
3468  *          1  :  csp = Current client state (buffers, headers, etc...)
3469  *
3470  * Returns     :  JB_ERR_OK on success, or
3471  *                JB_ERR_MEMORY on out-of-memory error.
3472  *
3473  *********************************************************************/
3474 static jb_err client_x_forwarded_for_adder(struct client_state *csp)
3475 {
3476    char *header = NULL;
3477    jb_err err;
3478
3479    if (!((csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR)
3480          && (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "add")))
3481       || (csp->flags & CSP_FLAG_X_FORWARDED_FOR_APPENDED))
3482    {
3483       /*
3484        * If we aren't adding X-Forwarded-For headers,
3485        * or we already appended an existing X-Forwarded-For
3486        * header, there's nothing left to do here.
3487        */
3488       return JB_ERR_OK;
3489    }
3490
3491    header = strdup("X-Forwarded-For: ");
3492    string_append(&header, csp->ip_addr_str);
3493
3494    if (header == NULL)
3495    {
3496       return JB_ERR_MEMORY;
3497    }
3498
3499    log_error(LOG_LEVEL_HEADER, "addh: %s", header);
3500    err = enlist(csp->headers, header);
3501    freez(header);
3502
3503    return err;
3504 }
3505
3506
3507 /*********************************************************************
3508  *
3509  * Function    :  server_connection_adder
3510  *
3511  * Description :  Adds an appropiate "Connection:" header to csp->headers
3512  *                unless the header was already present. Called from `sed'.
3513  *
3514  * Parameters  :
3515  *          1  :  csp = Current client state (buffers, headers, etc...)
3516  *
3517  * Returns     :  JB_ERR_OK on success, or
3518  *                JB_ERR_MEMORY on out-of-memory error.
3519  *
3520  *********************************************************************/
3521 static jb_err server_connection_adder(struct client_state *csp)
3522 {
3523    const unsigned int flags = csp->flags;
3524    const char *response_status_line = csp->headers->first->str;
3525    static const char connection_close[] = "Connection: close";
3526
3527    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3528     && (flags & CSP_FLAG_SERVER_CONNECTION_HEADER_SET))
3529    {
3530       return JB_ERR_OK;
3531    }
3532
3533    /*
3534     * XXX: if we downgraded the response, this check will fail.
3535     */
3536    if ((csp->config->feature_flags &
3537         RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3538     && (NULL != response_status_line)
3539     && !strncmpic(response_status_line, "HTTP/1.1", 8)
3540 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3541     && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
3542 #endif
3543        )
3544    {
3545       log_error(LOG_LEVEL_HEADER, "A HTTP/1.1 response "
3546          "without Connection header implies keep-alive.");
3547       csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
3548       return JB_ERR_OK;
3549    }
3550
3551    log_error(LOG_LEVEL_HEADER, "Adding: %s", connection_close);
3552
3553    return enlist(csp->headers, connection_close);
3554 }
3555
3556
3557 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3558 /*********************************************************************
3559  *
3560  * Function    :  server_proxy_connection_adder
3561  *
3562  * Description :  Adds a "Proxy-Connection: keep-alive" header to
3563  *                csp->headers if the client asked for keep-alive.
3564  *                XXX: We should reuse existant ones.
3565  *
3566  * Parameters  :
3567  *          1  :  csp = Current client state (buffers, headers, etc...)
3568  *
3569  * Returns     :  JB_ERR_OK on success, or
3570  *                JB_ERR_MEMORY on out-of-memory error.
3571  *
3572  *********************************************************************/
3573 static jb_err server_proxy_connection_adder(struct client_state *csp)
3574 {
3575    static const char proxy_connection_header[] = "Proxy-Connection: keep-alive";
3576    jb_err err = JB_ERR_OK;
3577
3578    if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
3579     && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
3580     && !(csp->flags & CSP_FLAG_SERVER_PROXY_CONNECTION_HEADER_SET))
3581    {
3582       log_error(LOG_LEVEL_HEADER, "Adding: %s", proxy_connection_header);
3583       err = enlist(csp->headers, proxy_connection_header);
3584    }
3585
3586    return err;
3587 }
3588 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3589
3590
3591 /*********************************************************************
3592  *
3593  * Function    :  client_connection_header_adder
3594  *
3595  * Description :  Adds a proper "Connection:" header to csp->headers
3596  *                unless the header was already present. Called from `sed'.
3597  *
3598  * Parameters  :
3599  *          1  :  csp = Current client state (buffers, headers, etc...)
3600  *
3601  * Returns     :  JB_ERR_OK on success, or
3602  *                JB_ERR_MEMORY on out-of-memory error.
3603  *
3604  *********************************************************************/
3605 static jb_err client_connection_header_adder(struct client_state *csp)
3606 {
3607    static const char connection_close[] = "Connection: close";
3608
3609    if (!(csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3610      && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_HEADER_SET))
3611    {
3612       return JB_ERR_OK;
3613    }
3614
3615 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3616    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3617       && (csp->http->ssl == 0)
3618       && !strcmpic(csp->http->ver, "HTTP/1.1"))
3619    {
3620       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
3621       return JB_ERR_OK;
3622    }
3623 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3624
3625    log_error(LOG_LEVEL_HEADER, "Adding: %s", connection_close);
3626
3627    return enlist(csp->headers, connection_close);
3628 }
3629
3630
3631 /*********************************************************************
3632  *
3633  * Function    :  server_http
3634  *
3635  * Description :  - Save the HTTP Status into csp->http->status
3636  *                - Set CT_TABOO to prevent filtering if the answer
3637  *                  is a partial range (HTTP status 206)
3638  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
3639  *                  action applies.
3640  *
3641  * Parameters  :
3642  *          1  :  csp = Current client state (buffers, headers, etc...)
3643  *          2  :  header = On input, pointer to header to modify.
3644  *                On output, pointer to the modified header, or NULL
3645  *                to remove the header.  This function frees the
3646  *                original string if necessary.
3647  *
3648  * Returns     :  JB_ERR_OK on success, or
3649  *                JB_ERR_MEMORY on out-of-memory error.
3650  *
3651  *********************************************************************/
3652 static jb_err server_http(struct client_state *csp, char **header)
3653 {
3654    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
3655    if (csp->http->status == 206)
3656    {
3657       csp->content_type = CT_TABOO;
3658    }
3659
3660    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
3661    {
3662       /* XXX: Should we do a real validity check here? */
3663       if (strlen(*header) > 8)
3664       {
3665          (*header)[7] = '0';
3666          log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
3667       }
3668       else
3669       {
3670          /*
3671           * XXX: Should we block the request or
3672           * enlist a valid status code line here?
3673           */
3674          log_error(LOG_LEVEL_INFO, "Malformed server response detected. "
3675             "Downgrading to HTTP/1.0 impossible.");
3676       }
3677    }
3678
3679    return JB_ERR_OK;
3680 }
3681
3682
3683 /*********************************************************************
3684  *
3685  * Function    :  server_set_cookie
3686  *
3687  * Description :  Handle the server "cookie" header properly.
3688  *                Crunch, accept or rewrite it to a session cookie.
3689  *                Called from `sed'.
3690  *
3691  *                TODO: Allow the user to specify a new expiration
3692  *                time to cause the cookie to expire even before the
3693  *                browser is closed.
3694  *
3695  * Parameters  :
3696  *          1  :  csp = Current client state (buffers, headers, etc...)
3697  *          2  :  header = On input, pointer to header to modify.
3698  *                On output, pointer to the modified header, or NULL
3699  *                to remove the header.  This function frees the
3700  *                original string if necessary.
3701  *
3702  * Returns     :  JB_ERR_OK on success, or
3703  *                JB_ERR_MEMORY on out-of-memory error.
3704  *
3705  *********************************************************************/
3706 static jb_err server_set_cookie(struct client_state *csp, char **header)
3707 {
3708    time_t now;
3709    time_t cookie_time; 
3710
3711    time(&now);
3712
3713    if ((csp->action->flags & ACTION_NO_COOKIE_SET) != 0)
3714    {
3715       log_error(LOG_LEVEL_HEADER, "Crunching incoming cookie: %s", *header);
3716       freez(*header);
3717    }
3718    else if ((csp->action->flags & ACTION_NO_COOKIE_KEEP) != 0)
3719    {
3720       /* Flag whether or not to log a message */
3721       int changed = 0;
3722
3723       /* A variable to store the tag we're working on */
3724       char *cur_tag;
3725
3726       /* Skip "Set-Cookie:" (11 characters) in header */
3727       cur_tag = *header + 11;
3728
3729       /* skip whitespace between "Set-Cookie:" and value */
3730       while (*cur_tag && ijb_isspace(*cur_tag))
3731       {
3732          cur_tag++;
3733       }
3734
3735       /* Loop through each tag in the cookie */
3736       while (*cur_tag)
3737       {
3738          /* Find next tag */
3739          char *next_tag = strchr(cur_tag, ';');
3740          if (next_tag != NULL)
3741          {
3742             /* Skip the ';' character itself */
3743             next_tag++;
3744
3745             /* skip whitespace ";" and start of tag */
3746             while (*next_tag && ijb_isspace(*next_tag))
3747             {
3748                next_tag++;
3749             }
3750          }
3751          else
3752          {
3753             /* "Next tag" is the end of the string */
3754             next_tag = cur_tag + strlen(cur_tag);
3755          }
3756
3757          /*
3758           * Check the expiration date to see
3759           * if the cookie is still valid, if yes,
3760           * rewrite it to a session cookie.
3761           */
3762          if ((strncmpic(cur_tag, "expires=", 8) == 0) && *(cur_tag + 8))
3763          {
3764             char *expiration_date = cur_tag + 8; /* Skip "[Ee]xpires=" */
3765
3766             if ((expiration_date[0] == '"')
3767              && (expiration_date[1] != '\0'))
3768             {
3769                /*
3770                 * Skip quotation mark. RFC 2109 10.1.2 seems to hint
3771                 * that the expiration date isn't supposed to be quoted,
3772                 * but some servers do it anyway.
3773                 */
3774                expiration_date++;
3775             }
3776
3777             /* Did we detect the date properly? */
3778             if (JB_ERR_OK != parse_header_time(expiration_date, &cookie_time))
3779             {
3780                /*
3781                 * Nope, treat it as if it was still valid.
3782                 *
3783                 * XXX: Should we remove the whole cookie instead?
3784                 */
3785                log_error(LOG_LEVEL_ERROR,
3786                   "Can't parse \'%s\', send by %s. Unsupported time format?", cur_tag, csp->http->url);
3787                string_move(cur_tag, next_tag);
3788                changed = 1;
3789             }
3790             else
3791             {
3792                /*
3793                 * Yes. Check if the cookie is still valid.
3794                 *
3795                 * If the cookie is already expired it's probably
3796                 * a delete cookie and even if it isn't, the browser
3797                 * will discard it anyway.
3798                 */
3799
3800                /*
3801                 * XXX: timegm() isn't available on some AmigaOS
3802                 * versions and our replacement doesn't work.
3803                 *
3804                 * Our options are to either:
3805                 *
3806                 * - disable session-cookies-only completely if timegm
3807                 *   is missing,
3808                 *
3809                 * - to simply remove all expired tags, like it has
3810                 *   been done until Privoxy 3.0.6 and to live with
3811                 *    the consequence that it can cause login/logout
3812                 *   problems on servers that don't validate their
3813                 *   input properly, or
3814                 *
3815                 * - to replace it with mktime in which
3816                 *   case there is a slight chance of valid cookies
3817                 *   passing as already expired.
3818                 *
3819                 *   This is the way it's currently done and it's not
3820                 *   as bad as it sounds. If the missing GMT offset is
3821                 *   enough to change the result of the expiration check
3822                 *   the cookie will be only valid for a few hours
3823                 *   anyway, which in many cases will be shorter
3824                 *   than a browser session.
3825                 */
3826                if (cookie_time - now < 0)
3827                {
3828                   log_error(LOG_LEVEL_HEADER,
3829                      "Cookie \'%s\' is already expired and can pass unmodified.", *header);
3830                   /* Just in case some clown sets more then one expiration date */
3831                   cur_tag = next_tag;
3832                }
3833                else
3834                {
3835                   /*
3836                    * Still valid, delete expiration date by copying
3837                    * the rest of the string over it.
3838                    */
3839                   string_move(cur_tag, next_tag);
3840
3841                   /* That changed the header, need to issue a log message */
3842                   changed = 1;
3843
3844                   /*
3845                    * Note that the next tag has now been moved to *cur_tag,
3846                    * so we do not need to update the cur_tag pointer.
3847                    */
3848                }
3849             }
3850
3851          }
3852          else
3853          {
3854             /* Move on to next cookie tag */
3855             cur_tag = next_tag;
3856          }
3857       }
3858
3859       if (changed)
3860       {
3861          assert(NULL != *header);
3862          log_error(LOG_LEVEL_HEADER, "Cookie rewritten to a temporary one: %s",
3863             *header);
3864       }
3865    }
3866
3867    return JB_ERR_OK;
3868 }
3869
3870
3871 #ifdef FEATURE_FORCE_LOAD
3872 /*********************************************************************
3873  *
3874  * Function    :  strclean
3875  *
3876  * Description :  In-Situ-Eliminate all occurances of substring in
3877  *                string
3878  *
3879  * Parameters  :
3880  *          1  :  string = string to clean
3881  *          2  :  substring = substring to eliminate
3882  *
3883  * Returns     :  Number of eliminations
3884  *
3885  *********************************************************************/
3886 int strclean(char *string, const char *substring)
3887 {
3888    int hits = 0;
3889    size_t len;
3890    char *pos, *p;
3891
3892    len = strlen(substring);
3893
3894    while((pos = strstr(string, substring)) != NULL)
3895    {
3896       p = pos + len;
3897       do
3898       {
3899          *(p - len) = *p;
3900       }
3901       while (*p++ != '\0');
3902
3903       hits++;
3904    }
3905
3906    return(hits);
3907 }
3908 #endif /* def FEATURE_FORCE_LOAD */
3909
3910
3911 /*********************************************************************
3912  *
3913  * Function    :  parse_header_time
3914  *
3915  * Description :  Parses time formats used in HTTP header strings
3916  *                to get the numerical respresentation.
3917  *
3918  * Parameters  :
3919  *          1  :  header_time = HTTP header time as string. 
3920  *          2  :  result = storage for header_time in seconds
3921  *
3922  * Returns     :  JB_ERR_OK if the time format was recognized, or
3923  *                JB_ERR_PARSE otherwise.
3924  *
3925  *********************************************************************/
3926 static jb_err parse_header_time(const char *header_time, time_t *result)
3927 {
3928    struct tm gmt;
3929
3930    /*
3931     * Zero out gmt to prevent time zone offsets.
3932     *
3933     * While this is only necessary on some platforms
3934     * (mingw32 for example), I don't know how to
3935     * detect these automatically and doing it everywhere
3936     * shouldn't hurt.
3937     */
3938    memset(&gmt, 0, sizeof(gmt));
3939
3940                             /* Tue, 02 Jun 2037 20:00:00 */
3941    if ((NULL == strptime(header_time, "%a, %d %b %Y %H:%M:%S", &gmt))
3942                             /* Tue, 02-Jun-2037 20:00:00 */
3943     && (NULL == strptime(header_time, "%a, %d-%b-%Y %H:%M:%S", &gmt))
3944                             /* Tue, 02-Jun-37 20:00:00 */
3945     && (NULL == strptime(header_time, "%a, %d-%b-%y %H:%M:%S", &gmt))
3946                         /* Tuesday, 02-Jun-2037 20:00:00 */
3947     && (NULL == strptime(header_time, "%A, %d-%b-%Y %H:%M:%S", &gmt))
3948                         /* Tuesday Jun 02 20:00:00 2037 */
3949     && (NULL == strptime(header_time, "%A %b %d %H:%M:%S %Y", &gmt)))
3950    {
3951       return JB_ERR_PARSE;
3952    }
3953
3954    *result = timegm(&gmt);
3955
3956    return JB_ERR_OK;
3957
3958 }
3959
3960
3961 /*********************************************************************
3962  *
3963  * Function    :  get_destination_from_headers
3964  *
3965  * Description :  Parse the "Host:" header to get the request's destination.
3966  *                Only needed if the client's request was forcefully
3967  *                redirected into Privoxy.
3968  *
3969  *                Code mainly copied from client_host() which is currently
3970  *                run too late for this purpose.
3971  *
3972  * Parameters  :
3973  *          1  :  headers = List of headers (one of them hopefully being
3974  *                the "Host:" header)
3975  *          2  :  http = storage for the result (host, port and hostport). 
3976  *
3977  * Returns     :  JB_ERR_MEMORY in case of memory problems,
3978  *                JB_ERR_PARSE if the host header couldn't be found,
3979  *                JB_ERR_OK otherwise.
3980  *
3981  *********************************************************************/
3982 jb_err get_destination_from_headers(const struct list *headers, struct http_request *http)
3983 {
3984    char *q;
3985    char *p;
3986    char *host;
3987
3988    host = get_header_value(headers, "Host:");
3989
3990    if (NULL == host)
3991    {
3992       log_error(LOG_LEVEL_ERROR, "No \"Host:\" header found.");
3993       return JB_ERR_PARSE;
3994    }
3995
3996    if (NULL == (p = strdup((host))))
3997    {
3998       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
3999       return JB_ERR_MEMORY;
4000    }
4001    chomp(p);
4002    if (NULL == (q = strdup(p)))
4003    {
4004       freez(p);
4005       log_error(LOG_LEVEL_ERROR, "Out of memory while parsing \"Host:\" header");
4006       return JB_ERR_MEMORY;
4007    }
4008
4009    freez(http->hostport);
4010    http->hostport = p;
4011    freez(http->host);
4012    http->host = q;
4013    q = strchr(http->host, ':');
4014    if (q != NULL)
4015    {
4016       /* Terminate hostname and evaluate port string */
4017       *q++ = '\0';
4018       http->port = atoi(q);
4019    }
4020    else
4021    {
4022       http->port = http->ssl ? 443 : 80;
4023    }
4024
4025    /* Rebuild request URL */
4026    freez(http->url);
4027    http->url = strdup(http->ssl ? "https://" : "http://");
4028    string_append(&http->url, http->hostport);
4029    string_append(&http->url, http->path);
4030    if (http->url == NULL)
4031    {
4032       return JB_ERR_MEMORY;
4033    }
4034
4035    log_error(LOG_LEVEL_HEADER, "Destination extracted from \"Host:\" header. New request URL: %s",
4036       http->url);
4037
4038    return JB_ERR_OK;
4039
4040 }
4041
4042
4043 /*********************************************************************
4044  *
4045  * Function    :  create_forged_referrer
4046  *
4047  * Description :  Helper for client_referrer to forge a referer as
4048  *                'http://[hostname:port/' to fool stupid
4049  *                checks for in-site links 
4050  *
4051  * Parameters  :
4052  *          1  :  header   = Pointer to header pointer
4053  *          2  :  hostport = Host and optionally port as string
4054  *
4055  * Returns     :  JB_ERR_OK in case of success, or
4056  *                JB_ERR_MEMORY in case of memory problems.
4057  *
4058  *********************************************************************/
4059 static jb_err create_forged_referrer(char **header, const char *hostport)
4060 {
4061     assert(NULL == *header);
4062
4063     *header = strdup("Referer: http://");
4064     string_append(header, hostport);
4065     string_append(header, "/");
4066
4067     if (NULL == *header)
4068     {
4069        return JB_ERR_MEMORY;
4070     }
4071
4072     log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
4073
4074     return JB_ERR_OK;
4075
4076 }
4077
4078
4079 /*********************************************************************
4080  *
4081  * Function    :  create_fake_referrer
4082  *
4083  * Description :  Helper for client_referrer to create a fake referrer
4084  *                based on a string supplied by the user.
4085  *
4086  * Parameters  :
4087  *          1  :  header   = Pointer to header pointer
4088  *          2  :  hosthost = Referrer to fake
4089  *
4090  * Returns     :  JB_ERR_OK in case of success, or
4091  *                JB_ERR_MEMORY in case of memory problems.
4092  *
4093  *********************************************************************/
4094 static jb_err create_fake_referrer(char **header, const char *fake_referrer)
4095 {
4096    assert(NULL == *header);
4097
4098    if ((0 != strncmpic(fake_referrer, "http://", 7)) && (0 != strncmpic(fake_referrer, "https://", 8)))
4099    {
4100       log_error(LOG_LEVEL_HEADER,
4101          "Parameter: +hide-referrer{%s} is a bad idea, but I don't care.", fake_referrer);
4102    }
4103    *header = strdup("Referer: ");
4104    string_append(header, fake_referrer);
4105
4106    if (NULL == *header)
4107    {
4108       return JB_ERR_MEMORY;
4109    }
4110
4111    log_error(LOG_LEVEL_HEADER, "Referer replaced with: %s", *header);
4112
4113    return JB_ERR_OK;
4114
4115 }
4116
4117
4118 /*********************************************************************
4119  *
4120  * Function    :  handle_conditional_hide_referrer_parameter
4121  *
4122  * Description :  Helper for client_referrer to crunch or forge
4123  *                the referrer header if the host has changed.
4124  *
4125  * Parameters  :
4126  *          1  :  header = Pointer to header pointer
4127  *          2  :  host   = The target host (may include the port)
4128  *          3  :  parameter_conditional_block = Boolean to signal
4129  *                if we're in conditional-block mode. If not set,
4130  *                we're in conditional-forge mode.
4131  *
4132  * Returns     :  JB_ERR_OK in case of success, or
4133  *                JB_ERR_MEMORY in case of memory problems.
4134  *
4135  *********************************************************************/
4136 static jb_err handle_conditional_hide_referrer_parameter(char **header,
4137    const char *host, const int parameter_conditional_block)
4138 {
4139    char *referer = strdup(*header);
4140    const size_t hostlength = strlen(host);
4141    const char *referer_url = NULL;
4142
4143    if (NULL == referer)
4144    {
4145       freez(*header);
4146       return JB_ERR_MEMORY;
4147    }
4148
4149    /* referer begins with 'Referer: http[s]://' */
4150    if ((hostlength+17) < strlen(referer))
4151    {
4152       /*
4153        * Shorten referer to make sure the referer is blocked
4154        * if www.example.org/www.example.com-shall-see-the-referer/
4155        * links to www.example.com/
4156        */
4157       referer[hostlength+17] = '\0';
4158    }
4159    referer_url = strstr(referer, "http://");
4160    if ((NULL == referer_url) || (NULL == strstr(referer_url, host)))
4161    {
4162       /* Host has changed, Referer is invalid or a https URL. */
4163       if (parameter_conditional_block)
4164       {
4165          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
4166          freez(*header);
4167       }
4168       else
4169       {
4170          freez(*header);
4171          freez(referer);
4172          return create_forged_referrer(header, host);
4173       }
4174    }
4175    freez(referer);
4176
4177    return JB_ERR_OK;
4178
4179 }
4180
4181
4182 /*********************************************************************
4183  *
4184  * Function    :  create_content_length_header
4185  *
4186  * Description :  Creates a Content-Length header.
4187  *
4188  * Parameters  :
4189  *          1  :  content_length = The content length to be used in the header.
4190  *          2  :  header = Allocated space to safe the header.
4191  *          3  :  buffer_length = The length of the allocated space.
4192  *
4193  * Returns     :  void
4194  *
4195  *********************************************************************/
4196 static void create_content_length_header(unsigned long long content_length,
4197                                          char *header, size_t buffer_length)
4198 {
4199    snprintf(header, buffer_length, "Content-Length: %llu", content_length);
4200 }
4201
4202
4203 /*
4204   Local Variables:
4205   tab-width: 3
4206   end:
4207 */