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