SocksCmdRequest and SocksCmdResponse are trying to convert host from IDN for the non-DOMAIN address types
Motivation: In the SocksCmdRequest and SocksCmdResponse constructors a host param converts from IDN to ascii compatible form regardless address type. Modifications: Use `IDN#toASCII` only for `DOMAIN` address type. Result: More correct host handling in socks commands.
This commit is contained in:
parent
f35047765f
commit
8d0e0922a5
@ -51,9 +51,11 @@ public final class SocksCmdRequest extends SocksRequest {
|
||||
}
|
||||
break;
|
||||
case DOMAIN:
|
||||
if (IDN.toASCII(host).length() > 255) {
|
||||
throw new IllegalArgumentException(host + " IDN: " + IDN.toASCII(host) + " exceeds 255 char limit");
|
||||
String asciiHost = IDN.toASCII(host);
|
||||
if (asciiHost.length() > 255) {
|
||||
throw new IllegalArgumentException(host + " IDN: " + asciiHost + " exceeds 255 char limit");
|
||||
}
|
||||
host = asciiHost;
|
||||
break;
|
||||
case IPv6:
|
||||
if (!NetUtil.isValidIpV6Address(host)) {
|
||||
@ -68,7 +70,7 @@ public final class SocksCmdRequest extends SocksRequest {
|
||||
}
|
||||
this.cmdType = cmdType;
|
||||
this.addressType = addressType;
|
||||
this.host = IDN.toASCII(host);
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@ -96,7 +98,7 @@ public final class SocksCmdRequest extends SocksRequest {
|
||||
* @return host that is used as a parameter in {@link SocksCmdType}
|
||||
*/
|
||||
public String host() {
|
||||
return IDN.toUnicode(host);
|
||||
return addressType == SocksAddressType.DOMAIN ? IDN.toUnicode(host) : host;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,10 +75,11 @@ public final class SocksCmdResponse extends SocksResponse {
|
||||
}
|
||||
break;
|
||||
case DOMAIN:
|
||||
if (IDN.toASCII(host).length() > 255) {
|
||||
throw new IllegalArgumentException(host + " IDN: " +
|
||||
IDN.toASCII(host) + " exceeds 255 char limit");
|
||||
String asciiHost = IDN.toASCII(host);
|
||||
if (asciiHost.length() > 255) {
|
||||
throw new IllegalArgumentException(host + " IDN: " + asciiHost + " exceeds 255 char limit");
|
||||
}
|
||||
host = asciiHost;
|
||||
break;
|
||||
case IPv6:
|
||||
if (!NetUtil.isValidIpV6Address(host)) {
|
||||
@ -88,7 +89,6 @@ public final class SocksCmdResponse extends SocksResponse {
|
||||
case UNKNOWN:
|
||||
break;
|
||||
}
|
||||
host = IDN.toASCII(host);
|
||||
}
|
||||
if (port < 0 || port > 65535) {
|
||||
throw new IllegalArgumentException(port + " is not in bounds 0 <= x <= 65535");
|
||||
@ -126,11 +126,7 @@ public final class SocksCmdResponse extends SocksResponse {
|
||||
* or null when there was no host specified during response construction
|
||||
*/
|
||||
public String host() {
|
||||
if (host != null) {
|
||||
return IDN.toUnicode(host);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return host != null && addressType == SocksAddressType.DOMAIN ? IDN.toUnicode(host) : host;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,8 +15,13 @@
|
||||
*/
|
||||
package io.netty.handler.codec.socks;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.IDN;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksCmdRequestTest {
|
||||
@ -72,6 +77,51 @@ public class SocksCmdRequestTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostNotEncodedForUnknown() {
|
||||
String asciiHost = "xn--e1aybc.xn--p1ai";
|
||||
short port = 10000;
|
||||
|
||||
SocksCmdRequest rq = new SocksCmdRequest(SocksCmdType.BIND, SocksAddressType.UNKNOWN, asciiHost, port);
|
||||
assertEquals(asciiHost, rq.host());
|
||||
|
||||
ByteBuf buffer = Unpooled.buffer(16);
|
||||
rq.encodeAsByteBuf(buffer);
|
||||
|
||||
buffer.resetReaderIndex();
|
||||
assertEquals(SocksProtocolVersion.SOCKS5.byteValue(), buffer.readByte());
|
||||
assertEquals(SocksCmdType.BIND.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) 0x00, buffer.readByte());
|
||||
assertEquals(SocksAddressType.UNKNOWN.byteValue(), buffer.readByte());
|
||||
assertFalse(buffer.isReadable());
|
||||
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIDNEncodeToAsciiForDomain() {
|
||||
String host = "тест.рф";
|
||||
String asciiHost = IDN.toASCII(host);
|
||||
short port = 10000;
|
||||
|
||||
SocksCmdRequest rq = new SocksCmdRequest(SocksCmdType.BIND, SocksAddressType.DOMAIN, host, port);
|
||||
assertEquals(host, rq.host());
|
||||
|
||||
ByteBuf buffer = Unpooled.buffer(24);
|
||||
rq.encodeAsByteBuf(buffer);
|
||||
|
||||
buffer.resetReaderIndex();
|
||||
assertEquals(SocksProtocolVersion.SOCKS5.byteValue(), buffer.readByte());
|
||||
assertEquals(SocksCmdType.BIND.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) 0x00, buffer.readByte());
|
||||
assertEquals(SocksAddressType.DOMAIN.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) asciiHost.length(), buffer.readUnsignedByte());
|
||||
assertEquals(asciiHost, buffer.readCharSequence(asciiHost.length(), CharsetUtil.US_ASCII));
|
||||
assertEquals(port, buffer.readUnsignedShort());
|
||||
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidPortRange() {
|
||||
try {
|
||||
|
@ -17,8 +17,11 @@ package io.netty.handler.codec.socks;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.IDN;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SocksCmdResponseTest {
|
||||
@ -108,6 +111,51 @@ public class SocksCmdResponseTest {
|
||||
assertByteBufEquals(expected, buffer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostNotEncodedForUnknown() {
|
||||
String asciiHost = "xn--e1aybc.xn--p1ai";
|
||||
short port = 10000;
|
||||
|
||||
SocksCmdResponse rs = new SocksCmdResponse(SocksCmdStatus.SUCCESS, SocksAddressType.UNKNOWN, asciiHost, port);
|
||||
assertEquals(asciiHost, rs.host());
|
||||
|
||||
ByteBuf buffer = Unpooled.buffer(16);
|
||||
rs.encodeAsByteBuf(buffer);
|
||||
|
||||
buffer.resetReaderIndex();
|
||||
assertEquals(SocksProtocolVersion.SOCKS5.byteValue(), buffer.readByte());
|
||||
assertEquals(SocksCmdStatus.SUCCESS.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) 0x00, buffer.readByte());
|
||||
assertEquals(SocksAddressType.UNKNOWN.byteValue(), buffer.readByte());
|
||||
assertFalse(buffer.isReadable());
|
||||
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIDNEncodeToAsciiForDomain() {
|
||||
String host = "тест.рф";
|
||||
String asciiHost = IDN.toASCII(host);
|
||||
short port = 10000;
|
||||
|
||||
SocksCmdResponse rs = new SocksCmdResponse(SocksCmdStatus.SUCCESS, SocksAddressType.DOMAIN, host, port);
|
||||
assertEquals(host, rs.host());
|
||||
|
||||
ByteBuf buffer = Unpooled.buffer(24);
|
||||
rs.encodeAsByteBuf(buffer);
|
||||
|
||||
buffer.resetReaderIndex();
|
||||
assertEquals(SocksProtocolVersion.SOCKS5.byteValue(), buffer.readByte());
|
||||
assertEquals(SocksCmdStatus.SUCCESS.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) 0x00, buffer.readByte());
|
||||
assertEquals(SocksAddressType.DOMAIN.byteValue(), buffer.readByte());
|
||||
assertEquals((byte) asciiHost.length(), buffer.readUnsignedByte());
|
||||
assertEquals(asciiHost, buffer.readCharSequence(asciiHost.length(), CharsetUtil.US_ASCII));
|
||||
assertEquals(port, buffer.readUnsignedShort());
|
||||
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that Response cannot be constructed with invalid IP.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user