ARTEMIS-298 IPv6 escape broken

Previously we were using a long regular expression to detect whether or not a
given host was IPv6. However, this was brittle and hard to read. Since we are
already shipping Google Guava in the distribution it made sense to use the
Guava method com.google.common.net.InetAddresses#isInetAddress rather than
the regular expression.
This commit is contained in:
jbertram 2015-11-03 16:29:27 -06:00
parent 44b061d049
commit 4d54e43ddc
3 changed files with 36 additions and 46 deletions

View File

@ -55,6 +55,11 @@
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View File

@ -17,37 +17,30 @@
package org.apache.activemq.artemis.utils;
import java.util.regex.Pattern;
import com.google.common.net.InetAddresses;
public class IPV6Util {
// regex from http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
private static final Pattern IPV6 = Pattern.compile("(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" + // 1:2:3:4:5:6:7:8
"([0-9a-fA-F]{1,4}:){1,7}:|" + // 1:: 1:2:3:4:5:6:7::
"([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" + // 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8
"([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|" + // 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8
"([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" + // 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8
"([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|" + // 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8
"([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" + // 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8
"[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|" + // 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8
":((:[0-9a-fA-F]{1,4}){1,7}|:)|" + // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::
"[fF][eE]80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|" + // fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index)
"::([fF]{4}(:0{1,4}){0,1}:){0,1}" +
"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}" +
"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|" + // ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
"([0-9a-fA-F]{1,4}:){1,4}:" +
"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}" +
"(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"); // 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
/**
* It will enclose an IPV6 host with [], that we need before building URIs
* */
*/
public static String encloseHost(final String host) {
if (host != null && IPV6.matcher(host).matches()) {
return "[" + host + "]";
}
else {
return host;
// if the host contains a ':' then we know it's not IPv4
if (host != null && host.contains(":")) {
String hostToCheck = host;
/* strip off zone index since com.google.common.net.InetAddresses.isInetAddress() doesn't support it
* see https://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices for more info
*/
if (host.contains("%")) {
hostToCheck = host.substring(0, host.indexOf("%"));
}
if (InetAddresses.isInetAddress(hostToCheck)) {
return "[" + host + "]";
}
}
return host;
}
}
}

View File

@ -55,7 +55,7 @@ public class ConnectionFactoryURITest {
ConnectionFactoryParser parser = new ConnectionFactoryParser();
private static final String IPV6 = "fe80::baf6:b1ff:fe12:daf7%eth0";
private static final String[] V6IPs = {"fe80::baf6:b1ff:fe12:daf7%eth0", "2620:db8:1:2::1%em1"};
private static Set<String> ignoreList = new HashSet<String>();
@ -67,30 +67,22 @@ public class ConnectionFactoryURITest {
@Test
public void testIPv6() throws Exception {
Map<String,Object> params = new HashMap<>();
params.put("host", IPV6);
params.put("port", 5445);
TransportConfiguration transport = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transport);
for (String IPV6 : V6IPs) {
Map<String, Object> params = new HashMap<>();
params.put("host", IPV6);
params.put("port", 5445);
TransportConfiguration transport = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transport);
persistIP6(IPV6, factory);
}
@Test
public void testIPv6_2() throws Exception {
Map<String,Object> params = new HashMap<>();
params.put("host", "[" + IPV6 + "]");
params.put("port", 5445);
TransportConfiguration transport = new TransportConfiguration(NettyConnectorFactory.class.getName(), params);
ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transport);
persistIP6(IPV6, factory);
persistIP6(IPV6, factory);
}
}
@Test
public void testIPv6NewURI() throws Exception {
persistIP6(IPV6, new ActiveMQConnectionFactory("tcp://[" + IPV6 + "]:5445"));
for (String IPV6 : V6IPs) {
persistIP6(IPV6, new ActiveMQConnectionFactory("tcp://[" + IPV6 + "]:5445"));
}
}
private void persistIP6(String ipv6, ActiveMQConnectionFactory factory) throws IOException, ClassNotFoundException {