зеркало из https://github.com/github/putty.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.) [originally from svn r3496]
This commit is contained in:
Родитель
c8a6df1e1c
Коммит
4de860abcf
35
portfwd.c
35
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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче