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