Line data Source code
1 : /*********************************************************************
2 : *
3 : * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
4 : *
5 : * Purpose : Main file. Contains main() method, main loop, and
6 : * the main connection-handling function.
7 : *
8 : * Copyright : Written by and Copyright (C) 2001-2021 the
9 : * Privoxy team. https://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 : #include <stdio.h>
39 : #include <sys/types.h>
40 : #include <stdlib.h>
41 : #include <string.h>
42 : #include <signal.h>
43 : #include <fcntl.h>
44 : #include <errno.h>
45 : #include <assert.h>
46 :
47 : #ifdef _WIN32
48 : # ifndef FEATURE_PTHREAD
49 : # ifndef STRICT
50 : # define STRICT
51 : # endif
52 : # include <winsock2.h>
53 : # include <windows.h>
54 : # include <process.h>
55 : # endif /* ndef FEATURE_PTHREAD */
56 :
57 : # include "win32.h"
58 : # ifndef _WIN_CONSOLE
59 : # include "w32log.h"
60 : # endif /* ndef _WIN_CONSOLE */
61 : # include "w32svrapi.h"
62 :
63 : #else /* ifndef _WIN32 */
64 :
65 : # include <unistd.h>
66 : # include <sys/wait.h>
67 : # include <sys/time.h>
68 : # include <sys/stat.h>
69 : # include <sys/ioctl.h>
70 :
71 : #ifdef sun
72 : #include <sys/termios.h>
73 : #endif /* sun */
74 :
75 : #ifdef unix
76 : #include <pwd.h>
77 : #include <grp.h>
78 : #endif
79 :
80 : # include <signal.h>
81 :
82 : # ifdef __BEOS__
83 : # include <socket.h> /* BeOS has select() for sockets only. */
84 : # include <OS.h> /* declarations for threads and stuff. */
85 : # endif
86 :
87 : #ifdef HAVE_POLL
88 : #ifdef __GLIBC__
89 : #include <sys/poll.h>
90 : #else
91 : #include <poll.h>
92 : #endif /* def __GLIBC__ */
93 : #else
94 : # ifndef FD_ZERO
95 : # include <select.h>
96 : # endif
97 : #warning poll() appears to be unavailable. Your platform will become unsupported in the future.
98 : #endif /* HAVE_POLL */
99 :
100 : #endif
101 :
102 : #include "project.h"
103 : #include "list.h"
104 : #include "jcc.h"
105 : #ifdef FEATURE_HTTPS_INSPECTION
106 : #include "ssl.h"
107 : #endif
108 : #include "filters.h"
109 : #include "loaders.h"
110 : #include "parsers.h"
111 : #include "miscutil.h"
112 : #include "errlog.h"
113 : #include "jbsockets.h"
114 : #include "gateway.h"
115 : #include "actions.h"
116 : #include "cgi.h"
117 : #include "loadcfg.h"
118 : #include "urlmatch.h"
119 : #ifdef FEATURE_CLIENT_TAGS
120 : #include "client-tags.h"
121 : #endif
122 :
123 : int daemon_mode = 1;
124 : struct client_states clients[1];
125 : struct file_list files[1];
126 :
127 : #ifdef FEATURE_STATISTICS
128 : int urls_read = 0; /* total nr of urls read inc rejected */
129 : int urls_rejected = 0; /* total nr of urls rejected */
130 : #endif /* def FEATURE_STATISTICS */
131 :
132 : #ifdef FEATURE_GRACEFUL_TERMINATION
133 : int g_terminate = 0;
134 : #endif
135 :
136 : #if !defined(_WIN32)
137 : static void sig_handler(int the_signal);
138 : #endif
139 : static int client_protocol_is_unsupported(struct client_state *csp, char *req);
140 : static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers);
141 : static jb_err get_server_headers(struct client_state *csp);
142 : static const char *crunch_reason(const struct http_response *rsp);
143 : static void send_crunch_response(struct client_state *csp, struct http_response *rsp);
144 : static char *get_request_line(struct client_state *csp);
145 : static jb_err receive_client_request(struct client_state *csp);
146 : static jb_err parse_client_request(struct client_state *csp);
147 : static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line);
148 : static jb_err change_request_destination(struct client_state *csp);
149 : static void handle_established_connection(struct client_state *csp);
150 : static void chat(struct client_state *csp);
151 : static void serve(struct client_state *csp);
152 : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
153 : static void usage(const char *myname);
154 : #endif
155 : static void initialize_mutexes(void);
156 : static jb_socket bind_port_helper(const char *haddr, int hport, int backlog);
157 : static void bind_ports_helper(struct configuration_spec *config, jb_socket sockets[]);
158 : static void close_ports_helper(jb_socket sockets[]);
159 : static void listen_loop(void);
160 : static void serve(struct client_state *csp);
161 :
162 : #ifdef __BEOS__
163 : static int32 server_thread(void *data);
164 : #endif /* def __BEOS__ */
165 :
166 : #ifdef _WIN32
167 : #define sleep(N) Sleep(((N) * 1000))
168 : #endif
169 :
170 : #ifdef FUZZ
171 : int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file);
172 : void show_fuzz_usage(const char *name);
173 : #endif
174 :
175 : #ifdef MUTEX_LOCKS_AVAILABLE
176 : /*
177 : * XXX: Does the locking stuff really belong in this file?
178 : */
179 : privoxy_mutex_t log_mutex;
180 : privoxy_mutex_t log_init_mutex;
181 : privoxy_mutex_t connection_reuse_mutex;
182 :
183 : #ifdef FEATURE_HTTPS_INSPECTION
184 : privoxy_mutex_t certificate_mutex;
185 : privoxy_mutex_t ssl_init_mutex;
186 : #endif
187 :
188 : #ifdef FEATURE_EXTERNAL_FILTERS
189 : privoxy_mutex_t external_filter_mutex;
190 : #endif
191 : #ifdef FEATURE_CLIENT_TAGS
192 : privoxy_mutex_t client_tags_mutex;
193 : #endif
194 : #ifdef FEATURE_EXTENDED_STATISTICS
195 : privoxy_mutex_t filter_statistics_mutex;
196 : privoxy_mutex_t block_statistics_mutex;
197 : #endif
198 :
199 : #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
200 : privoxy_mutex_t resolver_mutex;
201 : #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
202 :
203 : #ifndef HAVE_GMTIME_R
204 : privoxy_mutex_t gmtime_mutex;
205 : #endif /* ndef HAVE_GMTIME_R */
206 :
207 : #ifndef HAVE_LOCALTIME_R
208 : privoxy_mutex_t localtime_mutex;
209 : #endif /* ndef HAVE_GMTIME_R */
210 :
211 : #if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
212 : privoxy_mutex_t rand_mutex;
213 : #endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
214 :
215 : #endif /* def MUTEX_LOCKS_AVAILABLE */
216 :
217 : #if defined(unix)
218 : const char *basedir = NULL;
219 : const char *pidfile = NULL;
220 : static int received_hup_signal = 0;
221 : #endif /* defined unix */
222 :
223 : /* HTTP snipplets. */
224 : static const char CSUCCEED[] =
225 : "HTTP/1.1 200 Connection established\r\n\r\n";
226 :
227 : static const char CHEADER[] =
228 : "HTTP/1.1 400 Invalid header received from client\r\n"
229 : "Content-Type: text/plain\r\n"
230 : "Connection: close\r\n\r\n"
231 : "Invalid header received from client.\r\n";
232 :
233 : static const char FTP_RESPONSE[] =
234 : "HTTP/1.1 400 Invalid request received from client\r\n"
235 : "Content-Type: text/plain\r\n"
236 : "Connection: close\r\n\r\n"
237 : "Invalid request. Privoxy doesn't support FTP.\r\n";
238 :
239 : static const char GOPHER_RESPONSE[] =
240 : "HTTP/1.1 400 Invalid request received from client\r\n"
241 : "Content-Type: text/plain\r\n"
242 : "Connection: close\r\n\r\n"
243 : "Invalid request. Privoxy doesn't support gopher.\r\n";
244 :
245 : /* XXX: should be a template */
246 : static const char MISSING_DESTINATION_RESPONSE[] =
247 : "HTTP/1.1 400 Bad request received from client\r\n"
248 : "Content-Type: text/plain\r\n"
249 : "Connection: close\r\n\r\n"
250 : "Bad request. Privoxy was unable to extract the destination.\r\n";
251 :
252 : /* XXX: should be a template */
253 : static const char INVALID_SERVER_HEADERS_RESPONSE[] =
254 : "HTTP/1.1 502 Server or forwarder response invalid\r\n"
255 : "Content-Type: text/plain\r\n"
256 : "Connection: close\r\n\r\n"
257 : "Bad response. The server or forwarder response doesn't look like HTTP.\r\n";
258 :
259 : /* XXX: should be a template */
260 : static const char MESSED_UP_REQUEST_RESPONSE[] =
261 : "HTTP/1.1 400 Malformed request after rewriting\r\n"
262 : "Content-Type: text/plain\r\n"
263 : "Connection: close\r\n\r\n"
264 : "Bad request. Messed up with header filters.\r\n";
265 :
266 : static const char TOO_MANY_CONNECTIONS_RESPONSE[] =
267 : "HTTP/1.1 503 Too many open connections\r\n"
268 : "Content-Type: text/plain\r\n"
269 : "Connection: close\r\n\r\n"
270 : "Maximum number of open connections reached.\r\n";
271 :
272 : static const char CLIENT_CONNECTION_TIMEOUT_RESPONSE[] =
273 : "HTTP/1.1 504 Connection timeout\r\n"
274 : "Content-Type: text/plain\r\n"
275 : "Connection: close\r\n\r\n"
276 : "The connection timed out because the client request didn't arrive in time.\r\n";
277 :
278 : static const char CLIENT_BODY_PARSE_ERROR_RESPONSE[] =
279 : "HTTP/1.1 400 Failed reading client body\r\n"
280 : "Content-Type: text/plain\r\n"
281 : "Connection: close\r\n\r\n"
282 : "Failed parsing or buffering the chunk-encoded client body.\r\n";
283 :
284 : static const char UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE[] =
285 : "HTTP/1.1 417 Expecting too much\r\n"
286 : "Content-Type: text/plain\r\n"
287 : "Connection: close\r\n\r\n"
288 : "Privoxy detected an unsupported Expect header value.\r\n";
289 :
290 : /* A function to crunch a response */
291 : typedef struct http_response *(*crunch_func_ptr)(struct client_state *);
292 :
293 : /* Crunch function flags */
294 : #define CF_NO_FLAGS 0
295 : /* Cruncher applies to forced requests as well */
296 : #define CF_IGNORE_FORCE 1
297 : /* Crunched requests are counted for the block statistics */
298 : #define CF_COUNT_AS_REJECT 2
299 :
300 : /* A crunch function and its flags */
301 : struct cruncher
302 : {
303 : const crunch_func_ptr cruncher;
304 : const int flags;
305 : };
306 :
307 : static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]);
308 :
309 : /* Complete list of cruncher functions */
310 : static const struct cruncher crunchers_all[] = {
311 : { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE},
312 : { block_url, CF_COUNT_AS_REJECT },
313 : #ifdef FEATURE_TRUST
314 : { trust_url, CF_COUNT_AS_REJECT },
315 : #endif /* def FEATURE_TRUST */
316 : { redirect_url, CF_NO_FLAGS },
317 : { dispatch_cgi, CF_IGNORE_FORCE},
318 : { NULL, 0 }
319 : };
320 :
321 : /* Light version, used after tags are applied */
322 : static const struct cruncher crunchers_light[] = {
323 : { block_url, CF_COUNT_AS_REJECT },
324 : { redirect_url, CF_NO_FLAGS },
325 : { NULL, 0 }
326 : };
327 :
328 :
329 : /*
330 : * XXX: Don't we really mean
331 : *
332 : * #if defined(unix)
333 : *
334 : * here?
335 : */
336 : #if !defined(_WIN32)
337 : /*********************************************************************
338 : *
339 : * Function : sig_handler
340 : *
341 : * Description : Signal handler for different signals.
342 : * Exit gracefully on TERM and INT
343 : * or set a flag that will cause the errlog
344 : * to be reopened by the main thread on HUP.
345 : *
346 : * Parameters :
347 : * 1 : the_signal = the signal cause this function to call
348 : *
349 : * Returns : -
350 : *
351 : *********************************************************************/
352 0 : static void sig_handler(int the_signal)
353 : {
354 0 : switch(the_signal)
355 : {
356 0 : case SIGTERM:
357 : case SIGINT:
358 0 : log_error(LOG_LEVEL_INFO, "exiting by signal %d .. bye", the_signal);
359 : #if defined(unix)
360 0 : if (pidfile)
361 : {
362 0 : unlink(pidfile);
363 : }
364 : #endif /* unix */
365 0 : exit(the_signal);
366 : break;
367 :
368 0 : case SIGHUP:
369 : #if defined(unix)
370 0 : received_hup_signal = 1;
371 : #endif
372 0 : break;
373 :
374 0 : default:
375 : /*
376 : * We shouldn't be here, unless we catch signals
377 : * in main() that we can't handle here!
378 : */
379 0 : log_error(LOG_LEVEL_FATAL,
380 : "sig_handler: exiting on unexpected signal %d", the_signal);
381 : }
382 0 : return;
383 :
384 : }
385 : #endif
386 :
387 :
388 : /*********************************************************************
389 : *
390 : * Function : get_write_delay
391 : *
392 : * Description : Parse the delay-response parameter.
393 : *
394 : * Parameters :
395 : * 1 : csp = Current client state (buffers, headers, etc...)
396 : *
397 : * Returns : Number of milliseconds to delay writes.
398 : *
399 : *********************************************************************/
400 60883 : static unsigned int get_write_delay(const struct client_state *csp)
401 : {
402 : unsigned int delay;
403 : char *endptr;
404 : char *newval;
405 :
406 60883 : if ((csp->action->flags & ACTION_DELAY_RESPONSE) == 0)
407 : {
408 60883 : return 0;
409 : }
410 0 : newval = csp->action->string[ACTION_STRING_DELAY_RESPONSE];
411 :
412 0 : delay = (unsigned)strtol(newval, &endptr, 0);
413 0 : if (*endptr != '\0')
414 : {
415 0 : log_error(LOG_LEVEL_FATAL,
416 : "Invalid delay-response{} parameter: '%s'", newval);
417 : }
418 :
419 0 : return delay;
420 :
421 : }
422 :
423 :
424 : /*********************************************************************
425 : *
426 : * Function : client_protocol_is_unsupported
427 : *
428 : * Description : Checks if the client used a known unsupported
429 : * protocol and deals with it by sending an error
430 : * response.
431 : *
432 : * Parameters :
433 : * 1 : csp = Current client state (buffers, headers, etc...)
434 : * 2 : req = the first request line send by the client
435 : *
436 : * Returns : TRUE if an error response has been generated, or
437 : * FALSE if the request doesn't look invalid.
438 : *
439 : *********************************************************************/
440 34220 : static int client_protocol_is_unsupported(struct client_state *csp, char *req)
441 : {
442 : /*
443 : * If it's a FTP or gopher request, we don't support it.
444 : *
445 : * These checks are better than nothing, but they might
446 : * not work in all configurations and some clients might
447 : * have problems digesting the answer.
448 : *
449 : * They should, however, never cause more problems than
450 : * Privoxy's old behaviour (returning the misleading HTML
451 : * error message:
452 : *
453 : * "Could not resolve http://(ftp|gopher)://example.org").
454 : */
455 34220 : if (!strncmpic(req, "GET ftp://", 10) || !strncmpic(req, "GET gopher://", 13))
456 : {
457 3 : const char *response = NULL;
458 3 : const char *protocol = NULL;
459 :
460 3 : if (!strncmpic(req, "GET ftp://", 10))
461 : {
462 2 : response = FTP_RESPONSE;
463 2 : protocol = "FTP";
464 : }
465 : else
466 : {
467 1 : response = GOPHER_RESPONSE;
468 1 : protocol = "GOPHER";
469 : }
470 3 : log_error(LOG_LEVEL_ERROR,
471 : "%s tried to use Privoxy as %s proxy: %s",
472 : csp->ip_addr_str, protocol, req);
473 3 : log_error(LOG_LEVEL_CLF,
474 : "%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
475 3 : freez(req);
476 :
477 : #ifdef FEATURE_HTTPS_INSPECTION
478 3 : if (client_use_ssl(csp))
479 : {
480 1 : ssl_send_data_delayed(&(csp->ssl_client_attr),
481 : (const unsigned char *)response, strlen(response),
482 : get_write_delay(csp));
483 : }
484 : else
485 : #endif
486 : {
487 2 : write_socket_delayed(csp->cfd, response, strlen(response),
488 : get_write_delay(csp));
489 : }
490 :
491 3 : return TRUE;
492 : }
493 :
494 34217 : return FALSE;
495 : }
496 :
497 :
498 : /*********************************************************************
499 : *
500 : * Function : client_has_unsupported_expectations
501 : *
502 : * Description : Checks if the client used an unsupported expectation
503 : * in which case an error message is delivered.
504 : *
505 : * Parameters :
506 : * 1 : csp = Current client state (buffers, headers, etc...)
507 : *
508 : * Returns : TRUE if an error response has been generated, or
509 : * FALSE if the request doesn't look invalid.
510 : *
511 : *********************************************************************/
512 31138 : static int client_has_unsupported_expectations(const struct client_state *csp)
513 : {
514 31138 : if ((csp->flags & CSP_FLAG_UNSUPPORTED_CLIENT_EXPECTATION))
515 : {
516 20 : log_error(LOG_LEVEL_ERROR,
517 : "Rejecting request from client %s with unsupported Expect header value",
518 : csp->ip_addr_str);
519 20 : log_error(LOG_LEVEL_CLF,
520 : "%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd);
521 20 : write_socket_delayed(csp->cfd,
522 : UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE,
523 : strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE),
524 : get_write_delay(csp));
525 :
526 20 : return TRUE;
527 : }
528 :
529 31118 : return FALSE;
530 :
531 : }
532 :
533 :
534 : /*********************************************************************
535 : *
536 : * Function : get_request_destination_elsewhere
537 : *
538 : * Description : If the client's request was redirected into
539 : * Privoxy without the client's knowledge,
540 : * the request line lacks the destination host.
541 : *
542 : * This function tries to get it elsewhere,
543 : * provided accept-intercepted-requests is enabled.
544 : *
545 : * "Elsewhere" currently only means "Host: header",
546 : * but in the future we may ask the redirecting
547 : * packet filter to look the destination up.
548 : *
549 : * If the destination stays unknown, an error
550 : * response is send to the client and headers
551 : * are freed so that chat() can return directly.
552 : *
553 : * Parameters :
554 : * 1 : csp = Current client state (buffers, headers, etc...)
555 : * 2 : headers = a header list
556 : *
557 : * Returns : JB_ERR_OK if the destination is now known, or
558 : * JB_ERR_PARSE if it isn't.
559 : *
560 : *********************************************************************/
561 15190 : static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers)
562 : {
563 15190 : if (!(csp->config->feature_flags & RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS))
564 : {
565 0 : log_error(LOG_LEVEL_ERROR, "%s's request: \'%s\' is invalid."
566 : " Privoxy isn't configured to accept intercepted requests.",
567 : csp->ip_addr_str, csp->http->cmd);
568 : /* XXX: Use correct size */
569 0 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
570 : csp->ip_addr_str, csp->http->cmd);
571 :
572 0 : write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
573 : get_write_delay(csp));
574 0 : destroy_list(headers);
575 :
576 0 : return JB_ERR_PARSE;
577 : }
578 15190 : else if (JB_ERR_OK == get_destination_from_headers(headers, csp->http))
579 : {
580 : /* Split the domain we just got for pattern matching */
581 15170 : init_domain_components(csp->http);
582 :
583 15170 : return JB_ERR_OK;
584 : }
585 : else
586 : {
587 : /* We can't work without destination. Go spread the news.*/
588 :
589 : /* XXX: Use correct size */
590 20 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
591 : csp->ip_addr_str, csp->http->cmd);
592 20 : log_error(LOG_LEVEL_ERROR,
593 : "Privoxy was unable to get the destination for %s's request: %s",
594 : csp->ip_addr_str, csp->http->cmd);
595 :
596 20 : write_socket_delayed(csp->cfd, MISSING_DESTINATION_RESPONSE,
597 : strlen(MISSING_DESTINATION_RESPONSE), get_write_delay(csp));
598 20 : destroy_list(headers);
599 :
600 20 : return JB_ERR_PARSE;
601 : }
602 : /*
603 : * TODO: If available, use PF's ioctl DIOCNATLOOK as last resort
604 : * to get the destination IP address, use it as host directly
605 : * or do a reverse DNS lookup first.
606 : */
607 : }
608 :
609 :
610 : /*********************************************************************
611 : *
612 : * Function : get_server_headers
613 : *
614 : * Description : Parses server headers in iob and fills them
615 : * into csp->headers so that they can later be
616 : * handled by sed().
617 : *
618 : * Parameters :
619 : * 1 : csp = Current client state (buffers, headers, etc...)
620 : *
621 : * Returns : JB_ERR_OK if everything went fine, or
622 : * JB_ERR_PARSE if the headers were incomplete.
623 : *
624 : *********************************************************************/
625 10831 : static jb_err get_server_headers(struct client_state *csp)
626 : {
627 10831 : int continue_hack_in_da_house = 0;
628 : char * header;
629 :
630 100233 : while (((header = get_header(csp->iob)) != NULL) || continue_hack_in_da_house)
631 : {
632 94044 : if (header == NULL)
633 : {
634 : /*
635 : * continue hack in da house. Ignore the ending of
636 : * this head and continue enlisting header lines.
637 : * The reason is described below.
638 : */
639 81 : enlist(csp->headers, "");
640 81 : continue_hack_in_da_house = 0;
641 81 : continue;
642 : }
643 93963 : else if (0 == strncmpic(header, "HTTP/1.1 100", 12))
644 : {
645 : /*
646 : * It's a bodyless continue response, don't
647 : * stop header parsing after reaching its end.
648 : *
649 : * As a result Privoxy will concatenate the
650 : * next response's head and parse and deliver
651 : * the headers as if they belonged to one request.
652 : *
653 : * The client will separate them because of the
654 : * empty line between them.
655 : *
656 : * XXX: What we're doing here is clearly against
657 : * the intended purpose of the continue header,
658 : * and under some conditions (HTTP/1.0 client request)
659 : * it's a standard violation.
660 : *
661 : * Anyway, "sort of against the spec" is preferable
662 : * to "always getting confused by Continue responses"
663 : * (Privoxy's behaviour before this hack was added)
664 : */
665 86 : log_error(LOG_LEVEL_HEADER, "Continue hack in da house.");
666 86 : continue_hack_in_da_house = 1;
667 : }
668 93877 : else if (*header == '\0')
669 : {
670 : /*
671 : * If the header is empty, but the Continue hack
672 : * isn't active, we can assume that we reached the
673 : * end of the buffer before we hit the end of the
674 : * head.
675 : *
676 : * Inform the caller an let it decide how to handle it.
677 : */
678 4642 : return JB_ERR_PARSE;
679 : }
680 :
681 89321 : if (JB_ERR_MEMORY == enlist(csp->headers, header))
682 : {
683 : /*
684 : * XXX: Should we quit the request and return a
685 : * out of memory error page instead?
686 : */
687 0 : log_error(LOG_LEVEL_ERROR,
688 : "Out of memory while enlisting server headers. %s lost.",
689 : header);
690 : }
691 89321 : freez(header);
692 : }
693 :
694 6189 : return JB_ERR_OK;
695 : }
696 :
697 :
698 : /*********************************************************************
699 : *
700 : * Function : crunch_reason
701 : *
702 : * Description : Translates the crunch reason code into a string.
703 : *
704 : * Parameters :
705 : * 1 : rsp = a http_response
706 : *
707 : * Returns : A string with the crunch reason or an error description.
708 : *
709 : *********************************************************************/
710 26436 : static const char *crunch_reason(const struct http_response *rsp)
711 : {
712 26436 : char * reason = NULL;
713 :
714 26436 : assert(rsp != NULL);
715 26436 : if (rsp == NULL)
716 : {
717 0 : return "Internal error while searching for crunch reason";
718 : }
719 :
720 26436 : switch (rsp->crunch_reason)
721 : {
722 928 : case UNSUPPORTED:
723 928 : reason = "Unsupported HTTP feature";
724 928 : break;
725 2309 : case BLOCKED:
726 2309 : reason = "Blocked";
727 2309 : break;
728 0 : case UNTRUSTED:
729 0 : reason = "Untrusted";
730 0 : break;
731 872 : case REDIRECTED:
732 872 : reason = "Redirected";
733 872 : break;
734 22219 : case CGI_CALL:
735 22219 : reason = "CGI Call";
736 22219 : break;
737 0 : case NO_SUCH_DOMAIN:
738 0 : reason = "DNS failure";
739 0 : break;
740 0 : case FORWARDING_FAILED:
741 0 : reason = "Forwarding failed";
742 0 : break;
743 41 : case CONNECT_FAILED:
744 41 : reason = "Connection failure";
745 41 : break;
746 0 : case OUT_OF_MEMORY:
747 0 : reason = "Out of memory (may mask other reasons)";
748 0 : break;
749 0 : case CONNECTION_TIMEOUT:
750 0 : reason = "Connection timeout";
751 0 : break;
752 67 : case NO_SERVER_DATA:
753 67 : reason = "No server data received";
754 67 : break;
755 0 : default:
756 0 : reason = "No reason recorded";
757 0 : break;
758 : }
759 :
760 26436 : return reason;
761 : }
762 :
763 :
764 : /*********************************************************************
765 : *
766 : * Function : log_applied_actions
767 : *
768 : * Description : Logs the applied actions if LOG_LEVEL_ACTIONS is
769 : * enabled.
770 : *
771 : * Parameters :
772 : * 1 : actions = Current action spec to log
773 : *
774 : * Returns : Nothing.
775 : *
776 : *********************************************************************/
777 35226 : static void log_applied_actions(const struct current_action_spec *actions)
778 : {
779 : /*
780 : * The conversion to text requires lots of memory allocations so
781 : * we only do the conversion if the user is actually interested.
782 : */
783 35226 : if (debug_level_is_enabled(LOG_LEVEL_ACTIONS))
784 : {
785 35226 : char *actions_as_text = actions_to_line_of_text(actions);
786 35226 : log_error(LOG_LEVEL_ACTIONS, "%s", actions_as_text);
787 35226 : freez(actions_as_text);
788 : }
789 35226 : }
790 :
791 :
792 : /*********************************************************************
793 : *
794 : * Function : send_crunch_response
795 : *
796 : * Description : Delivers already prepared response for
797 : * intercepted requests, logs the interception
798 : * and frees the response.
799 : *
800 : * Parameters :
801 : * 1 : csp = Current client state (buffers, headers, etc...)
802 : * 2 : rsp = Fully prepared response. Will be freed on exit.
803 : *
804 : * Returns : Nothing.
805 : *
806 : *********************************************************************/
807 26436 : static void send_crunch_response(struct client_state *csp, struct http_response *rsp)
808 : {
809 26436 : const struct http_request *http = csp->http;
810 : char status_code[4];
811 :
812 26436 : assert(rsp != NULL);
813 26436 : assert(rsp->head != NULL);
814 :
815 26436 : if (rsp == NULL)
816 : {
817 0 : log_error(LOG_LEVEL_FATAL, "NULL response in send_crunch_response.");
818 : }
819 :
820 : /*
821 : * Extract the status code from the actual head
822 : * that will be send to the client. It is the only
823 : * way to get it right for all requests, including
824 : * the fixed ones for out-of-memory problems.
825 : *
826 : * A head starts like this: 'HTTP/1.1 200...'
827 : * 0123456789|11
828 : * 10
829 : */
830 26436 : status_code[0] = rsp->head[9];
831 26436 : status_code[1] = rsp->head[10];
832 26436 : status_code[2] = rsp->head[11];
833 26436 : status_code[3] = '\0';
834 :
835 : /* Log that the request was crunched and why. */
836 26436 : log_applied_actions(csp->action);
837 : #ifdef FEATURE_HTTPS_INSPECTION
838 26436 : if (client_use_ssl(csp))
839 : {
840 1903 : log_error(LOG_LEVEL_CRUNCH, "%s: https://%s%s", crunch_reason(rsp),
841 : http->hostport, http->path);
842 1903 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" %s %lu",
843 : csp->ip_addr_str, http->gpc, http->hostport, http->path,
844 : http->version, status_code, rsp->content_length);
845 : }
846 : else
847 : #endif
848 : {
849 24533 : log_error(LOG_LEVEL_CRUNCH, "%s: %s", crunch_reason(rsp), http->url);
850 24533 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" %s %lu",
851 : csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
852 : }
853 : /* Write the answer to the client */
854 : #ifdef FEATURE_HTTPS_INSPECTION
855 26436 : if (client_use_ssl(csp))
856 : {
857 1903 : if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
858 1903 : (const unsigned char *)rsp->head, rsp->head_length,
859 : get_write_delay(csp)) < 0)
860 1903 : || (ssl_send_data_delayed(&(csp->ssl_client_attr),
861 1903 : (const unsigned char *)rsp->body, rsp->content_length,
862 : get_write_delay(csp)) < 0))
863 : {
864 : /* There is nothing we can do about it. */
865 0 : log_error(LOG_LEVEL_CONNECT, "Couldn't deliver the error message "
866 : "for https://%s%s through client socket %d using TLS/SSL",
867 : http->hostport, http->url, csp->cfd);
868 : }
869 : }
870 : else
871 : #endif
872 : {
873 24533 : if (write_socket_delayed(csp->cfd, rsp->head, rsp->head_length,
874 : get_write_delay(csp))
875 24533 : || write_socket_delayed(csp->cfd, rsp->body, rsp->content_length,
876 : get_write_delay(csp)))
877 : {
878 : /* There is nothing we can do about it. */
879 0 : log_error(LOG_LEVEL_CONNECT,
880 : "Couldn't deliver the error message for %s through client socket %d: %E",
881 : http->url, csp->cfd);
882 : }
883 : }
884 :
885 : /* Clean up and return */
886 : // if (cgi_error_memory() != rsp)
887 26436 : if(!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING))
888 : {
889 26436 : free_http_response(rsp);
890 : }
891 52872 : return;
892 : }
893 :
894 :
895 : /*********************************************************************
896 : *
897 : * Function : crunch_response_triggered
898 : *
899 : * Description : Checks if the request has to be crunched,
900 : * and delivers the crunch response if necessary.
901 : *
902 : * Parameters :
903 : * 1 : csp = Current client state (buffers, headers, etc...)
904 : * 2 : crunchers = list of cruncher functions to run
905 : *
906 : * Returns : TRUE if the request was answered with a crunch response
907 : * FALSE otherwise.
908 : *
909 : *********************************************************************/
910 38895 : static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[])
911 : {
912 38895 : struct http_response *rsp = NULL;
913 : const struct cruncher *c;
914 :
915 : /*
916 : * If CGI request crunching is disabled,
917 : * check the CGI dispatcher out of order to
918 : * prevent unintentional blocks or redirects.
919 : */
920 38895 : if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_CRUNCHING)
921 38895 : && (NULL != (rsp = dispatch_cgi(csp))))
922 : {
923 : /* Deliver, log and free the interception response. */
924 22219 : send_crunch_response(csp, rsp);
925 22219 : csp->flags |= CSP_FLAG_CRUNCHED;
926 22219 : return TRUE;
927 : }
928 :
929 66484 : for (c = crunchers; c->cruncher != NULL; c++)
930 : {
931 : /*
932 : * Check the cruncher if either Privoxy is toggled
933 : * on and the request isn't forced, or if the cruncher
934 : * applies to forced requests as well.
935 : */
936 53917 : if (((csp->flags & CSP_FLAG_TOGGLED_ON) &&
937 53917 : !(csp->flags & CSP_FLAG_FORCED)) ||
938 4202 : (c->flags & CF_IGNORE_FORCE))
939 : {
940 50959 : rsp = c->cruncher(csp);
941 50959 : if (NULL != rsp)
942 : {
943 : /* Deliver, log and free the interception response. */
944 4109 : send_crunch_response(csp, rsp);
945 4109 : csp->flags |= CSP_FLAG_CRUNCHED;
946 : #ifdef FEATURE_STATISTICS
947 4109 : if (c->flags & CF_COUNT_AS_REJECT)
948 : {
949 3237 : csp->flags |= CSP_FLAG_REJECTED;
950 : }
951 : #endif /* def FEATURE_STATISTICS */
952 :
953 4109 : return TRUE;
954 : }
955 : }
956 : }
957 :
958 12567 : return FALSE;
959 : }
960 :
961 :
962 : /*********************************************************************
963 : *
964 : * Function : build_request_line
965 : *
966 : * Description : Builds the HTTP request line.
967 : *
968 : * If a HTTP forwarder is used it expects the whole URL,
969 : * web servers only get the path.
970 : *
971 : * Parameters :
972 : * 1 : csp = Current client state (buffers, headers, etc...)
973 : * 2 : fwd = The forwarding spec used for the request.
974 : * Can be NULL.
975 : * 3 : request_line = The old request line which will be replaced.
976 : *
977 : * Returns : Nothing. Terminates in case of memory problems.
978 : *
979 : *********************************************************************/
980 31169 : static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line)
981 : {
982 31169 : struct http_request *http = csp->http;
983 :
984 : /*
985 : * Downgrade http version from 1.1 to 1.0
986 : * if +downgrade action applies.
987 : */
988 31169 : if ((csp->action->flags & ACTION_DOWNGRADE)
989 278 : && (!strcmpic(http->version, "HTTP/1.1")))
990 : {
991 180 : freez(http->version);
992 180 : http->version = strdup_or_die("HTTP/1.0");
993 : }
994 :
995 : /*
996 : * Rebuild the request line.
997 : */
998 31169 : freez(*request_line);
999 31169 : *request_line = strdup(http->gpc);
1000 31169 : string_append(request_line, " ");
1001 :
1002 31169 : if (fwd != NULL && fwd->forward_host && fwd->type != FORWARD_WEBSERVER)
1003 : {
1004 0 : string_append(request_line, http->url);
1005 : }
1006 : else
1007 : {
1008 31169 : string_append(request_line, http->path);
1009 : }
1010 31169 : string_append(request_line, " ");
1011 31169 : string_append(request_line, http->version);
1012 :
1013 31169 : if (*request_line == NULL)
1014 : {
1015 0 : log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command");
1016 : }
1017 31169 : log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line);
1018 31169 : }
1019 :
1020 :
1021 : /*********************************************************************
1022 : *
1023 : * Function : change_request_destination
1024 : *
1025 : * Description : Parse a (rewritten) request line and regenerate
1026 : * the http request data.
1027 : *
1028 : * Parameters :
1029 : * 1 : csp = Current client state (buffers, headers, etc...)
1030 : *
1031 : * Returns : Forwards the parse_http_request() return code.
1032 : * Terminates in case of memory problems.
1033 : *
1034 : *********************************************************************/
1035 52 : static jb_err change_request_destination(struct client_state *csp)
1036 : {
1037 52 : struct http_request *http = csp->http;
1038 : jb_err err;
1039 :
1040 52 : log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s",
1041 52 : csp->headers->first->str);
1042 52 : free_http_request(http);
1043 52 : err = parse_http_request(csp->headers->first->str, http);
1044 52 : if (JB_ERR_OK != err)
1045 : {
1046 1 : log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
1047 : jb_err_to_string(err));
1048 : }
1049 52 : if (http->ssl && strcmpic(csp->http->gpc, "CONNECT"))
1050 : {
1051 : /*
1052 : * A client header filter changed the request URL from
1053 : * http:// to https:// which we currently don't support.
1054 : */
1055 1 : log_error(LOG_LEVEL_ERROR, "Changing the request destination from http "
1056 : "to https behind the client's back currently isn't supported.");
1057 1 : return JB_ERR_PARSE;
1058 : }
1059 :
1060 51 : return err;
1061 : }
1062 :
1063 :
1064 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1065 : /*********************************************************************
1066 : *
1067 : * Function : server_response_is_complete
1068 : *
1069 : * Description : Determines whether we should stop reading
1070 : * from the server socket.
1071 : *
1072 : * Parameters :
1073 : * 1 : csp = Current client state (buffers, headers, etc...)
1074 : * 2 : content_length = Length of content received so far.
1075 : *
1076 : * Returns : TRUE if the response is complete,
1077 : * FALSE otherwise.
1078 : *
1079 : *********************************************************************/
1080 9497 : static int server_response_is_complete(struct client_state *csp,
1081 : unsigned long long content_length)
1082 : {
1083 9497 : int content_length_known = !!(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET);
1084 :
1085 9497 : if (!strcmpic(csp->http->gpc, "HEAD"))
1086 : {
1087 : /*
1088 : * "HEAD" implies no body, we are thus expecting
1089 : * no content. XXX: incomplete "list" of methods?
1090 : */
1091 183 : csp->expected_content_length = 0;
1092 183 : content_length_known = TRUE;
1093 183 : csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
1094 : }
1095 :
1096 9497 : if (csp->http->status == 204 || csp->http->status == 304)
1097 : {
1098 : /*
1099 : * Expect no body. XXX: incomplete "list" of status codes?
1100 : */
1101 2923 : csp->expected_content_length = 0;
1102 2923 : content_length_known = TRUE;
1103 2923 : csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
1104 : }
1105 :
1106 12366 : return (content_length_known && ((0 == csp->expected_content_length)
1107 2869 : || (csp->expected_content_length <= content_length)));
1108 : }
1109 :
1110 :
1111 : #ifdef FEATURE_CONNECTION_SHARING
1112 : /*********************************************************************
1113 : *
1114 : * Function : wait_for_alive_connections
1115 : *
1116 : * Description : Waits for alive connections to timeout.
1117 : *
1118 : * Parameters : N/A
1119 : *
1120 : * Returns : N/A
1121 : *
1122 : *********************************************************************/
1123 0 : static void wait_for_alive_connections(void)
1124 : {
1125 0 : int connections_alive = close_unusable_connections();
1126 :
1127 0 : while (0 < connections_alive)
1128 : {
1129 0 : log_error(LOG_LEVEL_CONNECT,
1130 : "Waiting for %d connections to timeout.",
1131 : connections_alive);
1132 0 : sleep(60);
1133 0 : connections_alive = close_unusable_connections();
1134 : }
1135 :
1136 0 : log_error(LOG_LEVEL_CONNECT, "No connections to wait for left.");
1137 :
1138 0 : }
1139 : #endif /* def FEATURE_CONNECTION_SHARING */
1140 :
1141 :
1142 : /*********************************************************************
1143 : *
1144 : * Function : save_connection_destination
1145 : *
1146 : * Description : Remembers a connection for reuse later on.
1147 : *
1148 : * Parameters :
1149 : * 1 : sfd = Open socket to remember.
1150 : * 2 : http = The destination for the connection.
1151 : * 3 : fwd = The forwarder settings used.
1152 : * 4 : server_connection = storage.
1153 : *
1154 : * Returns : void
1155 : *
1156 : *********************************************************************/
1157 6474 : void save_connection_destination(jb_socket sfd,
1158 : const struct http_request *http,
1159 : const struct forward_spec *fwd,
1160 : struct reusable_connection *server_connection)
1161 : {
1162 6474 : assert(sfd != JB_INVALID_SOCKET);
1163 6474 : assert(NULL != http->host);
1164 :
1165 6474 : server_connection->sfd = sfd;
1166 6474 : server_connection->host = strdup_or_die(http->host);
1167 6474 : server_connection->port = http->port;
1168 :
1169 6474 : assert(NULL != fwd);
1170 6474 : assert(server_connection->gateway_host == NULL);
1171 6474 : assert(server_connection->gateway_port == 0);
1172 6474 : assert(server_connection->forwarder_type == 0);
1173 6474 : assert(server_connection->forward_host == NULL);
1174 6474 : assert(server_connection->forward_port == 0);
1175 :
1176 6474 : server_connection->forwarder_type = fwd->type;
1177 6474 : if (NULL != fwd->gateway_host)
1178 : {
1179 0 : server_connection->gateway_host = strdup_or_die(fwd->gateway_host);
1180 : }
1181 : else
1182 : {
1183 6474 : server_connection->gateway_host = NULL;
1184 : }
1185 6474 : server_connection->gateway_port = fwd->gateway_port;
1186 6474 : if (NULL != fwd->auth_username)
1187 : {
1188 0 : server_connection->auth_username = strdup_or_die(fwd->auth_username);
1189 : }
1190 : else
1191 : {
1192 6474 : server_connection->auth_username = NULL;
1193 : }
1194 6474 : if (NULL != fwd->auth_password)
1195 : {
1196 0 : server_connection->auth_password = strdup_or_die(fwd->auth_password);
1197 : }
1198 : else
1199 : {
1200 6474 : server_connection->auth_password = NULL;
1201 : }
1202 :
1203 6474 : if (NULL != fwd->forward_host)
1204 : {
1205 0 : server_connection->forward_host = strdup_or_die(fwd->forward_host);
1206 : }
1207 : else
1208 : {
1209 6474 : server_connection->forward_host = NULL;
1210 : }
1211 6474 : server_connection->forward_port = fwd->forward_port;
1212 6474 : }
1213 : #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
1214 :
1215 :
1216 : /*********************************************************************
1217 : *
1218 : * Function : verify_request_length
1219 : *
1220 : * Description : Checks if we already got the whole client requests
1221 : * and sets CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ if
1222 : * we do.
1223 : *
1224 : * Data that doesn't belong to the current request is
1225 : * either thrown away to let the client retry on a clean
1226 : * socket, or stashed to be dealt with after the current
1227 : * request is served.
1228 : *
1229 : * Parameters :
1230 : * 1 : csp = Current client state (buffers, headers, etc...)
1231 : *
1232 : * Returns : void
1233 : *
1234 : *********************************************************************/
1235 30671 : static void verify_request_length(struct client_state *csp)
1236 : {
1237 30671 : unsigned long long buffered_request_bytes =
1238 30671 : (unsigned long long)(csp->client_iob->eod - csp->client_iob->cur);
1239 :
1240 30671 : if ((csp->expected_client_content_length != 0)
1241 1194 : && (buffered_request_bytes != 0))
1242 : {
1243 1158 : if (csp->expected_client_content_length >= buffered_request_bytes)
1244 : {
1245 1126 : csp->expected_client_content_length -= buffered_request_bytes;
1246 1126 : log_error(LOG_LEVEL_CONNECT, "Reduced expected bytes to %llu "
1247 : "to account for the %llu ones we already got.",
1248 : csp->expected_client_content_length, buffered_request_bytes);
1249 : }
1250 : else
1251 : {
1252 32 : assert(csp->client_iob->eod > csp->client_iob->cur + csp->expected_client_content_length);
1253 32 : csp->client_iob->eod = csp->client_iob->cur + csp->expected_client_content_length;
1254 32 : log_error(LOG_LEVEL_CONNECT, "Reducing expected bytes to 0. "
1255 : "Marking the server socket tainted after throwing %llu bytes away.",
1256 32 : buffered_request_bytes - csp->expected_client_content_length);
1257 32 : csp->expected_client_content_length = 0;
1258 32 : csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
1259 : }
1260 :
1261 1158 : if (csp->expected_client_content_length == 0)
1262 : {
1263 1107 : csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
1264 : }
1265 : }
1266 :
1267 30671 : if (!(csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)
1268 29564 : && ((csp->client_iob->cur < csp->client_iob->eod)
1269 17111 : || (csp->expected_client_content_length != 0)))
1270 : {
1271 12489 : if (strcmpic(csp->http->gpc, "GET")
1272 2357 : && strcmpic(csp->http->gpc, "HEAD")
1273 2128 : && strcmpic(csp->http->gpc, "TRACE")
1274 1567 : && strcmpic(csp->http->gpc, "OPTIONS")
1275 1280 : && strcmpic(csp->http->gpc, "DELETE"))
1276 : {
1277 : /* XXX: this is an incomplete hack */
1278 1271 : csp->flags &= ~CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
1279 1271 : log_error(LOG_LEVEL_CONNECT, "There better be a request body.");
1280 : }
1281 : else
1282 : {
1283 11218 : csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
1284 :
1285 11218 : if ((csp->config->feature_flags & RUNTIME_FEATURE_TOLERATE_PIPELINING) == 0)
1286 : {
1287 0 : csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
1288 0 : log_error(LOG_LEVEL_CONNECT,
1289 : "Possible pipeline attempt detected. The connection will not "
1290 : "be kept alive and we will only serve the first request.");
1291 : /* Nuke the pipelined requests from orbit, just to be sure. */
1292 0 : clear_iob(csp->client_iob);
1293 : }
1294 : else
1295 : {
1296 : /*
1297 : * Keep the pipelined data around for now, we'll deal with
1298 : * it once we're done serving the current request.
1299 : */
1300 11218 : csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
1301 11218 : assert(csp->client_iob->eod >= csp->client_iob->cur);
1302 11218 : log_error(LOG_LEVEL_CONNECT, "Complete client request followed by "
1303 : "%d bytes of pipelined data received.",
1304 11218 : (int)(csp->client_iob->eod - csp->client_iob->cur));
1305 : }
1306 : }
1307 : }
1308 : else
1309 : {
1310 18182 : csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
1311 18182 : log_error(LOG_LEVEL_CONNECT, "Complete client request received.");
1312 : }
1313 30671 : }
1314 :
1315 :
1316 : /*********************************************************************
1317 : *
1318 : * Function : mark_server_socket_tainted
1319 : *
1320 : * Description : Makes sure we don't reuse a server socket
1321 : * (if we didn't read everything the server sent
1322 : * us reusing the socket would lead to garbage).
1323 : *
1324 : * Parameters :
1325 : * 1 : csp = Current client state (buffers, headers, etc...)
1326 : *
1327 : * Returns : void.
1328 : *
1329 : *********************************************************************/
1330 932 : static void mark_server_socket_tainted(struct client_state *csp)
1331 : {
1332 : /*
1333 : * For consistency we always mark the server socket
1334 : * tainted, however, to reduce the log noise we only
1335 : * emit a log message if the server socket could have
1336 : * actually been reused.
1337 : */
1338 932 : if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
1339 172 : && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
1340 : {
1341 172 : log_error(LOG_LEVEL_CONNECT,
1342 : "Marking the server socket %d tainted.",
1343 : csp->server_connection.sfd);
1344 : }
1345 932 : csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
1346 932 : }
1347 :
1348 : /*********************************************************************
1349 : *
1350 : * Function : get_request_line
1351 : *
1352 : * Description : Read the client request line.
1353 : *
1354 : * Parameters :
1355 : * 1 : csp = Current client state (buffers, headers, etc...)
1356 : *
1357 : * Returns : Pointer to request line or NULL in case of errors.
1358 : *
1359 : *********************************************************************/
1360 32220 : static char *get_request_line(struct client_state *csp)
1361 : {
1362 : char buf[BUFFER_SIZE];
1363 32220 : char *request_line = NULL;
1364 : int len;
1365 :
1366 32220 : memset(buf, 0, sizeof(buf));
1367 :
1368 32220 : if ((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
1369 : {
1370 : /*
1371 : * If there are multiple pipelined requests waiting,
1372 : * the flag will be set again once the next request
1373 : * has been parsed.
1374 : */
1375 10571 : csp->flags &= ~CSP_FLAG_PIPELINED_REQUEST_WAITING;
1376 :
1377 10571 : request_line = get_header(csp->client_iob);
1378 10571 : if ((NULL != request_line) && ('\0' != *request_line))
1379 : {
1380 9836 : return request_line;
1381 : }
1382 : else
1383 : {
1384 735 : log_error(LOG_LEVEL_CONNECT, "No complete request line "
1385 : "received yet. Continuing reading from %d.", csp->cfd);
1386 : }
1387 : }
1388 :
1389 : do
1390 : {
1391 23923 : if (
1392 : #ifdef FUZZ
1393 44379 : 0 == (csp->flags & CSP_FLAG_FUZZED_INPUT) &&
1394 : #endif
1395 20456 : !data_is_available(csp->cfd, csp->config->socket_timeout)
1396 : )
1397 : {
1398 134 : if (socket_is_still_alive(csp->cfd))
1399 : {
1400 0 : log_error(LOG_LEVEL_CONNECT,
1401 : "No request line on socket %d received in time. Timeout: %d.",
1402 0 : csp->cfd, csp->config->socket_timeout);
1403 0 : write_socket_delayed(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
1404 : strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE),
1405 : get_write_delay(csp));
1406 : }
1407 : else
1408 : {
1409 134 : log_error(LOG_LEVEL_CONNECT,
1410 : "The client side of the connection on socket %d got "
1411 : "closed without sending a complete request line.", csp->cfd);
1412 : }
1413 134 : return NULL;
1414 : }
1415 :
1416 23789 : len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1417 :
1418 23789 : if (len <= 0) return NULL;
1419 :
1420 : /*
1421 : * If there is no memory left for buffering the
1422 : * request, there is nothing we can do but hang up
1423 : */
1424 23756 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
1425 : {
1426 0 : return NULL;
1427 : }
1428 :
1429 23756 : request_line = get_header(csp->client_iob);
1430 :
1431 23756 : } while ((NULL != request_line) && ('\0' == *request_line));
1432 :
1433 22217 : return request_line;
1434 :
1435 : }
1436 :
1437 : enum chunk_status
1438 : {
1439 : CHUNK_STATUS_MISSING_DATA,
1440 : CHUNK_STATUS_BODY_COMPLETE,
1441 : CHUNK_STATUS_PARSE_ERROR
1442 : };
1443 :
1444 :
1445 : /*********************************************************************
1446 : *
1447 : * Function : chunked_body_is_complete
1448 : *
1449 : * Description : Figures out whether or not a chunked body is complete.
1450 : *
1451 : * Currently it always starts at the beginning of the
1452 : * buffer which is somewhat wasteful and prevents Privoxy
1453 : * from starting to forward the correctly parsed chunks
1454 : * as soon as theoretically possible.
1455 : *
1456 : * Should be modified to work with a common buffer,
1457 : * and allow the caller to skip already parsed chunks.
1458 : *
1459 : * This would allow the function to be used for unbuffered
1460 : * response bodies as well.
1461 : *
1462 : * Parameters :
1463 : * 1 : iob = Buffer with the body to check.
1464 : * 2 : length = Length of complete body
1465 : *
1466 : * Returns : Enum with the result of the check.
1467 : *
1468 : *********************************************************************/
1469 677 : static enum chunk_status chunked_body_is_complete(struct iob *iob, size_t *length)
1470 : {
1471 : unsigned int chunksize;
1472 677 : char *p = iob->cur;
1473 :
1474 : do
1475 : {
1476 : /*
1477 : * We need at least a single digit, followed by "\r\n",
1478 : * followed by an unknown amount of data, followed by "\r\n".
1479 : */
1480 893 : if (p + 5 > iob->eod)
1481 : {
1482 17 : return CHUNK_STATUS_MISSING_DATA;
1483 : }
1484 876 : if (sscanf(p, "%x", &chunksize) != 1)
1485 : {
1486 2 : return CHUNK_STATUS_PARSE_ERROR;
1487 : }
1488 :
1489 : /*
1490 : * We want at least a single digit, followed by "\r\n",
1491 : * followed by the specified amount of data, followed by "\r\n".
1492 : */
1493 874 : if (p + chunksize + 5 > iob->eod)
1494 : {
1495 510 : return CHUNK_STATUS_MISSING_DATA;
1496 : }
1497 :
1498 : /* Skip chunk-size. */
1499 364 : p = strstr(p, "\r\n");
1500 364 : if (NULL == p)
1501 : {
1502 2 : return CHUNK_STATUS_PARSE_ERROR;
1503 : }
1504 : /* Move beyond the chunkdata. */
1505 362 : p += 2 + chunksize;
1506 :
1507 : /* Make sure we're still within the buffer and have two bytes left */
1508 362 : if (p + 2 > iob->eod)
1509 : {
1510 85 : return CHUNK_STATUS_MISSING_DATA;
1511 : }
1512 :
1513 : /* There should be another "\r\n" to skip */
1514 277 : if (memcmp(p, "\r\n", 2))
1515 : {
1516 14 : return CHUNK_STATUS_PARSE_ERROR;
1517 : }
1518 263 : p += 2;
1519 263 : } while (chunksize > 0U);
1520 :
1521 47 : *length = (size_t)(p - iob->cur);
1522 47 : assert(*length <= (size_t)(iob->eod - iob->cur));
1523 47 : assert(p <= iob->eod);
1524 :
1525 47 : return CHUNK_STATUS_BODY_COMPLETE;
1526 :
1527 : }
1528 :
1529 :
1530 : /*********************************************************************
1531 : *
1532 : * Function : receive_chunked_client_request_body
1533 : *
1534 : * Description : Read the chunk-encoded client request body.
1535 : * Failures are dealt with.
1536 : *
1537 : * Parameters :
1538 : * 1 : csp = Current client state (buffers, headers, etc...)
1539 : *
1540 : * Returns : JB_ERR_OK or JB_ERR_PARSE
1541 : *
1542 : *********************************************************************/
1543 81 : static jb_err receive_chunked_client_request_body(struct client_state *csp)
1544 : {
1545 : size_t body_length;
1546 : enum chunk_status status;
1547 :
1548 758 : while (CHUNK_STATUS_MISSING_DATA ==
1549 677 : (status = chunked_body_is_complete(csp->client_iob, &body_length)))
1550 : {
1551 : char buf[BUFFER_SIZE];
1552 : int len;
1553 :
1554 612 : if (!data_is_available(csp->cfd, csp->config->socket_timeout))
1555 : {
1556 15 : log_error(LOG_LEVEL_ERROR,
1557 : "Timeout while waiting for the client body.");
1558 16 : break;
1559 : }
1560 597 : len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1561 597 : if (len <= 0)
1562 : {
1563 1 : log_error(LOG_LEVEL_ERROR,
1564 : "Reading the client body failed: %E");
1565 1 : break;
1566 : }
1567 596 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
1568 : {
1569 0 : break;
1570 : }
1571 : }
1572 81 : if (status != CHUNK_STATUS_BODY_COMPLETE)
1573 : {
1574 34 : write_socket_delayed(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE,
1575 : strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE), get_write_delay(csp));
1576 34 : log_error(LOG_LEVEL_CLF,
1577 : "%s - - [%T] \"Failed reading chunked client body\" 400 0", csp->ip_addr_str);
1578 34 : return JB_ERR_PARSE;
1579 : }
1580 47 : log_error(LOG_LEVEL_CONNECT,
1581 : "Chunked client body completely read. Length: %lu", body_length);
1582 47 : csp->expected_client_content_length = body_length;
1583 :
1584 47 : return JB_ERR_OK;
1585 :
1586 : }
1587 :
1588 :
1589 : #ifdef FUZZ
1590 : /*********************************************************************
1591 : *
1592 : * Function : fuzz_chunked_transfer_encoding
1593 : *
1594 : * Description : Treat the fuzzed input as chunked transfer encoding
1595 : * to check and dechunk.
1596 : *
1597 : * Parameters :
1598 : * 1 : csp = Used to store the data.
1599 : * 2 : fuzz_input_file = File to read the input from.
1600 : *
1601 : * Returns : Result of dechunking
1602 : *
1603 : *********************************************************************/
1604 0 : extern int fuzz_chunked_transfer_encoding(struct client_state *csp, char *fuzz_input_file)
1605 : {
1606 : size_t length;
1607 0 : size_t size = (size_t)(csp->iob->eod - csp->iob->cur);
1608 : enum chunk_status status;
1609 :
1610 0 : status = chunked_body_is_complete(csp->iob, &length);
1611 0 : if (CHUNK_STATUS_BODY_COMPLETE != status)
1612 : {
1613 0 : log_error(LOG_LEVEL_INFO, "Chunked body is incomplete or invalid");
1614 : }
1615 :
1616 0 : return (JB_ERR_OK == remove_chunked_transfer_coding(csp->iob->cur, &size));
1617 :
1618 : }
1619 :
1620 :
1621 : /*********************************************************************
1622 : *
1623 : * Function : fuzz_client_request
1624 : *
1625 : * Description : Try to get a client request from the fuzzed input.
1626 : *
1627 : * Parameters :
1628 : * 1 : csp = Current client state (buffers, headers, etc...)
1629 : * 2 : fuzz_input_file = File to read the input from.
1630 : *
1631 : * Returns : Result of fuzzing.
1632 : *
1633 : *********************************************************************/
1634 3098 : extern int fuzz_client_request(struct client_state *csp, char *fuzz_input_file)
1635 : {
1636 :
1637 : jb_err err;
1638 :
1639 3098 : csp->cfd = 0; //stdin
1640 3098 : csp->ip_addr_str = "255.255.255.255";
1641 3098 : if (strcmp(fuzz_input_file, "-") != 0)
1642 : {
1643 0 : log_error(LOG_LEVEL_FATAL,
1644 : "Fuzzed client requests can currently only be read from stdin (-).");
1645 : }
1646 3098 : csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
1647 :
1648 3098 : serve(csp);
1649 : // free_csp_resources(csp); //static...
1650 3098 : return 0;
1651 :
1652 : }
1653 : #endif /* def FUZZ */
1654 :
1655 :
1656 : #ifdef FEATURE_FORCE_LOAD
1657 : /*********************************************************************
1658 : *
1659 : * Function : force_required
1660 : *
1661 : * Description : Checks a request line to see if it contains
1662 : * the FORCE_PREFIX. If it does, it is removed
1663 : * unless enforcing requests has beend disabled.
1664 : *
1665 : * Parameters :
1666 : * 1 : request_line = HTTP request line
1667 : *
1668 : * Returns : TRUE if force is required, FALSE otherwise.
1669 : *
1670 : *********************************************************************/
1671 34217 : static int force_required(const struct client_state *csp, char *request_line)
1672 : {
1673 : char *p;
1674 :
1675 34217 : p = strstr(request_line, "http://");
1676 34217 : if (p != NULL)
1677 : {
1678 : /* Skip protocol */
1679 15978 : p += strlen("http://");
1680 : }
1681 : else
1682 : {
1683 : /* Intercepted request usually don't specify the protocol. */
1684 18239 : p = request_line;
1685 : }
1686 :
1687 : /* Go to the beginning of the path */
1688 34217 : p = strstr(p, "/");
1689 34217 : if (p == NULL)
1690 : {
1691 : /*
1692 : * If the path is missing the request line is invalid and we
1693 : * are done here. The client-visible rejection happens later on.
1694 : */
1695 95 : return 0;
1696 : }
1697 :
1698 34122 : if (0 == strncmpic(p, FORCE_PREFIX, strlen(FORCE_PREFIX) - 1))
1699 : {
1700 902 : if (!(csp->config->feature_flags & RUNTIME_FEATURE_ENFORCE_BLOCKS))
1701 : {
1702 : /* XXX: Should clean more carefully */
1703 902 : strclean(request_line, FORCE_PREFIX);
1704 902 : log_error(LOG_LEVEL_FORCE,
1705 : "Enforcing request: \"%s\".", request_line);
1706 :
1707 902 : return 1;
1708 : }
1709 0 : log_error(LOG_LEVEL_FORCE,
1710 : "Ignored force prefix in request: \"%s\".", request_line);
1711 : }
1712 :
1713 33220 : return 0;
1714 :
1715 : }
1716 : #endif /* def FEATURE_FORCE_LOAD */
1717 :
1718 :
1719 : /*********************************************************************
1720 : *
1721 : * Function : receive_client_request
1722 : *
1723 : * Description : Read the client's request (more precisely the
1724 : * client headers) and answer it if necessary.
1725 : *
1726 : * Parameters :
1727 : * 1 : csp = Current client state (buffers, headers, etc...)
1728 : *
1729 : * Returns : JB_ERR_OK, JB_ERR_PARSE or JB_ERR_MEMORY
1730 : *
1731 : *********************************************************************/
1732 32220 : static jb_err receive_client_request(struct client_state *csp)
1733 : {
1734 : char buf[BUFFER_SIZE];
1735 : char *p;
1736 32220 : char *req = NULL;
1737 : struct http_request *http;
1738 : int len;
1739 : jb_err err;
1740 :
1741 : /* Temporary copy of the client's headers before they get enlisted in csp->headers */
1742 : struct list header_list;
1743 32220 : struct list *headers = &header_list;
1744 :
1745 : /* We don't care if the arriving data is a valid HTTP request or not. */
1746 32220 : csp->requests_received_total++;
1747 :
1748 32220 : http = csp->http;
1749 :
1750 32220 : memset(buf, 0, sizeof(buf));
1751 :
1752 32220 : req = get_request_line(csp);
1753 32220 : if (req == NULL)
1754 : {
1755 173 : mark_server_socket_tainted(csp);
1756 173 : return JB_ERR_PARSE;
1757 : }
1758 32047 : assert(*req != '\0');
1759 :
1760 32047 : if (client_protocol_is_unsupported(csp, req))
1761 : {
1762 2 : return JB_ERR_PARSE;
1763 : }
1764 :
1765 : #ifdef FEATURE_FORCE_LOAD
1766 32045 : if (force_required(csp, req))
1767 : {
1768 892 : csp->flags |= CSP_FLAG_FORCED;
1769 : }
1770 : #endif /* def FEATURE_FORCE_LOAD */
1771 :
1772 32045 : err = parse_http_request(req, http);
1773 32045 : freez(req);
1774 32045 : if (JB_ERR_OK != err)
1775 : {
1776 435 : write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
1777 : get_write_delay(csp));
1778 : /* XXX: Use correct size */
1779 435 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
1780 435 : log_error(LOG_LEVEL_ERROR,
1781 : "Couldn't parse request line received from %s: %s",
1782 : csp->ip_addr_str, jb_err_to_string(err));
1783 :
1784 435 : free_http_request(http);
1785 435 : return JB_ERR_PARSE;
1786 : }
1787 :
1788 : /* grab the rest of the client's headers */
1789 31610 : init_list(headers);
1790 : for (;;)
1791 : {
1792 338406 : p = get_header(csp->client_iob);
1793 :
1794 338406 : if (p == NULL)
1795 : {
1796 : /* There are no additional headers to read. */
1797 31197 : break;
1798 : }
1799 :
1800 307209 : if (*p == '\0')
1801 : {
1802 : /*
1803 : * We didn't receive a complete header
1804 : * line yet, get the rest of it.
1805 : */
1806 9272 : if (!data_is_available(csp->cfd, csp->config->socket_timeout))
1807 : {
1808 402 : log_error(LOG_LEVEL_ERROR,
1809 : "Stopped grabbing the client headers.");
1810 402 : destroy_list(headers);
1811 402 : return JB_ERR_PARSE;
1812 : }
1813 :
1814 8870 : len = read_socket(csp->cfd, buf, sizeof(buf) - 1);
1815 8870 : if (len <= 0)
1816 : {
1817 11 : log_error(LOG_LEVEL_ERROR, "read from client failed: %E");
1818 11 : destroy_list(headers);
1819 11 : return JB_ERR_PARSE;
1820 : }
1821 :
1822 8859 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
1823 : {
1824 : /*
1825 : * If there is no memory left for buffering the
1826 : * request, there is nothing we can do but hang up
1827 : */
1828 0 : destroy_list(headers);
1829 0 : return JB_ERR_MEMORY;
1830 : }
1831 : }
1832 : else
1833 : {
1834 297937 : if (!strncmpic(p, "Transfer-Encoding:", 18))
1835 : {
1836 : /*
1837 : * XXX: should be called through sed()
1838 : * but currently can't.
1839 : */
1840 784 : client_transfer_encoding(csp, &p);
1841 : }
1842 : /*
1843 : * We were able to read a complete
1844 : * header and can finally enlist it.
1845 : */
1846 297937 : enlist(headers, p);
1847 297937 : freez(p);
1848 : }
1849 : }
1850 :
1851 31197 : if (http->host == NULL)
1852 : {
1853 : /*
1854 : * If we still don't know the request destination,
1855 : * the request is invalid or the client uses
1856 : * Privoxy without its knowledge.
1857 : */
1858 15190 : if (JB_ERR_OK != get_request_destination_elsewhere(csp, headers))
1859 : {
1860 : /*
1861 : * Our attempts to get the request destination
1862 : * elsewhere failed or Privoxy is configured
1863 : * to only accept proxy requests.
1864 : *
1865 : * An error response has already been sent
1866 : * and we're done here.
1867 : */
1868 20 : return JB_ERR_PARSE;
1869 : }
1870 : }
1871 :
1872 : #ifdef FEATURE_CLIENT_TAGS
1873 : /* XXX: If the headers were enlisted sooner, passing csp would do. */
1874 31177 : set_client_address(csp, headers);
1875 31177 : get_tag_list_for_client(csp->client_tags, csp->client_address);
1876 : #endif
1877 :
1878 : /*
1879 : * Determine the actions for this URL
1880 : */
1881 : #ifdef FEATURE_TOGGLE
1882 31177 : if (!(csp->flags & CSP_FLAG_TOGGLED_ON))
1883 : {
1884 : /* Most compatible set of actions (i.e. none) */
1885 1100 : init_current_action(csp->action);
1886 : }
1887 : else
1888 : #endif /* ndef FEATURE_TOGGLE */
1889 : {
1890 30077 : get_url_actions(csp, http);
1891 : }
1892 :
1893 31177 : enlist(csp->headers, http->cmd);
1894 :
1895 : /* Append the previously read headers */
1896 31177 : err = list_append_list_unique(csp->headers, headers);
1897 31177 : destroy_list(headers);
1898 :
1899 31177 : return err;
1900 :
1901 : }
1902 :
1903 :
1904 : /*********************************************************************
1905 : *
1906 : * Function : parse_client_request
1907 : *
1908 : * Description : Parses the client's request and decides what to do
1909 : * with it.
1910 : *
1911 : * Note that since we're not using select() we could get
1912 : * blocked here if a client connected, then didn't say
1913 : * anything!
1914 : *
1915 : * Parameters :
1916 : * 1 : csp = Current client state (buffers, headers, etc...)
1917 : *
1918 : * Returns : JB_ERR_OK or JB_ERR_PARSE
1919 : *
1920 : *********************************************************************/
1921 31177 : static jb_err parse_client_request(struct client_state *csp)
1922 : {
1923 31177 : struct http_request *http = csp->http;
1924 : jb_err err;
1925 :
1926 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1927 31177 : if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
1928 31177 : && (!strcmpic(csp->http->version, "HTTP/1.1"))
1929 27525 : && (csp->http->ssl == 0))
1930 : {
1931 : /* Assume persistence until further notice */
1932 27096 : csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
1933 : }
1934 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
1935 :
1936 31177 : if (csp->http->ssl == 0)
1937 : {
1938 : /*
1939 : * This whole block belongs to chat() but currently
1940 : * has to be executed before sed().
1941 : */
1942 30705 : if (csp->flags & CSP_FLAG_CHUNKED_CLIENT_BODY)
1943 : {
1944 81 : if (receive_chunked_client_request_body(csp) != JB_ERR_OK)
1945 : {
1946 34 : return JB_ERR_PARSE;
1947 : }
1948 : }
1949 : else
1950 : {
1951 30624 : csp->expected_client_content_length = get_expected_content_length(csp->headers);
1952 : }
1953 30671 : verify_request_length(csp);
1954 : }
1955 : #ifndef FEATURE_HTTPS_INSPECTION
1956 : else
1957 : {
1958 : csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
1959 : }
1960 : #endif
1961 :
1962 31143 : err = sed(csp, FILTER_CLIENT_HEADERS);
1963 31143 : if (JB_ERR_OK != err)
1964 : {
1965 2 : log_error(LOG_LEVEL_ERROR, "Failed to parse client request from %s.",
1966 : csp->ip_addr_str);
1967 2 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
1968 : csp->ip_addr_str, csp->http->cmd);
1969 2 : write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), get_write_delay(csp));
1970 2 : return JB_ERR_PARSE;
1971 : }
1972 31141 : csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
1973 :
1974 : /* Check request line for rewrites. */
1975 31141 : if ((NULL == csp->headers->first->str)
1976 31192 : || (strcmp(http->cmd, csp->headers->first->str) &&
1977 52 : (JB_ERR_OK != change_request_destination(csp))))
1978 : {
1979 : /*
1980 : * A header filter broke the request line - bail out.
1981 : */
1982 3 : write_socket_delayed(csp->cfd, MESSED_UP_REQUEST_RESPONSE,
1983 : strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp));
1984 : /* XXX: Use correct size */
1985 3 : log_error(LOG_LEVEL_CLF,
1986 : "%s - - [%T] \"Invalid request generated\" 400 0", csp->ip_addr_str);
1987 3 : log_error(LOG_LEVEL_ERROR,
1988 : "Invalid request line after applying header filters.");
1989 3 : free_http_request(http);
1990 :
1991 3 : return JB_ERR_PARSE;
1992 : }
1993 :
1994 31138 : if (client_has_unsupported_expectations(csp))
1995 : {
1996 20 : return JB_ERR_PARSE;
1997 : }
1998 :
1999 31118 : return JB_ERR_OK;
2000 :
2001 : }
2002 :
2003 :
2004 : /*********************************************************************
2005 : *
2006 : * Function : read_http_request_body
2007 : *
2008 : * Description : Reads remaining request body from the client.
2009 : *
2010 : * Parameters :
2011 : * 1 : csp = Current client state (buffers, headers, etc...)
2012 : *
2013 : * Returns : 0 on success, anything else is an error.
2014 : *
2015 : *********************************************************************/
2016 833 : static int read_http_request_body(struct client_state *csp)
2017 : {
2018 833 : size_t to_read = csp->expected_client_content_length;
2019 : int len;
2020 :
2021 833 : assert(to_read != 0);
2022 :
2023 : /* check if all data has been already read */
2024 833 : if (to_read <= (csp->client_iob->eod - csp->client_iob->cur))
2025 : {
2026 786 : return 0;
2027 : }
2028 :
2029 574 : for (to_read -= (size_t)(csp->client_iob->eod - csp->client_iob->cur);
2030 550 : to_read > 0 && data_is_available(csp->cfd, csp->config->socket_timeout);
2031 527 : to_read -= (unsigned)len)
2032 : {
2033 : char buf[BUFFER_SIZE];
2034 527 : size_t max_bytes_to_read = to_read < sizeof(buf) ? to_read : sizeof(buf);
2035 :
2036 527 : log_error(LOG_LEVEL_CONNECT,
2037 : "Waiting for up to %d bytes of request body from the client.",
2038 : max_bytes_to_read);
2039 527 : len = read_socket(csp->cfd, buf, (int)max_bytes_to_read);
2040 527 : if (len <= -1)
2041 : {
2042 0 : log_error(LOG_LEVEL_CONNECT, "Failed receiving request body from %s: %E", csp->ip_addr_str);
2043 0 : return 1;
2044 : }
2045 527 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, (char *)buf, len))
2046 : {
2047 0 : return 1;
2048 : }
2049 527 : assert(to_read >= len);
2050 : }
2051 :
2052 47 : if (to_read != 0)
2053 : {
2054 23 : log_error(LOG_LEVEL_CONNECT, "Not enough request body has been read: expected %d more bytes",
2055 : csp->expected_client_content_length);
2056 23 : return 1;
2057 : }
2058 24 : log_error(LOG_LEVEL_CONNECT, "The last %d bytes of the request body have been read",
2059 : csp->expected_client_content_length);
2060 24 : return 0;
2061 : }
2062 :
2063 :
2064 : /*********************************************************************
2065 : *
2066 : * Function : update_client_headers
2067 : *
2068 : * Description : Updates the HTTP headers from the client request.
2069 : *
2070 : * Parameters :
2071 : * 1 : csp = Current client state (buffers, headers, etc...)
2072 : * 2 : new_content_length = new content length value to set
2073 : *
2074 : * Returns : 0 on success, anything else is an error.
2075 : *
2076 : *********************************************************************/
2077 246 : static int update_client_headers(struct client_state *csp, size_t new_content_length)
2078 : {
2079 : static const char content_length[] = "Content-Length:";
2080 246 : int updated = 0;
2081 : struct list_entry *p;
2082 :
2083 : #ifndef FEATURE_HTTPS_INSPECTION
2084 : for (p = csp->headers->first;
2085 : #else
2086 3217 : for (p = csp->http->client_ssl ? csp->https_headers->first : csp->headers->first;
2087 : #endif
2088 5948 : !updated && (p != NULL); p = p->next)
2089 : {
2090 : /* Header crunch()ed in previous run? -> ignore */
2091 2971 : if (p->str == NULL)
2092 : {
2093 0 : continue;
2094 : }
2095 :
2096 : /* Does the current parser handle this header? */
2097 2971 : if (0 == strncmpic(p->str, content_length, sizeof(content_length) - 1))
2098 : {
2099 240 : updated = (JB_ERR_OK == header_adjust_content_length((char **)&(p->str), new_content_length));
2100 240 : if (!updated)
2101 : {
2102 0 : return 1;
2103 : }
2104 : }
2105 : }
2106 :
2107 246 : return !updated;
2108 : }
2109 :
2110 :
2111 : /*********************************************************************
2112 : *
2113 : * Function : can_filter_request_body
2114 : *
2115 : * Description : Checks if the current request body can be stored in
2116 : * the client_iob without hitting buffer limit.
2117 : *
2118 : * Parameters :
2119 : * 1 : csp = Current client state (buffers, headers, etc...)
2120 : *
2121 : * Returns : TRUE if the current request size do not exceed buffer limit
2122 : * FALSE otherwise.
2123 : *
2124 : *********************************************************************/
2125 926 : static int can_filter_request_body(const struct client_state *csp)
2126 : {
2127 926 : if (!can_add_to_iob(csp->client_iob, csp->config->buffer_limit,
2128 926 : csp->expected_client_content_length))
2129 : {
2130 29 : log_error(LOG_LEVEL_INFO,
2131 : "Not filtering request body from %s: buffer limit %d will be exceeded "
2132 29 : "(content length %d)", csp->ip_addr_str, csp->config->buffer_limit,
2133 : csp->expected_client_content_length);
2134 29 : return FALSE;
2135 : }
2136 897 : return TRUE;
2137 : }
2138 :
2139 :
2140 : /*********************************************************************
2141 : *
2142 : * Function : send_http_request
2143 : *
2144 : * Description : Sends the HTTP headers from the client request
2145 : * and all the body data that has already been received.
2146 : *
2147 : * Parameters :
2148 : * 1 : csp = Current client state (buffers, headers, etc...)
2149 : *
2150 : * Returns : 0 on success, anything else is an error.
2151 : *
2152 : *********************************************************************/
2153 6316 : static int send_http_request(struct client_state *csp)
2154 : {
2155 : char *hdr;
2156 : int write_failure;
2157 : const char *to_send;
2158 : size_t to_send_len;
2159 13756 : int filter_client_body = csp->expected_client_content_length != 0 &&
2160 7440 : client_body_filters_enabled(csp->action) && can_filter_request_body(csp);
2161 :
2162 6316 : if (filter_client_body)
2163 : {
2164 833 : if (read_http_request_body(csp))
2165 : {
2166 23 : return 1;
2167 : }
2168 810 : to_send_len = csp->expected_client_content_length;
2169 810 : to_send = execute_client_body_filters(csp, &to_send_len);
2170 810 : if (to_send == NULL)
2171 : {
2172 : /* just flush client_iob */
2173 590 : filter_client_body = FALSE;
2174 : }
2175 439 : else if (to_send_len != csp->expected_client_content_length &&
2176 219 : update_client_headers(csp, to_send_len))
2177 : {
2178 1 : log_error(LOG_LEVEL_HEADER, "Error updating client headers");
2179 1 : return 1;
2180 : }
2181 809 : csp->expected_client_content_length = 0;
2182 : }
2183 :
2184 6292 : hdr = list_to_text(csp->headers);
2185 6292 : if (hdr == NULL)
2186 : {
2187 : /* FIXME Should handle error properly */
2188 0 : log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
2189 : }
2190 6292 : list_remove_all(csp->headers);
2191 :
2192 : /*
2193 : * Write the client's (modified) header to the server
2194 : * (along with anything else that may be in the buffer)
2195 : */
2196 6292 : write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
2197 6292 : freez(hdr);
2198 :
2199 6292 : if (write_failure)
2200 : {
2201 0 : log_error(LOG_LEVEL_CONNECT, "Failed sending request headers to: %s: %E",
2202 : csp->http->hostport);
2203 0 : return 1;
2204 : }
2205 :
2206 6292 : if (filter_client_body)
2207 : {
2208 219 : write_failure = 0 != write_socket(csp->server_connection.sfd, to_send, to_send_len);
2209 219 : freez(to_send);
2210 219 : if (write_failure)
2211 : {
2212 0 : log_error(LOG_LEVEL_CONNECT, "Failed sending filtered request body to: %s: %E",
2213 : csp->http->hostport);
2214 0 : return 1;
2215 : }
2216 : }
2217 :
2218 6292 : if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
2219 6090 : && (flush_iob(csp->server_connection.sfd, csp->client_iob, 0) < 0))
2220 : {
2221 0 : log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
2222 : csp->http->hostport);
2223 0 : return 1;
2224 : }
2225 6292 : return 0;
2226 : }
2227 :
2228 :
2229 : #ifdef FEATURE_HTTPS_INSPECTION
2230 : /*********************************************************************
2231 : *
2232 : * Function : read_https_request_body
2233 : *
2234 : * Description : Reads remaining request body from the client.
2235 : *
2236 : * Parameters :
2237 : * 1 : csp = Current client state (buffers, headers, etc...)
2238 : *
2239 : * Returns : 0 on success, anything else is an error.
2240 : *
2241 : *********************************************************************/
2242 64 : static int read_https_request_body(struct client_state *csp)
2243 : {
2244 64 : size_t to_read = csp->expected_client_content_length;
2245 : int len;
2246 :
2247 64 : assert(to_read != 0);
2248 :
2249 : /* check if all data has been already read */
2250 64 : if (to_read <= (csp->client_iob->eod - csp->client_iob->cur))
2251 : {
2252 42 : return 0;
2253 : }
2254 :
2255 438 : for (to_read -= (size_t)(csp->client_iob->eod - csp->client_iob->cur);
2256 429 : to_read > 0 && (is_ssl_pending(&(csp->ssl_client_attr)) ||
2257 0 : data_is_available(csp->cfd, csp->config->socket_timeout));
2258 416 : to_read -= (unsigned)len)
2259 : {
2260 : unsigned char buf[BUFFER_SIZE];
2261 429 : size_t max_bytes_to_read = to_read < sizeof(buf) ? to_read : sizeof(buf);
2262 :
2263 429 : log_error(LOG_LEVEL_CONNECT,
2264 : "Waiting for up to %d bytes of request body from the client.",
2265 : max_bytes_to_read);
2266 429 : len = read_socket(csp->cfd, (char *)buf,
2267 : // len = ssl_recv_data(&(csp->ssl_client_attr), buf,
2268 : (unsigned)max_bytes_to_read);
2269 429 : if (len <= 0)
2270 : {
2271 13 : log_error(LOG_LEVEL_CONNECT, "Failed receiving request body from %s", csp->ip_addr_str);
2272 13 : return 1;
2273 : }
2274 416 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, (char *)buf, len))
2275 : {
2276 0 : return 1;
2277 : }
2278 416 : assert(to_read >= len);
2279 : }
2280 :
2281 9 : if (to_read != 0)
2282 : {
2283 0 : log_error(LOG_LEVEL_CONNECT, "Not enough request body has been read: expected %d more bytes", to_read);
2284 0 : return 1;
2285 : }
2286 :
2287 9 : log_error(LOG_LEVEL_CONNECT, "The last %d bytes of the request body have been read",
2288 : csp->expected_client_content_length);
2289 9 : return 0;
2290 : }
2291 :
2292 :
2293 : /*********************************************************************
2294 : *
2295 : * Function : receive_and_send_encrypted_post_data
2296 : *
2297 : * Description : Reads remaining request body from the client and sends
2298 : * it to the server.
2299 : *
2300 : * Parameters :
2301 : * 1 : csp = Current client state (buffers, headers, etc...)
2302 : *
2303 : * Returns : 0 on success, anything else is an error.
2304 : *
2305 : *********************************************************************/
2306 26 : static int receive_and_send_encrypted_post_data(struct client_state *csp)
2307 : {
2308 26 : int content_length_known = csp->expected_client_content_length != 0;
2309 :
2310 597 : while (is_ssl_pending(&(csp->ssl_client_attr))
2311 0 : || (content_length_known && csp->expected_client_content_length != 0))
2312 : {
2313 : unsigned char buf[BUFFER_SIZE];
2314 : int len;
2315 597 : int max_bytes_to_read = sizeof(buf);
2316 :
2317 597 : if (content_length_known && csp->expected_client_content_length < sizeof(buf))
2318 : {
2319 1 : max_bytes_to_read = (int)csp->expected_client_content_length;
2320 : }
2321 597 : log_error(LOG_LEVEL_CONNECT,
2322 : "Waiting for up to %d bytes of request body from the client.",
2323 : max_bytes_to_read);
2324 597 : len = read_socket(csp->cfd, (char *)buf,
2325 : // len = ssl_recv_data(&(csp->ssl_client_attr), buf,
2326 : (unsigned)max_bytes_to_read);
2327 597 : if (len == -1)
2328 : {
2329 0 : return 1;
2330 : }
2331 597 : if (len == 0)
2332 : {
2333 : /* XXX: Does this actually happen? */
2334 26 : break;
2335 : }
2336 572 : log_error(LOG_LEVEL_CONNECT, "Forwarding %d bytes of encrypted request body",
2337 : len);
2338 572 : len = ssl_send_data(&(csp->ssl_server_attr), buf, (size_t)len);
2339 572 : if (len == -1)
2340 : {
2341 0 : return 1;
2342 : }
2343 572 : if (csp->expected_client_content_length != 0)
2344 : {
2345 312 : if (csp->expected_client_content_length >= len)
2346 : {
2347 312 : csp->expected_client_content_length -= (unsigned)len;
2348 : }
2349 312 : if (csp->expected_client_content_length == 0)
2350 : {
2351 1 : log_error(LOG_LEVEL_CONNECT, "Forwarded the last %d bytes", len);
2352 1 : break;
2353 : }
2354 : }
2355 : }
2356 :
2357 26 : log_error(LOG_LEVEL_CONNECT, "Done forwarding encrypted request body");
2358 :
2359 26 : return 0;
2360 :
2361 : }
2362 :
2363 :
2364 : /*********************************************************************
2365 : *
2366 : * Function : send_https_request
2367 : *
2368 : * Description : Sends the HTTP headers from the client request
2369 : * and all the body data that has already been received.
2370 : *
2371 : * Parameters :
2372 : * 1 : csp = Current client state (buffers, headers, etc...)
2373 : *
2374 : * Returns : 0 on success, anything else is an error.
2375 : *
2376 : *********************************************************************/
2377 199 : static int send_https_request(struct client_state *csp)
2378 : {
2379 : char *hdr;
2380 : int ret;
2381 199 : long flushed = 0;
2382 : const char *to_send;
2383 : size_t to_send_len;
2384 489 : int filter_client_body = csp->expected_client_content_length != 0 &&
2385 290 : client_body_filters_enabled(csp->action) && can_filter_request_body(csp);
2386 :
2387 199 : if (filter_client_body)
2388 : {
2389 64 : if (read_https_request_body(csp))
2390 : {
2391 13 : return 1;
2392 : }
2393 51 : to_send_len = csp->expected_client_content_length;
2394 51 : to_send = execute_client_body_filters(csp, &to_send_len);
2395 51 : if (to_send == NULL)
2396 : {
2397 : /* just flush client_iob */
2398 23 : filter_client_body = FALSE;
2399 : }
2400 55 : else if (to_send_len != csp->expected_client_content_length &&
2401 27 : update_client_headers(csp, to_send_len))
2402 : {
2403 5 : log_error(LOG_LEVEL_HEADER, "Error updating client headers");
2404 5 : return 1;
2405 : }
2406 46 : csp->expected_client_content_length = 0;
2407 : }
2408 :
2409 181 : hdr = list_to_text(csp->https_headers);
2410 181 : if (hdr == NULL)
2411 : {
2412 : /* FIXME Should handle error properly */
2413 0 : log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
2414 : }
2415 181 : list_remove_all(csp->https_headers);
2416 :
2417 : /*
2418 : * Write the client's (modified) header to the server
2419 : * (along with anything else that may be in the buffer)
2420 : */
2421 181 : ret = ssl_send_data(&(csp->ssl_server_attr),
2422 : (const unsigned char *)hdr, strlen(hdr));
2423 181 : freez(hdr);
2424 :
2425 181 : if (ret < 0)
2426 : {
2427 0 : log_error(LOG_LEVEL_CONNECT,
2428 : "Failed sending encrypted request headers to: %s: %E",
2429 : csp->http->hostport);
2430 0 : mark_server_socket_tainted(csp);
2431 0 : return 1;
2432 : }
2433 :
2434 181 : if (filter_client_body)
2435 : {
2436 23 : ret = ssl_send_data(&(csp->ssl_server_attr), (const unsigned char *)to_send, to_send_len);
2437 23 : freez(to_send);
2438 23 : if (ret < 0)
2439 : {
2440 0 : log_error(LOG_LEVEL_CONNECT, "Failed sending filtered request body to: %s",
2441 : csp->http->hostport);
2442 0 : return 1;
2443 : }
2444 : }
2445 :
2446 181 : if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
2447 180 : && ((flushed = ssl_flush_socket(&(csp->ssl_server_attr),
2448 180 : csp->client_iob)) < 0))
2449 : {
2450 0 : log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
2451 : csp->http->hostport);
2452 0 : return 1;
2453 : }
2454 181 : if (flushed != 0 || csp->expected_client_content_length != 0)
2455 : {
2456 67 : if (csp->expected_client_content_length != 0)
2457 : {
2458 27 : if (csp->expected_client_content_length < flushed)
2459 : {
2460 1 : log_error(LOG_LEVEL_ERROR,
2461 : "Flushed %ld bytes of request body while only expecting %llu",
2462 : flushed, csp->expected_client_content_length);
2463 1 : csp->expected_client_content_length = 0;
2464 : }
2465 : else
2466 : {
2467 26 : log_error(LOG_LEVEL_CONNECT,
2468 : "Flushed %ld bytes of request body while expecting %llu",
2469 : flushed, csp->expected_client_content_length);
2470 26 : csp->expected_client_content_length -= (unsigned)flushed;
2471 26 : if (receive_and_send_encrypted_post_data(csp))
2472 : {
2473 0 : return 1;
2474 : }
2475 : }
2476 : }
2477 : else
2478 : {
2479 40 : log_error(LOG_LEVEL_CONNECT,
2480 : "Flushed %ld bytes of request body", flushed);
2481 : }
2482 : }
2483 :
2484 181 : log_error(LOG_LEVEL_CONNECT, "Encrypted request sent");
2485 :
2486 181 : return 0;
2487 :
2488 : }
2489 :
2490 :
2491 : /*********************************************************************
2492 : *
2493 : * Function : receive_encrypted_request
2494 : *
2495 : * Description : Receives an encrypted request.
2496 : *
2497 : * Parameters :
2498 : * 1 : csp = Current client state (buffers, headers, etc...)
2499 : *
2500 : * Returns : JB_ERR_OK on success,
2501 : * JB_ERR_PARSE or JB_ERR_MEMORY otherwise
2502 : *
2503 : *********************************************************************/
2504 3789 : static jb_err receive_encrypted_request(struct client_state *csp)
2505 : {
2506 : char buf[BUFFER_SIZE];
2507 : int len;
2508 : char *p;
2509 :
2510 : do
2511 : {
2512 3789 : log_error(LOG_LEVEL_HEADER, "Reading encrypted headers");
2513 3789 : if (!is_ssl_pending(&(csp->ssl_client_attr)) &&
2514 0 : !data_is_available(csp->cfd, csp->config->socket_timeout))
2515 : {
2516 0 : log_error(LOG_LEVEL_CONNECT,
2517 : "Socket %d timed out while waiting for client headers", csp->cfd);
2518 0 : return JB_ERR_PARSE;
2519 : }
2520 : // len = ssl_recv_data(&(csp->ssl_client_attr),
2521 3789 : len = read_socket(csp->cfd,
2522 : buf, sizeof(buf));
2523 3789 : if (len == 0)
2524 : {
2525 75 : log_error(LOG_LEVEL_CONNECT,
2526 : "Socket %d closed while waiting for client headers", csp->cfd);
2527 75 : return JB_ERR_PARSE;
2528 : }
2529 3714 : if (len == -1)
2530 : {
2531 0 : return JB_ERR_PARSE;
2532 : }
2533 3714 : if (add_to_iob(csp->client_iob, csp->config->buffer_limit, buf, len))
2534 : {
2535 0 : return JB_ERR_MEMORY;
2536 : }
2537 3714 : p = strstr(csp->client_iob->cur, "\r\n\r\n");
2538 3714 : } while (p == NULL);
2539 :
2540 2177 : log_error(LOG_LEVEL_HEADER, "Encrypted headers received completely");
2541 :
2542 2177 : return JB_ERR_OK;
2543 : }
2544 :
2545 :
2546 : /*********************************************************************
2547 : *
2548 : * Function : change_encrypted_request_destination
2549 : *
2550 : * Description : Parse a (rewritten) request line from an encrypted
2551 : * request and regenerate the http request data.
2552 : *
2553 : * Parameters :
2554 : * 1 : csp = Current client state (buffers, headers, etc...)
2555 : *
2556 : * Returns : Forwards the parse_http_request() return code.
2557 : * Terminates in case of memory problems.
2558 : *
2559 : *********************************************************************/
2560 51 : static jb_err change_encrypted_request_destination(struct client_state *csp)
2561 : {
2562 : jb_err err;
2563 51 : char *original_host = csp->http->host;
2564 51 : int original_port = csp->http->port;
2565 :
2566 51 : log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s",
2567 51 : csp->https_headers->first->str);
2568 51 : csp->http->host = NULL;
2569 51 : free_http_request(csp->http);
2570 51 : err = parse_http_request(csp->https_headers->first->str, csp->http);
2571 51 : if (JB_ERR_OK != err)
2572 : {
2573 0 : log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.",
2574 : jb_err_to_string(err));
2575 0 : freez(original_host);
2576 0 : return err;
2577 : }
2578 :
2579 51 : if (csp->http->host == NULL)
2580 : {
2581 : char port_string[10];
2582 : /*
2583 : * The rewritten request line did not specify a host
2584 : * which means we can use the original host specified
2585 : * by the client.
2586 : */
2587 43 : csp->http->host = original_host;
2588 43 : csp->http->port = original_port;
2589 43 : log_error(LOG_LEVEL_REDIRECTS, "Keeping the original host: %s",
2590 : csp->http->host);
2591 : /*
2592 : * If the rewritten request line didn't contain a host
2593 : * it also didn't contain a port so we can reuse the host
2594 : * port.
2595 : */
2596 43 : freez(csp->http->hostport);
2597 43 : csp->http->hostport = strdup_or_die(csp->http->host);
2598 43 : snprintf(port_string, sizeof(port_string), ":%d", original_port);
2599 43 : err = string_append(&csp->http->hostport, port_string);
2600 43 : if (err != JB_ERR_OK)
2601 : {
2602 0 : log_error(LOG_LEVEL_ERROR, "Failed to rebuild hostport: %s.",
2603 : jb_err_to_string(err));
2604 0 : return err;
2605 : }
2606 :
2607 : /*
2608 : * While the request line didn't mention it,
2609 : * we're https-inspecting and want to speak TLS
2610 : * with the server.
2611 : */
2612 43 : csp->http->server_ssl = 1;
2613 43 : csp->http->ssl = 1;
2614 : }
2615 : else
2616 : {
2617 : /* The rewrite filter added a host so we can ditch the original */
2618 8 : freez(original_host);
2619 8 : csp->http->server_ssl = csp->http->ssl;
2620 : }
2621 :
2622 51 : csp->http->client_ssl = 1;
2623 :
2624 51 : freez(csp->https_headers->first->str);
2625 51 : build_request_line(csp, NULL, &csp->https_headers->first->str);
2626 :
2627 51 : if (!server_use_ssl(csp))
2628 : {
2629 8 : log_error(LOG_LEVEL_REDIRECTS,
2630 : "Rewritten request line results in downgrade to http");
2631 : /*
2632 : * Replace the unencryptd headers received with the
2633 : * CONNECT request with the ones we received securely.
2634 : */
2635 8 : destroy_list(csp->headers);
2636 8 : csp->headers->first = csp->https_headers->first;
2637 8 : csp->headers->last = csp->https_headers->last;
2638 8 : csp->https_headers->first = NULL;
2639 8 : csp->https_headers->last = NULL;
2640 : }
2641 :
2642 51 : return JB_ERR_OK;
2643 :
2644 : }
2645 :
2646 :
2647 : /*********************************************************************
2648 : *
2649 : * Function : process_encrypted_request
2650 : *
2651 : * Description : Receives and parses an encrypted request.
2652 : *
2653 : * Parameters :
2654 : * 1 : csp = Current client state (buffers, headers, etc...)
2655 : *
2656 : * Returns : JB_ERR_OK on success,
2657 : * JB_ERR_PARSE or JB_ERR_MEMORY otherwise
2658 : *
2659 : *********************************************************************/
2660 2252 : static jb_err process_encrypted_request(struct client_state *csp)
2661 : {
2662 : char *p;
2663 : char *request_line;
2664 : jb_err err;
2665 : /* Temporary copy of the client's headers before they get enlisted in csp->https_headers */
2666 : struct list header_list;
2667 2252 : struct list *headers = &header_list;
2668 :
2669 2252 : assert(csp->ssl_with_client_is_opened);
2670 :
2671 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2672 2252 : if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
2673 : {
2674 2252 : csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
2675 : }
2676 : #endif
2677 2252 : err = receive_encrypted_request(csp);
2678 2252 : if (err != JB_ERR_OK)
2679 : {
2680 75 : if (csp->client_iob->cur == NULL ||
2681 72 : csp->client_iob->cur == csp->client_iob->eod)
2682 : {
2683 : /*
2684 : * We did not receive any data, most likely because the
2685 : * client is done. Don't log this as a parse failure.
2686 : */
2687 5 : return JB_ERR_PARSE;
2688 : }
2689 : /* XXX: Also used for JB_ERR_MEMORY */
2690 70 : log_error(LOG_LEVEL_ERROR, "Failed to receive encrypted request: %s",
2691 : jb_err_to_string(err));
2692 70 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2693 : (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
2694 70 : return err;
2695 : }
2696 :
2697 : /* We don't need get_request_line() because the whole HTTP head is buffered. */
2698 2177 : request_line = get_header(csp->client_iob);
2699 2177 : if (request_line == NULL)
2700 : {
2701 4 : log_error(LOG_LEVEL_ERROR, "Failed to get the encrypted request line");
2702 4 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2703 : (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
2704 4 : return JB_ERR_PARSE;
2705 : }
2706 2173 : assert(*request_line != '\0');
2707 :
2708 2173 : if (client_protocol_is_unsupported(csp, request_line))
2709 : {
2710 : /*
2711 : * If the protocol is unsupported we're done here.
2712 : * client_protocol_is_unsupported() took care of sending
2713 : * the error response and logging the error message.
2714 : */
2715 1 : return JB_ERR_PARSE;
2716 : }
2717 :
2718 : #ifdef FEATURE_FORCE_LOAD
2719 2172 : if (force_required(csp, request_line))
2720 : {
2721 10 : csp->flags |= CSP_FLAG_FORCED;
2722 : }
2723 : #endif /* def FEATURE_FORCE_LOAD */
2724 :
2725 2172 : free_http_request(csp->http);
2726 :
2727 2172 : err = parse_http_request(request_line, csp->http);
2728 : /* XXX: Restore ssl setting. This is ugly */
2729 2172 : csp->http->client_ssl = 1;
2730 2172 : csp->http->server_ssl = 1;
2731 :
2732 2172 : freez(request_line);
2733 2172 : if (JB_ERR_OK != err)
2734 : {
2735 36 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2736 : (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
2737 : /* XXX: Use correct size */
2738 36 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
2739 36 : log_error(LOG_LEVEL_ERROR,
2740 : "Couldn't parse request line received from %s: %s",
2741 : csp->ip_addr_str, jb_err_to_string(err));
2742 :
2743 36 : free_http_request(csp->http);
2744 36 : return JB_ERR_PARSE;
2745 : }
2746 :
2747 : /* Parse the rest of the client's headers. */
2748 2136 : init_list(headers);
2749 : for (;;)
2750 : {
2751 26163 : p = get_header(csp->client_iob);
2752 :
2753 26163 : if (p == NULL)
2754 : {
2755 : /* There are no additional headers to read. */
2756 2136 : break;
2757 : }
2758 24027 : enlist(headers, p);
2759 24027 : freez(p);
2760 : }
2761 :
2762 2136 : if (JB_ERR_OK != get_destination_from_https_headers(headers, csp->http))
2763 : {
2764 : /*
2765 : * Our attempts to get the request destination
2766 : * elsewhere failed.
2767 : */
2768 7 : log_error(LOG_LEVEL_ERROR,
2769 : "Failed to get the encrypted request destination");
2770 7 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2771 : (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
2772 7 : return JB_ERR_PARSE;
2773 : }
2774 :
2775 : /* Split the domain we just got for pattern matching */
2776 2129 : init_domain_components(csp->http);
2777 :
2778 : #ifdef FEATURE_CLIENT_TAGS
2779 : /* XXX: If the headers were enlisted sooner, passing csp would do. */
2780 2129 : if (csp->client_address == NULL)
2781 : {
2782 1833 : set_client_address(csp, headers);
2783 1833 : get_tag_list_for_client(csp->client_tags, csp->client_address);
2784 : }
2785 : #endif
2786 :
2787 : #ifdef FEATURE_TOGGLE
2788 2129 : if ((csp->flags & CSP_FLAG_TOGGLED_ON) != 0)
2789 : #endif
2790 : {
2791 : /*
2792 : * Determine the actions for this request after
2793 : * clearing the ones from the previous one.
2794 : */
2795 2042 : free_current_action(csp->action);
2796 2042 : get_url_actions(csp, csp->http);
2797 : }
2798 :
2799 2129 : enlist(csp->https_headers, csp->http->cmd);
2800 :
2801 : /* Append the previously read headers */
2802 2129 : err = list_append_list_unique(csp->https_headers, headers);
2803 2129 : destroy_list(headers);
2804 2129 : if (JB_ERR_OK != err)
2805 : {
2806 : /* XXX: Send error message */
2807 0 : return err;
2808 : }
2809 :
2810 : /* XXX: Work around crash */
2811 2129 : csp->error_message = NULL;
2812 :
2813 : /* XXX: Why do this here? */
2814 2129 : csp->http->ssl = 1;
2815 :
2816 2129 : err = sed_https(csp);
2817 2129 : if (JB_ERR_OK != err)
2818 : {
2819 1 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2820 : (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp));
2821 1 : log_error(LOG_LEVEL_ERROR, "Failed to parse client request from %s.",
2822 : csp->ip_addr_str);
2823 1 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
2824 : csp->ip_addr_str, csp->http->cmd);
2825 1 : return JB_ERR_PARSE;
2826 : }
2827 :
2828 2128 : if ((NULL == csp->https_headers->first->str)
2829 2178 : || (strcmp(csp->http->cmd, csp->https_headers->first->str) &&
2830 51 : (JB_ERR_OK != change_encrypted_request_destination(csp))))
2831 : {
2832 1 : ssl_send_data_delayed(&(csp->ssl_client_attr),
2833 : (const unsigned char *)MESSED_UP_REQUEST_RESPONSE,
2834 : strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp));
2835 1 : log_error(LOG_LEVEL_ERROR,
2836 : "Invalid request line after applying header filters.");
2837 : /* XXX: Use correct size */
2838 1 : log_error(LOG_LEVEL_CLF,
2839 : "%s - - [%T] \"Invalid request generated\" 400 0", csp->ip_addr_str);
2840 :
2841 1 : return JB_ERR_PARSE;
2842 : }
2843 :
2844 2127 : log_error(LOG_LEVEL_HEADER, "Encrypted request processed");
2845 2127 : log_applied_actions(csp->action);
2846 2127 : log_error(LOG_LEVEL_REQUEST, "https://%s%s", csp->http->hostport,
2847 : csp->http->path);
2848 :
2849 2127 : return err;
2850 :
2851 : }
2852 :
2853 : /*********************************************************************
2854 : *
2855 : * Function : cgi_page_requested
2856 : *
2857 : * Description : Checks if a request is for an internal CGI page.
2858 : *
2859 : * Parameters :
2860 : * 1 : host = The host requested by the client.
2861 : *
2862 : * Returns : 1 if a CGI page has been requested, 0 otherwise
2863 : *
2864 : *********************************************************************/
2865 41 : static int cgi_page_requested(const char *host)
2866 : {
2867 41 : if ((0 == strcmpic(host, CGI_SITE_1_HOST))
2868 24 : || (0 == strcmpic(host, CGI_SITE_1_HOST "."))
2869 23 : || (0 == strcmpic(host, CGI_SITE_2_HOST))
2870 21 : || (0 == strcmpic(host, CGI_SITE_2_HOST ".")))
2871 : {
2872 20 : return 1;
2873 : }
2874 :
2875 21 : return 0;
2876 :
2877 : }
2878 :
2879 :
2880 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2881 : /*********************************************************************
2882 : *
2883 : * Function : continue_https_chat
2884 : *
2885 : * Description : Behaves similar to chat() but only deals with
2886 : * https-inspected requests that arrive on an already
2887 : * established connection. The first request is always
2888 : * served by chat() which is a lot more complex as it
2889 : * has to deal with forwarding settings and connection
2890 : * failures etc.
2891 : *
2892 : * If a connection to the server has already been
2893 : * opened it is reused unless the request is blocked
2894 : * or the forwarder changed.
2895 : *
2896 : * If a connection to the server has not yet been
2897 : * opened (because the previous request was crunched),
2898 : * or the forwarder changed, the connection is dropped
2899 : * so that the client retries on a fresh one.
2900 : *
2901 : * Parameters :
2902 : * 1 : csp = Current client state (buffers, headers, etc...)
2903 : *
2904 : * Returns : Nothing.
2905 : *
2906 : *********************************************************************/
2907 1918 : static void continue_https_chat(struct client_state *csp)
2908 : {
2909 : const struct forward_spec *fwd;
2910 :
2911 1918 : if (JB_ERR_OK != process_encrypted_request(csp))
2912 : {
2913 85 : csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
2914 85 : return;
2915 : }
2916 :
2917 1833 : csp->requests_received_total++;
2918 :
2919 : /*
2920 : * We have an encrypted request. Check if one of the crunchers wants it.
2921 : */
2922 1833 : if (crunch_response_triggered(csp, crunchers_all))
2923 : {
2924 : /*
2925 : * Yes. The client got the crunch response and we're done here.
2926 : */
2927 1746 : return;
2928 : }
2929 87 : if (csp->ssl_with_server_is_opened == 0)
2930 : {
2931 46 : log_error(LOG_LEVEL_CONNECT,
2932 : "Dropping the client connection on socket %d. "
2933 : "The server connection has not been established yet.",
2934 : csp->cfd);
2935 46 : csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
2936 46 : return;
2937 : }
2938 41 : assert(csp->server_connection.sfd != JB_INVALID_SOCKET);
2939 :
2940 41 : fwd = forward_url(csp, csp->http);
2941 41 : if (!connection_destination_matches(&csp->server_connection, csp->http, fwd))
2942 : {
2943 1 : log_error(LOG_LEVEL_CONNECT,
2944 : "Dropping the client connection on socket %d with "
2945 : "server socket %d connected to %s. The forwarder has changed.",
2946 : csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
2947 1 : csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
2948 1 : return;
2949 : }
2950 :
2951 40 : log_error(LOG_LEVEL_CONNECT,
2952 : "Reusing server socket %d connected to %s. Requests already sent: %u.",
2953 : csp->server_connection.sfd, csp->server_connection.host,
2954 : csp->server_connection.requests_sent_total);
2955 :
2956 40 : if (send_https_request(csp))
2957 : {
2958 : /*
2959 : * Most likely the server connection timed out. We can't easily
2960 : * create a new one so simply drop the client connection without a
2961 : * error response to let the client retry.
2962 : */
2963 1 : log_error(LOG_LEVEL_CONNECT,
2964 : "Dropping client connection on socket %d. "
2965 : "Forwarding the encrypted client request failed.",
2966 : csp->cfd);
2967 1 : return;
2968 : }
2969 39 : csp->server_connection.requests_sent_total++;
2970 39 : handle_established_connection(csp);
2971 39 : freez(csp->receive_buffer);
2972 : }
2973 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2974 : #endif
2975 :
2976 :
2977 : /*********************************************************************
2978 : *
2979 : * Function : handle_established_connection
2980 : *
2981 : * Description : Shuffle data between client and server once the
2982 : * connection has been established.
2983 : *
2984 : * Parameters :
2985 : * 1 : csp = Current client state (buffers, headers, etc...)
2986 : *
2987 : * Returns : Nothing.
2988 : *
2989 : *********************************************************************/
2990 6494 : static void handle_established_connection(struct client_state *csp)
2991 : {
2992 : char *hdr;
2993 : char *p;
2994 : int n;
2995 : #ifdef HAVE_POLL
2996 : struct pollfd poll_fds[2];
2997 : #else
2998 : fd_set rfds;
2999 : jb_socket maxfd;
3000 : struct timeval timeout;
3001 : #endif
3002 : int server_body;
3003 6494 : int ms_iis5_hack = 0;
3004 6494 : unsigned long long byte_count = 0;
3005 : struct http_request *http;
3006 6494 : long len = 0; /* for buffer sizes (and negative error codes) */
3007 6494 : int buffer_and_filter_content = 0;
3008 : unsigned int write_delay;
3009 : #ifdef FEATURE_HTTPS_INSPECTION
3010 6494 : int ret = 0;
3011 6494 : int use_ssl_tunnel = 0;
3012 6494 : csp->dont_verify_certificate = 0;
3013 6494 : if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION))
3014 : {
3015 : /* Pass encrypted content without filtering. */
3016 35 : use_ssl_tunnel = 1;
3017 : }
3018 : #endif
3019 :
3020 : /* Skeleton for HTTP response, if we should intercept the request */
3021 : struct http_response *rsp;
3022 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3023 : int watch_client_socket;
3024 : #endif
3025 :
3026 6494 : csp->receive_buffer_size = csp->config->receive_buffer_size;
3027 6494 : csp->receive_buffer = zalloc(csp->receive_buffer_size + 1);
3028 6494 : if (csp->receive_buffer == NULL)
3029 : {
3030 0 : log_error(LOG_LEVEL_ERROR,
3031 : "Out of memory. Failed to allocate the receive buffer.");
3032 0 : rsp = cgi_error_memory();
3033 0 : send_crunch_response(csp, rsp);
3034 465 : return;
3035 : }
3036 :
3037 6494 : http = csp->http;
3038 :
3039 : #ifndef HAVE_POLL
3040 : maxfd = (csp->cfd > csp->server_connection.sfd) ?
3041 : csp->cfd : csp->server_connection.sfd;
3042 : #endif
3043 :
3044 : /* pass data between the client and server
3045 : * until one or the other shuts down the connection.
3046 : */
3047 :
3048 6494 : server_body = 0;
3049 :
3050 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3051 6494 : watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING);
3052 : #endif
3053 6494 : write_delay = get_write_delay(csp);
3054 :
3055 : for (;;)
3056 : {
3057 : #ifndef HAVE_POLL
3058 : FD_ZERO(&rfds);
3059 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3060 : if (!watch_client_socket)
3061 : {
3062 : maxfd = csp->server_connection.sfd;
3063 : }
3064 : else
3065 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
3066 : {
3067 : FD_SET(csp->cfd, &rfds);
3068 : }
3069 :
3070 : FD_SET(csp->server_connection.sfd, &rfds);
3071 : #endif /* ndef HAVE_POLL */
3072 :
3073 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3074 27710 : if ((csp->flags & CSP_FLAG_CHUNKED)
3075 3858 : && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
3076 1395 : && ((csp->iob->eod - csp->iob->cur) >= 5)
3077 632 : && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
3078 : {
3079 : /*
3080 : * XXX: This check should be obsolete now,
3081 : * but let's wait a while to be sure.
3082 : */
3083 10 : log_error(LOG_LEVEL_CONNECT,
3084 : "Looks like we got the last chunk together with "
3085 : "the server headers but didn't detect it earlier. "
3086 : "We better stop reading.");
3087 10 : byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
3088 10 : csp->expected_content_length = byte_count;
3089 10 : csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
3090 : }
3091 27710 : if (server_body && server_response_is_complete(csp, byte_count))
3092 : {
3093 5706 : if (csp->expected_content_length == byte_count)
3094 : {
3095 3659 : log_error(LOG_LEVEL_CONNECT,
3096 : "Done reading from server. Content length: %llu as expected. "
3097 : "Bytes most recently read: %ld.",
3098 : byte_count, len);
3099 : }
3100 : else
3101 : {
3102 2047 : log_error(LOG_LEVEL_CONNECT,
3103 : "Done reading from server. Expected content length: %llu. "
3104 : "Actual content length: %llu. Bytes most recently read: %ld.",
3105 : csp->expected_content_length, byte_count, len);
3106 : }
3107 5706 : len = 0;
3108 : /*
3109 : * XXX: Should not jump around, handle_established_connection()
3110 : * is complicated enough already.
3111 : */
3112 5706 : goto reading_done;
3113 : }
3114 : #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3115 :
3116 : #ifdef HAVE_POLL
3117 22004 : poll_fds[0].fd = csp->cfd;
3118 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3119 22004 : if (!watch_client_socket)
3120 : {
3121 : /*
3122 : * Ignore incoming data, but still watch out
3123 : * for disconnects etc. These flags are always
3124 : * implied anyway but explicitly setting them
3125 : * doesn't hurt.
3126 : */
3127 15000 : poll_fds[0].events = POLLERR|POLLHUP;
3128 : }
3129 : else
3130 : #endif
3131 : {
3132 7004 : poll_fds[0].events = POLLIN;
3133 : }
3134 22004 : poll_fds[1].fd = csp->server_connection.sfd;
3135 22004 : poll_fds[1].events = POLLIN;
3136 22004 : n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
3137 : #else
3138 : timeout.tv_sec = csp->config->socket_timeout;
3139 : timeout.tv_usec = 0;
3140 : n = select((int)maxfd + 1, &rfds, NULL, NULL, &timeout);
3141 : #endif /* def HAVE_POLL */
3142 :
3143 : /*server or client not responding in timeout */
3144 22004 : if (n == 0)
3145 : {
3146 0 : log_error(LOG_LEVEL_CONNECT, "Socket timeout %d reached: %s",
3147 0 : csp->config->socket_timeout, http->url);
3148 0 : if ((byte_count == 0) && (http->ssl == 0))
3149 : {
3150 0 : send_crunch_response(csp, error_response(csp, "connection-timeout"));
3151 : }
3152 0 : mark_server_socket_tainted(csp);
3153 : #ifdef FEATURE_HTTPS_INSPECTION
3154 0 : close_client_and_server_ssl_connections(csp);
3155 : #endif
3156 0 : return;
3157 : }
3158 22004 : else if (n < 0)
3159 : {
3160 : #ifdef HAVE_POLL
3161 0 : log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
3162 : #else
3163 : log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
3164 : #endif
3165 0 : mark_server_socket_tainted(csp);
3166 : #ifdef FEATURE_HTTPS_INSPECTION
3167 0 : close_client_and_server_ssl_connections(csp);
3168 : #endif
3169 0 : return;
3170 : }
3171 :
3172 : /*
3173 : * This is the body of the browser's request,
3174 : * just read and write it.
3175 : *
3176 : * Receives data from browser and sends it to server
3177 : *
3178 : * XXX: Make sure the client doesn't use pipelining
3179 : * behind Privoxy's back.
3180 : */
3181 : #ifdef HAVE_POLL
3182 22004 : if ((poll_fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) != 0)
3183 : {
3184 0 : log_error(LOG_LEVEL_CONNECT,
3185 : "The client socket %d has become unusable while "
3186 : "the server socket %d is still open.",
3187 : csp->cfd, csp->server_connection.sfd);
3188 0 : mark_server_socket_tainted(csp);
3189 0 : break;
3190 : }
3191 :
3192 22004 : if (poll_fds[0].revents != 0)
3193 : #else
3194 : if (FD_ISSET(csp->cfd, &rfds))
3195 : #endif /* def HAVE_POLL*/
3196 : {
3197 7004 : int max_bytes_to_read = (int)csp->receive_buffer_size;
3198 :
3199 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3200 7004 : if ((csp->http->ssl) || (csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
3201 : {
3202 6203 : if (data_is_available(csp->cfd, 0))
3203 : {
3204 : /*
3205 : * If the next request is already waiting, we have
3206 : * to stop select()ing the client socket. Otherwise
3207 : * we would always return right away and get nothing
3208 : * else done.
3209 : */
3210 6128 : watch_client_socket = 0;
3211 6128 : log_error(LOG_LEVEL_CONNECT,
3212 : "Stop watching client socket %d. "
3213 : "There's already another request waiting.",
3214 : csp->cfd);
3215 6128 : continue;
3216 : }
3217 : /*
3218 : * If the client socket is set, but there's no data
3219 : * available on the socket, the client went fishing
3220 : * and continuing talking to the server makes no sense.
3221 : */
3222 75 : log_error(LOG_LEVEL_CONNECT,
3223 : "The client closed socket %d while "
3224 : "the server socket %d is still open.",
3225 : csp->cfd, csp->server_connection.sfd);
3226 75 : mark_server_socket_tainted(csp);
3227 75 : break;
3228 : }
3229 801 : if (csp->expected_client_content_length != 0)
3230 : {
3231 260 : if (csp->expected_client_content_length < csp->receive_buffer_size)
3232 : {
3233 1 : max_bytes_to_read = (int)csp->expected_client_content_length;
3234 : }
3235 260 : log_error(LOG_LEVEL_CONNECT,
3236 : "Waiting for up to %d bytes from the client.",
3237 : max_bytes_to_read);
3238 : }
3239 801 : assert(max_bytes_to_read <= csp->receive_buffer_size);
3240 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
3241 :
3242 : #ifdef FEATURE_HTTPS_INSPECTION
3243 801 : if (client_use_ssl(csp))
3244 : {
3245 8 : if (csp->http->status == 101)
3246 : {
3247 : // len = ssl_recv_data(&(csp->ssl_client_attr),
3248 0 : len = read_socket(csp->server_connection.sfd,
3249 : csp->receive_buffer,
3250 : (int)max_bytes_to_read);
3251 0 : if (len == -1)
3252 : {
3253 0 : log_error(LOG_LEVEL_ERROR, "Failed to receive data "
3254 : "on client socket %d for an upgraded connection",
3255 : csp->cfd);
3256 0 : break;
3257 : }
3258 0 : if (len == 0)
3259 : {
3260 0 : log_error(LOG_LEVEL_CONNECT, "Done receiving data "
3261 : "on client socket %d for an upgraded connection",
3262 : csp->cfd);
3263 0 : break;
3264 : }
3265 0 : byte_count += (unsigned long long)len;
3266 0 : len = ssl_send_data(&(csp->ssl_server_attr),
3267 0 : (unsigned char *)csp->receive_buffer, (size_t)len);
3268 0 : if (len == -1)
3269 : {
3270 0 : log_error(LOG_LEVEL_ERROR, "Failed to send data "
3271 : "on server socket %d for an upgraded connection",
3272 : csp->server_connection.sfd);
3273 0 : break;
3274 : }
3275 0 : continue;
3276 : }
3277 8 : log_error(LOG_LEVEL_CONNECT, "Breaking with TLS/SSL.");
3278 8 : break;
3279 : }
3280 : else
3281 : #endif /* def FEATURE_HTTPS_INSPECTION */
3282 : {
3283 793 : len = read_socket(csp->cfd, csp->receive_buffer, max_bytes_to_read);
3284 :
3285 793 : if (len <= 0)
3286 : {
3287 : /* XXX: not sure if this is necessary. */
3288 80 : mark_server_socket_tainted(csp);
3289 80 : break; /* "game over, man" */
3290 : }
3291 :
3292 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3293 713 : if (csp->expected_client_content_length != 0)
3294 : {
3295 249 : assert(len <= max_bytes_to_read);
3296 249 : csp->expected_client_content_length -= (unsigned)len;
3297 249 : log_error(LOG_LEVEL_CONNECT,
3298 : "Expected client content length set to %llu "
3299 : "after reading %ld bytes.",
3300 : csp->expected_client_content_length, len);
3301 249 : if (csp->expected_client_content_length == 0)
3302 : {
3303 1 : log_error(LOG_LEVEL_CONNECT,
3304 : "Done reading from the client.");
3305 1 : csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ;
3306 : }
3307 : }
3308 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
3309 :
3310 713 : if (write_socket(csp->server_connection.sfd, csp->receive_buffer, (size_t)len))
3311 : {
3312 0 : log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
3313 0 : mark_server_socket_tainted(csp);
3314 0 : return;
3315 : }
3316 : }
3317 713 : continue;
3318 : }
3319 :
3320 : /*
3321 : * The server wants to talk. It could be the header or the body.
3322 : * If `hdr' is null, then it's the header otherwise it's the body.
3323 : * FIXME: Does `hdr' really mean `host'? No.
3324 : */
3325 : #ifdef HAVE_POLL
3326 15000 : if (poll_fds[1].revents != 0)
3327 : #else
3328 : if (FD_ISSET(csp->server_connection.sfd, &rfds))
3329 : #endif /* HAVE_POLL */
3330 : {
3331 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3332 : /*
3333 : * If we are buffering content, we don't want to eat up to
3334 : * buffer-limit bytes if the client no longer cares about them.
3335 : * If we aren't buffering, however, a dead client socket will be
3336 : * noticed pretty much right away anyway, so we can reduce the
3337 : * overhead by skipping the check.
3338 : */
3339 15000 : if (buffer_and_filter_content && !socket_is_still_alive(csp->cfd))
3340 : {
3341 : #ifdef _WIN32
3342 : log_error(LOG_LEVEL_CONNECT,
3343 : "The server still wants to talk, but the client may already have hung up on us.");
3344 : #else
3345 119 : log_error(LOG_LEVEL_CONNECT,
3346 : "The server still wants to talk, but the client hung up on us.");
3347 119 : mark_server_socket_tainted(csp);
3348 : #ifdef FEATURE_HTTPS_INSPECTION
3349 119 : close_client_and_server_ssl_connections(csp);
3350 : #endif
3351 119 : return;
3352 : #endif /* def _WIN32 */
3353 : }
3354 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
3355 :
3356 : #ifdef FEATURE_HTTPS_INSPECTION
3357 : /*
3358 : * Reading data from standard or secured connection (HTTP/HTTPS)
3359 : */
3360 : /* if (server_use_ssl(csp))
3361 : {
3362 : len = ssl_recv_data(&(csp->ssl_server_attr),
3363 : (unsigned char *)csp->receive_buffer, csp->receive_buffer_size);
3364 : }
3365 : else
3366 : */
3367 : #endif
3368 : {
3369 14881 : len = read_socket(csp->server_connection.sfd, csp->receive_buffer,
3370 14881 : (int)csp->receive_buffer_size);
3371 : }
3372 :
3373 14881 : if (len < 0)
3374 : {
3375 0 : log_error(LOG_LEVEL_ERROR, "read from: %s failed: %E", http->host);
3376 :
3377 0 : if ((http->ssl && (csp->fwd == NULL))
3378 : #ifdef FEATURE_HTTPS_INSPECTION
3379 0 : && use_ssl_tunnel
3380 : #endif
3381 : )
3382 : {
3383 : /*
3384 : * Just hang up. We already confirmed the client's CONNECT
3385 : * request with status code 200 and unencrypted content is
3386 : * no longer welcome.
3387 : */
3388 0 : log_error(LOG_LEVEL_ERROR,
3389 : "CONNECT already confirmed. Unable to tell the client about the problem.");
3390 0 : return;
3391 : }
3392 0 : else if (byte_count)
3393 : {
3394 : /*
3395 : * Just hang up. We already transmitted the original headers
3396 : * and parts of the original content and therefore missed the
3397 : * chance to send an error message (without risking data corruption).
3398 : *
3399 : * XXX: we could retry with a fancy range request here.
3400 : */
3401 0 : log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
3402 : "Unable to tell the client about the problem.");
3403 0 : mark_server_socket_tainted(csp);
3404 : #ifdef FEATURE_HTTPS_INSPECTION
3405 0 : close_client_and_server_ssl_connections(csp);
3406 : #endif
3407 0 : return;
3408 : }
3409 : /*
3410 : * XXX: Consider handling the cases above the same.
3411 : */
3412 0 : mark_server_socket_tainted(csp);
3413 0 : len = 0;
3414 : }
3415 :
3416 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
3417 14881 : if (csp->flags & CSP_FLAG_CHUNKED)
3418 : {
3419 1321 : if ((len >= 5) && !memcmp(csp->receive_buffer+len-5, "0\r\n\r\n", 5))
3420 : {
3421 : /* XXX: this is a temporary hack */
3422 669 : log_error(LOG_LEVEL_CONNECT,
3423 : "Looks like we reached the end of the last chunk. "
3424 : "We better stop reading.");
3425 669 : csp->expected_content_length = byte_count + (unsigned long long)len;
3426 669 : csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
3427 : }
3428 : }
3429 20587 : reading_done:
3430 : #endif /* FEATURE_CONNECTION_KEEP_ALIVE */
3431 :
3432 : /*
3433 : * This is guaranteed by allocating with zalloc_or_die()
3434 : * and never (intentionally) writing to the last byte.
3435 : *
3436 : * csp->receive_buffer_size is the size of the part of the
3437 : * buffer we intentionally write to, but we actually
3438 : * allocated csp->receive_buffer_size+1 bytes so the assertion
3439 : * stays within the allocated range.
3440 : */
3441 20587 : assert(csp->receive_buffer[csp->receive_buffer_size] == '\0');
3442 :
3443 : /*
3444 : * Add a trailing zero to let be able to use string operations.
3445 : * XXX: do we still need this with filter_popups gone?
3446 : */
3447 20587 : assert(len <= csp->receive_buffer_size);
3448 20587 : csp->receive_buffer[len] = '\0';
3449 :
3450 : /*
3451 : * Normally, this would indicate that we've read
3452 : * as much as the server has sent us and we can
3453 : * close the client connection. However, Microsoft
3454 : * in its wisdom has released IIS/5 with a bug that
3455 : * prevents it from sending the trailing \r\n in
3456 : * a 302 redirect header (and possibly other headers).
3457 : * To work around this if we've haven't parsed
3458 : * a full header we'll append a trailing \r\n
3459 : * and see if this now generates a valid one.
3460 : *
3461 : * This hack shouldn't have any impacts. If we've
3462 : * already transmitted the header or if this is a
3463 : * SSL connection, then we won't bother with this
3464 : * hack. So we only work on partially received
3465 : * headers. If we append a \r\n and this still
3466 : * doesn't generate a valid header, then we won't
3467 : * transmit anything to the client.
3468 : */
3469 20587 : if (len == 0)
3470 : {
3471 :
3472 6074 : if (server_body || (http->ssl
3473 : #ifdef FEATURE_HTTPS_INSPECTION
3474 54 : && use_ssl_tunnel
3475 : #endif
3476 : ))
3477 : {
3478 : /*
3479 : * If we have been buffering up the document,
3480 : * now is the time to apply content modification
3481 : * and send the result to the client.
3482 : */
3483 5866 : if (buffer_and_filter_content)
3484 : {
3485 4492 : p = execute_content_filters(csp);
3486 : /*
3487 : * If content filtering fails, use the original
3488 : * buffer and length.
3489 : * (see p != NULL ? p : csp->iob->cur below)
3490 : */
3491 4492 : if (NULL == p)
3492 : {
3493 4473 : csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur);
3494 : }
3495 : #ifdef FEATURE_COMPRESSION
3496 19 : else if ((csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE)
3497 13 : && (csp->content_length > LOWER_LENGTH_LIMIT_FOR_COMPRESSION))
3498 : {
3499 12 : char *compressed_content = compress_buffer(p,
3500 12 : (size_t *)&csp->content_length, csp->config->compression_level);
3501 12 : if (compressed_content != NULL)
3502 : {
3503 12 : freez(p);
3504 12 : p = compressed_content;
3505 12 : csp->flags |= CSP_FLAG_BUFFERED_CONTENT_DEFLATED;
3506 : }
3507 : }
3508 : #endif
3509 :
3510 4492 : if (JB_ERR_OK != update_server_headers(csp))
3511 : {
3512 0 : log_error(LOG_LEVEL_FATAL,
3513 : "Failed to update server headers. after filtering.");
3514 : }
3515 :
3516 4492 : hdr = list_to_text(csp->headers);
3517 4492 : if (hdr == NULL)
3518 : {
3519 : /* FIXME Should handle error properly */
3520 0 : log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
3521 : }
3522 :
3523 : #ifdef FEATURE_HTTPS_INSPECTION
3524 : /*
3525 : * Sending data with standard or secured connection (HTTP/HTTPS)
3526 : */
3527 4492 : if (client_use_ssl(csp))
3528 : {
3529 65 : if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
3530 : (const unsigned char *)hdr, strlen(hdr),
3531 : get_write_delay(csp)) < 0)
3532 65 : || (ssl_send_data_delayed(&(csp->ssl_client_attr),
3533 : (const unsigned char *) ((p != NULL) ? p : csp->iob->cur),
3534 65 : csp->content_length, get_write_delay(csp)) < 0))
3535 : {
3536 0 : log_error(LOG_LEVEL_ERROR, "write modified content to "
3537 : "client over TLS/SSL failed");
3538 0 : freez(hdr);
3539 0 : freez(p);
3540 0 : mark_server_socket_tainted(csp);
3541 0 : close_client_and_server_ssl_connections(csp);
3542 0 : return;
3543 : }
3544 : }
3545 : else
3546 : #endif /* def FEATURE_HTTPS_INSPECTION */
3547 : {
3548 4427 : if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
3549 4427 : || write_socket_delayed(csp->cfd, ((p != NULL) ? p : csp->iob->cur),
3550 4427 : (size_t)csp->content_length, write_delay))
3551 : {
3552 0 : log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
3553 0 : freez(hdr);
3554 0 : freez(p);
3555 0 : mark_server_socket_tainted(csp);
3556 0 : return;
3557 : }
3558 : }
3559 :
3560 4492 : freez(hdr);
3561 4492 : freez(p);
3562 : }
3563 :
3564 5866 : break; /* "game over, man" */
3565 : }
3566 :
3567 : /*
3568 : * This is NOT the body, so
3569 : * Let's pretend the server just sent us a blank line.
3570 : */
3571 208 : snprintf(csp->receive_buffer, csp->receive_buffer_size, "\r\n");
3572 208 : len = (int)strlen(csp->receive_buffer);
3573 :
3574 : /*
3575 : * Now, let the normal header parsing algorithm below do its
3576 : * job. If it fails, we'll exit instead of continuing.
3577 : */
3578 :
3579 208 : ms_iis5_hack = 1;
3580 : }
3581 :
3582 : /*
3583 : * If we're in the body of the server document, just write it to
3584 : * the client, unless we need to buffer the body for later
3585 : * content-filtering.
3586 : */
3587 14721 : if (server_body || (http->ssl
3588 : #ifdef FEATURE_HTTPS_INSPECTION
3589 1259 : && use_ssl_tunnel
3590 : #endif
3591 : ))
3592 : {
3593 3890 : if (buffer_and_filter_content)
3594 : {
3595 : /*
3596 : * If there is no memory left for buffering the content, or the buffer limit
3597 : * has been reached, switch to non-filtering mode, i.e. make & write the
3598 : * header, flush the iob and buf, and get out of the way.
3599 : */
3600 2527 : if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len))
3601 : {
3602 : size_t hdrlen;
3603 : long flushed;
3604 :
3605 0 : log_error(LOG_LEVEL_INFO,
3606 : "Flushing header and buffers. Stepping back from filtering.");
3607 :
3608 0 : hdr = list_to_text(csp->headers);
3609 0 : if (hdr == NULL)
3610 : {
3611 : /*
3612 : * Memory is too tight to even generate the header.
3613 : * Send our static "Out-of-memory" page.
3614 : */
3615 0 : log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
3616 0 : rsp = cgi_error_memory();
3617 0 : send_crunch_response(csp, rsp);
3618 0 : mark_server_socket_tainted(csp);
3619 : #ifdef FEATURE_HTTPS_INSPECTION
3620 0 : close_client_and_server_ssl_connections(csp);
3621 : #endif
3622 0 : return;
3623 : }
3624 0 : hdrlen = strlen(hdr);
3625 :
3626 : #ifdef FEATURE_HTTPS_INSPECTION
3627 : /*
3628 : * Sending data with standard or secured connection (HTTP/HTTPS)
3629 : */
3630 0 : if (client_use_ssl(csp))
3631 : {
3632 0 : if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
3633 : (const unsigned char *)hdr, hdrlen, get_write_delay(csp)) < 0)
3634 0 : || ((flushed = ssl_flush_socket(&(csp->ssl_client_attr),
3635 0 : csp->iob)) < 0)
3636 0 : || (ssl_send_data_delayed(&(csp->ssl_client_attr),
3637 0 : (const unsigned char *)csp->receive_buffer, (size_t)len,
3638 : get_write_delay(csp)) < 0))
3639 : {
3640 0 : log_error(LOG_LEVEL_CONNECT,
3641 : "Flush header and buffers to client failed");
3642 0 : freez(hdr);
3643 0 : mark_server_socket_tainted(csp);
3644 0 : close_client_and_server_ssl_connections(csp);
3645 0 : return;
3646 : }
3647 : }
3648 : else
3649 : #endif /* def FEATURE_HTTPS_INSPECTION */
3650 : {
3651 0 : if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay)
3652 0 : || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)
3653 0 : || write_socket_delayed(csp->cfd, csp->receive_buffer, (size_t)len,
3654 : write_delay))
3655 : {
3656 0 : log_error(LOG_LEVEL_CONNECT,
3657 : "Flush header and buffers to client failed: %E");
3658 0 : freez(hdr);
3659 0 : mark_server_socket_tainted(csp);
3660 0 : return;
3661 : }
3662 : }
3663 :
3664 : /*
3665 : * Reset the byte_count to the amount of bytes
3666 : * we just flushed. len will be added a few lines below,
3667 : * hdrlen doesn't matter for LOG_LEVEL_CLF.
3668 : */
3669 0 : byte_count = (unsigned long long)flushed;
3670 0 : freez(hdr);
3671 0 : buffer_and_filter_content = 0;
3672 0 : server_body = 1;
3673 : }
3674 : }
3675 : else
3676 : {
3677 : #ifdef FEATURE_HTTPS_INSPECTION
3678 : /*
3679 : * Sending data with standard or secured connection (HTTP/HTTPS)
3680 : */
3681 1363 : if (client_use_ssl(csp))
3682 : {
3683 336 : ret = ssl_send_data_delayed(&(csp->ssl_client_attr),
3684 336 : (const unsigned char *)csp->receive_buffer, (size_t)len,
3685 : get_write_delay(csp));
3686 336 : if (ret < 0)
3687 : {
3688 0 : log_error(LOG_LEVEL_ERROR,
3689 : "Sending data to client failed");
3690 0 : mark_server_socket_tainted(csp);
3691 0 : close_client_and_server_ssl_connections(csp);
3692 0 : return;
3693 : }
3694 : }
3695 : else
3696 : #endif /* def FEATURE_HTTPS_INSPECTION */
3697 : {
3698 1027 : if (write_socket_delayed(csp->cfd, csp->receive_buffer,
3699 : (size_t)len, write_delay))
3700 : {
3701 0 : log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
3702 0 : mark_server_socket_tainted(csp);
3703 0 : return;
3704 : }
3705 : }
3706 : }
3707 3890 : byte_count += (unsigned long long)len;
3708 3890 : continue;
3709 : }
3710 : else
3711 : {
3712 : /*
3713 : * We're still looking for the end of the server's header.
3714 : * Buffer up the data we just read. If that fails, there's
3715 : * little we can do but send our static out-of-memory page.
3716 : */
3717 10831 : if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len))
3718 : {
3719 0 : log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
3720 0 : rsp = cgi_error_memory();
3721 0 : send_crunch_response(csp, rsp);
3722 0 : mark_server_socket_tainted(csp);
3723 : #ifdef FEATURE_HTTPS_INSPECTION
3724 0 : close_client_and_server_ssl_connections(csp);
3725 : #endif
3726 0 : return;
3727 : }
3728 :
3729 : /* Convert iob into something sed() can digest */
3730 10831 : if (JB_ERR_PARSE == get_server_headers(csp))
3731 : {
3732 4642 : if (ms_iis5_hack)
3733 : {
3734 : /*
3735 : * Well, we tried our MS IIS/5 hack and it didn't work.
3736 : * The header is incomplete and there isn't anything
3737 : * we can do about it.
3738 : */
3739 116 : log_error(LOG_LEVEL_ERROR, "Invalid server headers. "
3740 : "Applying the MS IIS5 hack didn't help.");
3741 116 : log_error(LOG_LEVEL_CLF,
3742 : "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
3743 : #ifdef FEATURE_HTTPS_INSPECTION
3744 : /*
3745 : * Sending data with standard or secured connection (HTTP/HTTPS)
3746 : */
3747 116 : if (client_use_ssl(csp))
3748 : {
3749 24 : ssl_send_data_delayed(&(csp->ssl_client_attr),
3750 : (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
3751 : strlen(INVALID_SERVER_HEADERS_RESPONSE), get_write_delay(csp));
3752 : }
3753 : else
3754 : #endif /* def FEATURE_HTTPS_INSPECTION */
3755 : {
3756 92 : write_socket_delayed(csp->cfd,
3757 : INVALID_SERVER_HEADERS_RESPONSE,
3758 : strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
3759 : }
3760 116 : mark_server_socket_tainted(csp);
3761 : #ifdef FEATURE_HTTPS_INSPECTION
3762 116 : close_client_and_server_ssl_connections(csp);
3763 : #endif
3764 116 : return;
3765 : }
3766 : else
3767 : {
3768 : /*
3769 : * Since we have to wait for more from the server before
3770 : * we can parse the headers we just continue here.
3771 : */
3772 4526 : log_error(LOG_LEVEL_CONNECT,
3773 : "Continuing buffering server headers from socket %d. "
3774 : "Bytes most recently read: %ld.", csp->cfd, len);
3775 4526 : continue;
3776 : }
3777 : }
3778 : else
3779 : {
3780 : /*
3781 : * Account for the content bytes we
3782 : * might have gotten with the headers.
3783 : */
3784 6189 : assert(csp->iob->eod >= csp->iob->cur);
3785 6189 : byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
3786 : }
3787 :
3788 : /* Did we actually get anything? */
3789 6189 : if (NULL == csp->headers->first)
3790 : {
3791 77 : if ((csp->flags & CSP_FLAG_REUSED_CLIENT_CONNECTION))
3792 : {
3793 10 : log_error(LOG_LEVEL_ERROR,
3794 : "No server or forwarder response received on socket %d. "
3795 : "Closing client socket %d without sending data.",
3796 : csp->server_connection.sfd, csp->cfd);
3797 10 : log_error(LOG_LEVEL_CLF,
3798 : "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
3799 : }
3800 : else
3801 : {
3802 67 : log_error(LOG_LEVEL_ERROR,
3803 : "No server or forwarder response received on socket %d.",
3804 : csp->server_connection.sfd);
3805 67 : send_crunch_response(csp, error_response(csp, "no-server-data"));
3806 : }
3807 77 : free_http_request(http);
3808 77 : mark_server_socket_tainted(csp);
3809 : #ifdef FEATURE_HTTPS_INSPECTION
3810 77 : close_client_and_server_ssl_connections(csp);
3811 : #endif
3812 77 : return;
3813 : }
3814 :
3815 6112 : if (!csp->headers->first->str)
3816 : {
3817 0 : log_error(LOG_LEVEL_ERROR, "header search: csp->headers->first->str == NULL, assert will be called");
3818 : }
3819 6112 : assert(csp->headers->first->str);
3820 :
3821 6225 : if (strncmpic(csp->headers->first->str, "HTTP", 4) &&
3822 113 : strncmpic(csp->headers->first->str, "ICY", 3))
3823 : {
3824 : /*
3825 : * It doesn't look like a HTTP (or Shoutcast) response:
3826 : * tell the client and log the problem.
3827 : */
3828 103 : if (strlen(csp->headers->first->str) > 30)
3829 : {
3830 38 : csp->headers->first->str[30] = '\0';
3831 : }
3832 103 : log_error(LOG_LEVEL_ERROR,
3833 : "Invalid server or forwarder response. Starts with: %s",
3834 103 : csp->headers->first->str);
3835 103 : log_error(LOG_LEVEL_CLF,
3836 : "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
3837 : #ifdef FEATURE_HTTPS_INSPECTION
3838 : /*
3839 : * Sending data with standard or secured connection (HTTP/HTTPS)
3840 : */
3841 103 : if (client_use_ssl(csp))
3842 : {
3843 4 : ssl_send_data_delayed(&(csp->ssl_client_attr),
3844 : (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
3845 : strlen(INVALID_SERVER_HEADERS_RESPONSE),
3846 : get_write_delay(csp));
3847 : }
3848 : else
3849 : #endif /* def FEATURE_HTTPS_INSPECTION */
3850 : {
3851 99 : write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
3852 : strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
3853 : }
3854 103 : free_http_request(http);
3855 103 : mark_server_socket_tainted(csp);
3856 : #ifdef FEATURE_HTTPS_INSPECTION
3857 103 : close_client_and_server_ssl_connections(csp);
3858 : #endif
3859 103 : return;
3860 : }
3861 :
3862 : /*
3863 : * We have now received the entire server header,
3864 : * filter it and send the result to the client
3865 : */
3866 6009 : if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS))
3867 : {
3868 25 : log_error(LOG_LEVEL_CLF,
3869 : "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
3870 : #ifdef FEATURE_HTTPS_INSPECTION
3871 : /*
3872 : * Sending data with standard or secured connection (HTTP/HTTPS)
3873 : */
3874 25 : if (client_use_ssl(csp))
3875 : {
3876 3 : ssl_send_data_delayed(&(csp->ssl_client_attr),
3877 : (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
3878 : strlen(INVALID_SERVER_HEADERS_RESPONSE),
3879 : get_write_delay(csp));
3880 : }
3881 : else
3882 : #endif
3883 : {
3884 22 : write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
3885 : strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
3886 : }
3887 25 : free_http_request(http);
3888 25 : mark_server_socket_tainted(csp);
3889 : #ifdef FEATURE_HTTPS_INSPECTION
3890 25 : close_client_and_server_ssl_connections(csp);
3891 : #endif
3892 25 : return;
3893 : }
3894 5984 : hdr = list_to_text(csp->headers);
3895 5984 : if (hdr == NULL)
3896 : {
3897 : /* FIXME Should handle error properly */
3898 0 : log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
3899 : }
3900 :
3901 5984 : if ((csp->flags & CSP_FLAG_CHUNKED)
3902 2578 : && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
3903 2564 : && ((csp->iob->eod - csp->iob->cur) >= 5)
3904 2142 : && !memcmp(csp->iob->eod-5, "0\r\n\r\n", 5))
3905 : {
3906 1777 : log_error(LOG_LEVEL_CONNECT,
3907 : "Looks like we got the last chunk together with "
3908 : "the server headers. We better stop reading.");
3909 1777 : byte_count = (unsigned long long)(csp->iob->eod - csp->iob->cur);
3910 1777 : csp->expected_content_length = byte_count;
3911 1777 : csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
3912 : }
3913 :
3914 5984 : csp->server_connection.response_received = time(NULL);
3915 :
3916 5984 : if (crunch_response_triggered(csp, crunchers_light))
3917 : {
3918 : /*
3919 : * One of the tags created by a server-header
3920 : * tagger triggered a crunch. We already
3921 : * delivered the crunch response to the client
3922 : * and are done here after cleaning up.
3923 : */
3924 0 : freez(hdr);
3925 0 : mark_server_socket_tainted(csp);
3926 : #ifdef FEATURE_HTTPS_INSPECTION
3927 0 : close_client_and_server_ssl_connections(csp);
3928 : #endif
3929 0 : return;
3930 : }
3931 :
3932 : /* Buffer and pcrs filter this if appropriate. */
3933 5984 : buffer_and_filter_content = content_requires_filtering(csp);
3934 :
3935 5984 : if (!buffer_and_filter_content)
3936 : {
3937 : /*
3938 : * Write the server's (modified) header to
3939 : * the client (along with anything else that
3940 : * may be in the buffer). Use standard or secured
3941 : * connection.
3942 : */
3943 : #ifdef FEATURE_HTTPS_INSPECTION
3944 1352 : if (client_use_ssl(csp))
3945 : {
3946 28 : if ((ssl_send_data_delayed(&(csp->ssl_client_attr),
3947 : (const unsigned char *)hdr, strlen(hdr),
3948 : get_write_delay(csp)) < 0)
3949 28 : || ((len = ssl_flush_socket(&(csp->ssl_client_attr),
3950 28 : csp->iob)) < 0))
3951 : {
3952 0 : log_error(LOG_LEVEL_CONNECT, "Write header to client failed");
3953 :
3954 : /*
3955 : * The write failed, so don't bother mentioning it
3956 : * to the client... it probably can't hear us anyway.
3957 : */
3958 0 : freez(hdr);
3959 0 : mark_server_socket_tainted(csp);
3960 : #ifdef FEATURE_HTTPS_INSPECTION
3961 0 : close_client_and_server_ssl_connections(csp);
3962 : #endif
3963 0 : return;
3964 : }
3965 : }
3966 : else
3967 : #endif /* def FEATURE_HTTPS_INSPECTION */
3968 : {
3969 1324 : if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
3970 1324 : || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0))
3971 : {
3972 0 : log_error(LOG_LEVEL_ERROR,
3973 : "write header to client failed");
3974 : /*
3975 : * The write failed, so don't bother mentioning it
3976 : * to the client... it probably can't hear us anyway.
3977 : */
3978 0 : freez(hdr);
3979 0 : mark_server_socket_tainted(csp);
3980 0 : return;
3981 : }
3982 : }
3983 : }
3984 :
3985 : /* we're finished with the server's header */
3986 :
3987 5984 : freez(hdr);
3988 5984 : server_body = 1;
3989 :
3990 : /*
3991 : * If this was a MS IIS/5 hack then it means the server
3992 : * has already closed the connection. Nothing more to read.
3993 : * Time to bail.
3994 : */
3995 5984 : if (ms_iis5_hack)
3996 : {
3997 25 : log_error(LOG_LEVEL_ERROR,
3998 : "Closed server connection detected. "
3999 : "Applying the MS IIS5 hack didn't help.");
4000 25 : log_error(LOG_LEVEL_CLF,
4001 : "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
4002 : #ifdef FEATURE_HTTPS_INSPECTION
4003 : /*
4004 : * Sending data with standard or secured connection (HTTP/HTTPS)
4005 : */
4006 25 : if (client_use_ssl(csp))
4007 : {
4008 1 : ssl_send_data_delayed(&(csp->ssl_client_attr),
4009 : (const unsigned char *)INVALID_SERVER_HEADERS_RESPONSE,
4010 : strlen(INVALID_SERVER_HEADERS_RESPONSE),
4011 : get_write_delay(csp));
4012 : }
4013 : else
4014 : #endif /* def FEATURE_HTTPS_INSPECTION */
4015 : {
4016 24 : write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
4017 : strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
4018 : }
4019 25 : mark_server_socket_tainted(csp);
4020 : #ifdef FEATURE_HTTPS_INSPECTION
4021 25 : close_client_and_server_ssl_connections(csp);
4022 : #endif
4023 25 : return;
4024 : }
4025 : }
4026 5959 : continue;
4027 : }
4028 0 : mark_server_socket_tainted(csp);
4029 : #ifdef FEATURE_HTTPS_INSPECTION
4030 0 : close_client_and_server_ssl_connections(csp);
4031 : #endif
4032 0 : return; /* huh? we should never get here */
4033 : }
4034 :
4035 6029 : if (csp->content_length == 0)
4036 : {
4037 : /*
4038 : * If Privoxy didn't recalculate the Content-Length,
4039 : * byte_count is still correct.
4040 : */
4041 3032 : csp->content_length = byte_count;
4042 : }
4043 :
4044 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4045 6029 : if ((csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)
4046 2635 : && (csp->expected_content_length != byte_count))
4047 : {
4048 139 : log_error(LOG_LEVEL_CONNECT,
4049 : "Received %llu bytes while expecting %llu.",
4050 : byte_count, csp->expected_content_length);
4051 139 : mark_server_socket_tainted(csp);
4052 : }
4053 : #endif
4054 :
4055 : #ifdef FEATURE_HTTPS_INSPECTION
4056 6029 : if (client_use_ssl(csp))
4057 : {
4058 135 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s https://%s%s %s\" 200 %llu",
4059 : csp->ip_addr_str, http->gpc, http->hostport, http->path,
4060 : http->version, csp->content_length);
4061 : }
4062 : else
4063 : #endif
4064 : {
4065 5894 : log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu",
4066 : csp->ip_addr_str, http->ocmd, csp->content_length);
4067 : }
4068 6029 : csp->server_connection.timestamp = time(NULL);
4069 : }
4070 :
4071 :
4072 : /*********************************************************************
4073 : *
4074 : * Function : chat
4075 : *
4076 : * Description : Once a connection from the client has been accepted,
4077 : * this function is called (via serve()) to handle the
4078 : * main business of the communication. This function
4079 : * returns after dealing with a single request. It can
4080 : * be called multiple times with the same client socket
4081 : * if the client is keeping the connection alive.
4082 : *
4083 : * The decision whether or not a client connection will
4084 : * be kept alive is up to the caller which also must
4085 : * close the client socket when done.
4086 : *
4087 : * FIXME: chat is nearly thousand lines long.
4088 : * Ridiculous.
4089 : *
4090 : * Parameters :
4091 : * 1 : csp = Current client state (buffers, headers, etc...)
4092 : *
4093 : * Returns : Nothing.
4094 : *
4095 : *********************************************************************/
4096 32220 : static void chat(struct client_state *csp)
4097 : {
4098 : const struct forward_spec *fwd;
4099 : struct http_request *http;
4100 : /* Skeleton for HTTP response, if we should intercept the request */
4101 : struct http_response *rsp;
4102 : #ifdef FEATURE_HTTPS_INSPECTION
4103 32220 : int use_ssl_tunnel = 0;
4104 : #endif
4105 :
4106 32220 : http = csp->http;
4107 :
4108 32220 : if (receive_client_request(csp) != JB_ERR_OK)
4109 : {
4110 1043 : return;
4111 : }
4112 31177 : if (parse_client_request(csp) != JB_ERR_OK)
4113 : {
4114 59 : return;
4115 : }
4116 :
4117 : /* decide how to route the HTTP request */
4118 31118 : fwd = forward_url(csp, http);
4119 :
4120 : #ifdef FEATURE_HTTPS_INSPECTION
4121 : /*
4122 : * Setting flags to use old solution with SSL tunnel and to disable
4123 : * certificate verification.
4124 : */
4125 31118 : if (csp->http->ssl && !(csp->action->flags & ACTION_HTTPS_INSPECTION)
4126 41 : && !cgi_page_requested(csp->http->host))
4127 : {
4128 21 : use_ssl_tunnel = 1;
4129 : }
4130 :
4131 31118 : if (http->ssl && (csp->action->flags & ACTION_IGNORE_CERTIFICATE_ERRORS))
4132 : {
4133 410 : csp->dont_verify_certificate = 1;
4134 : }
4135 : #endif
4136 :
4137 : /*
4138 : * build the http request to send to the server
4139 : * we have to do one of the following:
4140 : *
4141 : * create = use the original HTTP request to create a new
4142 : * HTTP request that has either the path component
4143 : * without the http://domainspec (w/path) or the
4144 : * full orininal URL (w/url)
4145 : * Note that the path and/or the HTTP version may
4146 : * have been altered by now.
4147 : *
4148 : * SSL proxy = Open a socket to the host:port of the server
4149 : * and create TLS/SSL connection with server and
4150 : * with client. Then behave like mediator between
4151 : * client and server over TLS/SSL.
4152 : *
4153 : * SSL proxy = Pass the request unchanged if forwarding a CONNECT
4154 : * with request to a parent proxy. Note that we'll be sending
4155 : * forwarding the CFAIL message ourselves if connecting to the parent
4156 : * fails, but we won't send a CSUCCEED message if it works,
4157 : * since that would result in a double message (ours and the
4158 : * parent's). After sending the request to the parent, we
4159 : * must parse answer and send it to client. If connection
4160 : * with server is established, we do TLS/SSL proxy. Otherwise
4161 : * we send parent response to client and close connections.
4162 : *
4163 : * here's the matrix:
4164 : * SSL
4165 : * 0 1
4166 : * +--------+--------+
4167 : * | | |
4168 : * 0 | create | SSL |
4169 : * | w/path | proxy |
4170 : * Forwarding +--------+--------+
4171 : * | | SSL |
4172 : * 1 | create | proxy |
4173 : * | w/url |+forward|
4174 : * +--------+--------+
4175 : *
4176 : */
4177 :
4178 : #ifdef FEATURE_HTTPS_INSPECTION
4179 : /*
4180 : * Presetting SSL client and server flags
4181 : */
4182 31118 : if (http->ssl && !use_ssl_tunnel)
4183 : {
4184 432 : http->client_ssl = 1;
4185 432 : http->server_ssl = 1;
4186 : }
4187 : else
4188 : {
4189 30686 : http->client_ssl = 0;
4190 30686 : http->server_ssl = 0;
4191 : }
4192 : #endif
4193 :
4194 : #ifdef FEATURE_HTTPS_INSPECTION
4195 : /*
4196 : * Log the request unless we're https inspecting
4197 : * in which case we don't have the path yet and
4198 : * will log the request later.
4199 : */
4200 31118 : if (!client_use_ssl(csp))
4201 : #endif
4202 : {
4203 30686 : log_error(LOG_LEVEL_REQUEST, "%s%s", http->hostport, http->path);
4204 : }
4205 :
4206 31118 : if (http->ssl && connect_port_is_forbidden(csp))
4207 : {
4208 98 : const char *acceptable_connect_ports =
4209 : csp->action->string[ACTION_STRING_LIMIT_CONNECT];
4210 98 : assert(NULL != acceptable_connect_ports);
4211 98 : log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. "
4212 : "limit-connect{%s} doesn't allow CONNECT requests to %s",
4213 : csp->ip_addr_str, acceptable_connect_ports, csp->http->hostport);
4214 98 : csp->action->flags |= ACTION_BLOCK;
4215 98 : http->ssl = 0;
4216 : #ifdef FEATURE_HTTPS_INSPECTION
4217 98 : http->client_ssl = 0;
4218 98 : http->server_ssl = 0;
4219 : #endif
4220 : }
4221 :
4222 :
4223 31118 : freez(csp->headers->first->str);
4224 31118 : build_request_line(csp, fwd, &csp->headers->first->str);
4225 :
4226 : /*
4227 : * We have a request. Check if one of the crunchers wants it
4228 : * unless the client wants to use TLS/SSL in which case we
4229 : * haven't setup the TLS context yet and will send the crunch
4230 : * response later.
4231 : */
4232 31118 : if (
4233 : #ifdef FEATURE_HTTPS_INSPECTION
4234 61902 : !client_use_ssl(csp) &&
4235 : #endif
4236 30784 : crunch_response_triggered(csp, crunchers_all))
4237 : {
4238 : /*
4239 : * Yes. The client got the crunch response and we're done here.
4240 : */
4241 24455 : return;
4242 : }
4243 :
4244 6663 : log_applied_actions(csp->action);
4245 6663 : if (fwd->forward_host)
4246 : {
4247 0 : log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
4248 : fwd->forward_host, fwd->forward_port, http->hostport);
4249 : }
4250 : else
4251 : {
4252 6663 : log_error(LOG_LEVEL_CONNECT, "to %s", http->hostport);
4253 : }
4254 :
4255 : /* here we connect to the server, gateway, or the forwarder */
4256 :
4257 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4258 6663 : if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
4259 196 : && socket_is_still_alive(csp->server_connection.sfd)
4260 193 : && connection_destination_matches(&csp->server_connection, http, fwd))
4261 : {
4262 22 : log_error(LOG_LEVEL_CONNECT,
4263 : "Reusing server socket %d connected to %s. Total requests: %u.",
4264 : csp->server_connection.sfd, csp->server_connection.host,
4265 : csp->server_connection.requests_sent_total);
4266 : }
4267 : else
4268 : {
4269 6641 : if (csp->server_connection.sfd != JB_INVALID_SOCKET)
4270 : {
4271 : #ifdef FEATURE_CONNECTION_SHARING
4272 174 : if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING
4273 : #ifdef FEATURE_HTTPS_INSPECTION
4274 0 : && !server_use_ssl(csp)
4275 : #endif
4276 : )
4277 : {
4278 0 : remember_connection(&csp->server_connection);
4279 : }
4280 : else
4281 : #endif /* def FEATURE_CONNECTION_SHARING */
4282 : {
4283 174 : log_error(LOG_LEVEL_CONNECT,
4284 : "Closing server socket %d connected to %s. Total requests: %u.",
4285 : csp->server_connection.sfd, csp->server_connection.host,
4286 : csp->server_connection.requests_sent_total);
4287 174 : close_socket(csp->server_connection.sfd);
4288 : }
4289 174 : mark_connection_closed(&csp->server_connection);
4290 : }
4291 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
4292 : #ifdef FEATURE_HTTPS_INSPECTION
4293 6641 : if (client_use_ssl(csp) && !use_ssl_tunnel)
4294 : {
4295 : int ret;
4296 : /*
4297 : * Creating a SSL proxy.
4298 : *
4299 : * By sending the CSUCCEED message we're lying to the client as
4300 : * the connection hasn't actually been established yet. We don't
4301 : * establish the connection until we have seen and parsed the
4302 : * encrypted client headers.
4303 : */
4304 334 : if (write_socket_delayed(csp->cfd, CSUCCEED,
4305 : strlen(CSUCCEED), get_write_delay(csp)) != 0)
4306 : {
4307 0 : log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed");
4308 0 : return;
4309 : }
4310 :
4311 334 : ret = create_client_ssl_connection(csp);
4312 334 : if (ret != 0)
4313 : {
4314 0 : log_error(LOG_LEVEL_ERROR,
4315 : "Failed to open a secure connection with the client");
4316 0 : return;
4317 : }
4318 334 : if (JB_ERR_OK != process_encrypted_request(csp))
4319 : {
4320 40 : close_client_ssl_connection(csp);
4321 40 : return;
4322 : }
4323 : /*
4324 : * We have an encrypted request. Check if one of the crunchers now
4325 : * wants it (for example because the previously invisible path was
4326 : * required to match).
4327 : */
4328 294 : if (crunch_response_triggered(csp, crunchers_all))
4329 : {
4330 : /*
4331 : * Yes. The client got the crunch response and we're done here.
4332 : */
4333 127 : return;
4334 : }
4335 : }
4336 : #endif
4337 : /*
4338 : * Connecting to destination server
4339 : */
4340 6474 : csp->server_connection.sfd = forwarded_connect(fwd, http, csp);
4341 :
4342 6474 : if (csp->server_connection.sfd == JB_INVALID_SOCKET)
4343 : {
4344 0 : if (fwd->type != SOCKS_NONE)
4345 : {
4346 : /* Socks error. */
4347 0 : rsp = error_response(csp, "forwarding-failed");
4348 : }
4349 0 : else if (errno == EINVAL)
4350 : {
4351 0 : rsp = error_response(csp, "no-such-domain");
4352 : }
4353 : else
4354 : {
4355 0 : rsp = error_response(csp, "connect-failed");
4356 : }
4357 :
4358 : /* Write the answer to the client */
4359 0 : if (rsp != NULL)
4360 : {
4361 0 : send_crunch_response(csp, rsp);
4362 : }
4363 :
4364 : /*
4365 : * Temporary workaround to prevent already-read client
4366 : * bodies from being parsed as new requests. For now we
4367 : * err on the safe side and throw all the following
4368 : * requests under the bus, even if no client body has been
4369 : * buffered. A compliant client will repeat the dropped
4370 : * requests on an untainted connection.
4371 : *
4372 : * The proper fix is to discard the no longer needed
4373 : * client body in the buffer (if there is one) and to
4374 : * continue parsing the bytes that follow.
4375 : */
4376 : #ifdef FEATURE_HTTPS_INSPECTION
4377 0 : close_client_ssl_connection(csp);
4378 : #endif
4379 0 : drain_and_close_socket(csp->cfd);
4380 0 : csp->cfd = JB_INVALID_SOCKET;
4381 :
4382 0 : return;
4383 : }
4384 :
4385 : #ifdef FEATURE_HTTPS_INSPECTION
4386 : /*
4387 : * Creating TLS/SSL connections with destination server or parent
4388 : * proxy. If forwarding is enabled, we must send client request to
4389 : * parent proxy and receive, parse and resend parent proxy answer.
4390 : */
4391 6474 : if (http->ssl && !use_ssl_tunnel)
4392 : {
4393 159 : if (fwd->forward_host != NULL)
4394 : {
4395 : char server_response[BUFFER_SIZE];
4396 0 : int ret = 0;
4397 0 : int len = 0;
4398 0 : char *hdr = list_to_text(csp->headers);
4399 0 : memset(server_response, 0, sizeof(server_response));
4400 :
4401 0 : if (hdr == NULL)
4402 : {
4403 0 : log_error(LOG_LEVEL_FATAL,
4404 : "Out of memory parsing client header");
4405 : }
4406 0 : list_remove_all(csp->headers);
4407 :
4408 : /*
4409 : * Sending client's CONNECT request to the parent proxy
4410 : */
4411 0 : ret = write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
4412 :
4413 0 : freez(hdr);
4414 :
4415 0 : if (ret != 0)
4416 : {
4417 0 : log_error(LOG_LEVEL_CONNECT,
4418 : "Sending request headers to: %s failed", http->hostport);
4419 0 : mark_server_socket_tainted(csp);
4420 0 : close_client_ssl_connection(csp);
4421 0 : return;
4422 : }
4423 :
4424 : /* Waiting for parent proxy server response */
4425 0 : len = read_socket(csp->server_connection.sfd, server_response,
4426 : sizeof(server_response)-1);
4427 :
4428 0 : if (len <= 0)
4429 : {
4430 0 : log_error(LOG_LEVEL_ERROR, "No response from parent proxy "
4431 : "server on socket %d.", csp->server_connection.sfd);
4432 :
4433 0 : rsp = error_response(csp, "no-server-data");
4434 0 : if (rsp)
4435 : {
4436 0 : send_crunch_response(csp, rsp);
4437 : }
4438 0 : mark_server_socket_tainted(csp);
4439 0 : close_client_ssl_connection(csp);
4440 0 : return;
4441 : }
4442 :
4443 : /*
4444 : * Test if the connection to the destination server was
4445 : * established successfully by the parent proxy.
4446 : */
4447 0 : if (!tunnel_established_successfully(server_response, (unsigned int)len))
4448 : {
4449 0 : log_error(LOG_LEVEL_ERROR,
4450 : "The forwarder %s failed to establish a connection with %s",
4451 : fwd->forward_host, http->host);
4452 0 : rsp = error_response(csp, "connect-failed");
4453 0 : if (rsp)
4454 : {
4455 0 : send_crunch_response(csp, rsp);
4456 : }
4457 0 : mark_server_socket_tainted(csp);
4458 0 : close_client_ssl_connection(csp);
4459 0 : return;
4460 : }
4461 : } /* -END- if (fwd->forward_host != NULL) */
4462 :
4463 : /*
4464 : * We can now create the TLS/SSL connection with the destination server.
4465 : */
4466 159 : int ret = 0;
4467 159 : csp->ssl_with_server_is_opened = 1;// int ret = create_server_ssl_connection(csp);
4468 159 : if (ret != 0)
4469 : {
4470 0 : if (csp->server_cert_verification_result != SSL_CERT_VALID &&
4471 0 : csp->server_cert_verification_result != SSL_CERT_NOT_VERIFIED)
4472 : {
4473 : /*
4474 : * If the server certificate is invalid, we must inform
4475 : * the client and then close connection to the client.
4476 : */
4477 0 : ssl_send_certificate_error(csp);
4478 0 : close_client_and_server_ssl_connections(csp);
4479 0 : return;
4480 : }
4481 0 : if (csp->server_cert_verification_result == SSL_CERT_NOT_VERIFIED
4482 0 : || csp->server_cert_verification_result == SSL_CERT_VALID)
4483 : {
4484 : /*
4485 : * The TLS/SSL connection wasn't created but an invalid
4486 : * certificate wasn't detected. Report it as connection
4487 : * failure.
4488 : */
4489 0 : rsp = error_response(csp, "connect-failed");
4490 0 : if (rsp)
4491 : {
4492 0 : send_crunch_response(csp, rsp);
4493 : }
4494 0 : close_client_and_server_ssl_connections(csp);
4495 0 : return;
4496 : }
4497 : }
4498 :
4499 : }/* -END- if (http->ssl) */
4500 : #endif /* def FEATURE_HTTPS_INSPECTION */
4501 :
4502 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4503 6474 : save_connection_destination(csp->server_connection.sfd,
4504 : http, fwd, &csp->server_connection);
4505 6474 : csp->server_connection.keep_alive_timeout =
4506 6474 : (unsigned)csp->config->keep_alive_timeout;
4507 : }
4508 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
4509 :
4510 6496 : csp->server_connection.requests_sent_total++;
4511 :
4512 6496 : if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first))
4513 : {
4514 : /* Client headers have been sent optimistically */
4515 0 : assert(csp->headers->last == NULL);
4516 : }
4517 6496 : else if (http->ssl == 0 || (fwd->forward_host
4518 : #ifdef FEATURE_HTTPS_INSPECTION
4519 0 : && use_ssl_tunnel
4520 : #endif
4521 : ))
4522 : {
4523 6316 : if (send_http_request(csp))
4524 : {
4525 24 : rsp = error_response(csp, "connect-failed");
4526 24 : if (rsp)
4527 : {
4528 24 : send_crunch_response(csp, rsp);
4529 : }
4530 24 : return;
4531 : }
4532 : }
4533 : else
4534 : {
4535 : /*
4536 : * Using old solution with SSL tunnel or new solution with SSL proxy
4537 : */
4538 180 : list_remove_all(csp->headers);
4539 : #ifdef FEATURE_HTTPS_INSPECTION
4540 180 : if (use_ssl_tunnel)
4541 : #endif
4542 : {
4543 : /*
4544 : * We're running an SSL tunnel and we're not forwarding,
4545 : * so just ditch the client headers, send the "connect succeeded"
4546 : * message to the client, flush the rest, and get out of the way.
4547 : */
4548 21 : if (write_socket_delayed(csp->cfd, CSUCCEED,
4549 : strlen(CSUCCEED), get_write_delay(csp)))
4550 : {
4551 0 : return;
4552 : }
4553 : }
4554 : #ifdef FEATURE_HTTPS_INSPECTION
4555 : else
4556 : {
4557 : /*
4558 : * If server certificate has been verified and is invalid,
4559 : * we must inform the client and then close the connection
4560 : * with client and server.
4561 : */
4562 : /* if (csp->server_cert_verification_result != SSL_CERT_VALID &&
4563 : csp->server_cert_verification_result != SSL_CERT_NOT_VERIFIED)
4564 : {
4565 : ssl_send_certificate_error(csp);
4566 : close_client_and_server_ssl_connections(csp);
4567 : return;
4568 : }
4569 : */
4570 159 : if (send_https_request(csp))
4571 : {
4572 17 : rsp = error_response(csp, "connect-failed");
4573 17 : if (rsp)
4574 : {
4575 17 : send_crunch_response(csp, rsp);
4576 : }
4577 17 : close_client_and_server_ssl_connections(csp);
4578 17 : return;
4579 : }
4580 : }
4581 : #endif /* def FEATURE_HTTPS_INSPECTION */
4582 163 : clear_iob(csp->client_iob);
4583 : }/* -END- else ... if (http->ssl == 1) */
4584 :
4585 6455 : log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport);
4586 :
4587 : /* XXX: should the time start earlier for optimistically sent data? */
4588 6455 : csp->server_connection.request_sent = time(NULL);
4589 :
4590 6455 : handle_established_connection(csp);
4591 6455 : freez(csp->receive_buffer);
4592 : }
4593 :
4594 :
4595 : #ifdef FUZZ
4596 : /*********************************************************************
4597 : *
4598 : * Function : fuzz_server_response
4599 : *
4600 : * Description : Treat the input as a whole server response.
4601 : *
4602 : * Parameters :
4603 : * 1 : csp = Current client state (buffers, headers, etc...)
4604 : * 2 : fuzz_input_file = File to read the input from.
4605 : *
4606 : * Returns : 0
4607 : *
4608 : *********************************************************************/
4609 0 : extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file)
4610 : {
4611 : static struct forward_spec fwd; /* Zero'd due to being static */
4612 0 : csp->cfd = 0;
4613 :
4614 0 : if (strcmp(fuzz_input_file, "-") == 0)
4615 : {
4616 : /* XXX: Doesn't work yet. */
4617 0 : csp->server_connection.sfd = 0;
4618 : }
4619 : else
4620 : {
4621 0 : csp->server_connection.sfd = open(fuzz_input_file, O_RDONLY);
4622 0 : if (csp->server_connection.sfd == -1)
4623 : {
4624 0 : log_error(LOG_LEVEL_FATAL, "Failed to open %s: %E",
4625 : fuzz_input_file);
4626 : }
4627 : }
4628 0 : csp->fwd = &fwd;
4629 0 : csp->content_type |= CT_GIF;
4630 0 : csp->action->flags |= ACTION_DEANIMATE;
4631 0 : csp->action->string[ACTION_STRING_DEANIMATE] = "last";
4632 :
4633 0 : csp->http->path = strdup_or_die("/");
4634 0 : csp->http->host = strdup_or_die("fuzz.example.org");
4635 0 : csp->http->hostport = strdup_or_die("fuzz.example.org:80");
4636 : /* Prevent client socket monitoring */
4637 0 : csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
4638 0 : csp->flags |= CSP_FLAG_CHUNKED;
4639 :
4640 0 : csp->config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
4641 0 : csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
4642 :
4643 0 : csp->content_type |= CT_DECLARED|CT_GIF;
4644 :
4645 0 : csp->config->socket_timeout = 0;
4646 :
4647 0 : cgi_init_error_messages();
4648 :
4649 0 : handle_established_connection(csp);
4650 0 : freez(csp->receive_buffer);
4651 :
4652 0 : return 0;
4653 : }
4654 : #endif
4655 :
4656 :
4657 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4658 : /*********************************************************************
4659 : *
4660 : * Function : prepare_csp_for_next_request
4661 : *
4662 : * Description : Put the csp in a mostly vergin state.
4663 : *
4664 : * Parameters :
4665 : * 1 : csp = Current client state (buffers, headers, etc...)
4666 : *
4667 : * Returns : N/A
4668 : *
4669 : *********************************************************************/
4670 31040 : static void prepare_csp_for_next_request(struct client_state *csp)
4671 : {
4672 31040 : csp->content_type = 0;
4673 31040 : csp->content_length = 0;
4674 31040 : csp->expected_content_length = 0;
4675 31040 : csp->expected_client_content_length = 0;
4676 31040 : list_remove_all(csp->headers);
4677 31040 : clear_iob(csp->iob);
4678 31040 : freez(csp->error_message);
4679 31040 : free_http_request(csp->http);
4680 31040 : destroy_list(csp->headers);
4681 : #ifdef FEATURE_HTTPS_INSPECTION
4682 31040 : destroy_list(csp->https_headers);
4683 : #endif
4684 31040 : destroy_list(csp->tags);
4685 : #ifdef FEATURE_CLIENT_TAGS
4686 31040 : destroy_list(csp->client_tags);
4687 31040 : freez(csp->client_address);
4688 : #endif
4689 31040 : free_current_action(csp->action);
4690 31040 : if (NULL != csp->fwd)
4691 : {
4692 0 : unload_forward_spec(csp->fwd);
4693 0 : csp->fwd = NULL;
4694 : }
4695 : /* XXX: Store per-connection flags someplace else. */
4696 31040 : csp->flags = (CSP_FLAG_ACTIVE | CSP_FLAG_REUSED_CLIENT_CONNECTION);
4697 : #ifdef FEATURE_TOGGLE
4698 31040 : if (global_toggle_state)
4699 : #endif /* def FEATURE_TOGGLE */
4700 : {
4701 29835 : csp->flags |= CSP_FLAG_TOGGLED_ON;
4702 : }
4703 :
4704 31040 : if (csp->client_iob->eod > csp->client_iob->cur)
4705 : {
4706 11356 : long bytes_to_shift = csp->client_iob->cur - csp->client_iob->buf;
4707 11356 : size_t data_length = (size_t)(csp->client_iob->eod - csp->client_iob->cur);
4708 :
4709 11356 : assert(bytes_to_shift > 0);
4710 11356 : assert(data_length > 0);
4711 :
4712 11356 : log_error(LOG_LEVEL_CONNECT, "Shifting %lu pipelined bytes by %ld bytes",
4713 : data_length, bytes_to_shift);
4714 11356 : memmove(csp->client_iob->buf, csp->client_iob->cur, data_length);
4715 11356 : csp->client_iob->cur = csp->client_iob->buf;
4716 11356 : assert(csp->client_iob->eod == csp->client_iob->buf + bytes_to_shift + data_length);
4717 11356 : csp->client_iob->eod = csp->client_iob->buf + data_length;
4718 11356 : memset(csp->client_iob->eod, '\0', (size_t)bytes_to_shift);
4719 :
4720 11356 : csp->flags |= CSP_FLAG_PIPELINED_REQUEST_WAITING;
4721 : }
4722 : else
4723 : {
4724 : /*
4725 : * We mainly care about resetting client_iob->cur so we don't
4726 : * waste buffer space at the beginning and don't mess up the
4727 : * request restoration done by cgi_show_request().
4728 : *
4729 : * Freeing the buffer itself isn't technically necessary,
4730 : * but makes debugging more convenient.
4731 : */
4732 19684 : clear_iob(csp->client_iob);
4733 : }
4734 31040 : }
4735 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
4736 :
4737 :
4738 : /*********************************************************************
4739 : *
4740 : * Function : serve
4741 : *
4742 : * Description : This is little more than chat. We only "serve" to
4743 : * to close (or remember) any socket that chat may have
4744 : * opened.
4745 : *
4746 : * Parameters :
4747 : * 1 : csp = Current client state (buffers, headers, etc...)
4748 : *
4749 : * Returns : N/A
4750 : *
4751 : *********************************************************************/
4752 3098 : static void serve(struct client_state *csp)
4753 : {
4754 3098 : int config_file_change_detected = 0; /* Only used for debugging */
4755 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4756 : #ifdef FEATURE_CONNECTION_SHARING
4757 : static int monitor_thread_running = 0;
4758 : #endif /* def FEATURE_CONNECTION_SHARING */
4759 3098 : int continue_chatting = 0;
4760 :
4761 3098 : log_error(LOG_LEVEL_CONNECT, "Accepted connection from %s on socket %d",
4762 : csp->ip_addr_str, csp->cfd);
4763 : do
4764 : {
4765 : unsigned int latency;
4766 : #ifdef FEATURE_HTTPS_INSPECTION
4767 34138 : if (continue_chatting && client_use_ssl(csp))
4768 : {
4769 1918 : continue_https_chat(csp);
4770 : }
4771 : else
4772 : #endif
4773 : {
4774 32220 : chat(csp);
4775 : }
4776 :
4777 : /*
4778 : * If the request has been crunched,
4779 : * the calculated latency is zero.
4780 : */
4781 34138 : latency = (unsigned)(csp->server_connection.response_received -
4782 34138 : csp->server_connection.request_sent) / 2;
4783 :
4784 34138 : if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
4785 32438 : && (csp->flags & CSP_FLAG_CRUNCHED)
4786 26057 : && (csp->expected_client_content_length != 0))
4787 : {
4788 26 : csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED;
4789 26 : log_error(LOG_LEVEL_CONNECT,
4790 : "Tainting client socket %d due to unread data.", csp->cfd);
4791 : }
4792 :
4793 68276 : continue_chatting = (csp->config->feature_flags
4794 34138 : & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
4795 34138 : && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
4796 33159 : && (csp->cfd != JB_INVALID_SOCKET)
4797 33159 : && (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
4798 69783 : && ((csp->flags & CSP_FLAG_SERVER_CONTENT_LENGTH_SET)
4799 1507 : || (csp->flags & CSP_FLAG_CHUNKED));
4800 :
4801 34138 : if (!(csp->flags & CSP_FLAG_CRUNCHED)
4802 7810 : && (csp->server_connection.sfd != JB_INVALID_SOCKET))
4803 : {
4804 6543 : if (!(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET))
4805 : {
4806 6285 : csp->server_connection.keep_alive_timeout = csp->config->default_server_timeout;
4807 : }
4808 6543 : if (!(csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
4809 4974 : || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)
4810 4802 : || !socket_is_still_alive(csp->server_connection.sfd)
4811 4686 : || !(latency < csp->server_connection.keep_alive_timeout))
4812 : {
4813 6298 : log_error(LOG_LEVEL_CONNECT,
4814 : "Closing server socket %d connected to %s. "
4815 : "Keep-alive: %u. Tainted: %u. Socket alive: %u. Timeout: %u.",
4816 : csp->server_connection.sfd, csp->server_connection.host,
4817 6298 : 0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
4818 6298 : 0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
4819 : socket_is_still_alive(csp->server_connection.sfd),
4820 : csp->server_connection.keep_alive_timeout);
4821 : #ifdef FEATURE_CONNECTION_SHARING
4822 6298 : if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
4823 : {
4824 0 : forget_connection(csp->server_connection.sfd);
4825 : }
4826 : #endif /* def FEATURE_CONNECTION_SHARING */
4827 : #ifdef FEATURE_HTTPS_INSPECTION
4828 6298 : close_server_ssl_connection(csp);
4829 : #endif
4830 6298 : close_socket(csp->server_connection.sfd);
4831 6298 : mark_connection_closed(&csp->server_connection);
4832 : }
4833 : }
4834 :
4835 34138 : if (continue_chatting && any_loaded_file_changed(csp))
4836 : {
4837 0 : continue_chatting = 0;
4838 0 : config_file_change_detected = 1;
4839 : }
4840 : #ifdef FEATURE_HTTPS_INSPECTION
4841 34138 : if (continue_chatting && client_use_ssl(csp) &&
4842 1952 : csp->ssl_with_client_is_opened == 0)
4843 : {
4844 16 : continue_chatting = 0;
4845 16 : log_error(LOG_LEVEL_CONNECT, "Client socket %d is no longer usable. "
4846 : "The TLS session has been terminated.", csp->cfd);
4847 : }
4848 : #endif
4849 :
4850 34138 : if (continue_chatting)
4851 : {
4852 31620 : if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) != 0)
4853 11533 : && socket_is_still_alive(csp->cfd))
4854 : {
4855 11226 : log_error(LOG_LEVEL_CONNECT, "Client request %d has been "
4856 : "pipelined on socket %d and the socket is still alive.",
4857 11226 : csp->requests_received_total+1, csp->cfd);
4858 11226 : prepare_csp_for_next_request(csp);
4859 11226 : continue;
4860 : }
4861 :
4862 20394 : if (0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE))
4863 : {
4864 20394 : if (csp->server_connection.sfd != JB_INVALID_SOCKET)
4865 : {
4866 247 : log_error(LOG_LEVEL_CONNECT,
4867 : "Waiting for the next client request on socket %d. "
4868 : "Keeping the server socket %d to %s open.",
4869 : csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
4870 : }
4871 : else
4872 : {
4873 20147 : log_error(LOG_LEVEL_CONNECT,
4874 : "Waiting for the next client request on socket %d. "
4875 : "No server socket to keep open.", csp->cfd);
4876 : }
4877 : }
4878 :
4879 20394 : if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
4880 20394 : && data_is_available(csp->cfd, (int)csp->config->keep_alive_timeout)
4881 19814 : && socket_is_still_alive(csp->cfd))
4882 : {
4883 19814 : log_error(LOG_LEVEL_CONNECT,
4884 : "Data arrived in time on client socket %d. Requests so far: %u",
4885 : csp->cfd, csp->requests_received_total);
4886 19814 : prepare_csp_for_next_request(csp);
4887 : }
4888 : else
4889 : {
4890 : #ifdef FEATURE_CONNECTION_SHARING
4891 580 : if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
4892 0 : && (csp->server_connection.sfd != JB_INVALID_SOCKET)
4893 0 : && (socket_is_still_alive(csp->server_connection.sfd))
4894 : #ifdef FEATURE_HTTPS_INSPECTION
4895 0 : && !server_use_ssl(csp)
4896 : #endif
4897 : )
4898 : {
4899 0 : time_t time_open = time(NULL) - csp->server_connection.timestamp;
4900 :
4901 0 : if (csp->server_connection.keep_alive_timeout < time_open - (time_t)latency)
4902 : {
4903 0 : break;
4904 : }
4905 0 : remember_connection(&csp->server_connection);
4906 0 : csp->server_connection.sfd = JB_INVALID_SOCKET;
4907 0 : drain_and_close_socket(csp->cfd);
4908 0 : csp->cfd = JB_INVALID_SOCKET;
4909 0 : privoxy_mutex_lock(&connection_reuse_mutex);
4910 0 : if (!monitor_thread_running)
4911 : {
4912 0 : monitor_thread_running = 1;
4913 0 : privoxy_mutex_unlock(&connection_reuse_mutex);
4914 0 : wait_for_alive_connections();
4915 0 : privoxy_mutex_lock(&connection_reuse_mutex);
4916 0 : monitor_thread_running = 0;
4917 : }
4918 0 : privoxy_mutex_unlock(&connection_reuse_mutex);
4919 : }
4920 : #endif /* def FEATURE_CONNECTION_SHARING */
4921 580 : break;
4922 : }
4923 : }
4924 2518 : else if (csp->server_connection.sfd != JB_INVALID_SOCKET)
4925 : {
4926 1 : log_error(LOG_LEVEL_CONNECT,
4927 : "Closing server socket %d connected to %s. Keep-alive: %u. "
4928 : "Tainted: %u. Socket alive: %u. Timeout: %u. "
4929 : "Configuration file change detected: %u",
4930 : csp->server_connection.sfd, csp->server_connection.host,
4931 1 : 0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
4932 1 : 0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
4933 : socket_is_still_alive(csp->server_connection.sfd),
4934 : csp->server_connection.keep_alive_timeout,
4935 : config_file_change_detected);
4936 : }
4937 33558 : } while (continue_chatting);
4938 : // return;
4939 : #else
4940 : chat(csp);
4941 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
4942 :
4943 3098 : if (csp->cfd != JB_INVALID_SOCKET)
4944 : {
4945 3098 : log_error(LOG_LEVEL_CONNECT, "Closing client socket %d. "
4946 : "Keep-alive: %u. Socket alive: %u. Data available: %u. "
4947 : "Configuration file change detected: %u. Requests received: %u.",
4948 3098 : csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE),
4949 : socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0),
4950 : config_file_change_detected, csp->requests_received_total);
4951 : #ifdef FEATURE_HTTPS_INSPECTION
4952 3098 : close_client_ssl_connection(csp);
4953 : #endif
4954 3098 : drain_and_close_socket(csp->cfd);
4955 : }
4956 :
4957 3098 : if (csp->server_connection.sfd != JB_INVALID_SOCKET)
4958 : {
4959 : #ifdef FEATURE_CONNECTION_SHARING
4960 2 : if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
4961 : {
4962 0 : forget_connection(csp->server_connection.sfd);
4963 : }
4964 : #endif /* def FEATURE_CONNECTION_SHARING */
4965 :
4966 : #ifdef FEATURE_HTTPS_INSPECTION
4967 2 : close_server_ssl_connection(csp);
4968 : #endif /* def FEATURE_HTTPS_INSPECTION */
4969 :
4970 2 : close_socket(csp->server_connection.sfd);
4971 : }
4972 :
4973 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
4974 3098 : mark_connection_closed(&csp->server_connection);
4975 : #endif
4976 :
4977 : //free_csp_resources(csp); now static
4978 3098 : csp->flags &= ~CSP_FLAG_ACTIVE;
4979 :
4980 3098 : }
4981 :
4982 :
4983 : #ifdef __BEOS__
4984 : /*********************************************************************
4985 : *
4986 : * Function : server_thread
4987 : *
4988 : * Description : We only exist to call `serve' in a threaded environment.
4989 : *
4990 : * Parameters :
4991 : * 1 : data = Current client state (buffers, headers, etc...)
4992 : *
4993 : * Returns : Always 0.
4994 : *
4995 : *********************************************************************/
4996 : static int32 server_thread(void *data)
4997 : {
4998 : serve((struct client_state *) data);
4999 : return 0;
5000 :
5001 : }
5002 : #endif
5003 :
5004 :
5005 : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
5006 : /*********************************************************************
5007 : *
5008 : * Function : usage
5009 : *
5010 : * Description : Print usage info & exit.
5011 : *
5012 : * Parameters : Pointer to argv[0] for identifying ourselves
5013 : *
5014 : * Returns : No. ,-)
5015 : *
5016 : *********************************************************************/
5017 0 : static void usage(const char *name)
5018 : {
5019 0 : printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n"
5020 : "Usage: %s [--config-test] "
5021 : #if defined(unix)
5022 : "[--chroot] "
5023 : #endif /* defined(unix) */
5024 : "[--help] "
5025 : #if defined(unix)
5026 : "[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] "
5027 : #endif /* defined(unix) */
5028 : "[--version] [configfile]\n",
5029 : name);
5030 :
5031 : #ifdef FUZZ
5032 0 : show_fuzz_usage(name);
5033 : #endif
5034 :
5035 0 : printf("Aborting\n");
5036 :
5037 0 : exit(2);
5038 :
5039 : }
5040 : #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */
5041 :
5042 :
5043 : #ifdef MUTEX_LOCKS_AVAILABLE
5044 : /*********************************************************************
5045 : *
5046 : * Function : privoxy_mutex_lock
5047 : *
5048 : * Description : Locks a mutex.
5049 : *
5050 : * Parameters :
5051 : * 1 : mutex = The mutex to lock.
5052 : *
5053 : * Returns : Void. May exit in case of errors.
5054 : *
5055 : *********************************************************************/
5056 4074961 : void privoxy_mutex_lock(privoxy_mutex_t *mutex)
5057 : {
5058 : #ifdef FEATURE_PTHREAD
5059 4074961 : int err = pthread_mutex_lock(mutex);
5060 4074961 : if (err)
5061 : {
5062 0 : if (mutex != &log_mutex)
5063 : {
5064 0 : log_error(LOG_LEVEL_FATAL,
5065 : "Mutex locking failed: %s.\n", strerror(err));
5066 : }
5067 0 : exit(1);
5068 : }
5069 : #else
5070 : EnterCriticalSection(mutex);
5071 : #endif /* def FEATURE_PTHREAD */
5072 4074961 : }
5073 :
5074 :
5075 : /*********************************************************************
5076 : *
5077 : * Function : privoxy_mutex_unlock
5078 : *
5079 : * Description : Unlocks a mutex.
5080 : *
5081 : * Parameters :
5082 : * 1 : mutex = The mutex to unlock.
5083 : *
5084 : * Returns : Void. May exit in case of errors.
5085 : *
5086 : *********************************************************************/
5087 4074961 : void privoxy_mutex_unlock(privoxy_mutex_t *mutex)
5088 : {
5089 : #ifdef FEATURE_PTHREAD
5090 4074961 : int err = pthread_mutex_unlock(mutex);
5091 4074961 : if (err)
5092 : {
5093 0 : if (mutex != &log_mutex)
5094 : {
5095 0 : log_error(LOG_LEVEL_FATAL,
5096 : "Mutex unlocking failed: %s.\n", strerror(err));
5097 : }
5098 0 : exit(1);
5099 : }
5100 : #else
5101 : LeaveCriticalSection(mutex);
5102 : #endif /* def FEATURE_PTHREAD */
5103 4074961 : }
5104 :
5105 :
5106 : /*********************************************************************
5107 : *
5108 : * Function : privoxy_mutex_init
5109 : *
5110 : * Description : Prepares a mutex.
5111 : *
5112 : * Parameters :
5113 : * 1 : mutex = The mutex to initialize.
5114 : *
5115 : * Returns : Void. May exit in case of errors.
5116 : *
5117 : *********************************************************************/
5118 27882 : static void privoxy_mutex_init(privoxy_mutex_t *mutex)
5119 : {
5120 : #ifdef FEATURE_PTHREAD
5121 27882 : int err = pthread_mutex_init(mutex, 0);
5122 27882 : if (err)
5123 : {
5124 0 : printf("Fatal error. Mutex initialization failed: %s.\n",
5125 : strerror(err));
5126 0 : exit(1);
5127 : }
5128 : #else
5129 : InitializeCriticalSection(mutex);
5130 : #endif /* def FEATURE_PTHREAD */
5131 27882 : }
5132 : #endif /* def MUTEX_LOCKS_AVAILABLE */
5133 :
5134 : /*********************************************************************
5135 : *
5136 : * Function : initialize_mutexes
5137 : *
5138 : * Description : Prepares mutexes if mutex support is available.
5139 : *
5140 : * Parameters : None
5141 : *
5142 : * Returns : Void, exits in case of errors.
5143 : *
5144 : *********************************************************************/
5145 3098 : static void initialize_mutexes(void)
5146 : {
5147 : #ifdef MUTEX_LOCKS_AVAILABLE
5148 : /*
5149 : * Prepare global mutex semaphores
5150 : */
5151 :
5152 : #ifdef FEATURE_HTTPS_INSPECTION
5153 3098 : privoxy_mutex_init(&certificate_mutex);
5154 3098 : privoxy_mutex_init(&ssl_init_mutex);
5155 : #endif
5156 :
5157 3098 : privoxy_mutex_init(&log_mutex);
5158 3098 : privoxy_mutex_init(&log_init_mutex);
5159 3098 : privoxy_mutex_init(&connection_reuse_mutex);
5160 : #ifdef FEATURE_EXTERNAL_FILTERS
5161 3098 : privoxy_mutex_init(&external_filter_mutex);
5162 : #endif
5163 : #ifdef FEATURE_CLIENT_TAGS
5164 3098 : privoxy_mutex_init(&client_tags_mutex);
5165 : #endif
5166 : #ifdef FEATURE_EXTENDED_STATISTICS
5167 3098 : privoxy_mutex_init(&filter_statistics_mutex);
5168 3098 : privoxy_mutex_init(&block_statistics_mutex);
5169 : #endif
5170 :
5171 : /*
5172 : * XXX: The assumptions below are a bit naive
5173 : * and can cause locks that aren't necessary.
5174 : *
5175 : * For example older FreeBSD versions (< 6.x?)
5176 : * have no gethostbyname_r, but gethostbyname is
5177 : * thread safe.
5178 : */
5179 : #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R)
5180 : privoxy_mutex_init(&resolver_mutex);
5181 : #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */
5182 : /*
5183 : * XXX: should we use a single mutex for
5184 : * localtime() and gmtime() as well?
5185 : */
5186 : #ifndef HAVE_GMTIME_R
5187 : privoxy_mutex_init(&gmtime_mutex);
5188 : #endif /* ndef HAVE_GMTIME_R */
5189 :
5190 : #ifndef HAVE_LOCALTIME_R
5191 : privoxy_mutex_init(&localtime_mutex);
5192 : #endif /* ndef HAVE_GMTIME_R */
5193 :
5194 : #if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
5195 : privoxy_mutex_init(&rand_mutex);
5196 : #endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
5197 :
5198 : #endif /* def MUTEX_LOCKS_AVAILABLE */
5199 3098 : }
5200 :
5201 : /*********************************************************************
5202 : *
5203 : * Function : main
5204 : *
5205 : * Description : Load the config file and start the listen loop.
5206 : * This function is a lot more *sane* with the `load_config'
5207 : * and `listen_loop' functions; although it stills does
5208 : * a *little* too much for my taste.
5209 : *
5210 : * Parameters :
5211 : * 1 : argc = Number of parameters (including $0).
5212 : * 2 : argv = Array of (char *)'s to the parameters.
5213 : *
5214 : * Returns : 1 if : can't open config file, unrecognized directive,
5215 : * stats requested in multi-thread mode, can't open the
5216 : * log file, can't open the jar file, listen port is invalid,
5217 : * any load fails, and can't bind port.
5218 : *
5219 : * Else main never returns, the process must be signaled
5220 : * to terminate execution. Or, on Windows, use the
5221 : * "File", "Exit" menu option.
5222 : *
5223 : *********************************************************************/
5224 : #ifdef __MINGW32__
5225 : int real_main(int argc, char **argv)
5226 : #else
5227 3098 : int main(int argc, char **argv)
5228 : #endif
5229 : {
5230 :
5231 :
5232 3098 : int argc_pos = 0;
5233 3098 : int do_config_test = 0;
5234 : #ifndef HAVE_ARC4RANDOM
5235 : unsigned int random_seed;
5236 : #endif
5237 : #ifdef unix
5238 3098 : struct passwd *pw = NULL;
5239 3098 : struct group *grp = NULL;
5240 3098 : int do_chroot = 0;
5241 3098 : char *pre_chroot_nslookup_to_load_resolver = NULL;
5242 : #endif
5243 : #ifdef FUZZ
5244 3098 : char *fuzz_input_type = NULL;
5245 3098 : char *fuzz_input_file = NULL;
5246 : #endif
5247 :
5248 3098 : Argc = argc;
5249 3098 : Argv = argv;
5250 :
5251 3098 : configfile =
5252 : #if !defined(_WIN32)
5253 : "config"
5254 : #else
5255 : "config.txt"
5256 : #endif
5257 : ;
5258 :
5259 :
5260 : /* Prepare mutexes if supported and necessary. */
5261 3098 : initialize_mutexes();
5262 :
5263 : /* Enable logging until further notice. */
5264 3098 : init_log_module();
5265 :
5266 : /*
5267 : * Parse the command line arguments
5268 : *
5269 : * XXX: simply printing usage information in case of
5270 : * invalid arguments isn't particularly user friendly.
5271 : */
5272 9294 : while (++argc_pos < argc)
5273 : {
5274 : #ifdef _WIN32
5275 : /* Check to see if the service must be installed or uninstalled */
5276 : if (strncmp(argv[argc_pos], "--install", 9) == 0)
5277 : {
5278 : const char *pName = argv[argc_pos] + 9;
5279 : if (*pName == ':')
5280 : pName++;
5281 : exit((install_service(pName)) ? 0 : 1);
5282 : }
5283 : else if (strncmp(argv[argc_pos], "--uninstall", 11) == 0)
5284 : {
5285 : const char *pName = argv[argc_pos] + 11;
5286 : if (*pName == ':')
5287 : pName++;
5288 : exit((uninstall_service(pName)) ? 0 : 1);
5289 : }
5290 : else if (strcmp(argv[argc_pos], "--service") == 0)
5291 : {
5292 : bRunAsService = TRUE;
5293 : w32_set_service_cwd();
5294 : atexit(w32_service_exit_notify);
5295 : }
5296 : else
5297 : #endif /* defined(_WIN32) */
5298 :
5299 :
5300 : #if !defined(_WIN32) || defined(_WIN_CONSOLE)
5301 :
5302 6196 : if (strcmp(argv[argc_pos], "--help") == 0)
5303 : {
5304 0 : usage(argv[0]);
5305 : }
5306 :
5307 6196 : else if (strcmp(argv[argc_pos], "--version") == 0)
5308 : {
5309 0 : printf("Privoxy version " VERSION " (" HOME_PAGE_URL ")\n");
5310 0 : exit(0);
5311 : }
5312 :
5313 : #if defined(unix)
5314 :
5315 6196 : else if (strcmp(argv[argc_pos], "--no-daemon") == 0)
5316 : {
5317 3098 : set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);
5318 3098 : daemon_mode = 0;
5319 : }
5320 :
5321 3098 : else if (strcmp(argv[argc_pos], "--pidfile") == 0)
5322 : {
5323 0 : if (++argc_pos == argc) usage(argv[0]);
5324 0 : pidfile = strdup_or_die(argv[argc_pos]);
5325 : }
5326 :
5327 3098 : else if (strcmp(argv[argc_pos], "--user") == 0)
5328 : {
5329 : char *user_arg;
5330 : char *group_name;
5331 :
5332 0 : if (++argc_pos == argc) usage(argv[argc_pos]);
5333 :
5334 0 : user_arg = strdup_or_die(argv[argc_pos]);
5335 0 : group_name = strchr(user_arg, '.');
5336 0 : if (NULL != group_name)
5337 : {
5338 : /* Nul-terminate the user name */
5339 0 : *group_name = '\0';
5340 :
5341 : /* Skip the former delimiter to actually reach the group name */
5342 0 : group_name++;
5343 :
5344 0 : grp = getgrnam(group_name);
5345 0 : if (NULL == grp)
5346 : {
5347 0 : log_error(LOG_LEVEL_FATAL, "Group '%s' not found.", group_name);
5348 : }
5349 : }
5350 0 : pw = getpwnam(user_arg);
5351 0 : if (NULL == pw)
5352 : {
5353 0 : log_error(LOG_LEVEL_FATAL, "User '%s' not found.", user_arg);
5354 : }
5355 :
5356 0 : freez(user_arg);
5357 : }
5358 :
5359 3098 : else if (strcmp(argv[argc_pos], "--pre-chroot-nslookup") == 0)
5360 : {
5361 0 : if (++argc_pos == argc) usage(argv[0]);
5362 0 : pre_chroot_nslookup_to_load_resolver = strdup_or_die(argv[argc_pos]);
5363 : }
5364 :
5365 3098 : else if (strcmp(argv[argc_pos], "--chroot") == 0)
5366 : {
5367 0 : do_chroot = 1;
5368 : }
5369 : #endif /* defined(unix) */
5370 :
5371 3098 : else if (strcmp(argv[argc_pos], "--config-test") == 0)
5372 : {
5373 0 : do_config_test = 1;
5374 : }
5375 : #ifdef FUZZ
5376 3098 : else if (strcmp(argv[argc_pos], "--fuzz") == 0)
5377 : {
5378 3098 : argc_pos++;
5379 3098 : if (argc < argc_pos + 2) usage(argv[0]);
5380 3098 : fuzz_input_type = argv[argc_pos];
5381 3098 : argc_pos++;
5382 3098 : fuzz_input_file = argv[argc_pos];
5383 : }
5384 0 : else if (strcmp(argv[argc_pos], "--stfu") == 0)
5385 : {
5386 0 : set_debug_level(LOG_LEVEL_STFU);
5387 : }
5388 : #endif
5389 0 : else if (argc_pos + 1 != argc)
5390 : {
5391 : /*
5392 : * This is neither the last command line
5393 : * option, nor was it recognized before,
5394 : * therefore it must be invalid.
5395 : */
5396 0 : usage(argv[0]);
5397 : }
5398 : else
5399 :
5400 : #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
5401 : {
5402 0 : configfile = argv[argc_pos];
5403 : }
5404 :
5405 : } /* -END- while (more arguments) */
5406 :
5407 3098 : show_version(Argv[0]);
5408 :
5409 : #if defined(unix)
5410 3098 : if (*configfile != '/')
5411 : {
5412 : char cwd[BUFFER_SIZE];
5413 : char *abs_file;
5414 : size_t abs_file_size;
5415 :
5416 : /* make config-filename absolute here */
5417 3098 : if (NULL == getcwd(cwd, sizeof(cwd)))
5418 : {
5419 0 : perror("failed to get current working directory");
5420 0 : exit(1);
5421 : }
5422 :
5423 3098 : basedir = strdup_or_die(cwd);
5424 : /* XXX: why + 5? */
5425 3098 : abs_file_size = strlen(cwd) + strlen(configfile) + 5;
5426 3098 : abs_file = malloc_or_die(abs_file_size);
5427 3098 : strlcpy(abs_file, basedir, abs_file_size);
5428 3098 : strlcat(abs_file, "/", abs_file_size);
5429 3098 : strlcat(abs_file, configfile, abs_file_size);
5430 3098 : configfile = abs_file;
5431 : }
5432 : #endif /* defined unix */
5433 :
5434 :
5435 3098 : files->next = NULL;
5436 3098 : clients->next = NULL;
5437 :
5438 : /* XXX: factor out initialising after the next stable release. */
5439 : #ifdef _WIN32
5440 : InitWin32();
5441 : #endif
5442 :
5443 : #ifndef HAVE_ARC4RANDOM
5444 3098 : random_seed = (unsigned int)time(NULL);
5445 : #ifdef HAVE_RANDOM
5446 3098 : srandom(random_seed);
5447 : #else
5448 : srand(random_seed);
5449 : #endif /* ifdef HAVE_RANDOM */
5450 : #endif /* ifndef HAVE_ARC4RANDOM */
5451 :
5452 : /*
5453 : * Unix signal handling
5454 : *
5455 : * Catch the abort, interrupt and terminate signals for a graceful exit
5456 : * Catch the hangup signal so the errlog can be reopened.
5457 : *
5458 : * Ignore the broken pipe signal as connection failures
5459 : * are handled when and where they occur without relying
5460 : * on a signal.
5461 : */
5462 : #if !defined(_WIN32)
5463 : {
5464 : int idx;
5465 3098 : const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP };
5466 :
5467 12392 : for (idx = 0; idx < SZ(catched_signals); idx++)
5468 : {
5469 : #ifdef sun /* FIXME: Is it safe to check for HAVE_SIGSET instead? */
5470 : if (sigset(catched_signals[idx], sig_handler) == SIG_ERR)
5471 : #else
5472 9294 : if (signal(catched_signals[idx], sig_handler) == SIG_ERR)
5473 : #endif /* ifdef sun */
5474 : {
5475 0 : log_error(LOG_LEVEL_FATAL, "Can't set signal-handler for signal %d: %E", catched_signals[idx]);
5476 : }
5477 : }
5478 :
5479 3098 : if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
5480 : {
5481 0 : log_error(LOG_LEVEL_FATAL, "Can't set ignore-handler for SIGPIPE: %E");
5482 : }
5483 :
5484 : }
5485 : #else /* ifdef _WIN32 */
5486 : # ifdef _WIN_CONSOLE
5487 : /*
5488 : * We *are* in a windows console app.
5489 : * Print a verbose messages about FAQ's and such
5490 : */
5491 : printf("%s", win32_blurb);
5492 : # endif /* def _WIN_CONSOLE */
5493 : #endif /* def _WIN32 */
5494 :
5495 : #ifdef FUZZ
5496 3098 : if (fuzz_input_type != NULL)
5497 : {
5498 3098 : process_fuzzed_input(fuzz_input_type, fuzz_input_file);
5499 3098 : exit(0);
5500 : }
5501 0 : log_error(LOG_LEVEL_FATAL,
5502 : "When compiled with fuzzing support, Privoxy should only be used for fuzzing. "
5503 : "Various data structures are static which is unsafe when using threads.");
5504 : #endif
5505 :
5506 0 : if (do_config_test)
5507 : {
5508 0 : exit(NULL == load_config());
5509 : }
5510 :
5511 : /* Initialize the CGI subsystem */
5512 0 : cgi_init_error_messages();
5513 :
5514 : /*
5515 : * If running on unix and without the --no-daemon
5516 : * option, become a daemon. I.e. fork, detach
5517 : * from tty and get process group leadership
5518 : */
5519 : #if defined(unix)
5520 : {
5521 0 : if (daemon_mode)
5522 : {
5523 : int fd;
5524 0 : pid_t pid = fork();
5525 :
5526 0 : if (pid < 0) /* error */
5527 : {
5528 0 : perror("fork");
5529 0 : exit(3);
5530 : }
5531 0 : else if (pid != 0) /* parent */
5532 : {
5533 : int status;
5534 : pid_t wpid;
5535 : /*
5536 : * must check for errors
5537 : * child died due to missing files aso
5538 : */
5539 0 : sleep(1);
5540 0 : wpid = waitpid(pid, &status, WNOHANG);
5541 0 : if (wpid != 0)
5542 : {
5543 0 : exit(1);
5544 : }
5545 0 : exit(0);
5546 : }
5547 : /* child */
5548 :
5549 0 : setsid();
5550 :
5551 : /*
5552 : * stderr (fd 2) will be closed later on,
5553 : * when the config file has been parsed.
5554 : */
5555 0 : close(0);
5556 0 : close(1);
5557 :
5558 : /*
5559 : * Reserve fd 0 and 1 to prevent abort() and friends
5560 : * from sending stuff to the clients or servers.
5561 : */
5562 0 : fd = open("/dev/null", O_RDONLY);
5563 0 : if (fd == -1)
5564 : {
5565 0 : log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
5566 : }
5567 0 : else if (fd != 0)
5568 : {
5569 0 : if (dup2(fd, 0) == -1)
5570 : {
5571 0 : log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 0: %E");
5572 : }
5573 0 : close(fd);
5574 : }
5575 0 : fd = open("/dev/null", O_WRONLY);
5576 0 : if (fd == -1)
5577 : {
5578 0 : log_error(LOG_LEVEL_FATAL, "Failed to open /dev/null: %E");
5579 : }
5580 0 : else if (fd != 1)
5581 : {
5582 0 : if (dup2(fd, 1) == -1)
5583 : {
5584 0 : log_error(LOG_LEVEL_FATAL, "Failed to reserve fd 1: %E");
5585 : }
5586 0 : close(fd);
5587 : }
5588 :
5589 : #ifdef FEATURE_EXTERNAL_FILTERS
5590 0 : for (fd = 0; fd < 3; fd++)
5591 : {
5592 0 : mark_socket_for_close_on_execute(fd);
5593 : }
5594 : #endif
5595 :
5596 0 : if (chdir("/") != 0)
5597 : {
5598 0 : log_error(LOG_LEVEL_FATAL, "Failed to cd into '/': %E");
5599 : }
5600 :
5601 : } /* -END- if (daemon_mode) */
5602 :
5603 : /*
5604 : * As soon as we have written the PID file, we can switch
5605 : * to the user and group ID indicated by the --user option
5606 : */
5607 0 : if (pidfile != NULL)
5608 : {
5609 0 : write_pid_file(pidfile);
5610 : }
5611 0 : if (NULL != pw)
5612 : {
5613 0 : if (setgid((NULL != grp) ? grp->gr_gid : pw->pw_gid))
5614 : {
5615 0 : log_error(LOG_LEVEL_FATAL, "Cannot setgid(): Insufficient permissions.");
5616 : }
5617 0 : if (NULL != grp)
5618 : {
5619 0 : if (setgroups(1, &grp->gr_gid))
5620 : {
5621 0 : log_error(LOG_LEVEL_FATAL, "setgroups() failed: %E");
5622 : }
5623 : }
5624 0 : else if (initgroups(pw->pw_name, pw->pw_gid))
5625 : {
5626 0 : log_error(LOG_LEVEL_FATAL, "initgroups() failed: %E");
5627 : }
5628 0 : if (do_chroot)
5629 : {
5630 0 : if (!pw->pw_dir)
5631 : {
5632 0 : log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name);
5633 : }
5634 : /* Read the time zone file from /etc before doing chroot. */
5635 0 : tzset();
5636 0 : if (NULL != pre_chroot_nslookup_to_load_resolver
5637 0 : && '\0' != pre_chroot_nslookup_to_load_resolver[0])
5638 : {
5639 : /* Initialize resolver library. */
5640 0 : (void) resolve_hostname_to_ip(pre_chroot_nslookup_to_load_resolver);
5641 : }
5642 0 : if (chroot(pw->pw_dir) < 0)
5643 : {
5644 0 : log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);
5645 : }
5646 0 : if (chdir ("/"))
5647 : {
5648 0 : log_error(LOG_LEVEL_FATAL, "Cannot chdir /");
5649 : }
5650 : }
5651 0 : if (setuid(pw->pw_uid))
5652 : {
5653 0 : log_error(LOG_LEVEL_FATAL, "Cannot setuid(): Insufficient permissions.");
5654 : }
5655 0 : if (do_chroot)
5656 : {
5657 : char putenv_dummy[64];
5658 :
5659 0 : strlcpy(putenv_dummy, "HOME=/", sizeof(putenv_dummy));
5660 0 : if (putenv(putenv_dummy) != 0)
5661 : {
5662 0 : log_error(LOG_LEVEL_FATAL, "Cannot putenv(): HOME");
5663 : }
5664 :
5665 0 : snprintf(putenv_dummy, sizeof(putenv_dummy), "USER=%s", pw->pw_name);
5666 0 : if (putenv(putenv_dummy) != 0)
5667 : {
5668 0 : log_error(LOG_LEVEL_FATAL, "Cannot putenv(): USER");
5669 : }
5670 : }
5671 : }
5672 0 : else if (do_chroot)
5673 : {
5674 0 : log_error(LOG_LEVEL_FATAL, "Cannot chroot without --user argument.");
5675 : }
5676 : }
5677 : #endif /* defined unix */
5678 :
5679 : #ifdef _WIN32
5680 : /* This will be FALSE unless the command line specified --service
5681 : */
5682 : if (bRunAsService)
5683 : {
5684 : /* Yup, so now we must attempt to establish a connection
5685 : * with the service dispatcher. This will only work if this
5686 : * process was launched by the service control manager to
5687 : * actually run as a service. If this isn't the case, i've
5688 : * known it take around 30 seconds or so for the call to return.
5689 : */
5690 :
5691 : /* The StartServiceCtrlDispatcher won't return until the service is stopping */
5692 : if (w32_start_service_ctrl_dispatcher(w32ServiceDispatchTable))
5693 : {
5694 : /* Service has run, and at this point is now being stopped, so just return */
5695 : return 0;
5696 : }
5697 :
5698 : #ifdef _WIN_CONSOLE
5699 : printf("Warning: Failed to connect to Service Control Dispatcher\nwhen starting as a service!\n");
5700 : #endif
5701 : /* An error occurred. Usually it's because --service was wrongly specified
5702 : * and we were unable to connect to the Service Control Dispatcher because
5703 : * it wasn't expecting us and is therefore not listening.
5704 : *
5705 : * For now, just continue below to call the listen_loop function.
5706 : */
5707 : }
5708 : #endif /* def _WIN32 */
5709 :
5710 0 : listen_loop();
5711 :
5712 : /* NOTREACHED */
5713 0 : return(-1);
5714 :
5715 : }
5716 :
5717 :
5718 : /*********************************************************************
5719 : *
5720 : * Function : bind_port_helper
5721 : *
5722 : * Description : Bind the listen port. Handles logging, and aborts
5723 : * on failure.
5724 : *
5725 : * Parameters :
5726 : * 1 : haddr = Host address to bind to. Use NULL to bind to
5727 : * INADDR_ANY.
5728 : * 2 : hport = Specifies port to bind to.
5729 : * 3 : backlog = Listen backlog.
5730 : *
5731 : * Returns : Port that was opened.
5732 : *
5733 : *********************************************************************/
5734 0 : static jb_socket bind_port_helper(const char *haddr, int hport, int backlog)
5735 : {
5736 : int result;
5737 : jb_socket bfd;
5738 :
5739 0 : result = bind_port(haddr, hport, backlog, &bfd);
5740 :
5741 0 : if (result < 0)
5742 : {
5743 0 : const char *bind_address = (NULL != haddr) ? haddr : "INADDR_ANY";
5744 0 : switch(result)
5745 : {
5746 0 : case -3:
5747 0 : log_error(LOG_LEVEL_FATAL,
5748 : "can't bind to %s:%d: There may be another Privoxy "
5749 : "or some other proxy running on port %d",
5750 : bind_address, hport, hport);
5751 :
5752 0 : case -2:
5753 0 : log_error(LOG_LEVEL_FATAL,
5754 : "can't bind to %s:%d: The hostname is not resolvable",
5755 : bind_address, hport);
5756 :
5757 0 : default:
5758 0 : log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: %E",
5759 : bind_address, hport);
5760 : }
5761 :
5762 : /* shouldn't get here */
5763 0 : return JB_INVALID_SOCKET;
5764 : }
5765 :
5766 : #ifndef HAVE_POLL
5767 : #ifndef _WIN32
5768 : if (bfd >= FD_SETSIZE)
5769 : {
5770 : log_error(LOG_LEVEL_FATAL,
5771 : "Bind socket number too high to use select(): %d >= %d",
5772 : bfd, FD_SETSIZE);
5773 : }
5774 : #endif
5775 : #endif
5776 :
5777 0 : if (haddr == NULL)
5778 : {
5779 0 : log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses",
5780 : hport);
5781 : }
5782 : else
5783 : {
5784 0 : log_error(LOG_LEVEL_INFO, "Listening on port %d on IP address %s",
5785 : hport, haddr);
5786 : }
5787 :
5788 0 : return bfd;
5789 : }
5790 :
5791 :
5792 : /*********************************************************************
5793 : *
5794 : * Function : bind_ports_helper
5795 : *
5796 : * Description : Bind the listen ports. Handles logging, and aborts
5797 : * on failure.
5798 : *
5799 : * Parameters :
5800 : * 1 : config = Privoxy configuration. Specifies ports
5801 : * to bind to.
5802 : * 2 : sockets = Preallocated array of opened sockets
5803 : * corresponding to specification in config.
5804 : * All non-opened sockets will be set to
5805 : * JB_INVALID_SOCKET.
5806 : *
5807 : * Returns : Nothing. Inspect sockets argument.
5808 : *
5809 : *********************************************************************/
5810 0 : static void bind_ports_helper(struct configuration_spec * config,
5811 : jb_socket sockets[])
5812 : {
5813 : int i;
5814 :
5815 0 : for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
5816 : {
5817 0 : if (config->hport[i])
5818 : {
5819 0 : sockets[i] = bind_port_helper(config->haddr[i],
5820 : config->hport[i], config->listen_backlog);
5821 : #if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER)
5822 : if (config->enable_accept_filter && sockets[i] != JB_INVALID_SOCKET)
5823 : {
5824 : struct accept_filter_arg af_options;
5825 : bzero(&af_options, sizeof(af_options));
5826 : strlcpy(af_options.af_name, "httpready", sizeof(af_options.af_name));
5827 : if (setsockopt(sockets[i], SOL_SOCKET, SO_ACCEPTFILTER, &af_options,
5828 : sizeof(af_options)))
5829 : {
5830 : log_error(LOG_LEVEL_ERROR,
5831 : "Enabling accept filter for socket %d failed: %E", sockets[i]);
5832 : }
5833 : }
5834 : #endif
5835 : }
5836 : else
5837 : {
5838 0 : sockets[i] = JB_INVALID_SOCKET;
5839 : }
5840 : }
5841 0 : config->need_bind = 0;
5842 0 : }
5843 :
5844 :
5845 : /*********************************************************************
5846 : *
5847 : * Function : close_ports_helper
5848 : *
5849 : * Description : Close listenings ports.
5850 : *
5851 : * Parameters :
5852 : * 1 : sockets = Array of opened and non-opened sockets to
5853 : * close. All sockets will be set to
5854 : * JB_INVALID_SOCKET.
5855 : *
5856 : * Returns : Nothing.
5857 : *
5858 : *********************************************************************/
5859 0 : static void close_ports_helper(jb_socket sockets[])
5860 : {
5861 : int i;
5862 :
5863 0 : for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
5864 : {
5865 0 : if (JB_INVALID_SOCKET != sockets[i])
5866 : {
5867 0 : close_socket(sockets[i]);
5868 : }
5869 0 : sockets[i] = JB_INVALID_SOCKET;
5870 : }
5871 0 : }
5872 :
5873 :
5874 : #ifdef _WIN32
5875 : /* Without this simple workaround we get this compiler warning from _beginthread
5876 : * warning C4028: formal parameter 1 different from declaration
5877 : */
5878 : void w32_service_listen_loop(void *p)
5879 : {
5880 : listen_loop();
5881 : }
5882 : #endif /* def _WIN32 */
5883 :
5884 :
5885 : /*********************************************************************
5886 : *
5887 : * Function : listen_loop
5888 : *
5889 : * Description : bind the listen port and enter a "FOREVER" listening loop.
5890 : *
5891 : * Parameters : N/A
5892 : *
5893 : * Returns : Never.
5894 : *
5895 : *********************************************************************/
5896 0 : static void listen_loop(void)
5897 : {
5898 0 : struct client_states *csp_list = NULL;
5899 0 : struct client_state *csp = NULL;
5900 : jb_socket bfds[MAX_LISTENING_SOCKETS];
5901 : struct configuration_spec *config;
5902 0 : unsigned int active_threads = 0;
5903 : #if defined(FEATURE_PTHREAD)
5904 : pthread_attr_t attrs;
5905 :
5906 0 : pthread_attr_init(&attrs);
5907 0 : pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
5908 : #endif
5909 :
5910 0 : config = load_config();
5911 :
5912 : #ifdef FEATURE_CONNECTION_SHARING
5913 : /*
5914 : * XXX: Should be relocated once it no
5915 : * longer needs to emit log messages.
5916 : */
5917 0 : initialize_reusable_connections();
5918 : #endif /* def FEATURE_CONNECTION_SHARING */
5919 :
5920 0 : bind_ports_helper(config, bfds);
5921 :
5922 : #ifdef FEATURE_GRACEFUL_TERMINATION
5923 : while (!g_terminate)
5924 : #else
5925 : for (;;)
5926 : #endif
5927 : {
5928 : #if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__)
5929 : while (waitpid(-1, NULL, WNOHANG) > 0)
5930 : {
5931 : /* zombie children */
5932 : }
5933 : #endif /* !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) */
5934 :
5935 : /*
5936 : * Free data that was used by died threads
5937 : */
5938 0 : active_threads = sweep();
5939 :
5940 : #if defined(unix)
5941 : /*
5942 : * Re-open the errlog after HUP signal
5943 : */
5944 0 : if (received_hup_signal)
5945 : {
5946 0 : if (NULL != config->logfile)
5947 : {
5948 0 : init_error_log(Argv[0], config->logfile);
5949 : }
5950 0 : received_hup_signal = 0;
5951 : }
5952 : #endif
5953 :
5954 0 : csp_list = zalloc_or_die(sizeof(*csp_list));
5955 0 : csp = &csp_list->csp;
5956 :
5957 0 : log_error(LOG_LEVEL_CONNECT,
5958 : "Waiting for the next client connection. Currently active threads: %u",
5959 : active_threads);
5960 :
5961 : /*
5962 : * This config may be outdated, but for accept_connection()
5963 : * it's fresh enough.
5964 : */
5965 0 : csp->config = config;
5966 :
5967 0 : if (!accept_connection(csp, bfds))
5968 : {
5969 0 : log_error(LOG_LEVEL_CONNECT, "accept failed: %E");
5970 0 : freez(csp_list);
5971 0 : continue;
5972 : }
5973 :
5974 0 : csp->flags |= CSP_FLAG_ACTIVE;
5975 0 : csp->server_connection.sfd = JB_INVALID_SOCKET;
5976 :
5977 0 : csp->config = config = load_config();
5978 :
5979 0 : if (config->need_bind)
5980 : {
5981 : /*
5982 : * Since we were listening to the "old port", we will not see
5983 : * a "listen" param change until the next request. So, at
5984 : * least 1 more request must be made for us to find the new
5985 : * setting. I am simply closing the old socket and binding the
5986 : * new one.
5987 : *
5988 : * Which-ever is correct, we will serve 1 more page via the
5989 : * old settings. This should probably be a "show-status"
5990 : * request. This should not be a so common of an operation
5991 : * that this will hurt people's feelings.
5992 : */
5993 :
5994 0 : close_ports_helper(bfds);
5995 :
5996 0 : bind_ports_helper(config, bfds);
5997 : }
5998 :
5999 : #ifdef FEATURE_TOGGLE
6000 0 : if (global_toggle_state)
6001 : #endif /* def FEATURE_TOGGLE */
6002 : {
6003 0 : csp->flags |= CSP_FLAG_TOGGLED_ON;
6004 : }
6005 :
6006 0 : if (run_loader(csp))
6007 : {
6008 0 : log_error(LOG_LEVEL_FATAL, "a loader failed - must exit");
6009 : /* Never get here - LOG_LEVEL_FATAL causes program exit */
6010 : }
6011 :
6012 : #ifdef FEATURE_ACL
6013 0 : if (block_acl(NULL,csp))
6014 : {
6015 0 : log_error(LOG_LEVEL_CONNECT,
6016 : "Connection from %s on %s (socket %d) dropped due to ACL",
6017 : csp->ip_addr_str, csp->listen_addr_str, csp->cfd);
6018 0 : close_socket(csp->cfd);
6019 0 : freez(csp->ip_addr_str);
6020 0 : freez(csp->listen_addr_str);
6021 0 : freez(csp_list);
6022 0 : continue;
6023 : }
6024 : #endif /* def FEATURE_ACL */
6025 :
6026 0 : if ((0 != config->max_client_connections)
6027 0 : && (active_threads >= config->max_client_connections))
6028 : {
6029 0 : log_error(LOG_LEVEL_CONNECT,
6030 : "Rejecting connection from %s. Maximum number of connections reached.",
6031 : csp->ip_addr_str);
6032 0 : write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
6033 : strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
6034 0 : close_socket(csp->cfd);
6035 0 : freez(csp->ip_addr_str);
6036 0 : freez(csp->listen_addr_str);
6037 0 : freez(csp_list);
6038 0 : continue;
6039 : }
6040 :
6041 : /* add it to the list of clients */
6042 0 : csp_list->next = clients->next;
6043 0 : clients->next = csp_list;
6044 :
6045 0 : if (config->multi_threaded)
6046 : {
6047 : int child_id;
6048 :
6049 : /* this is a switch () statement in the C preprocessor - ugh */
6050 : #undef SELECTED_ONE_OPTION
6051 :
6052 : /* Use Pthreads in preference to native code */
6053 : #if defined(FEATURE_PTHREAD) && !defined(SELECTED_ONE_OPTION)
6054 : #define SELECTED_ONE_OPTION
6055 : {
6056 : pthread_t the_thread;
6057 : int ret;
6058 :
6059 0 : ret = pthread_create(&the_thread, &attrs,
6060 : (void * (*)(void *))serve, csp);
6061 0 : child_id = ret ? -1 : 0;
6062 : }
6063 : #endif
6064 :
6065 : #if defined(_WIN32) && !defined(_CYGWIN) && !defined(SELECTED_ONE_OPTION)
6066 : #define SELECTED_ONE_OPTION
6067 : child_id = _beginthread(
6068 : (void (*)(void *))serve,
6069 : 64 * 1024,
6070 : csp);
6071 : #endif
6072 :
6073 : #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
6074 : #define SELECTED_ONE_OPTION
6075 : {
6076 : thread_id tid = spawn_thread
6077 : (server_thread, "server", B_NORMAL_PRIORITY, csp);
6078 :
6079 : if ((tid >= 0) && (resume_thread(tid) == B_OK))
6080 : {
6081 : child_id = (int) tid;
6082 : }
6083 : else
6084 : {
6085 : child_id = -1;
6086 : }
6087 : }
6088 : #endif
6089 :
6090 : #if !defined(SELECTED_ONE_OPTION)
6091 : child_id = fork();
6092 :
6093 : /* This block is only needed when using fork().
6094 : * When using threads, the server thread was
6095 : * created and run by the call to _beginthread().
6096 : */
6097 : if (child_id == 0) /* child */
6098 : {
6099 : int rc = 0;
6100 : #ifdef FEATURE_TOGGLE
6101 : int inherited_toggle_state = global_toggle_state;
6102 : #endif /* def FEATURE_TOGGLE */
6103 :
6104 : serve(csp);
6105 :
6106 : /*
6107 : * If we've been toggled or we've blocked the request, tell Mom
6108 : */
6109 :
6110 : #ifdef FEATURE_TOGGLE
6111 : if (inherited_toggle_state != global_toggle_state)
6112 : {
6113 : rc |= RC_FLAG_TOGGLED;
6114 : }
6115 : #endif /* def FEATURE_TOGGLE */
6116 :
6117 : #ifdef FEATURE_STATISTICS
6118 : if (csp->flags & CSP_FLAG_REJECTED)
6119 : {
6120 : rc |= RC_FLAG_BLOCKED;
6121 : }
6122 : #endif /* ndef FEATURE_STATISTICS */
6123 :
6124 : _exit(rc);
6125 : }
6126 : else if (child_id > 0) /* parent */
6127 : {
6128 : /* in a fork()'d environment, the parent's
6129 : * copy of the client socket and the CSP
6130 : * are not used.
6131 : */
6132 : int child_status;
6133 : #if !defined(_WIN32) && !defined(__CYGWIN__)
6134 :
6135 : wait(&child_status);
6136 :
6137 : /*
6138 : * Evaluate child's return code: If the child has
6139 : * - been toggled, toggle ourselves
6140 : * - blocked its request, bump up the stats counter
6141 : */
6142 :
6143 : #ifdef FEATURE_TOGGLE
6144 : if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_TOGGLED))
6145 : {
6146 : global_toggle_state = !global_toggle_state;
6147 : }
6148 : #endif /* def FEATURE_TOGGLE */
6149 :
6150 : #ifdef FEATURE_STATISTICS
6151 : urls_read++;
6152 : if (WIFEXITED(child_status) && (WEXITSTATUS(child_status) & RC_FLAG_BLOCKED))
6153 : {
6154 : urls_rejected++;
6155 : }
6156 : #endif /* def FEATURE_STATISTICS */
6157 :
6158 : #endif /* !defined(_WIN32) && defined(__CYGWIN__) */
6159 : close_socket(csp->cfd);
6160 : csp->flags &= ~CSP_FLAG_ACTIVE;
6161 : }
6162 : #endif
6163 :
6164 : #undef SELECTED_ONE_OPTION
6165 : /* end of cpp switch () */
6166 :
6167 0 : if (child_id < 0)
6168 : {
6169 : /*
6170 : * Spawning the child failed, assume it's because
6171 : * there are too many children running already.
6172 : * XXX: If you assume ...
6173 : */
6174 0 : log_error(LOG_LEVEL_ERROR,
6175 : "Unable to take any additional connections: %E. Active threads: %u",
6176 : active_threads);
6177 0 : write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
6178 : strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
6179 0 : close_socket(csp->cfd);
6180 0 : csp->flags &= ~CSP_FLAG_ACTIVE;
6181 : }
6182 : }
6183 : else
6184 : {
6185 0 : serve(csp);
6186 : }
6187 : }
6188 :
6189 : #if defined(FEATURE_PTHREAD)
6190 : pthread_attr_destroy(&attrs);
6191 : #endif
6192 :
6193 : /* NOTREACHED unless FEATURE_GRACEFUL_TERMINATION is defined */
6194 :
6195 : #ifdef FEATURE_GRACEFUL_TERMINATION
6196 :
6197 : log_error(LOG_LEVEL_INFO, "Graceful termination requested.");
6198 :
6199 : unload_current_config_file();
6200 : unload_current_actions_file();
6201 : unload_current_re_filterfile();
6202 : #ifdef FEATURE_TRUST
6203 : unload_current_trust_file();
6204 : #endif
6205 :
6206 : if (config->multi_threaded)
6207 : {
6208 : int i = 60;
6209 : do
6210 : {
6211 : sleep(1);
6212 : sweep();
6213 : } while ((clients->next != NULL) && (--i > 0));
6214 :
6215 : if (i <= 0)
6216 : {
6217 : log_error(LOG_LEVEL_ERROR, "Graceful termination failed "
6218 : "- still some live clients after 1 minute wait.");
6219 : }
6220 : }
6221 : sweep();
6222 : sweep();
6223 :
6224 : #if defined(unix)
6225 : freez(basedir);
6226 : #endif
6227 :
6228 : #ifdef FEATURE_HTTPS_INSPECTION
6229 : /*
6230 : * Only release TLS backed resources if there
6231 : * are no active connections left.
6232 : */
6233 : if (clients->next == NULL)
6234 : {
6235 : ssl_release();
6236 : }
6237 : #endif
6238 :
6239 : log_error(LOG_LEVEL_INFO, "Exiting gracefully.");
6240 :
6241 : #if defined(_WIN32) && !defined(_WIN_CONSOLE)
6242 : /* Cleanup - remove taskbar icon etc. */
6243 : TermLogWindow();
6244 : #endif
6245 :
6246 : exit(0);
6247 : #endif /* FEATURE_GRACEFUL_TERMINATION */
6248 :
6249 : }
6250 :
6251 :
6252 : /*
6253 : Local Variables:
6254 : tab-width: 3
6255 : end:
6256 : */
|