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