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