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