add faq for what to do if editing the config file is access denied
[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