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