Move the CGI interface improvements to other sections
[privoxy.git] / parsers.c
1 const char parsers_rcs[] = "$Id: parsers.c,v 1.273 2013/01/04 12:19:47 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
5  *
6  * Purpose     :  Declares functions to parse/crunch headers and pages.
7  *
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       if (content_filters_enabled(csp->action))
2109       {
2110          /*
2111           * Making sure the client interprets the content the same way
2112           * Privoxy did is only relevant if Privoxy modified it.
2113           *
2114           * Checking for this is "hard" as it's not yet known when
2115           * this function is called, thus go shopping and and just
2116           * check if Privoxy could filter it.
2117           *
2118           * The main thing is that we don't mess with the headers
2119           * unless the user signalled that it's acceptable.
2120           */
2121          log_error(LOG_LEVEL_HEADER,
2122             "Multiple Content-Type headers detected. "
2123             "Removing and ignoring: %s",
2124             *header);
2125          freez(*header);
2126       }
2127       return JB_ERR_OK;
2128    }
2129
2130    /*
2131     * Signal that the Content-Type has been set.
2132     */
2133    csp->content_type |= CT_DECLARED;
2134
2135    if (!(csp->content_type & CT_TABOO))
2136    {
2137       /*
2138        * XXX: The assumption that text/plain is a sign of
2139        * binary data seems to be somewhat unreasonable nowadays
2140        * and should be dropped after 3.0.8 is out.
2141        */
2142       if ((strstr(*header, "text/") && !strstr(*header, "plain"))
2143         || strstr(*header, "xml")
2144         || strstr(*header, "script"))
2145       {
2146          csp->content_type |= CT_TEXT;
2147       }
2148       else if (strstr(*header, "image/gif"))
2149       {
2150          csp->content_type |= CT_GIF;
2151       }
2152    }
2153
2154    /*
2155     * Are we messing with the content type?
2156     */
2157    if (csp->action->flags & ACTION_CONTENT_TYPE_OVERWRITE)
2158    {
2159       /*
2160        * Make sure the user doesn't accidentally
2161        * change the content type of binary documents.
2162        */
2163       if ((csp->content_type & CT_TEXT) || (csp->action->flags & ACTION_FORCE_TEXT_MODE))
2164       {
2165          freez(*header);
2166          *header = strdup_or_die("Content-Type: ");
2167          string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]);
2168
2169          if (header == NULL)
2170          {
2171             log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!");
2172             return JB_ERR_MEMORY;
2173          }
2174          log_error(LOG_LEVEL_HEADER, "Modified: %s!", *header);
2175       }
2176       else
2177       {
2178          log_error(LOG_LEVEL_HEADER, "%s not replaced. "
2179             "It doesn't look like a content type that should be filtered. "
2180             "Enable force-text-mode if you know what you're doing.", *header);
2181       }
2182    }
2183
2184    return JB_ERR_OK;
2185 }
2186
2187
2188 /*********************************************************************
2189  *
2190  * Function    :  server_transfer_coding
2191  *
2192  * Description :  - Prohibit filtering (CT_TABOO) if transfer coding compresses
2193  *                - Raise the CSP_FLAG_CHUNKED flag if coding is "chunked"
2194  *                - Remove header if body was chunked but has been
2195  *                  de-chunked for filtering.
2196  *
2197  * Parameters  :
2198  *          1  :  csp = Current client state (buffers, headers, etc...)
2199  *          2  :  header = On input, pointer to header to modify.
2200  *                On output, pointer to the modified header, or NULL
2201  *                to remove the header.  This function frees the
2202  *                original string if necessary.
2203  *
2204  * Returns     :  JB_ERR_OK on success, or
2205  *                JB_ERR_MEMORY on out-of-memory error.
2206  *
2207  *********************************************************************/
2208 static jb_err server_transfer_coding(struct client_state *csp, char **header)
2209 {
2210    /*
2211     * Turn off pcrs and gif filtering if body compressed
2212     */
2213    if (strstr(*header, "gzip") || strstr(*header, "compress") || strstr(*header, "deflate"))
2214    {
2215 #ifdef FEATURE_ZLIB
2216       /*
2217        * XXX: Added to test if we could use CT_GZIP and CT_DEFLATE here.
2218        */
2219       log_error(LOG_LEVEL_INFO, "Marking content type for %s as CT_TABOO because of %s.",
2220          csp->http->cmd, *header);
2221 #endif /* def FEATURE_ZLIB */
2222       csp->content_type = CT_TABOO;
2223    }
2224
2225    /*
2226     * Raise flag if body chunked
2227     */
2228    if (strstr(*header, "chunked"))
2229    {
2230       csp->flags |= CSP_FLAG_CHUNKED;
2231
2232       /*
2233        * If the body was modified, it has been de-chunked first
2234        * and the header must be removed.
2235        *
2236        * FIXME: If there is more than one transfer encoding,
2237        * only the "chunked" part should be removed here.
2238        */
2239       if (csp->flags & CSP_FLAG_MODIFIED)
2240       {
2241          log_error(LOG_LEVEL_HEADER, "Removing: %s", *header);
2242          freez(*header);
2243       }
2244    }
2245
2246    return JB_ERR_OK;
2247 }
2248
2249
2250 /*********************************************************************
2251  *
2252  * Function    :  server_content_encoding
2253  *
2254  * Description :  Used to check if the content is compressed, and if
2255  *                FEATURE_ZLIB is disabled, filtering is disabled as
2256  *                well.
2257  *
2258  *                If FEATURE_ZLIB is enabled and the compression type
2259  *                supported, the content is marked for decompression.
2260  *
2261  *                XXX: Doesn't properly deal with multiple or with
2262  *                     unsupported but unknown encodings.
2263  *                     Is case-sensitive but shouldn't be.
2264  *
2265  * Parameters  :
2266  *          1  :  csp = Current client state (buffers, headers, etc...)
2267  *          2  :  header = On input, pointer to header to modify.
2268  *                On output, pointer to the modified header, or NULL
2269  *                to remove the header.  This function frees the
2270  *                original string if necessary.
2271  *
2272  * Returns     :  JB_ERR_OK on success, or
2273  *                JB_ERR_MEMORY on out-of-memory error.
2274  *
2275  *********************************************************************/
2276 static jb_err server_content_encoding(struct client_state *csp, char **header)
2277 {
2278 #ifdef FEATURE_ZLIB
2279    if (strstr(*header, "sdch"))
2280    {
2281       /*
2282        * Shared Dictionary Compression over HTTP isn't supported,
2283        * filtering it anyway is pretty much guaranteed to mess up
2284        * the encoding.
2285        */
2286       csp->content_type |= CT_TABOO;
2287
2288       /*
2289        * Log a warning if the user expects the content to be filtered.
2290        */
2291       if ((csp->rlist != NULL) &&
2292          (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
2293       {
2294          log_error(LOG_LEVEL_INFO,
2295             "SDCH-compressed content detected, content filtering disabled. "
2296             "Consider suppressing SDCH offers made by the client.");
2297       }
2298    }
2299    else if (strstr(*header, "gzip"))
2300    {
2301       /* Mark for gzip decompression */
2302       csp->content_type |= CT_GZIP;
2303    }
2304    else if (strstr(*header, "deflate"))
2305    {
2306       /* Mark for zlib decompression */
2307       csp->content_type |= CT_DEFLATE;
2308    }
2309    else if (strstr(*header, "compress"))
2310    {
2311       /*
2312        * We can't decompress this; therefore we can't filter
2313        * it either.
2314        */
2315       csp->content_type |= CT_TABOO;
2316    }
2317 #else /* !defined(FEATURE_ZLIB) */
2318    /*
2319     * XXX: Using a black list here isn't the right approach.
2320     *
2321     *      In case of SDCH, building with zlib support isn't
2322     *      going to help.
2323     */
2324    if (strstr(*header, "gzip") ||
2325        strstr(*header, "compress") ||
2326        strstr(*header, "deflate") ||
2327        strstr(*header, "sdch"))
2328    {
2329       /*
2330        * Body is compressed, turn off pcrs and gif filtering.
2331        */
2332       csp->content_type |= CT_TABOO;
2333
2334       /*
2335        * Log a warning if the user expects the content to be filtered.
2336        */
2337       if ((csp->rlist != NULL) &&
2338          (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER])))
2339       {
2340          log_error(LOG_LEVEL_INFO,
2341             "Compressed content detected, content filtering disabled. "
2342             "Consider recompiling Privoxy with zlib support or "
2343             "enable the prevent-compression action.");
2344       }
2345    }
2346 #endif /* defined(FEATURE_ZLIB) */
2347
2348    return JB_ERR_OK;
2349
2350 }
2351
2352
2353 #ifdef FEATURE_ZLIB
2354 /*********************************************************************
2355  *
2356  * Function    :  server_adjust_content_encoding
2357  *
2358  * Description :  Remove the Content-Encoding header if the
2359  *                decompression was successful and the content
2360  *                has been modifed.
2361  *
2362  * Parameters  :
2363  *          1  :  csp = Current client state (buffers, headers, etc...)
2364  *          2  :  header = On input, pointer to header to modify.
2365  *                On output, pointer to the modified header, or NULL
2366  *                to remove the header.  This function frees the
2367  *                original string if necessary.
2368  *
2369  * Returns     :  JB_ERR_OK on success, or
2370  *                JB_ERR_MEMORY on out-of-memory error.
2371  *
2372  *********************************************************************/
2373 static jb_err server_adjust_content_encoding(struct client_state *csp, char **header)
2374 {
2375    if ((csp->flags & CSP_FLAG_MODIFIED)
2376     && (csp->content_type & (CT_GZIP | CT_DEFLATE)))
2377    {
2378       /*
2379        * We successfully decompressed the content,
2380        * and have to clean the header now, so the
2381        * client no longer expects compressed data.
2382        *
2383        * XXX: There is a difference between cleaning
2384        * and removing it completely.
2385        */
2386       log_error(LOG_LEVEL_HEADER, "Crunching: %s", *header);
2387       freez(*header);
2388    }
2389
2390    return JB_ERR_OK;
2391
2392 }
2393 #endif /* defined(FEATURE_ZLIB) */
2394
2395
2396 /*********************************************************************
2397  *
2398  * Function    :  server_adjust_content_length
2399  *
2400  * Description :  Adjust Content-Length header if we modified
2401  *                the body.
2402  *
2403  * Parameters  :
2404  *          1  :  csp = Current client state (buffers, headers, etc...)
2405  *          2  :  header = On input, pointer to header to modify.
2406  *                On output, pointer to the modified header, or NULL
2407  *                to remove the header.  This function frees the
2408  *                original string if necessary.
2409  *
2410  * Returns     :  JB_ERR_OK on success, or
2411  *                JB_ERR_MEMORY on out-of-memory error.
2412  *
2413  *********************************************************************/
2414 static jb_err server_adjust_content_length(struct client_state *csp, char **header)
2415 {
2416    /* Regenerate header if the content was modified. */
2417    if (csp->flags & CSP_FLAG_MODIFIED)
2418    {
2419       const size_t header_length = 50;
2420       freez(*header);
2421       *header = malloc(header_length);
2422       if (*header == NULL)
2423       {
2424          return JB_ERR_MEMORY;
2425       }
2426       create_content_length_header(csp->content_length, *header, header_length);
2427       log_error(LOG_LEVEL_HEADER,
2428          "Adjusted Content-Length to %llu", csp->content_length);
2429    }
2430
2431    return JB_ERR_OK;
2432 }
2433
2434
2435 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2436 /*********************************************************************
2437  *
2438  * Function    :  server_save_content_length
2439  *
2440  * Description :  Save the Content-Length sent by the server.
2441  *
2442  * Parameters  :
2443  *          1  :  csp = Current client state (buffers, headers, etc...)
2444  *          2  :  header = On input, pointer to header to modify.
2445  *                On output, pointer to the modified header, or NULL
2446  *                to remove the header.  This function frees the
2447  *                original string if necessary.
2448  *
2449  * Returns     :  JB_ERR_OK on success, or
2450  *                JB_ERR_MEMORY on out-of-memory error.
2451  *
2452  *********************************************************************/
2453 static jb_err server_save_content_length(struct client_state *csp, char **header)
2454 {
2455    unsigned long long content_length = 0;
2456    const char *header_value;
2457
2458    assert(*(*header+14) == ':');
2459
2460    header_value = *header + 15;
2461    if (JB_ERR_OK != get_content_length(header_value, &content_length))
2462    {
2463       log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
2464       freez(*header);
2465    }
2466    else
2467    {
2468       csp->expected_content_length = content_length;
2469       csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
2470       csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
2471    }
2472
2473    return JB_ERR_OK;
2474 }
2475 #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2476
2477
2478 /*********************************************************************
2479  *
2480  * Function    :  server_content_md5
2481  *
2482  * Description :  Crumble any Content-MD5 headers if the document was
2483  *                modified. FIXME: Should we re-compute instead?
2484  *
2485  * Parameters  :
2486  *          1  :  csp = Current client state (buffers, headers, etc...)
2487  *          2  :  header = On input, pointer to header to modify.
2488  *                On output, pointer to the modified header, or NULL
2489  *                to remove the header.  This function frees the
2490  *                original string if necessary.
2491  *
2492  * Returns     :  JB_ERR_OK on success, or
2493  *                JB_ERR_MEMORY on out-of-memory error.
2494  *
2495  *********************************************************************/
2496 static jb_err server_content_md5(struct client_state *csp, char **header)
2497 {
2498    if (csp->flags & CSP_FLAG_MODIFIED)
2499    {
2500       log_error(LOG_LEVEL_HEADER, "Crunching Content-MD5");
2501       freez(*header);
2502    }
2503
2504    return JB_ERR_OK;
2505 }
2506
2507
2508 /*********************************************************************
2509  *
2510  * Function    :  server_content_disposition
2511  *
2512  * Description :  If enabled, blocks or modifies the "Content-Disposition" header.
2513  *                Called from `sed'.
2514  *
2515  * Parameters  :
2516  *          1  :  csp = Current client state (buffers, headers, etc...)
2517  *          2  :  header = On input, pointer to header to modify.
2518  *                On output, pointer to the modified header, or NULL
2519  *                to remove the header.  This function frees the
2520  *                original string if necessary.
2521  *
2522  * Returns     :  JB_ERR_OK on success, or
2523  *                JB_ERR_MEMORY on out-of-memory error.
2524  *
2525  *********************************************************************/
2526 static jb_err server_content_disposition(struct client_state *csp, char **header)
2527 {
2528    const char *newval;
2529
2530    /*
2531     * Are we messing with the Content-Disposition header?
2532     */
2533    if ((csp->action->flags & ACTION_HIDE_CONTENT_DISPOSITION) == 0)
2534    {
2535       /* Me tinks not */
2536       return JB_ERR_OK;
2537    }
2538
2539    newval = csp->action->string[ACTION_STRING_CONTENT_DISPOSITION];
2540
2541    if ((newval == NULL) || (0 == strcmpic(newval, "block")))
2542    {
2543       /*
2544        * Blocking content-disposition header
2545        */
2546       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2547       freez(*header);
2548       return JB_ERR_OK;
2549    }
2550    else
2551    {
2552       /*
2553        * Replacing Content-Disposition header
2554        */
2555       freez(*header);
2556       *header = strdup("Content-Disposition: ");
2557       string_append(header, newval);
2558
2559       if (*header != NULL)
2560       {
2561          log_error(LOG_LEVEL_HEADER,
2562             "Content-Disposition header crunched and replaced with: %s", *header);
2563       }
2564    }
2565    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2566 }
2567
2568
2569 /*********************************************************************
2570  *
2571  * Function    :  server_last_modified
2572  *
2573  * Description :  Changes Last-Modified header to the actual date
2574  *                to help hide-if-modified-since.
2575  *                Called from `sed'.
2576  *
2577  * Parameters  :
2578  *          1  :  csp = Current client state (buffers, headers, etc...)
2579  *          2  :  header = On input, pointer to header to modify.
2580  *                On output, pointer to the modified header, or NULL
2581  *                to remove the header.  This function frees the
2582  *                original string if necessary.
2583  *
2584  * Returns     :  JB_ERR_OK on success, or
2585  *                JB_ERR_MEMORY on out-of-memory error.
2586  *
2587  *********************************************************************/
2588 static jb_err server_last_modified(struct client_state *csp, char **header)
2589 {
2590    const char *newval;
2591    time_t last_modified;
2592    char newheader[50];
2593
2594    /*
2595     * Are we messing with the Last-Modified header?
2596     */
2597    if ((csp->action->flags & ACTION_OVERWRITE_LAST_MODIFIED) == 0)
2598    {
2599       /*Nope*/
2600       return JB_ERR_OK;
2601    }
2602
2603    newval = csp->action->string[ACTION_STRING_LAST_MODIFIED];
2604
2605    if (0 == strcmpic(newval, "block"))
2606    {
2607       /*
2608        * Blocking Last-Modified header. Useless but why not.
2609        */
2610       log_error(LOG_LEVEL_HEADER, "Crunching %s!", *header);
2611       freez(*header);
2612       return JB_ERR_OK;
2613    }
2614    else if (0 == strcmpic(newval, "reset-to-request-time"))
2615    {
2616       /*
2617        * Setting Last-Modified Header to now.
2618        */
2619       char buf[30];
2620       get_http_time(0, buf, sizeof(buf));
2621       freez(*header);
2622       *header = strdup("Last-Modified: ");
2623       string_append(header, buf);
2624
2625       if (*header == NULL)
2626       {
2627          log_error(LOG_LEVEL_HEADER, "Insufficient memory. Last-Modified header got lost, boohoo.");
2628       }
2629       else
2630       {
2631          log_error(LOG_LEVEL_HEADER, "Reset to present time: %s", *header);
2632       }
2633    }
2634    else if (0 == strcmpic(newval, "randomize"))
2635    {
2636       const char *header_time = *header + sizeof("Last-Modified:");
2637
2638       log_error(LOG_LEVEL_HEADER, "Randomizing: %s", *header);
2639
2640       if (JB_ERR_OK != parse_header_time(header_time, &last_modified))
2641       {
2642          log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
2643          freez(*header);
2644       }
2645       else
2646       {
2647          time_t now;
2648          struct tm *timeptr = NULL;
2649          long int rtime;
2650 #ifdef HAVE_GMTIME_R
2651          struct tm gmt;
2652 #endif
2653          now = time(NULL);
2654          rtime = (long int)difftime(now, last_modified);
2655          if (rtime)
2656          {
2657             long int days, hours, minutes, seconds;
2658             const int negative_delta = (rtime < 0);
2659
2660             if (negative_delta)
2661             {
2662                rtime *= -1;
2663                log_error(LOG_LEVEL_HEADER, "Server time in the future.");
2664             }
2665             rtime = pick_from_range(rtime);
2666             if (negative_delta)
2667             {
2668                rtime *= -1;
2669             }
2670             last_modified += rtime;
2671 #ifdef HAVE_GMTIME_R
2672             timeptr = gmtime_r(&last_modified, &gmt);
2673 #elif defined(MUTEX_LOCKS_AVAILABLE)
2674             privoxy_mutex_lock(&gmtime_mutex);
2675             timeptr = gmtime(&last_modified);
2676             privoxy_mutex_unlock(&gmtime_mutex);
2677 #else
2678             timeptr = gmtime(&last_modified);
2679 #endif
2680             if ((NULL == timeptr) || !strftime(newheader,
2681                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
2682             {
2683                log_error(LOG_LEVEL_ERROR,
2684                   "Randomizing '%s' failed. Crunching the header without replacement.",
2685                   *header);
2686                freez(*header);
2687                return JB_ERR_OK;
2688             }
2689
2690             freez(*header);
2691             *header = strdup("Last-Modified: ");
2692             string_append(header, newheader);
2693
2694             if (*header == NULL)
2695             {
2696                log_error(LOG_LEVEL_ERROR, "Insufficient memory, header crunched without replacement.");
2697                return JB_ERR_MEMORY;
2698             }
2699
2700             days    = rtime / (3600 * 24);
2701             hours   = rtime / 3600 % 24;
2702             minutes = rtime / 60 % 60;
2703             seconds = rtime % 60;
2704
2705             log_error(LOG_LEVEL_HEADER,
2706                "Randomized:  %s (added %d da%s %d hou%s %d minut%s %d second%s",
2707                *header, days, (days == 1) ? "y" : "ys", hours, (hours == 1) ? "r" : "rs",
2708                minutes, (minutes == 1) ? "e" : "es", seconds, (seconds == 1) ? ")" : "s)");
2709          }
2710          else
2711          {
2712             log_error(LOG_LEVEL_HEADER, "Randomized ... or not. No time difference to work with.");
2713          }
2714       }
2715    }
2716
2717    return JB_ERR_OK;
2718 }
2719
2720
2721 /*********************************************************************
2722  *
2723  * Function    :  client_accept_encoding
2724  *
2725  * Description :  Rewrite the client's Accept-Encoding header so that
2726  *                if doesn't allow compression, if the action applies.
2727  *                Note: For HTTP/1.0 the absence of the header is enough.
2728  *
2729  * Parameters  :
2730  *          1  :  csp = Current client state (buffers, headers, etc...)
2731  *          2  :  header = On input, pointer to header to modify.
2732  *                On output, pointer to the modified header, or NULL
2733  *                to remove the header.  This function frees the
2734  *                original string if necessary.
2735  *
2736  * Returns     :  JB_ERR_OK on success, or
2737  *                JB_ERR_MEMORY on out-of-memory error.
2738  *
2739  *********************************************************************/
2740 static jb_err client_accept_encoding(struct client_state *csp, char **header)
2741 {
2742 #ifdef FEATURE_COMPRESSION
2743    if ((csp->config->feature_flags & RUNTIME_FEATURE_COMPRESSION)
2744       && strstr(*header, "deflate"))
2745    {
2746       csp->flags |= CSP_FLAG_CLIENT_SUPPORTS_DEFLATE;
2747    }
2748 #endif
2749    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2750    {
2751       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress content");
2752       freez(*header);
2753    }
2754
2755    return JB_ERR_OK;
2756 }
2757
2758
2759 /*********************************************************************
2760  *
2761  * Function    :  client_te
2762  *
2763  * Description :  Rewrite the client's TE header so that
2764  *                if doesn't allow compression, if the action applies.
2765  *
2766  * Parameters  :
2767  *          1  :  csp = Current client state (buffers, headers, etc...)
2768  *          2  :  header = On input, pointer to header to modify.
2769  *                On output, pointer to the modified header, or NULL
2770  *                to remove the header.  This function frees the
2771  *                original string if necessary.
2772  *
2773  * Returns     :  JB_ERR_OK on success, or
2774  *                JB_ERR_MEMORY on out-of-memory error.
2775  *
2776  *********************************************************************/
2777 static jb_err client_te(struct client_state *csp, char **header)
2778 {
2779    if ((csp->action->flags & ACTION_NO_COMPRESSION) != 0)
2780    {
2781       freez(*header);
2782       log_error(LOG_LEVEL_HEADER, "Suppressed offer to compress transfer");
2783    }
2784
2785    return JB_ERR_OK;
2786 }
2787
2788
2789 /*********************************************************************
2790  *
2791  * Function    :  client_referrer
2792  *
2793  * Description :  Handle the "referer" config setting properly.
2794  *                Called from `sed'.
2795  *
2796  * Parameters  :
2797  *          1  :  csp = Current client state (buffers, headers, etc...)
2798  *          2  :  header = On input, pointer to header to modify.
2799  *                On output, pointer to the modified header, or NULL
2800  *                to remove the header.  This function frees the
2801  *                original string if necessary.
2802  *
2803  * Returns     :  JB_ERR_OK on success, or
2804  *                JB_ERR_MEMORY on out-of-memory error.
2805  *
2806  *********************************************************************/
2807 static jb_err client_referrer(struct client_state *csp, char **header)
2808 {
2809    const char *parameter;
2810    /* booleans for parameters we have to check multiple times */
2811    int parameter_conditional_block;
2812    int parameter_conditional_forge;
2813
2814 #ifdef FEATURE_FORCE_LOAD
2815    /*
2816     * Since the referrer can include the prefix even
2817     * if the request itself is non-forced, we must
2818     * clean it unconditionally.
2819     *
2820     * XXX: strclean is too broad
2821     */
2822    strclean(*header, FORCE_PREFIX);
2823 #endif /* def FEATURE_FORCE_LOAD */
2824
2825    if ((csp->action->flags & ACTION_HIDE_REFERER) == 0)
2826    {
2827       /* Nothing left to do */
2828       return JB_ERR_OK;
2829    }
2830
2831    parameter = csp->action->string[ACTION_STRING_REFERER];
2832    assert(parameter != NULL);
2833    parameter_conditional_block = (0 == strcmpic(parameter, "conditional-block"));
2834    parameter_conditional_forge = (0 == strcmpic(parameter, "conditional-forge"));
2835
2836    if (!parameter_conditional_block && !parameter_conditional_forge)
2837    {
2838       /*
2839        * As conditional-block and conditional-forge are the only
2840        * parameters that rely on the original referrer, we can
2841        * remove it now for all the others.
2842        */
2843       freez(*header);
2844    }
2845
2846    if (0 == strcmpic(parameter, "block"))
2847    {
2848       log_error(LOG_LEVEL_HEADER, "Referer crunched!");
2849       return JB_ERR_OK;
2850    }
2851    else if (parameter_conditional_block || parameter_conditional_forge)
2852    {
2853       return handle_conditional_hide_referrer_parameter(header,
2854          csp->http->hostport, parameter_conditional_block);
2855    }
2856    else if (0 == strcmpic(parameter, "forge"))
2857    {
2858       return create_forged_referrer(header, csp->http->hostport);
2859    }
2860    else
2861    {
2862       /* interpret parameter as user-supplied referer to fake */
2863       return create_fake_referrer(header, parameter);
2864    }
2865 }
2866
2867
2868 /*********************************************************************
2869  *
2870  * Function    :  client_accept_language
2871  *
2872  * Description :  Handle the "Accept-Language" config setting properly.
2873  *                Called from `sed'.
2874  *
2875  * Parameters  :
2876  *          1  :  csp = Current client state (buffers, headers, etc...)
2877  *          2  :  header = On input, pointer to header to modify.
2878  *                On output, pointer to the modified header, or NULL
2879  *                to remove the header.  This function frees the
2880  *                original string if necessary.
2881  *
2882  * Returns     :  JB_ERR_OK on success, or
2883  *                JB_ERR_MEMORY on out-of-memory error.
2884  *
2885  *********************************************************************/
2886 static jb_err client_accept_language(struct client_state *csp, char **header)
2887 {
2888    const char *newval;
2889
2890    /*
2891     * Are we messing with the Accept-Language?
2892     */
2893    if ((csp->action->flags & ACTION_HIDE_ACCEPT_LANGUAGE) == 0)
2894    {
2895       /*I don't think so*/
2896       return JB_ERR_OK;
2897    }
2898
2899    newval = csp->action->string[ACTION_STRING_LANGUAGE];
2900
2901    if ((newval == NULL) || (0 == strcmpic(newval, "block")))
2902    {
2903       /*
2904        * Blocking Accept-Language header
2905        */
2906       log_error(LOG_LEVEL_HEADER, "Crunching Accept-Language!");
2907       freez(*header);
2908       return JB_ERR_OK;
2909    }
2910    else
2911    {
2912       /*
2913        * Replacing Accept-Language header
2914        */
2915       freez(*header);
2916       *header = strdup("Accept-Language: ");
2917       string_append(header, newval);
2918
2919       if (*header == NULL)
2920       {
2921          log_error(LOG_LEVEL_ERROR,
2922             "Insufficient memory. Accept-Language header crunched without replacement.");
2923       }
2924       else
2925       {
2926          log_error(LOG_LEVEL_HEADER,
2927             "Accept-Language header crunched and replaced with: %s", *header);
2928       }
2929    }
2930    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
2931 }
2932
2933
2934 /*********************************************************************
2935  *
2936  * Function    :  crunch_client_header
2937  *
2938  * Description :  Crunch client header if it matches a string supplied by the
2939  *                user. Called from `sed'.
2940  *
2941  * Parameters  :
2942  *          1  :  csp = Current client state (buffers, headers, etc...)
2943  *          2  :  header = On input, pointer to header to modify.
2944  *                On output, pointer to the modified header, or NULL
2945  *                to remove the header.  This function frees the
2946  *                original string if necessary.
2947  *
2948  * Returns     :  JB_ERR_OK on success and always succeeds
2949  *
2950  *********************************************************************/
2951 static jb_err crunch_client_header(struct client_state *csp, char **header)
2952 {
2953    const char *crunch_pattern;
2954
2955    /* Do we feel like crunching? */
2956    if ((csp->action->flags & ACTION_CRUNCH_CLIENT_HEADER))
2957    {
2958       crunch_pattern = csp->action->string[ACTION_STRING_CLIENT_HEADER];
2959
2960       /* Is the current header the lucky one? */
2961       if (strstr(*header, crunch_pattern))
2962       {
2963          log_error(LOG_LEVEL_HEADER, "Crunching client header: %s (contains: %s)", *header, crunch_pattern);
2964          freez(*header);
2965       }
2966    }
2967    return JB_ERR_OK;
2968 }
2969
2970
2971 /*********************************************************************
2972  *
2973  * Function    :  client_uagent
2974  *
2975  * Description :  Handle the "user-agent" config setting properly
2976  *                and remember its original value to enable browser
2977  *                bug workarounds. Called from `sed'.
2978  *
2979  * Parameters  :
2980  *          1  :  csp = Current client state (buffers, headers, etc...)
2981  *          2  :  header = On input, pointer to header to modify.
2982  *                On output, pointer to the modified header, or NULL
2983  *                to remove the header.  This function frees the
2984  *                original string if necessary.
2985  *
2986  * Returns     :  JB_ERR_OK on success, or
2987  *                JB_ERR_MEMORY on out-of-memory error.
2988  *
2989  *********************************************************************/
2990 static jb_err client_uagent(struct client_state *csp, char **header)
2991 {
2992    const char *newval;
2993
2994    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) == 0)
2995    {
2996       return JB_ERR_OK;
2997    }
2998
2999    newval = csp->action->string[ACTION_STRING_USER_AGENT];
3000    if (newval == NULL)
3001    {
3002       return JB_ERR_OK;
3003    }
3004
3005    freez(*header);
3006    *header = strdup("User-Agent: ");
3007    string_append(header, newval);
3008
3009    log_error(LOG_LEVEL_HEADER, "Modified: %s", *header);
3010
3011    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
3012 }
3013
3014
3015 /*********************************************************************
3016  *
3017  * Function    :  client_ua
3018  *
3019  * Description :  Handle "ua-" headers properly.  Called from `sed'.
3020  *
3021  * Parameters  :
3022  *          1  :  csp = Current client state (buffers, headers, etc...)
3023  *          2  :  header = On input, pointer to header to modify.
3024  *                On output, pointer to the modified header, or NULL
3025  *                to remove the header.  This function frees the
3026  *                original string if necessary.
3027  *
3028  * Returns     :  JB_ERR_OK on success, or
3029  *                JB_ERR_MEMORY on out-of-memory error.
3030  *
3031  *********************************************************************/
3032 static jb_err client_ua(struct client_state *csp, char **header)
3033 {
3034    if ((csp->action->flags & ACTION_HIDE_USER_AGENT) != 0)
3035    {
3036       log_error(LOG_LEVEL_HEADER, "crunched User-Agent!");
3037       freez(*header);
3038    }
3039
3040    return JB_ERR_OK;
3041 }
3042
3043
3044 /*********************************************************************
3045  *
3046  * Function    :  client_from
3047  *
3048  * Description :  Handle the "from" config setting properly.
3049  *                Called from `sed'.
3050  *
3051  * Parameters  :
3052  *          1  :  csp = Current client state (buffers, headers, etc...)
3053  *          2  :  header = On input, pointer to header to modify.
3054  *                On output, pointer to the modified header, or NULL
3055  *                to remove the header.  This function frees the
3056  *                original string if necessary.
3057  *
3058  * Returns     :  JB_ERR_OK on success, or
3059  *                JB_ERR_MEMORY on out-of-memory error.
3060  *
3061  *********************************************************************/
3062 static jb_err client_from(struct client_state *csp, char **header)
3063 {
3064    const char *newval;
3065
3066    if ((csp->action->flags & ACTION_HIDE_FROM) == 0)
3067    {
3068       return JB_ERR_OK;
3069    }
3070
3071    freez(*header);
3072
3073    newval = csp->action->string[ACTION_STRING_FROM];
3074
3075    /*
3076     * Are we blocking the e-mail address?
3077     */
3078    if ((newval == NULL) || (0 == strcmpic(newval, "block")))
3079    {
3080       log_error(LOG_LEVEL_HEADER, "crunched From!");
3081       return JB_ERR_OK;
3082    }
3083
3084    log_error(LOG_LEVEL_HEADER, " modified");
3085
3086    *header = strdup("From: ");
3087    string_append(header, newval);
3088
3089    return (*header == NULL) ? JB_ERR_MEMORY : JB_ERR_OK;
3090 }
3091
3092
3093 /*********************************************************************
3094  *
3095  * Function    :  client_send_cookie
3096  *
3097  * Description :  Crunches the "cookie" header if necessary.
3098  *                Called from `sed'.
3099  *
3100  *                XXX: Stupid name, doesn't send squat.
3101  *
3102  * Parameters  :
3103  *          1  :  csp = Current client state (buffers, headers, etc...)
3104  *          2  :  header = On input, pointer to header to modify.
3105  *                On output, pointer to the modified header, or NULL
3106  *                to remove the header.  This function frees the
3107  *                original string if necessary.
3108  *
3109  * Returns     :  JB_ERR_OK on success, or
3110  *                JB_ERR_MEMORY on out-of-memory error.
3111  *
3112  *********************************************************************/
3113 static jb_err client_send_cookie(struct client_state *csp, char **header)
3114 {
3115    if (csp->action->flags & ACTION_CRUNCH_OUTGOING_COOKIES)
3116    {
3117       log_error(LOG_LEVEL_HEADER, "Crunched outgoing cookie: %s", *header);
3118       freez(*header);
3119    }
3120
3121    return JB_ERR_OK;
3122 }
3123
3124
3125 /*********************************************************************
3126  *
3127  * Function    :  client_x_forwarded
3128  *
3129  * Description :  Handle the "x-forwarded-for" config setting properly,
3130  *                also used in the add_client_headers list.  Called from `sed'.
3131  *
3132  * Parameters  :
3133  *          1  :  csp = Current client state (buffers, headers, etc...)
3134  *          2  :  header = On input, pointer to header to modify.
3135  *                On output, pointer to the modified header, or NULL
3136  *                to remove the header.  This function frees the
3137  *                original string if necessary.
3138  *
3139  * Returns     :  JB_ERR_OK on success, or
3140  *                JB_ERR_MEMORY on out-of-memory error.
3141  *
3142  *********************************************************************/
3143 jb_err client_x_forwarded(struct client_state *csp, char **header)
3144 {
3145    if (0 != (csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR))
3146    {
3147       const char *parameter = csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR];
3148
3149       if (0 == strcmpic(parameter, "block"))
3150       {
3151          freez(*header);
3152          log_error(LOG_LEVEL_HEADER, "crunched x-forwarded-for!");
3153       }
3154       else if (0 == strcmpic(parameter, "add"))
3155       {
3156          string_append(header, ", ");
3157          string_append(header, csp->ip_addr_str);
3158
3159          if (*header == NULL)
3160          {
3161             return JB_ERR_MEMORY;
3162          }
3163          log_error(LOG_LEVEL_HEADER,
3164             "Appended client IP address to %s", *header);
3165          csp->flags |= CSP_FLAG_X_FORWARDED_FOR_APPENDED;
3166       }
3167       else
3168       {
3169          log_error(LOG_LEVEL_FATAL,
3170             "Invalid change-x-forwarded-for parameter: '%s'", parameter);
3171       }
3172    }
3173
3174    return JB_ERR_OK;
3175 }
3176
3177
3178 /*********************************************************************
3179  *
3180  * Function    :  client_max_forwards
3181  *
3182  * Description :  If the HTTP method is OPTIONS or TRACE, subtract one
3183  *                from the value of the Max-Forwards header field.
3184  *
3185  * Parameters  :
3186  *          1  :  csp = Current client state (buffers, headers, etc...)
3187  *          2  :  header = On input, pointer to header to modify.
3188  *                On output, pointer to the modified header, or NULL
3189  *                to remove the header.  This function frees the
3190  *                original string if necessary.
3191  *
3192  * Returns     :  JB_ERR_OK on success, or
3193  *                JB_ERR_MEMORY on out-of-memory error.
3194  *
3195  *********************************************************************/
3196 static jb_err client_max_forwards(struct client_state *csp, char **header)
3197 {
3198    int max_forwards;
3199
3200    if ((0 == strcmpic(csp->http->gpc, "trace")) ||
3201        (0 == strcmpic(csp->http->gpc, "options")))
3202    {
3203       assert(*(*header+12) == ':');
3204       if (1 == sscanf(*header+12, ": %d", &max_forwards))
3205       {
3206          if (max_forwards > 0)
3207          {
3208             snprintf(*header, strlen(*header)+1, "Max-Forwards: %d", --max_forwards);
3209             log_error(LOG_LEVEL_HEADER,
3210                "Max-Forwards value for %s request reduced to %d.",
3211                csp->http->gpc, max_forwards);
3212          }
3213          else if (max_forwards < 0)
3214          {
3215             log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3216             freez(*header);
3217          }
3218       }
3219       else
3220       {
3221          log_error(LOG_LEVEL_ERROR, "Crunching invalid header: %s", *header);
3222          freez(*header);
3223       }
3224    }
3225
3226    return JB_ERR_OK;
3227 }
3228
3229
3230 /*********************************************************************
3231  *
3232  * Function    :  client_host
3233  *
3234  * Description :  If the request URI did not contain host and
3235  *                port information, parse and evaluate the Host
3236  *                header field.
3237  *
3238  *                Also, kill ill-formed HOST: headers as sent by
3239  *                Apple's iTunes software when used with a proxy.
3240  *
3241  * Parameters  :
3242  *          1  :  csp = Current client state (buffers, headers, etc...)
3243  *          2  :  header = On input, pointer to header to modify.
3244  *                On output, pointer to the modified header, or NULL
3245  *                to remove the header.  This function frees the
3246  *                original string if necessary.
3247  *
3248  * Returns     :  JB_ERR_OK on success, or
3249  *                JB_ERR_MEMORY on out-of-memory error.
3250  *
3251  *********************************************************************/
3252 static jb_err client_host(struct client_state *csp, char **header)
3253 {
3254    char *p, *q;
3255
3256    /*
3257     * If the header field name is all upper-case, chances are that it's
3258     * an ill-formed one from iTunes. BTW, killing innocent headers here is
3259     * not a problem -- they are regenerated later.
3260     */
3261    if ((*header)[1] == 'O')
3262    {
3263       log_error(LOG_LEVEL_HEADER, "Killed all-caps Host header line: %s", *header);
3264       freez(*header);
3265       return JB_ERR_OK;
3266    }
3267
3268    if (!csp->http->hostport || (*csp->http->hostport == '*') ||
3269        *csp->http->hostport == ' ' || *csp->http->hostport == '\0')
3270    {
3271
3272       p = strdup_or_die((*header)+6);
3273       chomp(p);
3274       q = strdup_or_die(p);
3275
3276       freez(csp->http->hostport);
3277       csp->http->hostport = p;
3278       freez(csp->http->host);
3279       csp->http->host = q;
3280       q = strchr(csp->http->host, ':');
3281       if (q != NULL)
3282       {
3283          /* Terminate hostname and evaluate port string */
3284          *q++ = '\0';
3285          csp->http->port = atoi(q);
3286       }
3287       else
3288       {
3289          csp->http->port = csp->http->ssl ? 443 : 80;
3290       }
3291
3292       log_error(LOG_LEVEL_HEADER, "New host and port from Host field: %s = %s:%d",
3293                 csp->http->hostport, csp->http->host, csp->http->port);
3294    }
3295
3296    /* Signal client_host_adder() to return right away */
3297    csp->flags |= CSP_FLAG_HOST_HEADER_IS_SET;
3298
3299    return JB_ERR_OK;
3300 }
3301
3302
3303 /*********************************************************************
3304  *
3305  * Function    :  client_if_modified_since
3306  *
3307  * Description :  Remove or modify the If-Modified-Since header.
3308  *
3309  * Parameters  :
3310  *          1  :  csp = Current client state (buffers, headers, etc...)
3311  *          2  :  header = On input, pointer to header to modify.
3312  *                On output, pointer to the modified header, or NULL
3313  *                to remove the header.  This function frees the
3314  *                original string if necessary.
3315  *
3316  * Returns     :  JB_ERR_OK on success, or
3317  *                JB_ERR_MEMORY on out-of-memory error.
3318  *
3319  *********************************************************************/
3320 static jb_err client_if_modified_since(struct client_state *csp, char **header)
3321 {
3322    char newheader[50];
3323 #ifdef HAVE_GMTIME_R
3324    struct tm gmt;
3325 #endif
3326    struct tm *timeptr = NULL;
3327    time_t tm = 0;
3328    const char *newval;
3329    char * endptr;
3330
3331    if (0 == strcmpic(*header, "If-Modified-Since: Wed, 08 Jun 1955 12:00:00 GMT"))
3332    {
3333       /*
3334        * The client got an error message because of a temporary problem,
3335        * the problem is gone and the client now tries to revalidate our
3336        * error message on the real server. The revalidation would always
3337        * end with the transmission of the whole document and there is
3338        * no need to expose the bogus If-Modified-Since header.
3339        */
3340       log_error(LOG_LEVEL_HEADER, "Crunching useless If-Modified-Since header.");
3341       freez(*header);
3342    }
3343    else if (csp->action->flags & ACTION_HIDE_IF_MODIFIED_SINCE)
3344    {
3345       newval = csp->action->string[ACTION_STRING_IF_MODIFIED_SINCE];
3346
3347       if ((0 == strcmpic(newval, "block")))
3348       {
3349          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3350          freez(*header);
3351       }
3352       else /* add random value */
3353       {
3354          const char *header_time = *header + sizeof("If-Modified-Since:");
3355
3356          if (JB_ERR_OK != parse_header_time(header_time, &tm))
3357          {
3358             log_error(LOG_LEVEL_HEADER, "Couldn't parse: %s in %s (crunching!)", header_time, *header);
3359             freez(*header);
3360          }
3361          else
3362          {
3363             long int hours, minutes, seconds;
3364             long int rtime = strtol(newval, &endptr, 0);
3365             const int negative_range = (rtime < 0);
3366
3367             if (rtime)
3368             {
3369                log_error(LOG_LEVEL_HEADER, "Randomizing: %s (random range: %d minut%s)",
3370                   *header, rtime, (rtime == 1 || rtime == -1) ? "e": "es");
3371                if (negative_range)
3372                {
3373                   rtime *= -1;
3374                }
3375                rtime *= 60;
3376                rtime = pick_from_range(rtime);
3377             }
3378             else
3379             {
3380                log_error(LOG_LEVEL_ERROR, "Random range is 0. Assuming time transformation test.",
3381                   *header);
3382             }
3383             tm += rtime * (negative_range ? -1 : 1);
3384 #ifdef HAVE_GMTIME_R
3385             timeptr = gmtime_r(&tm, &gmt);
3386 #elif defined(MUTEX_LOCKS_AVAILABLE)
3387             privoxy_mutex_lock(&gmtime_mutex);
3388             timeptr = gmtime(&tm);
3389             privoxy_mutex_unlock(&gmtime_mutex);
3390 #else
3391             timeptr = gmtime(&tm);
3392 #endif
3393             if ((NULL == timeptr) || !strftime(newheader,
3394                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
3395             {
3396                log_error(LOG_LEVEL_ERROR,
3397                   "Randomizing '%s' failed. Crunching the header without replacement.",
3398                   *header);
3399                freez(*header);
3400                return JB_ERR_OK;
3401             }
3402
3403             freez(*header);
3404             *header = strdup("If-Modified-Since: ");
3405             string_append(header, newheader);
3406
3407             if (*header == NULL)
3408             {
3409                log_error(LOG_LEVEL_HEADER, "Insufficient memory, header crunched without replacement.");
3410                return JB_ERR_MEMORY;
3411             }
3412
3413             hours   = rtime / 3600;
3414             minutes = rtime / 60 % 60;
3415             seconds = rtime % 60;
3416
3417             log_error(LOG_LEVEL_HEADER,
3418                "Randomized:  %s (%s %d hou%s %d minut%s %d second%s",
3419                *header, (negative_range) ? "subtracted" : "added", hours,
3420                (hours == 1) ? "r" : "rs", minutes, (minutes == 1) ? "e" : "es",
3421                seconds, (seconds == 1) ? ")" : "s)");
3422          }
3423       }
3424    }
3425
3426    return JB_ERR_OK;
3427 }
3428
3429
3430 /*********************************************************************
3431  *
3432  * Function    :  client_if_none_match
3433  *
3434  * Description :  Remove the If-None-Match header.
3435  *
3436  * Parameters  :
3437  *          1  :  csp = Current client state (buffers, headers, etc...)
3438  *          2  :  header = On input, pointer to header to modify.
3439  *                On output, pointer to the modified header, or NULL
3440  *                to remove the header.  This function frees the
3441  *                original string if necessary.
3442  *
3443  * Returns     :  JB_ERR_OK on success, or
3444  *                JB_ERR_MEMORY on out-of-memory error.
3445  *
3446  *********************************************************************/
3447 static jb_err client_if_none_match(struct client_state *csp, char **header)
3448 {
3449    if (csp->action->flags & ACTION_CRUNCH_IF_NONE_MATCH)
3450    {
3451       log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3452       freez(*header);
3453    }
3454
3455    return JB_ERR_OK;
3456 }
3457
3458
3459 /*********************************************************************
3460  *
3461  * Function    :  client_x_filter
3462  *
3463  * Description :  Disables filtering if the client set "X-Filter: No".
3464  *                Called from `sed'.
3465  *
3466  * Parameters  :
3467  *          1  :  csp = Current client state (buffers, headers, etc...)
3468  *          2  :  header = On input, pointer to header to modify.
3469  *                On output, pointer to the modified header, or NULL
3470  *                to remove the header.  This function frees the
3471  *                original string if necessary.
3472  *
3473  * Returns     :  JB_ERR_OK on success
3474  *
3475  *********************************************************************/
3476 jb_err client_x_filter(struct client_state *csp, char **header)
3477 {
3478    if (0 == strcmpic(*header, "X-Filter: No"))
3479    {
3480       if (!(csp->config->feature_flags & RUNTIME_FEATURE_HTTP_TOGGLE))
3481       {
3482          log_error(LOG_LEVEL_INFO, "Ignored the client's request to fetch without filtering.");
3483       }
3484       else
3485       {
3486          if (csp->action->flags & ACTION_FORCE_TEXT_MODE)
3487          {
3488             log_error(LOG_LEVEL_HEADER,
3489                "force-text-mode overruled the client's request to fetch without filtering!");
3490          }
3491          else
3492          {
3493             csp->content_type = CT_TABOO; /* XXX: This hack shouldn't be necessary */
3494             csp->flags |= CSP_FLAG_NO_FILTERING;
3495             log_error(LOG_LEVEL_HEADER, "Accepted the client's request to fetch without filtering.");
3496          }
3497          log_error(LOG_LEVEL_HEADER, "Crunching %s", *header);
3498          freez(*header);
3499       }
3500    }
3501    return JB_ERR_OK;
3502 }
3503
3504
3505 /*********************************************************************
3506  *
3507  * Function    :  client_range
3508  *
3509  * Description :  Removes Range, Request-Range and If-Range headers if
3510  *                content filtering is enabled and the range doesn't
3511  *                start at byte 0.
3512  *
3513  *                If the client's version of the document has been
3514  *                altered by Privoxy, the server could interpret the
3515  *                range differently than the client intended in which
3516  *                case the user could end up with corrupted content.
3517  *
3518  *                If the range starts at byte 0 this isn't an issue
3519  *                so the header can pass. Partial requests like this
3520  *                are used to render preview images for videos without
3521  *                downloading the whole video.
3522  *
3523  *                While HTTP doesn't require that range requests are
3524  *                honoured and the client could simply abort the download
3525  *                after receiving a sufficient amount of data, various
3526  *                clients don't handle complete responses to range
3527  *                requests gracefully and emit misleading error messages
3528  *                instead.
3529  *
3530  * Parameters  :
3531  *          1  :  csp = Current client state (buffers, headers, etc...)
3532  *          2  :  header = On input, pointer to header to modify.
3533  *                On output, pointer to the modified header, or NULL
3534  *                to remove the header.  This function frees the
3535  *                original string if necessary.
3536  *
3537  * Returns     :  JB_ERR_OK
3538  *
3539  *********************************************************************/
3540 static jb_err client_range(struct client_state *csp, char **header)
3541 {
3542    if (content_filters_enabled(csp->action)
3543       && (0 != strncmpic(strstr(*header, ":"), ": bytes=0-", 10)))
3544    {
3545       log_error(LOG_LEVEL_HEADER, "Content filtering is enabled."
3546          " Crunching: \'%s\' to prevent range-mismatch problems.", *header);
3547       freez(*header);
3548    }
3549
3550    return JB_ERR_OK;
3551 }
3552
3553 /* the following functions add headers directly to the header list */
3554
3555 /*********************************************************************
3556  *
3557  * Function    :  client_host_adder
3558  *
3559  * Description :  Adds the Host: header field if it is missing.
3560  *                Called from `sed'.
3561  *
3562  * Parameters  :
3563  *          1  :  csp = Current client state (buffers, headers, etc...)
3564  *
3565  * Returns     :  JB_ERR_OK on success, or
3566  *                JB_ERR_MEMORY on out-of-memory error.
3567  *
3568  *********************************************************************/
3569 static jb_err client_host_adder(struct client_state *csp)
3570 {
3571    char *p;
3572    jb_err err;
3573
3574    if (csp->flags & CSP_FLAG_HOST_HEADER_IS_SET)
3575    {
3576       /* Header already set by the client, nothing to do. */
3577       return JB_ERR_OK;
3578    }
3579
3580    if (!csp->http->hostport || !*(csp->http->hostport))
3581    {
3582       /* XXX: When does this happen and why is it OK? */
3583       log_error(LOG_LEVEL_INFO, "Weirdness in client_host_adder detected and ignored.");
3584       return JB_ERR_OK;
3585    }
3586
3587    /*
3588     * remove 'user:pass@' from 'proto://user:pass@host'
3589     */
3590    if ((p = strchr( csp->http->hostport, '@')) != NULL)
3591    {
3592       p++;
3593    }
3594    else
3595    {
3596       p = csp->http->hostport;
3597    }
3598
3599    /* XXX: Just add it, we already made sure that it will be unique */
3600    log_error(LOG_LEVEL_HEADER, "addh-unique: Host: %s", p);
3601    err = enlist_unique_header(csp->headers, "Host", p);
3602    return err;
3603
3604 }
3605
3606
3607 /*********************************************************************
3608  *
3609  * Function    :  client_xtra_adder
3610  *
3611  * Description :  Used in the add_client_headers list.  Called from `sed'.
3612  *
3613  * Parameters  :
3614  *          1  :  csp = Current client state (buffers, headers, etc...)
3615  *
3616  * Returns     :  JB_ERR_OK on success, or
3617  *                JB_ERR_MEMORY on out-of-memory error.
3618  *
3619  *********************************************************************/
3620 static jb_err client_xtra_adder(struct client_state *csp)
3621 {
3622    struct list_entry *lst;
3623    jb_err err;
3624
3625    for (lst = csp->action->multi[ACTION_MULTI_ADD_HEADER]->first;
3626         lst ; lst = lst->next)
3627    {
3628       log_error(LOG_LEVEL_HEADER, "addh: %s", lst->str);
3629       err = enlist(csp->headers, lst->str);
3630       if (err)
3631       {
3632          return err;
3633       }
3634
3635    }
3636
3637    return JB_ERR_OK;
3638 }
3639
3640
3641 /*********************************************************************
3642  *
3643  * Function    :  client_x_forwarded_for_adder
3644  *
3645  * Description :  Used in the add_client_headers list.  Called from `sed'.
3646  *
3647  * Parameters  :
3648  *          1  :  csp = Current client state (buffers, headers, etc...)
3649  *
3650  * Returns     :  JB_ERR_OK on success, or
3651  *                JB_ERR_MEMORY on out-of-memory error.
3652  *
3653  *********************************************************************/
3654 static jb_err client_x_forwarded_for_adder(struct client_state *csp)
3655 {
3656    char *header = NULL;
3657    jb_err err;
3658
3659    if (!((csp->action->flags & ACTION_CHANGE_X_FORWARDED_FOR)
3660          && (0 == strcmpic(csp->action->string[ACTION_STRING_CHANGE_X_FORWARDED_FOR], "add")))
3661       || (csp->flags & CSP_FLAG_X_FORWARDED_FOR_APPENDED))
3662    {
3663       /*
3664        * If we aren't adding X-Forwarded-For headers,
3665        * or we already appended an existing X-Forwarded-For
3666        * header, there's nothing left to do here.
3667        */
3668       return JB_ERR_OK;
3669    }
3670
3671    header = strdup("X-Forwarded-For: ");
3672    string_append(&header, csp->ip_addr_str);
3673
3674    if (header == NULL)
3675    {
3676       return JB_ERR_MEMORY;
3677    }
3678
3679    log_error(LOG_LEVEL_HEADER, "addh: %s", header);
3680    err = enlist(csp->headers, header);
3681    freez(header);
3682
3683    return err;
3684 }
3685
3686
3687 /*********************************************************************
3688  *
3689  * Function    :  server_connection_adder
3690  *
3691  * Description :  Adds an appropriate "Connection:" header to csp->headers
3692  *                unless the header was already present. Called from `sed'.
3693  *
3694  * Parameters  :
3695  *          1  :  csp = Current client state (buffers, headers, etc...)
3696  *
3697  * Returns     :  JB_ERR_OK on success, or
3698  *                JB_ERR_MEMORY on out-of-memory error.
3699  *
3700  *********************************************************************/
3701 static jb_err server_connection_adder(struct client_state *csp)
3702 {
3703    const unsigned int flags = csp->flags;
3704    const char *response_status_line = csp->headers->first->str;
3705    static const char connection_close[] = "Connection: close";
3706
3707    if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3708     && (flags & CSP_FLAG_SERVER_CONNECTION_HEADER_SET))
3709    {
3710       return JB_ERR_OK;
3711    }
3712
3713    /*
3714     * XXX: if we downgraded the response, this check will fail.
3715     */
3716    if ((csp->config->feature_flags &
3717         RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3718     && (NULL != response_status_line)
3719     && !strncmpic(response_status_line, "HTTP/1.1", 8)
3720 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3721     && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
3722 #endif
3723       )
3724    {
3725       log_error(LOG_LEVEL_HEADER, "A HTTP/1.1 response "
3726          "without Connection header implies keep-alive.");
3727       csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
3728       return JB_ERR_OK;
3729    }
3730
3731    log_error(LOG_LEVEL_HEADER, "Adding: %s", connection_close);
3732
3733    return enlist(csp->headers, connection_close);
3734 }
3735
3736
3737 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3738 /*********************************************************************
3739  *
3740  * Function    :  server_proxy_connection_adder
3741  *
3742  * Description :  Adds a "Proxy-Connection: keep-alive" header to
3743  *                csp->headers when appropriate.
3744  *
3745  * Parameters  :
3746  *          1  :  csp = Current client state (buffers, headers, etc...)
3747  *
3748  * Returns     :  JB_ERR_OK on success, or
3749  *                JB_ERR_MEMORY on out-of-memory error.
3750  *
3751  *********************************************************************/
3752 static jb_err server_proxy_connection_adder(struct client_state *csp)
3753 {
3754    static const char proxy_connection_header[] = "Proxy-Connection: keep-alive";
3755    jb_err err = JB_ERR_OK;
3756
3757    if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
3758     && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
3759     && !(csp->flags & CSP_FLAG_SERVER_PROXY_CONNECTION_HEADER_SET)
3760     && ((csp->flags & CSP_FLAG_SERVER_CONTENT_LENGTH_SET)
3761        || (csp->flags & CSP_FLAG_CHUNKED)))
3762    {
3763       log_error(LOG_LEVEL_HEADER, "Adding: %s", proxy_connection_header);
3764       err = enlist(csp->headers, proxy_connection_header);
3765    }
3766
3767    return err;
3768 }
3769 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3770
3771
3772 /*********************************************************************
3773  *
3774  * Function    :  client_connection_header_adder
3775  *
3776  * Description :  Adds a proper "Connection:" header to csp->headers
3777  *                unless the header was already present. Called from `sed'.
3778  *
3779  * Parameters  :
3780  *          1  :  csp = Current client state (buffers, headers, etc...)
3781  *
3782  * Returns     :  JB_ERR_OK on success, or
3783  *                JB_ERR_MEMORY on out-of-memory error.
3784  *
3785  *********************************************************************/
3786 static jb_err client_connection_header_adder(struct client_state *csp)
3787 {
3788    static const char connection_close[] = "Connection: close";
3789
3790    if (!(csp->flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
3791      && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_HEADER_SET))
3792    {
3793       return JB_ERR_OK;
3794    }
3795
3796 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3797    if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
3798       && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
3799       && (csp->http->ssl == 0)
3800       && !strcmpic(csp->http->ver, "HTTP/1.1"))
3801    {
3802       csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
3803       return JB_ERR_OK;
3804    }
3805 #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3806
3807    log_error(LOG_LEVEL_HEADER, "Adding: %s", connection_close);
3808
3809    return enlist(csp->headers, connection_close);
3810 }
3811
3812
3813 /*********************************************************************
3814  *
3815  * Function    :  server_http
3816  *
3817  * Description :  - Save the HTTP Status into csp->http->status
3818  *                - Set CT_TABOO to prevent filtering if the answer
3819  *                  is a partial range (HTTP status 206)
3820  *                - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade
3821  *                  action applies.
3822  *
3823  * Parameters  :
3824  *          1  :  csp = Current client state (buffers, headers, etc...)
3825  *          2  :  header = On input, pointer to header to modify.
3826  *                On output, pointer to the modified header, or NULL
3827  *                to remove the header.  This function frees the
3828  *                original string if necessary.
3829  *
3830  * Returns     :  JB_ERR_OK on success, or
3831  *                JB_ERR_MEMORY on out-of-memory error.
3832  *
3833  *********************************************************************/
3834 static jb_err server_http(struct client_state *csp, char **header)
3835 {
3836    sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status));
3837    if (csp->http->status == 206)
3838    {
3839       csp->content_type = CT_TABOO;
3840    }
3841
3842    if ((csp->action->flags & ACTION_DOWNGRADE) != 0)
3843    {
3844       /* XXX: Should we do a real validity check here? */
3845       if (strlen(*header) > 8)
3846       {
3847          (*header)[7] = '0';
3848          log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0");
3849       }
3850       else
3851       {
3852          /*
3853           * XXX: Should we block the request or
3854           * enlist a valid status code line here?
3855           */
3856          log_error(LOG_LEVEL_INFO, "Malformed server response detected. "
3857             "Downgrading to HTTP/1.0 impossible.");
3858       }
3859    }
3860
3861    return JB_ERR_OK;
3862 }
3863
3864 /*********************************************************************
3865  *
3866  * Function    :  add_cooky_expiry_date
3867  *
3868  * Description :  Adds a cookie expiry date to a string.
3869  *
3870  * Parameters  :
3871  *          1  :  cookie = On input, pointer to cookie to modify.
3872  *                         On output, pointer to the modified header.
3873  *                         The original string is freed.
3874  *          2  :  lifetime = Seconds the cookie should be valid
3875  *
3876  * Returns     :  N/A
3877  *
3878  *********************************************************************/
3879 static void add_cookie_expiry_date(char **cookie, time_t lifetime)
3880 {
3881    char tmp[50];
3882    struct tm *timeptr = NULL;
3883    time_t expiry_date = time(NULL) + lifetime;
3884 #ifdef HAVE_GMTIME_R
3885    struct tm gmt;
3886
3887    timeptr = gmtime_r(&expiry_date, &gmt);
3888 #elif defined(MUTEX_LOCKS_AVAILABLE)
3889    privoxy_mutex_lock(&gmtime_mutex);
3890    timeptr = gmtime(&expiry_date);
3891    privoxy_mutex_unlock(&gmtime_mutex);
3892 #else
3893    timeptr = gmtime(&expiry_date);
3894 #endif
3895
3896    if (NULL == timeptr)
3897    {
3898       log_error(LOG_LEVEL_FATAL,
3899          "Failed to get the time in add_cooky_expiry_date()");
3900    }
3901    strftime(tmp, sizeof(tmp), "; expires=%a, %d-%b-%Y %H:%M:%S GMT", timeptr);
3902    if (JB_ERR_OK != string_append(cookie, tmp))
3903    {
3904       log_error(LOG_LEVEL_FATAL, "Out of memory in add_cooky_expiry()");
3905    }
3906 }
3907
3908
3909 /*********************************************************************
3910  *
3911  * Function    :  server_set_cookie
3912  *
3913  * Description :  Handle the server "cookie" header properly.
3914  *                Crunch, accept or rewrite it to a session cookie.
3915  *                Called from `sed'.
3916  *
3917  * Parameters  :
3918  *          1  :  csp = Current client state (buffers, headers, etc...)
3919  *          2  :  header = On input, pointer to header to modify.
3920  *                On output, pointer to the modified header, or NULL
3921  *                to remove the header.  This function frees the
3922  *                original string if necessary.
3923  *
3924  * Returns     :  JB_ERR_OK on success, or
3925  *                JB_ERR_MEMORY on out-of-memory error.
3926  *
3927  *********************************************************************/
3928 static jb_err server_set_cookie(struct client_state *csp, char **header)
3929 {
3930    if ((csp->action->flags & ACTION_CRUNCH_INCOMING_COOKIES) != 0)
3931    {
3932       log_error(LOG_LEVEL_HEADER, "Crunching incoming cookie: %s", *header);
3933       freez(*header);
3934    }
3935    else if ((0 != (csp->action->flags & ACTION_SESSION_COOKIES_ONLY))
3936          || (0 != (csp->action->flags & ACTION_LIMIT_COOKIE_LIFETIME)))
3937    {
3938       time_t now;
3939       time_t cookie_time;
3940       long cookie_lifetime = 0;
3941       enum
3942       {
3943          NO_EXPIRY_DATE_SPECIFIED,
3944          EXPIRY_DATE_ACCEPTABLE,
3945          EXPIRY_DATE_UNACCEPTABLE
3946       } expiry_date_status = NO_EXPIRY_DATE_SPECIFIED;
3947
3948       /* A variable to store the tag we're working on */
3949       char *cur_tag;
3950
3951       /* Skip "Set-Cookie:" (11 characters) in header */
3952       cur_tag = *header + 11;
3953
3954       /* skip whitespace between "Set-Cookie:" and value */
3955       while (*cur_tag && privoxy_isspace(*cur_tag))
3956       {
3957          cur_tag++;
3958       }
3959
3960       time(&now);
3961
3962       if ((csp->action->flags & ACTION_LIMIT_COOKIE_LIFETIME) != 0)
3963       {
3964          const char *param = csp->action->string[ACTION_STRING_LIMIT_COOKIE_LIFETIME];
3965
3966          cookie_lifetime = strtol(param, NULL, 0);
3967          if (cookie_lifetime < 0)
3968          {
3969             log_error(LOG_LEVEL_FATAL, "Invalid cookie lifetime limit: %s", param);
3970          }
3971          cookie_lifetime *= 60;
3972       }
3973
3974       /* Loop through each tag in the cookie */
3975       while (*cur_tag)
3976       {
3977          /* Find next tag */
3978          char *next_tag = strchr(cur_tag, ';');
3979          if (next_tag != NULL)
3980          {
3981             /* Skip the ';' character itself */
3982             next_tag++;
3983
3984             /* skip whitespace ";" and start of tag */
3985             while (*next_tag && privoxy_isspace(*next_tag))
3986             {
3987                next_tag++;
3988             }
3989          }
3990          else
3991          {
3992             /* "Next tag" is the end of the string */
3993             next_tag = cur_tag + strlen(cur_tag);
3994          }
3995
3996          /*
3997           * Check the expiration date to see
3998           * if the cookie is still valid, if yes,
3999           * rewrite it to a session cookie.
4000           */
4001          if ((strncmpic(cur_tag, "expires=", 8) == 0) && *(cur_tag + 8))
4002          {
4003             char *expiration_date = cur_tag + 8; /* Skip "[Ee]xpires=" */
4004
4005             if ((expiration_date[0] == '"')
4006              && (expiration_date[1] != '\0'))
4007             {
4008                /*
4009                 * Skip quotation mark. RFC 2109 10.1.2 seems to hint
4010                 * that the expiration date isn't supposed to be quoted,
4011                 * but some servers do it anyway.
4012                 */
4013                expiration_date++;
4014             }
4015
4016             /* Did we detect the date properly? */
4017             if (JB_ERR_OK != parse_header_time(expiration_date, &cookie_time))
4018             {
4019                /*
4020                 * Nope, treat it as if it was still valid.
4021                 *
4022                 * XXX: Should we remove the whole cookie instead?
4023                 */
4024                log_error(LOG_LEVEL_ERROR,
4025                   "Can't parse \'%s\', send by %s. Unsupported time format?", cur_tag, csp->http->url);
4026                string_move(cur_tag, next_tag);
4027                expiry_date_status = EXPIRY_DATE_UNACCEPTABLE;
4028             }
4029             else
4030             {
4031                /*
4032                 * Yes. Check if the cookie is still valid.
4033                 *
4034                 * If the cookie is already expired it's probably
4035                 * a delete cookie and even if it isn't, the browser
4036                 * will discard it anyway.
4037                 */
4038
4039                /*
4040                 * XXX: timegm() isn't available on some AmigaOS
4041                 * versions and our replacement doesn't work.
4042                 *
4043                 * Our options are to either:
4044                 *
4045                 * - disable session-cookies-only completely if timegm
4046                 *   is missing,
4047                 *
4048                 * - to simply remove all expired tags, like it has
4049                 *   been done until Privoxy 3.0.6 and to live with
4050                 *    the consequence that it can cause login/logout
4051                 *   problems on servers that don't validate their
4052                 *   input properly, or
4053                 *
4054                 * - to replace it with mktime in which
4055                 *   case there is a slight chance of valid cookies
4056                 *   passing as already expired.
4057                 *
4058                 *   This is the way it's currently done and it's not
4059                 *   as bad as it sounds. If the missing GMT offset is
4060                 *   enough to change the result of the expiration check
4061                 *   the cookie will be only valid for a few hours
4062                 *   anyway, which in many cases will be shorter
4063                 *   than a browser session.
4064                 */
4065                if (cookie_time < now)
4066                {
4067                   log_error(LOG_LEVEL_HEADER,
4068                      "Cookie \'%s\' is already expired and can pass unmodified.", *header);
4069                   /* Just in case some clown sets more then one expiration date */
4070                   cur_tag = next_tag;
4071                   expiry_date_status = EXPIRY_DATE_ACCEPTABLE;
4072                }
4073                else if ((cookie_lifetime != 0) && (cookie_time < (now + cookie_lifetime)))
4074                {
4075                   log_error(LOG_LEVEL_HEADER, "Cookie \'%s\' can pass unmodified. "
4076                      "Its lifetime is below the limit.", *header);
4077                   /* Just in case some clown sets more then one expiration date */
4078                   cur_tag = next_tag;
4079                   expiry_date_status = EXPIRY_DATE_ACCEPTABLE;
4080                }
4081                else
4082                {
4083                   /*
4084                    * Still valid, delete expiration date by copying
4085                    * the rest of the string over it.
4086                    */
4087                   string_move(cur_tag, next_tag);
4088
4089                   /* That changed the header, need to issue a log message */
4090                   expiry_date_status = EXPIRY_DATE_UNACCEPTABLE;
4091
4092                   /*
4093                    * Note that the next tag has now been moved to *cur_tag,
4094                    * so we do not need to update the cur_tag pointer.
4095                    */
4096                }
4097             }
4098
4099          }
4100          else
4101          {
4102             /* Move on to next cookie tag */
4103             cur_tag = next_tag;
4104          }
4105       }
4106
4107       if (expiry_date_status != EXPIRY_DATE_ACCEPTABLE)
4108       {
4109          assert(NULL != *header);
4110          if (cookie_lifetime != 0)
4111          {
4112             add_cookie_expiry_date(header, cookie_lifetime);
4113             log_error(LOG_LEVEL_HEADER, "Cookie rewritten to: %s", *header);
4114          }
4115          else if (expiry_date_status != NO_EXPIRY_DATE_SPECIFIED)
4116          {
4117             log_error(LOG_LEVEL_HEADER,
4118                "Cookie rewritten to a temporary one: %s", *header);
4119          }
4120       }
4121    }
4122
4123    return JB_ERR_OK;
4124 }
4125
4126
4127 #ifdef FEATURE_FORCE_LOAD
4128 /*********************************************************************
4129  *
4130  * Function    :  strclean
4131  *
4132  * Description :  In-Situ-Eliminate all occurrences of substring in
4133  *                string
4134  *
4135  * Parameters  :
4136  *          1  :  string = string to clean
4137  *          2  :  substring = substring to eliminate
4138  *
4139  * Returns     :  Number of eliminations
4140  *
4141  *********************************************************************/
4142 int strclean(char *string, const char *substring)
4143 {
4144    int hits = 0;
4145    size_t len;
4146    char *pos, *p;
4147
4148    len = strlen(substring);
4149
4150    while((pos = strstr(string, substring)) != NULL)
4151    {
4152       p = pos + len;
4153       do
4154       {
4155          *(p - len) = *p;
4156       }
4157       while (*p++ != '\0');
4158
4159       hits++;
4160    }
4161
4162    return(hits);
4163 }
4164 #endif /* def FEATURE_FORCE_LOAD */
4165
4166
4167 /*********************************************************************
4168  *
4169  * Function    :  parse_header_time
4170  *
4171  * Description :  Parses time formats used in HTTP header strings
4172  *                to get the numerical respresentation.
4173  *
4174  * Parameters  :
4175  *          1  :  header_time = HTTP header time as string.
4176  *          2  :  result = storage for header_time in seconds
4177  *
4178  * Returns     :  JB_ERR_OK if the time format was recognized, or
4179  *                JB_ERR_PARSE otherwise.
4180  *
4181  *********************************************************************/
4182 static jb_err parse_header_time(const char *header_time, time_t *result)
4183 {
4184    struct tm gmt;
4185    /*
4186     * Checking for two-digit years first in an
4187     * attempt to work around GNU libc's strptime()
4188     * reporting negative year values when using %Y.
4189     */
4190    static const char time_formats[][22] = {
4191       /* Tue, 02-Jun-37 20:00:00 */
4192       "%a, %d-%b-%y %H:%M:%S",
4193       /* Tue, 02 Jun 2037 20:00:00 */
4194       "%a, %d %b %Y %H:%M:%S",
4195       /* Tue, 02-Jun-2037 20:00:00 */
4196       "%a, %d-%b-%Y %H:%M:%S",
4197       /* Tuesday, 02-Jun-2037 20:00:00 */
4198       "%A, %d-%b-%Y %H:%M:%S",
4199       /* Tuesday Jun 02 20:00:00 2037 */
4200       "%A %b %d %H:%M:%S %Y"
4201    };
4202    unsigned int i;
4203
4204    for (i = 0; i < SZ(time_formats); i++)
4205    {
4206       /*
4207        * Zero out gmt to prevent time zone offsets.
4208        * Documented to be required for GNU libc.
4209        */
4210       memset(&gmt, 0, sizeof(gmt));
4211
4212       if (NULL != strptime(header_time, time_formats[i], &gmt))
4213       {
4214          /* Sanity check for GNU libc. */
4215          if (gmt.tm_year < 0)
4216          {
4217             log_error(LOG_LEVEL_HEADER,
4218                "Failed to parse '%s' using '%s'. Moving on.",
4219                header_time, time_formats[i]);
4220             continue;
4221          }
4222          *result = timegm(&gmt);
4223
4224 #ifdef FEATURE_STRPTIME_SANITY_CHECKS
4225          /*
4226           * Verify that parsing the date recreated from the first
4227           * parse operation gets the previous result. If it doesn't,
4228           * either strptime() or strftime() are malfunctioning.
4229           *
4230           * We could string-compare the recreated date with the original
4231           * header date, but this leads to false positives as strptime()
4232           * may let %a accept all day formats while strftime() will only
4233           * create one.
4234           */
4235          {
4236             char recreated_date[100];
4237             struct tm *tm;
4238             time_t result2;
4239
4240             tm = gmtime(result);
4241             strftime(recreated_date, sizeof(recreated_date), time_formats[i], tm);
4242             memset(&gmt, 0, sizeof(gmt));
4243             if (NULL == strptime(recreated_date, time_formats[i], &gmt))
4244             {
4245                log_error(LOG_LEVEL_ERROR,
4246                   "Failed to parse '%s' generated with '%s' to recreate '%s'.",
4247                   recreated_date, time_formats[i], header_time);
4248                continue;
4249             }
4250             result2 = timegm(&gmt);
4251             if (*result != result2)
4252             {
4253                log_error(LOG_LEVEL_ERROR, "strftime() and strptime() disagree. "
4254                   "Format: '%s'. In: '%s', out: '%s'. %d != %d. Rejecting.",
4255                   time_formats[i], header_time, recreated_date, *result, result2);
4256                continue;
4257             }
4258          }
4259 #endif
4260
4261          return JB_ERR_OK;
4262       }
4263    }
4264
4265    return JB_ERR_PARSE;
4266
4267 }
4268
4269
4270 /*********************************************************************
4271  *
4272  * Function    :  get_destination_from_headers
4273  *
4274  * Description :  Parse the "Host:" header to get the request's destination.
4275  *                Only needed if the client's request was forcefully
4276  *                redirected into Privoxy.
4277  *
4278  *                Code mainly copied from client_host() which is currently
4279  *                run too late for this purpose.
4280  *
4281  * Parameters  :
4282  *          1  :  headers = List of headers (one of them hopefully being
4283  *                the "Host:" header)
4284  *          2  :  http = storage for the result (host, port and hostport).
4285  *
4286  * Returns     :  JB_ERR_MEMORY (or terminates) in case of memory problems,
4287  *                JB_ERR_PARSE if the host header couldn't be found,
4288  *                JB_ERR_OK otherwise.
4289  *
4290  *********************************************************************/
4291 jb_err get_destination_from_headers(const struct list *headers, struct http_request *http)
4292 {
4293    char *q;
4294    char *p;
4295    char *host;
4296
4297    host = get_header_value(headers, "Host:");
4298
4299    if (NULL == host)
4300    {
4301       log_error(LOG_LEVEL_ERROR, "No \"Host:\" header found.");
4302       return JB_ERR_PARSE;
4303    }
4304
4305    p = strdup_or_die(host);
4306    chomp(p);
4307    q = strdup_or_die(p);
4308
4309    freez(http->hostport);
4310    http->hostport = p;
4311    freez(http->host);
4312    http->host = q;
4313    q = strchr(http->host, ':');
4314    if (q != NULL)
4315    {
4316       /* Terminate hostname and evaluate port string */
4317       *q++ = '\0';
4318       http->port = atoi(q);
4319    }
4320    else
4321    {
4322       http->port = http->ssl ? 443 : 80;
4323    }
4324
4325    /* Rebuild request URL */
4326    freez(http->url);
4327    http->url = strdup(http->ssl ? "https://" : "http://");
4328    string_append(&http->url, http->hostport);
4329    string_append(&http->url, http->path);
4330    if (http->url == NULL)
4331    {
4332       return JB_ERR_MEMORY;
4333    }
4334
4335    log_error(LOG_LEVEL_HEADER, "Destination extracted from \"Host:\" header. New request URL: %s",
4336       http->url);
4337
4338    return JB_ERR_OK;
4339
4340 }
4341
4342
4343 /*********************************************************************
4344  *
4345  * Function    :  create_forged_referrer
4346  *
4347  * Description :  Helper for client_referrer to forge a referer as
4348  *                'http://hostname[:port]/' to fool stupid
4349  *                checks for in-site links
4350  *
4351  * Parameters  :
4352  *          1  :  header   = Pointer to header pointer
4353  *          2  :  hostport = Host and optionally port as string
4354  *
4355  * Returns     :  JB_ERR_OK in case of success, or
4356  *                JB_ERR_MEMORY in case of memory problems.
4357  *
4358  *********************************************************************/
4359 static jb_err create_forged_referrer(char **header, const char *hostport)
4360 {
4361     assert(NULL == *header);
4362
4363     *header = strdup("Referer: http://");
4364     string_append(header, hostport);
4365     string_append(header, "/");
4366
4367     if (NULL == *header)
4368     {
4369        return JB_ERR_MEMORY;
4370     }
4371
4372     log_error(LOG_LEVEL_HEADER, "Referer forged to: %s", *header);
4373
4374     return JB_ERR_OK;
4375
4376 }
4377
4378
4379 /*********************************************************************
4380  *
4381  * Function    :  create_fake_referrer
4382  *
4383  * Description :  Helper for client_referrer to create a fake referrer
4384  *                based on a string supplied by the user.
4385  *
4386  * Parameters  :
4387  *          1  :  header   = Pointer to header pointer
4388  *          2  :  hosthost = Referrer to fake
4389  *
4390  * Returns     :  JB_ERR_OK in case of success, or
4391  *                JB_ERR_MEMORY in case of memory problems.
4392  *
4393  *********************************************************************/
4394 static jb_err create_fake_referrer(char **header, const char *fake_referrer)
4395 {
4396    assert(NULL == *header);
4397
4398    if ((0 != strncmpic(fake_referrer, "http://", 7)) && (0 != strncmpic(fake_referrer, "https://", 8)))
4399    {
4400       log_error(LOG_LEVEL_HEADER,
4401          "Parameter: +hide-referrer{%s} is a bad idea, but I don't care.", fake_referrer);
4402    }
4403    *header = strdup("Referer: ");
4404    string_append(header, fake_referrer);
4405
4406    if (NULL == *header)
4407    {
4408       return JB_ERR_MEMORY;
4409    }
4410
4411    log_error(LOG_LEVEL_HEADER, "Referer replaced with: %s", *header);
4412
4413    return JB_ERR_OK;
4414
4415 }
4416
4417
4418 /*********************************************************************
4419  *
4420  * Function    :  handle_conditional_hide_referrer_parameter
4421  *
4422  * Description :  Helper for client_referrer to crunch or forge
4423  *                the referrer header if the host has changed.
4424  *
4425  * Parameters  :
4426  *          1  :  header = Pointer to header pointer
4427  *          2  :  host   = The target host (may include the port)
4428  *          3  :  parameter_conditional_block = Boolean to signal
4429  *                if we're in conditional-block mode. If not set,
4430  *                we're in conditional-forge mode.
4431  *
4432  * Returns     :  JB_ERR_OK in case of success, or
4433  *                JB_ERR_MEMORY in case of memory problems.
4434  *
4435  *********************************************************************/
4436 static jb_err handle_conditional_hide_referrer_parameter(char **header,
4437    const char *host, const int parameter_conditional_block)
4438 {
4439    char *referer = strdup_or_die(*header);
4440    const size_t hostlength = strlen(host);
4441    const char *referer_url = NULL;
4442
4443    /* referer begins with 'Referer: http[s]://' */
4444    if ((hostlength+17) < strlen(referer))
4445    {
4446       /*
4447        * Shorten referer to make sure the referer is blocked
4448        * if www.example.org/www.example.com-shall-see-the-referer/
4449        * links to www.example.com/
4450        */
4451       referer[hostlength+17] = '\0';
4452    }
4453    referer_url = strstr(referer, "http://");
4454    if ((NULL == referer_url) || (NULL == strstr(referer_url, host)))
4455    {
4456       /* Host has changed, Referer is invalid or a https URL. */
4457       if (parameter_conditional_block)
4458       {
4459          log_error(LOG_LEVEL_HEADER, "New host is: %s. Crunching %s!", host, *header);
4460          freez(*header);
4461       }
4462       else
4463       {
4464          freez(*header);
4465          freez(referer);
4466          return create_forged_referrer(header, host);
4467       }
4468    }
4469    freez(referer);
4470
4471    return JB_ERR_OK;
4472
4473 }
4474
4475
4476 /*********************************************************************
4477  *
4478  * Function    :  create_content_length_header
4479  *
4480  * Description :  Creates a Content-Length header.
4481  *
4482  * Parameters  :
4483  *          1  :  content_length = The content length to be used in the header.
4484  *          2  :  header = Allocated space to safe the header.
4485  *          3  :  buffer_length = The length of the allocated space.
4486  *
4487  * Returns     :  void
4488  *
4489  *********************************************************************/
4490 static void create_content_length_header(unsigned long long content_length,
4491                                          char *header, size_t buffer_length)
4492 {
4493    snprintf(header, buffer_length, "Content-Length: %llu", content_length);
4494 }
4495
4496
4497 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4498 /*********************************************************************
4499  *
4500  * Function    :  get_expected_content_length
4501  *
4502  * Description :  Figures out the content length from a list of headers.
4503  *
4504  * Parameters  :
4505  *          1  :  headers = List of headers
4506  *
4507  * Returns     :  Number of bytes to expect
4508  *
4509  *********************************************************************/
4510 unsigned long long get_expected_content_length(struct list *headers)
4511 {
4512    const char *content_length_header;
4513    unsigned long long content_length = 0;
4514
4515    content_length_header = get_header_value(headers, "Content-Length:");
4516    if (content_length_header != NULL)
4517    {
4518       if (JB_ERR_OK != get_content_length(content_length_header, &content_length))
4519       {
4520          log_error(LOG_LEVEL_ERROR,
4521             "Failed to get the Content-Length in %s", content_length_header);
4522          /* XXX: The header will be removed later on */
4523          return 0;
4524       }
4525    }
4526
4527    return content_length;
4528 }
4529 #endif
4530
4531 /*
4532   Local Variables:
4533   tab-width: 3
4534   end:
4535 */