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