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