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