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