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