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