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