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