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