From 55a90b73e52e8ecd2f82fe34c11999252b64d02e Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Tue, 25 Oct 2016 10:43:00 +0000 Subject: [PATCH] socks5_connect(): Properly deal with socks replies that contain IPv6 addresses Previously parts of the reply were left unread and later on treated as invalid HTTP response data. Fixes #904 reported by Danny Goossen who also provided the initial version of this patch. --- gateway.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/gateway.c b/gateway.c index 22efba5e..304ecd49 100644 --- a/gateway.c +++ b/gateway.c @@ -1,4 +1,4 @@ -const char gateway_rcs[] = "$Id: gateway.c,v 1.95 2015/08/12 10:37:11 fabiankeil Exp $"; +const char gateway_rcs[] = "$Id: gateway.c,v 1.96 2016/01/16 12:30:43 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/gateway.c,v $ @@ -935,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; @@ -1134,8 +1137,8 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, } } - 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"; } @@ -1155,7 +1158,24 @@ 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)"; + } + } + if (errstr == NULL) + { + return(sfd); + } } } -- 2.39.2