X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=gateway.c;h=5c2f68e8637d8f981fcd3e4028980d5053abac43;hp=81b9b81a608f9596f907b5e53456506f3a0ec0c6;hb=e8069fb6e7863d3aeea9951c576451f144cac728;hpb=ea1124f5af4c17cb917bae403c9108563d0e4ff8 diff --git a/gateway.c b/gateway.c index 81b9b81a..5c2f68e8 100644 --- a/gateway.c +++ b/gateway.c @@ -1,4 +1,4 @@ -const char gateway_rcs[] = "$Id: gateway.c,v 1.92 2012/10/23 10:16:52 fabiankeil Exp $"; +const char gateway_rcs[] = "$Id: gateway.c,v 1.98 2016/10/25 10:45:56 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/gateway.c,v $ @@ -7,7 +7,7 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.92 2012/10/23 10:16:52 fabiankeil * using a "forwarder" (i.e. HTTP proxy and/or a SOCKS4 * or SOCKS5 proxy). * - * Copyright : Written by and Copyright (C) 2001-2009 the + * Copyright : Written by and Copyright (C) 2001-2016 the * Privoxy team. http://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -67,6 +67,7 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.92 2012/10/23 10:16:52 fabiankeil #include "gateway.h" #include "miscutil.h" #include "list.h" +#include "parsers.h" #ifdef FEATURE_CONNECTION_KEEP_ALIVE #ifdef HAVE_POLL @@ -634,6 +635,7 @@ jb_socket forwarded_connect(const struct forward_spec * fwd, switch (fwd->type) { case SOCKS_NONE: + case FORWARD_WEBSERVER: sfd = connect_to(dest_host, dest_port, csp); break; case SOCKS_4: @@ -893,7 +895,7 @@ static const char *translate_socks5_error(int socks_error) case SOCKS5_REQUEST_NETWORK_UNREACHABLE: return "SOCKS5 network unreachable"; case SOCKS5_REQUEST_HOST_UNREACHABLE: - return "SOCKS5 host unreachable"; + return "SOCKS5 destination host unreachable"; case SOCKS5_REQUEST_CONNECTION_REFUSED: return "SOCKS5 connection refused"; case SOCKS5_REQUEST_TTL_EXPIRED: @@ -933,9 +935,12 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, int target_port, struct client_state *csp) { +#define SIZE_SOCKS5_REPLY_IPV4 10 +#define SIZE_SOCKS5_REPLY_IPV6 22 +#define SOCKS5_REPLY_DIFFERENCE (SIZE_SOCKS5_REPLY_IPV6 - SIZE_SOCKS5_REPLY_IPV4) int err = 0; char cbuf[300]; - char sbuf[10]; + char sbuf[SIZE_SOCKS5_REPLY_IPV6]; size_t client_pos = 0; int server_size = 0; size_t hostlen = 0; @@ -1082,14 +1087,11 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, } /* - * Optimistically send the request headers with the initial - * request if the user requested use of Tor extensions, the - * CONNECT method isn't being used (in which case the client + * Optimistically send the HTTP request with the initial + * SOCKS request if the user enabled the use of Tor extensions, + * the CONNECT method isn't being used (in which case the client * doesn't send data until it gets our 200 response) and the - * client request has been already read completely. - * - * Not optimistically sending the request body (if there is one) - * makes it easier to implement, but isn't an actual requirement. + * client request has actually been completely read already. */ if ((fwd->type == SOCKS_5T) && (csp->http->ssl == 0) && (csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)) @@ -1116,10 +1118,27 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, return(JB_INVALID_SOCKET); } freez(client_headers); + if (csp->expected_client_content_length != 0) + { + unsigned long long buffered_request_bytes = + (unsigned long long)(csp->client_iob->eod - csp->client_iob->cur); + log_error(LOG_LEVEL_CONNECT, + "Optimistically sending %d bytes of client body. Expected %d", + csp->expected_client_content_length, buffered_request_bytes); + assert(csp->expected_client_content_length == buffered_request_bytes); + if (write_socket(sfd, csp->client_iob->cur, buffered_request_bytes)) + { + log_error(LOG_LEVEL_CONNECT, + "optimistically writing %d bytes of client body to: %s failed: %E", + buffered_request_bytes, csp->http->hostport); + return(JB_INVALID_SOCKET); + } + clear_iob(csp->client_iob); + } } - server_size = read_socket(sfd, sbuf, sizeof(sbuf)); - if (server_size != sizeof(sbuf)) + server_size = read_socket(sfd, sbuf, SIZE_SOCKS5_REPLY_IPV4); + if (server_size != SIZE_SOCKS5_REPLY_IPV4) { errstr = "SOCKS5 negotiation read failed"; } @@ -1139,7 +1158,28 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, } else { - return(sfd); + if (sbuf[3] == '\x04') + { + /* + * The address field contains an IPv6 address + * which means we didn't get the whole reply + * yet. Read and discard the rest of it to make + * sure it isn't treated as HTTP data later on. + */ + server_size = read_socket(sfd, sbuf, SOCKS5_REPLY_DIFFERENCE); + if (server_size != SOCKS5_REPLY_DIFFERENCE) + { + errstr = "SOCKS5 negotiation read failed (IPv6 address)"; + } + } + else if (sbuf[3] != '\x01') + { + errstr = "SOCKS5 reply contains unsupported address type"; + } + if (errstr == NULL) + { + return(sfd); + } } }