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