From: Jacob Nevins Date: Fri, 10 Oct 2003 21:20:01 +0000 (+0000) Subject: In SOCKS5 dynamic forwarding, we were echoing back DST.{ADDR,PORT} as X-Git-Tag: r8855-g4f798d~1306 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=a30da397be40ad505413e37b6041b840b96040f9;p=PuTTY_svn.git In SOCKS5 dynamic forwarding, we were echoing back DST.{ADDR,PORT} as BND.{ADDR,PORT}. Besides being clearly wrong, correspondence with Sascha Schwarz suggests that this can confuse some SOCKS5 clients (Aventail and sockscap32) which seem to assume that the reply must have ATYP=1 (IPv4 literal) and so get the length wrong. Now all replies have ATYP=1 with BND.{ADDR,PORT} = 0.0.0.0:0 -- this apparently follows practice in OpenSSH. (We don't have enough info to fill these fields in correctly.) git-svn-id: http://svn.tartarus.org/sgt/putty@3496 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/portfwd.c b/portfwd.c index e61c05b4..a8c8b045 100644 --- a/portfwd.c +++ b/portfwd.c @@ -108,6 +108,7 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) if (pr->dynamic) { while (len--) { if (pr->port >= lenof(pr->hostname)) { + /* Request too long. */ if ((pr->dynamic >> 12) == 4) { /* Send back a SOCKS 4 error before closing. */ char data[8]; @@ -220,7 +221,23 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) } if (pr->dynamic == 0x5001) { + /* + * We're receiving a SOCKS request. + */ + unsigned char reply[10]; /* SOCKS5 atyp=1 reply */ int atype, alen = 0; + + /* + * Pre-fill reply packet. + * In all cases, we set BND.{HOST,ADDR} to 0.0.0.0:0 + * (atyp=1) in the reply; if we succeed, we don't know + * the right answers, and if we fail, they should be + * ignored. + */ + memset(reply, 0, lenof(reply)); + reply[0] = 5; /* VER */ + reply[3] = 1; /* ATYP = 1 (IPv4, 0.0.0.0:0) */ + if (pr->port < 6) continue; atype = (unsigned char)pr->hostname[3]; if (atype == 1) /* IPv4 address */ @@ -231,9 +248,9 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) alen = 1 + (unsigned char)pr->hostname[4]; if (pr->port < 6 + alen) continue; if (pr->hostname[1] != 1 || pr->hostname[2] != 0) { - pr->hostname[1] = 1; /* generic failure */ - pr->hostname[2] = 0; /* reserved */ - sk_write(pr->s, pr->hostname, pr->port); + /* Not CONNECT or reserved field nonzero - error */ + reply[1] = 1; /* generic failure */ + sk_write(pr->s, reply, lenof(reply)); pfd_close(pr->s); return 1; } @@ -243,8 +260,8 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) */ pr->port = GET_16BIT_MSB_FIRST(pr->hostname+4+alen); if (atype == 1) { - pr->hostname[1] = 0; /* succeeded */ - sk_write(pr->s, pr->hostname, alen + 6); + /* REP=0 (success) already */ + sk_write(pr->s, reply, lenof(reply)); sprintf(pr->hostname, "%d.%d.%d.%d", (unsigned char)pr->hostname[4], (unsigned char)pr->hostname[5], @@ -252,8 +269,8 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) (unsigned char)pr->hostname[7]); goto connect; } else if (atype == 3) { - pr->hostname[1] = 0; /* succeeded */ - sk_write(pr->s, pr->hostname, alen + 6); + /* REP=0 (success) already */ + sk_write(pr->s, reply, lenof(reply)); memmove(pr->hostname, pr->hostname + 5, alen-1); pr->hostname[alen-1] = '\0'; goto connect; @@ -261,8 +278,8 @@ static int pfd_receive(Plug plug, int urgent, char *data, int len) /* * Unknown address type. (FIXME: support IPv6!) */ - pr->hostname[1] = 8; /* atype not supported */ - sk_write(pr->s, pr->hostname, pr->port); + reply[1] = 8; /* atype not supported */ + sk_write(pr->s, reply, lenof(reply)); pfd_close(pr->s); return 1; }