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