You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2025/12/15 11:10:58 UTC
(logging-log4j2) 01/06: Fix host name verification in `SslSocketManager`
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch verifyHostName
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit bc40056ffd0ead76b31c5f629b82ab7c2962974f
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Tue Dec 2 10:46:05 2025 +0100
Fix host name verification in `SslSocketManager`
---
.../log4j/core/net/ssl/SslSocketManagerTest.java | 62 +-
.../net/ssl/internal/InetAddressValidatorTest.java | 1082 ++++++++++++++++++++
.../logging/log4j/core/net/SslSocketManager.java | 61 +-
.../log4j/core/net/ssl/SslConfiguration.java | 12 +-
.../net/ssl/internal/InetAddressValidator.java | 171 ++++
5 files changed, 1356 insertions(+), 32 deletions(-)
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
index 85db9e8f0c..e9a748202c 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/SslSocketManagerTest.java
@@ -16,30 +16,64 @@
*/
package org.apache.logging.log4j.core.net.ssl;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.core.net.SslSocketManager;
+import org.apache.logging.log4j.test.junit.UsingStatusListener;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.Issue;
class SslSocketManagerTest {
- @Issue("https://github.com/apache/logging-log4j2/issues/3947")
+
+ private static final String HOST_NAME = "apache.org";
+
+ private static final int HOST_PORT = 443;
+
+ private static final Layout<?> LAYOUT = PatternLayout.createDefaultLayout();
+
@Test
- void shouldNotThrowExceptionWhenConfiguringTrustStore() {
- final TrustStoreConfiguration trustStoreConfiguration = assertDoesNotThrow(() -> new TrustStoreConfiguration(
+ @Issue("https://github.com/apache/logging-log4j2/issues/3947")
+ @UsingStatusListener // Suppresses `StatusLogger` output, unless there is a failure
+ void should_not_throw_exception_when_configuration_without_KeyStore() throws Exception {
+ final TrustStoreConfiguration trustStoreConfig = new TrustStoreConfiguration(
SslKeyStoreConstants.TRUSTSTORE_LOCATION,
SslKeyStoreConstants::TRUSTSTORE_PWD,
SslKeyStoreConstants.TRUSTSTORE_TYPE,
- null));
- final SslConfiguration sslConfiguration =
- SslConfiguration.createSSLConfiguration(null, null, trustStoreConfiguration);
- assertDoesNotThrow(() -> {
- // noinspection EmptyTryBlock (try-with-resources to close `SslSocketManager`, even on failure
- try (final SslSocketManager ignored = SslSocketManager.getSocketManager(
- sslConfiguration, "localhost", 0, 0, 0, true, PatternLayout.createDefaultLayout(), 8192, null)) {
- // Do nothing
- }
- });
+ null);
+ final SslConfiguration sslConfig = SslConfiguration.createSSLConfiguration(null, null, trustStoreConfig);
+ assertThatCode(() -> {
+ // noinspection EmptyTryBlock
+ try (final SslSocketManager ignored = createSocketManager(sslConfig)) {
+ // Do nothing
+ }
+ })
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void host_name_verification_should_take_effect() {
+ final SslConfiguration sslConfig = SslConfiguration.createSSLConfiguration(
+ null,
+ null,
+ null,
+ // Explicitly enable hostname verification
+ true);
+ try (final SslSocketManager ssm = createSocketManager(sslConfig)) {
+ final SSLSocket sslSocket = (SSLSocket) ssm.getSocket();
+ final SSLParameters sslParams = sslSocket.getSSLParameters();
+ assertThat(sslParams.getEndpointIdentificationAlgorithm()).isEqualTo("HTTPS");
+ assertThat(sslParams.getServerNames()).containsOnly(new SNIHostName(HOST_NAME));
+ }
+ }
+
+ private static SslSocketManager createSocketManager(final SslConfiguration sslConfig) {
+ return SslSocketManager.getSocketManager(
+ sslConfig, SslSocketManagerTest.HOST_NAME, HOST_PORT, 0, 0, true, LAYOUT, 8192, null);
}
}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java
new file mode 100644
index 0000000000..4cb3be2eaf
--- /dev/null
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidatorTest.java
@@ -0,0 +1,1082 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core.net.ssl.internal;
+
+import static org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator.isValid;
+import static org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator.isValidInet6Address;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * @see <a href="https://github.com/apache/commons-validator/blob/7c27355d86f7dc5a4a548658745b85c9f0d5b99f/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java"><code>InetAddressValidatorTest</code> of Apache Commons Validator</a>
+ */
+class InetAddressValidatorTest {
+
+ /**
+ * Test obviously broken IPs.
+ */
+ @Test
+ void testBrokenInetAddresses() {
+ assertFalse(isValid("124.14.32.abc"), "IP with characters should be invalid");
+ // TODO: there is some debate as to whether leading zeros should be allowed
+ // They are ambiguous: does the leading 0 mean octal?
+ assertFalse(isValid("124.14.32.01"), "IP with leading zeroes should be invalid");
+ assertFalse(isValid("23.64.12"), "IP with three groups should be invalid");
+ assertFalse(isValid("26.34.23.77.234"), "IP with five groups should be invalid");
+ assertFalse(isValidInet6Address(""), "IP empty string should be invalid"); // empty string
+ }
+
+ /**
+ * Test valid and invalid IPs from each address class.
+ */
+ @Test
+ void testInetAddressesByClass() {
+ assertTrue(isValid("24.25.231.12"), "class A IP should be valid");
+ assertFalse(isValid("2.41.32.324"), "illegal class A IP should be invalid");
+
+ assertTrue(isValid("135.14.44.12"), "class B IP should be valid");
+ assertFalse(isValid("154.123.441.123"), "illegal class B IP should be invalid");
+
+ assertTrue(isValid("213.25.224.32"), "class C IP should be valid");
+ assertFalse(isValid("201.543.23.11"), "illegal class C IP should be invalid");
+
+ assertTrue(isValid("229.35.159.6"), "class D IP should be valid");
+ assertFalse(isValid("231.54.11.987"), "illegal class D IP should be invalid");
+
+ assertTrue(isValid("248.85.24.92"), "class E IP should be valid");
+ assertFalse(isValid("250.21.323.48"), "illegal class E IP should be invalid");
+ }
+
+ /**
+ * Test IPs that point to real, well-known hosts (without actually looking them up).
+ */
+ @Test
+ void testInetAddressesFromTheWild() {
+ assertTrue(isValid("140.211.11.130"), "www.apache.org IP should be valid");
+ assertTrue(isValid("72.14.253.103"), "www.l.google.com IP should be valid");
+ assertTrue(isValid("199.232.41.5"), "fsf.org IP should be valid");
+ assertTrue(isValid("216.35.123.87"), "appscs.ign.com IP should be valid");
+ }
+
+ /**
+ * Test IPv6 addresses.
+ * <p>
+ * These tests were ported from a <a href="https://download.dartware.com/thirdparty/test-ipv6-regex.pl">Perl script</a>.
+ * </p>
+ */
+ @Test
+ void testIPv6() {
+ // The original Perl script contained a lot of duplicate tests.
+ // I removed the duplicates I noticed, but there may be more.
+ assertFalse(isValidInet6Address(""), "IPV6 empty string should be invalid"); // empty string
+ assertTrue(isValidInet6Address("::1"), "IPV6 ::1 should be valid"); // loopback, compressed, non-routable
+ assertTrue(isValidInet6Address("::"), "IPV6 :: should be valid"); // unspecified, compressed, non-routable
+ assertTrue(isValidInet6Address("0:0:0:0:0:0:0:1"), "IPV6 0:0:0:0:0:0:0:1 should be valid"); // loopback, full
+ assertTrue(isValidInet6Address("0:0:0:0:0:0:0:0"), "IPV6 0:0:0:0:0:0:0:0 should be valid"); // unspecified, full
+ assertTrue(
+ isValidInet6Address("2001:DB8:0:0:8:800:200C:417A"),
+ "IPV6 2001:DB8:0:0:8:800:200C:417A should be valid"); // unicast, full
+ assertTrue(
+ isValidInet6Address("FF01:0:0:0:0:0:0:101"),
+ "IPV6 FF01:0:0:0:0:0:0:101 should be valid"); // multicast, full
+ assertTrue(
+ isValidInet6Address("2001:DB8::8:800:200C:417A"),
+ "IPV6 2001:DB8::8:800:200C:417A should be valid"); // unicast, compressed
+ assertTrue(isValidInet6Address("FF01::101"), "IPV6 FF01::101 should be valid"); // multicast, compressed
+ assertFalse(
+ isValidInet6Address("2001:DB8:0:0:8:800:200C:417A:221"),
+ "IPV6 2001:DB8:0:0:8:800:200C:417A:221 should be invalid"); // unicast,
+ // full
+ assertFalse(
+ isValidInet6Address("FF01::101::2"), "IPV6 FF01::101::2 should be invalid"); // multicast, compressed
+ assertTrue(isValidInet6Address("fe80::217:f2ff:fe07:ed62"), "IPV6 fe80::217:f2ff:fe07:ed62 should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876"),
+ "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 should be valid");
+ assertTrue(
+ isValidInet6Address("3ffe:0b00:0000:0000:0001:0000:0000:000a"),
+ "IPV6 3ffe:0b00:0000:0000:0001:0000:0000:000a should be valid");
+ assertTrue(
+ isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0001"),
+ "IPV6 FF02:0000:0000:0000:0000:0000:0000:0001 should be valid");
+ assertTrue(
+ isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0001"),
+ "IPV6 0000:0000:0000:0000:0000:0000:0000:0001 should be valid");
+ assertTrue(
+ isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0000"),
+ "IPV6 0000:0000:0000:0000:0000:0000:0000:0000 should be valid");
+ assertFalse(
+ isValidInet6Address("02001:0000:1234:0000:0000:C1C0:ABCD:0876"),
+ "IPV6 02001:0000:1234:0000:0000:C1C0:ABCD:0876 should be invalid"); // extra 0 not allowed!
+ assertFalse(
+ isValidInet6Address("2001:0000:1234:0000:00001:C1C0:ABCD:0876"),
+ "IPV6 2001:0000:1234:0000:00001:C1C0:ABCD:0876 should be invalid"); // extra 0 not allowed!
+ assertFalse(
+ isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876 0"),
+ "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0 should be invalid"); // junk after valid address
+ assertFalse(
+ isValidInet6Address("2001:0000:1234: 0000:0000:C1C0:ABCD:0876"),
+ "IPV6 2001:0000:1234: 0000:0000:C1C0:ABCD:0876 should be invalid"); // internal space
+ assertFalse(
+ isValidInet6Address("3ffe:0b00:0000:0001:0000:0000:000a"),
+ "IPV6 3ffe:0b00:0000:0001:0000:0000:000a should be invalid"); // seven
+ // segments
+ assertFalse(
+ isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0000:0001"),
+ "IPV6 FF02:0000:0000:0000:0000:0000:0000:0000:0001 should be invalid"); // nine segments
+ assertFalse(isValidInet6Address("3ffe:b00::1::a"), "IPV6 3ffe:b00::1::a should be invalid"); // double "::"
+ assertFalse(
+ isValidInet6Address("::1111:2222:3333:4444:5555:6666::"),
+ "IPV6 ::1111:2222:3333:4444:5555:6666:: should be invalid"); // double
+ // "::"
+ assertTrue(isValidInet6Address("2::10"), "IPV6 2::10 should be valid");
+ assertTrue(isValidInet6Address("ff02::1"), "IPV6 ff02::1 should be valid");
+ assertTrue(isValidInet6Address("fe80::"), "IPV6 fe80:: should be valid");
+ assertTrue(isValidInet6Address("2002::"), "IPV6 2002:: should be valid");
+ assertTrue(isValidInet6Address("2001:db8::"), "IPV6 2001:db8:: should be valid");
+ assertTrue(isValidInet6Address("2001:0db8:1234::"), "IPV6 2001:0db8:1234:: should be valid");
+ assertTrue(isValidInet6Address("::ffff:0:0"), "IPV6 ::ffff:0:0 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5:6:7:8"), "IPV6 1:2:3:4:5:6:7:8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5:6::8"), "IPV6 1:2:3:4:5:6::8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5::8"), "IPV6 1:2:3:4:5::8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4::8"), "IPV6 1:2:3:4::8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3::8"), "IPV6 1:2:3::8 should be valid");
+ assertTrue(isValidInet6Address("1:2::8"), "IPV6 1:2::8 should be valid");
+ assertTrue(isValidInet6Address("1::8"), "IPV6 1::8 should be valid");
+ assertTrue(isValidInet6Address("1::2:3:4:5:6:7"), "IPV6 1::2:3:4:5:6:7 should be valid");
+ assertTrue(isValidInet6Address("1::2:3:4:5:6"), "IPV6 1::2:3:4:5:6 should be valid");
+ assertTrue(isValidInet6Address("1::2:3:4:5"), "IPV6 1::2:3:4:5 should be valid");
+ assertTrue(isValidInet6Address("1::2:3:4"), "IPV6 1::2:3:4 should be valid");
+ assertTrue(isValidInet6Address("1::2:3"), "IPV6 1::2:3 should be valid");
+ assertTrue(isValidInet6Address("::2:3:4:5:6:7:8"), "IPV6 ::2:3:4:5:6:7:8 should be valid");
+ assertTrue(isValidInet6Address("::2:3:4:5:6:7"), "IPV6 ::2:3:4:5:6:7 should be valid");
+ assertTrue(isValidInet6Address("::2:3:4:5:6"), "IPV6 ::2:3:4:5:6 should be valid");
+ assertTrue(isValidInet6Address("::2:3:4:5"), "IPV6 ::2:3:4:5 should be valid");
+ assertTrue(isValidInet6Address("::2:3:4"), "IPV6 ::2:3:4 should be valid");
+ assertTrue(isValidInet6Address("::2:3"), "IPV6 ::2:3 should be valid");
+ assertTrue(isValidInet6Address("::8"), "IPV6 ::8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5:6::"), "IPV6 1:2:3:4:5:6:: should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5::"), "IPV6 1:2:3:4:5:: should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4::"), "IPV6 1:2:3:4:: should be valid");
+ assertTrue(isValidInet6Address("1:2:3::"), "IPV6 1:2:3:: should be valid");
+ assertTrue(isValidInet6Address("1:2::"), "IPV6 1:2:: should be valid");
+ assertTrue(isValidInet6Address("1::"), "IPV6 1:: should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5::7:8"), "IPV6 1:2:3:4:5::7:8 should be valid");
+ assertFalse(isValidInet6Address("1:2:3::4:5::7:8"), "IPV6 1:2:3::4:5::7:8 should be invalid"); // Double "::"
+ assertFalse(isValidInet6Address("12345::6:7:8"), "IPV6 12345::6:7:8 should be invalid");
+ assertTrue(isValidInet6Address("1:2:3:4::7:8"), "IPV6 1:2:3:4::7:8 should be valid");
+ assertTrue(isValidInet6Address("1:2:3::7:8"), "IPV6 1:2:3::7:8 should be valid");
+ assertTrue(isValidInet6Address("1:2::7:8"), "IPV6 1:2::7:8 should be valid");
+ assertTrue(isValidInet6Address("1::7:8"), "IPV6 1::7:8 should be valid");
+ // IPv4 addresses as dotted-quads
+ assertTrue(isValidInet6Address("1:2:3:4:5:6:1.2.3.4"), "IPV6 1:2:3:4:5:6:1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4:5::1.2.3.4"), "IPV6 1:2:3:4:5::1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4::1.2.3.4"), "IPV6 1:2:3:4::1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2:3::1.2.3.4"), "IPV6 1:2:3::1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2::1.2.3.4"), "IPV6 1:2::1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1::1.2.3.4"), "IPV6 1::1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2:3:4::5:1.2.3.4"), "IPV6 1:2:3:4::5:1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2:3::5:1.2.3.4"), "IPV6 1:2:3::5:1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1:2::5:1.2.3.4"), "IPV6 1:2::5:1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1::5:1.2.3.4"), "IPV6 1::5:1.2.3.4 should be valid");
+ assertTrue(isValidInet6Address("1::5:11.22.33.44"), "IPV6 1::5:11.22.33.44 should be valid");
+ assertFalse(isValidInet6Address("1::5:400.2.3.4"), "IPV6 1::5:400.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:260.2.3.4"), "IPV6 1::5:260.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:256.2.3.4"), "IPV6 1::5:256.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.256.3.4"), "IPV6 1::5:1.256.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.256.4"), "IPV6 1::5:1.2.256.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.3.256"), "IPV6 1::5:1.2.3.256 should be invalid");
+ assertFalse(isValidInet6Address("1::5:300.2.3.4"), "IPV6 1::5:300.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.300.3.4"), "IPV6 1::5:1.300.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.300.4"), "IPV6 1::5:1.2.300.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.3.300"), "IPV6 1::5:1.2.3.300 should be invalid");
+ assertFalse(isValidInet6Address("1::5:900.2.3.4"), "IPV6 1::5:900.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.900.3.4"), "IPV6 1::5:1.900.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.900.4"), "IPV6 1::5:1.2.900.4 should be invalid");
+ assertFalse(isValidInet6Address("1::5:1.2.3.900"), "IPV6 1::5:1.2.3.900 should be invalid");
+ assertFalse(isValidInet6Address("1::5:300.300.300.300"), "IPV6 1::5:300.300.300.300 should be invalid");
+ assertFalse(isValidInet6Address("1::5:3000.30.30.30"), "IPV6 1::5:3000.30.30.30 should be invalid");
+ assertFalse(isValidInet6Address("1::400.2.3.4"), "IPV6 1::400.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::260.2.3.4"), "IPV6 1::260.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::256.2.3.4"), "IPV6 1::256.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.256.3.4"), "IPV6 1::1.256.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.256.4"), "IPV6 1::1.2.256.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.3.256"), "IPV6 1::1.2.3.256 should be invalid");
+ assertFalse(isValidInet6Address("1::300.2.3.4"), "IPV6 1::300.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.300.3.4"), "IPV6 1::1.300.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.300.4"), "IPV6 1::1.2.300.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.3.300"), "IPV6 1::1.2.3.300 should be invalid");
+ assertFalse(isValidInet6Address("1::900.2.3.4"), "IPV6 1::900.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.900.3.4"), "IPV6 1::1.900.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.900.4"), "IPV6 1::1.2.900.4 should be invalid");
+ assertFalse(isValidInet6Address("1::1.2.3.900"), "IPV6 1::1.2.3.900 should be invalid");
+ assertFalse(isValidInet6Address("1::300.300.300.300"), "IPV6 1::300.300.300.300 should be invalid");
+ assertFalse(isValidInet6Address("1::3000.30.30.30"), "IPV6 1::3000.30.30.30 should be invalid");
+ assertFalse(isValidInet6Address("::400.2.3.4"), "IPV6 ::400.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::260.2.3.4"), "IPV6 ::260.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::256.2.3.4"), "IPV6 ::256.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.256.3.4"), "IPV6 ::1.256.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.256.4"), "IPV6 ::1.2.256.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.3.256"), "IPV6 ::1.2.3.256 should be invalid");
+ assertFalse(isValidInet6Address("::300.2.3.4"), "IPV6 ::300.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.300.3.4"), "IPV6 ::1.300.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.300.4"), "IPV6 ::1.2.300.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.3.300"), "IPV6 ::1.2.3.300 should be invalid");
+ assertFalse(isValidInet6Address("::900.2.3.4"), "IPV6 ::900.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.900.3.4"), "IPV6 ::1.900.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.900.4"), "IPV6 ::1.2.900.4 should be invalid");
+ assertFalse(isValidInet6Address("::1.2.3.900"), "IPV6 ::1.2.3.900 should be invalid");
+ assertFalse(isValidInet6Address("::300.300.300.300"), "IPV6 ::300.300.300.300 should be invalid");
+ assertFalse(isValidInet6Address("::3000.30.30.30"), "IPV6 ::3000.30.30.30 should be invalid");
+ assertTrue(
+ isValidInet6Address("fe80::217:f2ff:254.7.237.98"), "IPV6 fe80::217:f2ff:254.7.237.98 should be valid");
+ assertTrue(isValidInet6Address("::ffff:192.168.1.26"), "IPV6 ::ffff:192.168.1.26 should be valid");
+ assertFalse(
+ isValidInet6Address("2001:1:1:1:1:1:255Z255X255Y255"),
+ "IPV6 2001:1:1:1:1:1:255Z255X255Y255 should be invalid"); // garbage
+ // instead of "."
+ // in IPv4
+ assertFalse(isValidInet6Address("::ffff:192x168.1.26"), "IPV6 ::ffff:192x168.1.26 should be invalid"); // ditto
+ assertTrue(isValidInet6Address("::ffff:192.168.1.1"), "IPV6 ::ffff:192.168.1.1 should be valid");
+ assertTrue(
+ isValidInet6Address("0:0:0:0:0:0:13.1.68.3"),
+ "IPV6 0:0:0:0:0:0:13.1.68.3 should be valid"); // IPv4-compatible IPv6 address, full,
+ // deprecated
+ assertTrue(
+ isValidInet6Address("0:0:0:0:0:FFFF:129.144.52.38"),
+ "IPV6 0:0:0:0:0:FFFF:129.144.52.38 should be valid"); // IPv4-mapped IPv6
+ // address, full
+ assertTrue(
+ isValidInet6Address("::13.1.68.3"),
+ "IPV6 ::13.1.68.3 should be valid"); // IPv4-compatible IPv6 address, compressed, deprecated
+ assertTrue(
+ isValidInet6Address("::FFFF:129.144.52.38"),
+ "IPV6 ::FFFF:129.144.52.38 should be valid"); // IPv4-mapped IPv6 address, compressed
+ assertTrue(
+ isValidInet6Address("fe80:0:0:0:204:61ff:254.157.241.86"),
+ "IPV6 fe80:0:0:0:204:61ff:254.157.241.86 should be valid");
+ assertTrue(
+ isValidInet6Address("fe80::204:61ff:254.157.241.86"),
+ "IPV6 fe80::204:61ff:254.157.241.86 should be valid");
+ assertTrue(isValidInet6Address("::ffff:12.34.56.78"), "IPV6 ::ffff:12.34.56.78 should be valid");
+ assertFalse(isValidInet6Address("::ffff:2.3.4"), "IPV6 ::ffff:2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::ffff:257.1.2.3"), "IPV6 ::ffff:257.1.2.3 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1.2.3.4:1111:2222:3333:4444::5555"),
+ "IPV6 1.2.3.4:1111:2222:3333:4444::5555 should be invalid");
+ assertFalse(
+ isValidInet6Address("1.2.3.4:1111:2222:3333::5555"),
+ "IPV6 1.2.3.4:1111:2222:3333::5555 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4:1111:2222::5555"), "IPV6 1.2.3.4:1111:2222::5555 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4:1111::5555"), "IPV6 1.2.3.4:1111::5555 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4::5555"), "IPV6 1.2.3.4::5555 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4::"), "IPV6 1.2.3.4:: should be invalid");
+ // Testing IPv4 addresses represented as dotted-quads
+ // Leading zeroes in IPv4 addresses not allowed: some systems treat the leading "0" in ".086" as the start of an
+ // octal number
+ // Update: The BNF in RFC-3986 explicitly defines the dec-octet (for IPv4 addresses) not to have a leading zero
+ assertFalse(
+ isValidInet6Address("fe80:0000:0000:0000:0204:61ff:254.157.241.086"),
+ "IPV6 fe80:0000:0000:0000:0204:61ff:254.157.241.086 should be invalid");
+ assertTrue(
+ isValidInet6Address("::ffff:192.0.2.128"),
+ "IPV6 ::ffff:192.0.2.128 should be valid"); // but this is OK, since there's a single
+ // digit
+ assertFalse(
+ isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4"),
+ "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:00.00.00.00"),
+ "IPV6 1111:2222:3333:4444:5555:6666:00.00.00.00 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:000.000.000.000"),
+ "IPV6 1111:2222:3333:4444:5555:6666:000.000.000.000 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:256.256.256.256"),
+ "IPV6 1111:2222:3333:4444:5555:6666:256.256.256.256 should be invalid");
+ assertTrue(
+ isValidInet6Address("fe80:0000:0000:0000:0204:61ff:fe9d:f156"),
+ "IPV6 fe80:0000:0000:0000:0204:61ff:fe9d:f156 should be valid");
+ assertTrue(
+ isValidInet6Address("fe80:0:0:0:204:61ff:fe9d:f156"),
+ "IPV6 fe80:0:0:0:204:61ff:fe9d:f156 should be valid");
+ assertTrue(isValidInet6Address("fe80::204:61ff:fe9d:f156"), "IPV6 fe80::204:61ff:fe9d:f156 should be valid");
+ assertFalse(isValidInet6Address(":"), "IPV6 : should be invalid");
+ assertTrue(isValidInet6Address("::ffff:c000:280"), "IPV6 ::ffff:c000:280 should be valid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::5555:"), "IPV6 1111:2222:3333:4444::5555: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333::5555:"), "IPV6 1111:2222:3333::5555: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222::5555:"), "IPV6 1111:2222::5555: should be invalid");
+ assertFalse(isValidInet6Address("1111::5555:"), "IPV6 1111::5555: should be invalid");
+ assertFalse(isValidInet6Address("::5555:"), "IPV6 ::5555: should be invalid");
+ assertFalse(isValidInet6Address(":::"), "IPV6 ::: should be invalid");
+ assertFalse(isValidInet6Address("1111:"), "IPV6 1111: should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::5555"), "IPV6 :1111:2222:3333:4444::5555 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222:3333::5555"), "IPV6 :1111:2222:3333::5555 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::5555"), "IPV6 :1111:2222::5555 should be invalid");
+ assertFalse(isValidInet6Address(":1111::5555"), "IPV6 :1111::5555 should be invalid");
+ assertFalse(isValidInet6Address(":::5555"), "IPV6 :::5555 should be invalid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
+ "IPV6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 should be valid");
+ assertTrue(
+ isValidInet6Address("2001:db8:85a3:0:0:8a2e:370:7334"),
+ "IPV6 2001:db8:85a3:0:0:8a2e:370:7334 should be valid");
+ assertTrue(
+ isValidInet6Address("2001:db8:85a3::8a2e:370:7334"),
+ "IPV6 2001:db8:85a3::8a2e:370:7334 should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:0000:0000:0000:0000:1428:57ab"),
+ "IPV6 2001:0db8:0000:0000:0000:0000:1428:57ab should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:0000:0000:0000::1428:57ab"),
+ "IPV6 2001:0db8:0000:0000:0000::1428:57ab should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:0:0:0:0:1428:57ab"), "IPV6 2001:0db8:0:0:0:0:1428:57ab should be valid");
+ assertTrue(isValidInet6Address("2001:0db8:0:0::1428:57ab"), "IPV6 2001:0db8:0:0::1428:57ab should be valid");
+ assertTrue(isValidInet6Address("2001:0db8::1428:57ab"), "IPV6 2001:0db8::1428:57ab should be valid");
+ assertTrue(isValidInet6Address("2001:db8::1428:57ab"), "IPV6 2001:db8::1428:57ab should be valid");
+ assertTrue(isValidInet6Address("::ffff:0c22:384e"), "IPV6 ::ffff:0c22:384e should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:1234:0000:0000:0000:0000:0000"),
+ "IPV6 2001:0db8:1234:0000:0000:0000:0000:0000 should be valid");
+ assertTrue(
+ isValidInet6Address("2001:0db8:1234:ffff:ffff:ffff:ffff:ffff"),
+ "IPV6 2001:0db8:1234:ffff:ffff:ffff:ffff:ffff should be valid");
+ assertTrue(isValidInet6Address("2001:db8:a::123"), "IPV6 2001:db8:a::123 should be valid");
+ assertFalse(isValidInet6Address("123"), "IPV6 123 should be invalid");
+ assertFalse(isValidInet6Address("ldkfj"), "IPV6 ldkfj should be invalid");
+ assertFalse(isValidInet6Address("2001::FFD3::57ab"), "IPV6 2001::FFD3::57ab should be invalid");
+ assertFalse(
+ isValidInet6Address("2001:db8:85a3::8a2e:37023:7334"),
+ "IPV6 2001:db8:85a3::8a2e:37023:7334 should be invalid");
+ assertFalse(
+ isValidInet6Address("2001:db8:85a3::8a2e:370k:7334"),
+ "IPV6 2001:db8:85a3::8a2e:370k:7334 should be invalid");
+ assertFalse(isValidInet6Address("1:2:3:4:5:6:7:8:9"), "IPV6 1:2:3:4:5:6:7:8:9 should be invalid");
+ assertFalse(isValidInet6Address("1::2::3"), "IPV6 1::2::3 should be invalid");
+ assertFalse(isValidInet6Address("1:::3:4:5"), "IPV6 1:::3:4:5 should be invalid");
+ assertFalse(isValidInet6Address("1:2:3::4:5:6:7:8:9"), "IPV6 1:2:3::4:5:6:7:8:9 should be invalid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777::"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:: should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666::"),
+ "IPV6 1111:2222:3333:4444:5555:6666:: should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555::"), "IPV6 1111:2222:3333:4444:5555:: should be valid");
+ assertTrue(isValidInet6Address("1111:2222:3333:4444::"), "IPV6 1111:2222:3333:4444:: should be valid");
+ assertTrue(isValidInet6Address("1111:2222:3333::"), "IPV6 1111:2222:3333:: should be valid");
+ assertTrue(isValidInet6Address("1111:2222::"), "IPV6 1111:2222:: should be valid");
+ assertTrue(isValidInet6Address("1111::"), "IPV6 1111:: should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666::8888"),
+ "IPV6 1111:2222:3333:4444:5555:6666::8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555::8888"),
+ "IPV6 1111:2222:3333:4444:5555::8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222:3333:4444::8888"), "IPV6 1111:2222:3333:4444::8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222:3333::8888"), "IPV6 1111:2222:3333::8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222::8888"), "IPV6 1111:2222::8888 should be valid");
+ assertTrue(isValidInet6Address("1111::8888"), "IPV6 1111::8888 should be valid");
+ assertTrue(isValidInet6Address("::8888"), "IPV6 ::8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555::7777:8888"),
+ "IPV6 1111:2222:3333:4444:5555::7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444::7777:8888"),
+ "IPV6 1111:2222:3333:4444::7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222:3333::7777:8888"), "IPV6 1111:2222:3333::7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222::7777:8888"), "IPV6 1111:2222::7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111::7777:8888"), "IPV6 1111::7777:8888 should be valid");
+ assertTrue(isValidInet6Address("::7777:8888"), "IPV6 ::7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444::6666:7777:8888"),
+ "IPV6 1111:2222:3333:4444::6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333::6666:7777:8888"),
+ "IPV6 1111:2222:3333::6666:7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111:2222::6666:7777:8888"), "IPV6 1111:2222::6666:7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111::6666:7777:8888"), "IPV6 1111::6666:7777:8888 should be valid");
+ assertTrue(isValidInet6Address("::6666:7777:8888"), "IPV6 ::6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333::5555:6666:7777:8888"),
+ "IPV6 1111:2222:3333::5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::5555:6666:7777:8888"),
+ "IPV6 1111:2222::5555:6666:7777:8888 should be valid");
+ assertTrue(isValidInet6Address("1111::5555:6666:7777:8888"), "IPV6 1111::5555:6666:7777:8888 should be valid");
+ assertTrue(isValidInet6Address("::5555:6666:7777:8888"), "IPV6 ::5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::4444:5555:6666:7777:8888"),
+ "IPV6 1111:2222::4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::4444:5555:6666:7777:8888"),
+ "IPV6 1111::4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("::4444:5555:6666:7777:8888"), "IPV6 ::4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::3333:4444:5555:6666:7777:8888"),
+ "IPV6 1111::3333:4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("::3333:4444:5555:6666:7777:8888"),
+ "IPV6 ::3333:4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 ::2222:3333:4444:5555:6666:7777:8888 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:123.123.123.123"),
+ "IPV6 1111:2222:3333:4444:5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444:5555::123.123.123.123"),
+ "IPV6 1111:2222:3333:4444:5555::123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444::123.123.123.123"),
+ "IPV6 1111:2222:3333:4444::123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333::123.123.123.123"),
+ "IPV6 1111:2222:3333::123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::123.123.123.123"), "IPV6 1111:2222::123.123.123.123 should be valid");
+ assertTrue(isValidInet6Address("1111::123.123.123.123"), "IPV6 1111::123.123.123.123 should be valid");
+ assertTrue(isValidInet6Address("::123.123.123.123"), "IPV6 ::123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333:4444::6666:123.123.123.123"),
+ "IPV6 1111:2222:3333:4444::6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333::6666:123.123.123.123"),
+ "IPV6 1111:2222:3333::6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::6666:123.123.123.123"),
+ "IPV6 1111:2222::6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::6666:123.123.123.123"), "IPV6 1111::6666:123.123.123.123 should be valid");
+ assertTrue(isValidInet6Address("::6666:123.123.123.123"), "IPV6 ::6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222:3333::5555:6666:123.123.123.123"),
+ "IPV6 1111:2222:3333::5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::5555:6666:123.123.123.123"),
+ "IPV6 1111:2222::5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::5555:6666:123.123.123.123"),
+ "IPV6 1111::5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("::5555:6666:123.123.123.123"), "IPV6 ::5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111:2222::4444:5555:6666:123.123.123.123"),
+ "IPV6 1111:2222::4444:5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::4444:5555:6666:123.123.123.123"),
+ "IPV6 1111::4444:5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("::4444:5555:6666:123.123.123.123"),
+ "IPV6 ::4444:5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("1111::3333:4444:5555:6666:123.123.123.123"),
+ "IPV6 1111::3333:4444:5555:6666:123.123.123.123 should be valid");
+ assertTrue(
+ isValidInet6Address("::2222:3333:4444:5555:6666:123.123.123.123"),
+ "IPV6 ::2222:3333:4444:5555:6666:123.123.123.123 should be valid");
+ // Trying combinations of "0" and "::"
+ // These are all syntactically correct, but are bad form
+ // because "0" adjacent to "::" should be combined into "::"
+ assertTrue(isValidInet6Address("::0:0:0:0:0:0:0"), "IPV6 ::0:0:0:0:0:0:0 should be valid");
+ assertTrue(isValidInet6Address("::0:0:0:0:0:0"), "IPV6 ::0:0:0:0:0:0 should be valid");
+ assertTrue(isValidInet6Address("::0:0:0:0:0"), "IPV6 ::0:0:0:0:0 should be valid");
+ assertTrue(isValidInet6Address("::0:0:0:0"), "IPV6 ::0:0:0:0 should be valid");
+ assertTrue(isValidInet6Address("::0:0:0"), "IPV6 ::0:0:0 should be valid");
+ assertTrue(isValidInet6Address("::0:0"), "IPV6 ::0:0 should be valid");
+ assertTrue(isValidInet6Address("::0"), "IPV6 ::0 should be valid");
+ assertTrue(isValidInet6Address("0:0:0:0:0:0:0::"), "IPV6 0:0:0:0:0:0:0:: should be valid");
+ assertTrue(isValidInet6Address("0:0:0:0:0:0::"), "IPV6 0:0:0:0:0:0:: should be valid");
+ assertTrue(isValidInet6Address("0:0:0:0:0::"), "IPV6 0:0:0:0:0:: should be valid");
+ assertTrue(isValidInet6Address("0:0:0:0::"), "IPV6 0:0:0:0:: should be valid");
+ assertTrue(isValidInet6Address("0:0:0::"), "IPV6 0:0:0:: should be valid");
+ assertTrue(isValidInet6Address("0:0::"), "IPV6 0:0:: should be valid");
+ assertTrue(isValidInet6Address("0::"), "IPV6 0:: should be valid");
+ // Invalid data
+ assertFalse(
+ isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"),
+ "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX should be invalid");
+ // Too many components
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:9999"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:9999 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888::"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:: should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:9999"),
+ "IPV6 ::2222:3333:4444:5555:6666:7777:8888:9999 should be invalid");
+ // Too few components
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666"),
+ "IPV6 1111:2222:3333:4444:5555:6666 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:4444:5555"), "IPV6 1111:2222:3333:4444:5555 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:4444"), "IPV6 1111:2222:3333:4444 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333"), "IPV6 1111:2222:3333 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222"), "IPV6 1111:2222 should be invalid");
+ assertFalse(isValidInet6Address("1111"), "IPV6 1111 should be invalid");
+ // Missing :
+ assertFalse(
+ isValidInet6Address("11112222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 11112222:3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:22223333:4444:5555:6666:7777:8888"),
+ "IPV6 1111:22223333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:33334444:5555:6666:7777:8888"),
+ "IPV6 1111:2222:33334444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:44445555:6666:7777:8888"),
+ "IPV6 1111:2222:3333:44445555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:55556666:7777:8888"),
+ "IPV6 1111:2222:3333:4444:55556666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:66667777:8888"),
+ "IPV6 1111:2222:3333:4444:5555:66667777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:77778888"),
+ "IPV6 1111:2222:3333:4444:5555:6666:77778888 should be invalid");
+ // Missing : intended for ::
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:"),
+ "IPV6 1111:2222:3333:4444:5555:6666: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:"), "IPV6 1111:2222:3333:4444:5555: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:4444:"), "IPV6 1111:2222:3333:4444: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:"), "IPV6 1111:2222:3333: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:"), "IPV6 1111:2222: should be invalid");
+ assertFalse(isValidInet6Address(":8888"), "IPV6 :8888 should be invalid");
+ assertFalse(isValidInet6Address(":7777:8888"), "IPV6 :7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":6666:7777:8888"), "IPV6 :6666:7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":5555:6666:7777:8888"), "IPV6 :5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":4444:5555:6666:7777:8888"), "IPV6 :4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":3333:4444:5555:6666:7777:8888"),
+ "IPV6 :3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 :2222:3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 :1111:2222:3333:4444:5555:6666:7777:8888 should be invalid");
+ // :::
+ assertFalse(
+ isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:::3333:4444:5555:6666:7777:8888"),
+ "IPV6 1111:::3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:::4444:5555:6666:7777:8888"),
+ "IPV6 1111:2222:::4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:::5555:6666:7777:8888"),
+ "IPV6 1111:2222:3333:::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:::6666:7777:8888"),
+ "IPV6 1111:2222:3333:4444:::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:::7777:8888"),
+ "IPV6 1111:2222:3333:4444:5555:::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:::8888"),
+ "IPV6 1111:2222:3333:4444:5555:6666:::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid");
+ // Double ::
+ assertFalse(
+ isValidInet6Address("::2222::4444:5555:6666:7777:8888"),
+ "IPV6 ::2222::4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333::5555:6666:7777:8888"),
+ "IPV6 ::2222:3333::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444::6666:7777:8888"),
+ "IPV6 ::2222:3333:4444::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555::7777:8888"),
+ "IPV6 ::2222:3333:4444:5555::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555:7777::8888"),
+ "IPV6 ::2222:3333:4444:5555:7777::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555:7777:8888::"),
+ "IPV6 ::2222:3333:4444:5555:7777:8888:: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333::5555:6666:7777:8888"),
+ "IPV6 1111::3333::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444::6666:7777:8888"),
+ "IPV6 1111::3333:4444::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444:5555::7777:8888"),
+ "IPV6 1111::3333:4444:5555::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444:5555:6666::8888"),
+ "IPV6 1111::3333:4444:5555:6666::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444:5555:6666:7777::"),
+ "IPV6 1111::3333:4444:5555:6666:7777:: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444::6666:7777:8888"),
+ "IPV6 1111:2222::4444::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444:5555::7777:8888"),
+ "IPV6 1111:2222::4444:5555::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444:5555:6666::8888"),
+ "IPV6 1111:2222::4444:5555:6666::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444:5555:6666:7777::"),
+ "IPV6 1111:2222::4444:5555:6666:7777:: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::5555::7777:8888"),
+ "IPV6 1111:2222:3333::5555::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::5555:6666::8888"),
+ "IPV6 1111:2222:3333::5555:6666::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::5555:6666:7777::"),
+ "IPV6 1111:2222:3333::5555:6666:7777:: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::6666::8888"),
+ "IPV6 1111:2222:3333:4444::6666::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::6666:7777::"),
+ "IPV6 1111:2222:3333:4444::6666:7777:: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555::7777::"),
+ "IPV6 1111:2222:3333:4444:5555::7777:: should be invalid");
+ // Too many components"
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666::1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:6666::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555:6666:7777:1.2.3.4"),
+ "IPV6 ::2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:1.2.3.4.5"),
+ "IPV6 1111:2222:3333:4444:5555:6666:1.2.3.4.5 should be invalid");
+ // Too few components
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:1.2.3.4"), "IPV6 1111:2222:3333:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:1.2.3.4"), "IPV6 1111:2222:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1111:1.2.3.4"), "IPV6 1111:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be invalid");
+ // Missing :
+ assertFalse(
+ isValidInet6Address("11112222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 11112222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:22223333:4444:5555:6666:1.2.3.4"),
+ "IPV6 1111:22223333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:33334444:5555:6666:1.2.3.4"),
+ "IPV6 1111:2222:33334444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:44445555:6666:1.2.3.4"),
+ "IPV6 1111:2222:3333:44445555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:55556666:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:55556666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:66661.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:66661.2.3.4 should be invalid");
+ // Missing .
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:255255.255.255"),
+ "IPV6 1111:2222:3333:4444:5555:6666:255255.255.255 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255255.255"),
+ "IPV6 1111:2222:3333:4444:5555:6666:255.255255.255 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255.255255"),
+ "IPV6 1111:2222:3333:4444:5555:6666:255.255.255255 should be invalid");
+ // Missing : intended for ::
+ assertFalse(isValidInet6Address(":1.2.3.4"), "IPV6 :1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":6666:1.2.3.4"), "IPV6 :6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":5555:6666:1.2.3.4"), "IPV6 :5555:6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":4444:5555:6666:1.2.3.4"), "IPV6 :4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":2222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ // :::
+ assertFalse(
+ isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:::3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 1111:::3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:::4444:5555:6666:1.2.3.4"),
+ "IPV6 1111:2222:::4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:::5555:6666:1.2.3.4"),
+ "IPV6 1111:2222:3333:::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:::6666:1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:::1.2.3.4"),
+ "IPV6 1111:2222:3333:4444:5555:::1.2.3.4 should be invalid");
+ // Double ::
+ assertFalse(
+ isValidInet6Address("::2222::4444:5555:6666:1.2.3.4"),
+ "IPV6 ::2222::4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333::5555:6666:1.2.3.4"),
+ "IPV6 ::2222:3333::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444::6666:1.2.3.4"),
+ "IPV6 ::2222:3333:4444::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555::1.2.3.4"),
+ "IPV6 ::2222:3333:4444:5555::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333::5555:6666:1.2.3.4"),
+ "IPV6 1111::3333::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444::6666:1.2.3.4"),
+ "IPV6 1111::3333:4444::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444:5555::1.2.3.4"),
+ "IPV6 1111::3333:4444:5555::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444::6666:1.2.3.4"),
+ "IPV6 1111:2222::4444::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444:5555::1.2.3.4"),
+ "IPV6 1111:2222::4444:5555::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::5555::1.2.3.4"),
+ "IPV6 1111:2222:3333::5555::1.2.3.4 should be invalid");
+ // Missing parts
+ assertFalse(isValidInet6Address("::."), "IPV6 ::. should be invalid");
+ assertFalse(isValidInet6Address("::.."), "IPV6 ::.. should be invalid");
+ assertFalse(isValidInet6Address("::..."), "IPV6 ::... should be invalid");
+ assertFalse(isValidInet6Address("::1..."), "IPV6 ::1... should be invalid");
+ assertFalse(isValidInet6Address("::1.2.."), "IPV6 ::1.2.. should be invalid");
+ assertFalse(isValidInet6Address("::1.2.3."), "IPV6 ::1.2.3. should be invalid");
+ assertFalse(isValidInet6Address("::.2.."), "IPV6 ::.2.. should be invalid");
+ assertFalse(isValidInet6Address("::.2.3."), "IPV6 ::.2.3. should be invalid");
+ assertFalse(isValidInet6Address("::.2.3.4"), "IPV6 ::.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address("::..3."), "IPV6 ::..3. should be invalid");
+ assertFalse(isValidInet6Address("::..3.4"), "IPV6 ::..3.4 should be invalid");
+ assertFalse(isValidInet6Address("::...4"), "IPV6 ::...4 should be invalid");
+ // Extra : in front
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777::"),
+ "IPV6 :1111:2222:3333:4444:5555:6666:7777:: should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666::"),
+ "IPV6 :1111:2222:3333:4444:5555:6666:: should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555::"),
+ "IPV6 :1111:2222:3333:4444:5555:: should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222:3333:4444::"), "IPV6 :1111:2222:3333:4444:: should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222:3333::"), "IPV6 :1111:2222:3333:: should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::"), "IPV6 :1111:2222:: should be invalid");
+ assertFalse(isValidInet6Address(":1111::"), "IPV6 :1111:: should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666::8888"),
+ "IPV6 :1111:2222:3333:4444:5555:6666::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555::8888"),
+ "IPV6 :1111:2222:3333:4444:5555::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::8888"), "IPV6 :1111:2222:3333:4444::8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222:3333::8888"), "IPV6 :1111:2222:3333::8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::8888"), "IPV6 :1111:2222::8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111::8888"), "IPV6 :1111::8888 should be invalid");
+ assertFalse(isValidInet6Address(":::8888"), "IPV6 :::8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555::7777:8888"),
+ "IPV6 :1111:2222:3333:4444:5555::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::7777:8888"),
+ "IPV6 :1111:2222:3333:4444::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333::7777:8888"), "IPV6 :1111:2222:3333::7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::7777:8888"), "IPV6 :1111:2222::7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111::7777:8888"), "IPV6 :1111::7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":::7777:8888"), "IPV6 :::7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::6666:7777:8888"),
+ "IPV6 :1111:2222:3333:4444::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333::6666:7777:8888"),
+ "IPV6 :1111:2222:3333::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222::6666:7777:8888"), "IPV6 :1111:2222::6666:7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":1111::6666:7777:8888"), "IPV6 :1111::6666:7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":::6666:7777:8888"), "IPV6 :::6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333::5555:6666:7777:8888"),
+ "IPV6 :1111:2222:3333::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222::5555:6666:7777:8888"),
+ "IPV6 :1111:2222::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111::5555:6666:7777:8888"), "IPV6 :1111::5555:6666:7777:8888 should be invalid");
+ assertFalse(isValidInet6Address(":::5555:6666:7777:8888"), "IPV6 :::5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222::4444:5555:6666:7777:8888"),
+ "IPV6 :1111:2222::4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111::4444:5555:6666:7777:8888"),
+ "IPV6 :1111::4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":::4444:5555:6666:7777:8888"),
+ "IPV6 :::4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111::3333:4444:5555:6666:7777:8888"),
+ "IPV6 :1111::3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":::3333:4444:5555:6666:7777:8888"),
+ "IPV6 :::3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"),
+ "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444:5555::1.2.3.4"),
+ "IPV6 :1111:2222:3333:4444:5555::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::1.2.3.4"),
+ "IPV6 :1111:2222:3333:4444::1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222:3333::1.2.3.4"), "IPV6 :1111:2222:3333::1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::1.2.3.4"), "IPV6 :1111:2222::1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111::1.2.3.4"), "IPV6 :1111::1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":::1.2.3.4"), "IPV6 :::1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333:4444::6666:1.2.3.4"),
+ "IPV6 :1111:2222:3333:4444::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333::6666:1.2.3.4"),
+ "IPV6 :1111:2222:3333::6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111:2222::6666:1.2.3.4"), "IPV6 :1111:2222::6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111::6666:1.2.3.4"), "IPV6 :1111::6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":::6666:1.2.3.4"), "IPV6 :::6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222:3333::5555:6666:1.2.3.4"),
+ "IPV6 :1111:2222:3333::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222::5555:6666:1.2.3.4"),
+ "IPV6 :1111:2222::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":1111::5555:6666:1.2.3.4"), "IPV6 :1111::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(isValidInet6Address(":::5555:6666:1.2.3.4"), "IPV6 :::5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111:2222::4444:5555:6666:1.2.3.4"),
+ "IPV6 :1111:2222::4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111::4444:5555:6666:1.2.3.4"),
+ "IPV6 :1111::4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":::4444:5555:6666:1.2.3.4"), "IPV6 :::4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":1111::3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :1111::3333:4444:5555:6666:1.2.3.4 should be invalid");
+ assertFalse(
+ isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"),
+ "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+ // Extra : at end
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"),
+ "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666:::"),
+ "IPV6 1111:2222:3333:4444:5555:6666::: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:::"),
+ "IPV6 1111:2222:3333:4444:5555::: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:4444:::"), "IPV6 1111:2222:3333:4444::: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333:::"), "IPV6 1111:2222:3333::: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:::"), "IPV6 1111:2222::: should be invalid");
+ assertFalse(isValidInet6Address("1111:::"), "IPV6 1111::: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555:6666::8888:"),
+ "IPV6 1111:2222:3333:4444:5555:6666::8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555::8888:"),
+ "IPV6 1111:2222:3333:4444:5555::8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::8888:"), "IPV6 1111:2222:3333:4444::8888: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222:3333::8888:"), "IPV6 1111:2222:3333::8888: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222::8888:"), "IPV6 1111:2222::8888: should be invalid");
+ assertFalse(isValidInet6Address("1111::8888:"), "IPV6 1111::8888: should be invalid");
+ assertFalse(isValidInet6Address("::8888:"), "IPV6 ::8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444:5555::7777:8888:"),
+ "IPV6 1111:2222:3333:4444:5555::7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::7777:8888:"),
+ "IPV6 1111:2222:3333:4444::7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::7777:8888:"), "IPV6 1111:2222:3333::7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("1111:2222::7777:8888:"), "IPV6 1111:2222::7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("1111::7777:8888:"), "IPV6 1111::7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("::7777:8888:"), "IPV6 ::7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333:4444::6666:7777:8888:"),
+ "IPV6 1111:2222:3333:4444::6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::6666:7777:8888:"),
+ "IPV6 1111:2222:3333::6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::6666:7777:8888:"), "IPV6 1111:2222::6666:7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("1111::6666:7777:8888:"), "IPV6 1111::6666:7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("::6666:7777:8888:"), "IPV6 ::6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222:3333::5555:6666:7777:8888:"),
+ "IPV6 1111:2222:3333::5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::5555:6666:7777:8888:"),
+ "IPV6 1111:2222::5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::5555:6666:7777:8888:"), "IPV6 1111::5555:6666:7777:8888: should be invalid");
+ assertFalse(isValidInet6Address("::5555:6666:7777:8888:"), "IPV6 ::5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111:2222::4444:5555:6666:7777:8888:"),
+ "IPV6 1111:2222::4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::4444:5555:6666:7777:8888:"),
+ "IPV6 1111::4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("::4444:5555:6666:7777:8888:"),
+ "IPV6 ::4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("1111::3333:4444:5555:6666:7777:8888:"),
+ "IPV6 1111::3333:4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("::3333:4444:5555:6666:7777:8888:"),
+ "IPV6 ::3333:4444:5555:6666:7777:8888: should be invalid");
+ assertFalse(
+ isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:"),
+ "IPV6 ::2222:3333:4444:5555:6666:7777:8888: should be invalid");
+ assertTrue(isValidInet6Address("0:a:b:c:d:e:f::"), "IPV6 0:a:b:c:d:e:f:: should be valid");
+ assertTrue(
+ isValidInet6Address("::0:a:b:c:d:e:f"),
+ "IPV6 ::0:a:b:c:d:e:f should be valid"); // syntactically correct, but bad form (::0:...
+ // could be combined)
+ assertTrue(isValidInet6Address("a:b:c:d:e:f:0::"), "IPV6 a:b:c:d:e:f:0:: should be valid");
+ assertFalse(isValidInet6Address("':10.0.0.1"), "IPV6 ':10.0.0.1 should be invalid");
+ }
+
+ /**
+ * Test reserved IPs.
+ */
+ @Test
+ void testReservedInetAddresses() {
+ assertTrue(isValid("127.0.0.1"), "localhost IP should be valid");
+ assertTrue(isValid("255.255.255.255"), "broadcast IP should be valid");
+ }
+
+ @Test
+ void testValidator335() {
+ assertTrue(
+ isValid("2001:0438:FFFE:0000:0000:0000:0000:0A35"),
+ "2001:0438:FFFE:0000:0000:0000:0000:0A35 should be valid");
+ }
+
+ @Test
+ void testValidator419() {
+ String addr;
+ addr = "0:0:0:0:0:0:13.1.68.3";
+ assertTrue(isValid(addr));
+ addr = "0:0:0:0:0:FFFF:129.144.52.38";
+ assertTrue(isValid(addr), addr);
+ addr = "::13.1.68.3";
+ assertTrue(isValid(addr), addr);
+ addr = "::FFFF:129.144.52.38";
+ assertTrue(isValid(addr), addr);
+
+ addr = "::ffff:192.168.1.1:192.168.1.1";
+ assertFalse(isValid(addr), addr);
+ addr = "::192.168.1.1:192.168.1.1";
+ assertFalse(isValid(addr), addr);
+ }
+
+ /**
+ * Inet6Address may also contain a scope id.
+ */
+ @Test
+ void testValidator445() {
+ final String[] valid = {
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876",
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/123",
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0",
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876%0",
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abcdefgh",
+ };
+ final String[] invalid = {
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/129", // too big
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/-0", // sign not allowed
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/+0", // sign not allowed
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/10O", // non-digit
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0%0", // /bits before %node-id
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc defgh", // space in node id
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc%defgh", // '%' in node id
+ };
+ for (final String item : valid) {
+ assertTrue(isValid(item), item + " should be valid");
+ }
+ for (final String item : invalid) {
+ assertFalse(isValid(item), item + " should be invalid");
+ }
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
index 994f11bbce..70f8e89d28 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SslSocketManager.java
@@ -30,19 +30,22 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
+import org.apache.logging.log4j.core.net.ssl.internal.InetAddressValidator;
import org.apache.logging.log4j.util.Strings;
-/**
- *
- */
public class SslSocketManager extends TcpSocketManager {
+
public static final int DEFAULT_PORT = 6514;
+
private static final SslSocketManagerFactory FACTORY = new SslSocketManagerFactory();
+
private final SslConfiguration sslConfig;
/**
@@ -285,10 +288,7 @@ public class SslSocketManager extends TcpSocketManager {
@Override
protected Socket createSocket(final InetSocketAddress socketAddress) throws IOException {
- final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfig);
- final Socket newSocket = socketFactory.createSocket();
- newSocket.connect(socketAddress, getConnectTimeoutMillis());
- return newSocket;
+ return createSocket(getHost(), socketAddress, getConnectTimeoutMillis(), sslConfig, getSocketOptions());
}
private static SSLSocketFactory createSslSocketFactory(final SslConfiguration sslConf) {
@@ -333,32 +333,65 @@ public class SslSocketManager extends TcpSocketManager {
for (InetSocketAddress socketAddress : socketAddresses) {
try {
return SslSocketManager.createSocket(
- socketAddress, data.connectTimeoutMillis, data.sslConfiguration, data.socketOptions);
+ data.host,
+ socketAddress,
+ data.connectTimeoutMillis,
+ data.sslConfiguration,
+ data.socketOptions);
} catch (IOException ex) {
- ioe = ex;
+ final String message = String.format(
+ "failed create a socket to `%s:%s` that is resolved to address `%s`",
+ data.host, data.port, socketAddress);
+ final IOException newEx = new IOException(message, ex);
+ if (ioe == null) {
+ ioe = newEx;
+ } else {
+ ioe.addSuppressed(newEx);
+ }
}
}
throw new IOException(errorMessage(data, socketAddresses), ioe);
}
}
- static Socket createSocket(
+ private static Socket createSocket(
+ final String hostName,
final InetSocketAddress socketAddress,
final int connectTimeoutMillis,
final SslConfiguration sslConfiguration,
final SocketOptions socketOptions)
throws IOException {
+
+ // Create the `SSLSocket`
final SSLSocketFactory socketFactory = createSslSocketFactory(sslConfiguration);
final SSLSocket socket = (SSLSocket) socketFactory.createSocket();
+
+ // Apply socket options before `connect()`
if (socketOptions != null) {
- // Not sure which options must be applied before or after the connect() call.
socketOptions.apply(socket);
}
+
+ // Connect the socket
socket.connect(socketAddress, connectTimeoutMillis);
- if (socketOptions != null) {
- // Not sure which options must be applied before or after the connect() call.
- socketOptions.apply(socket);
+
+ // Verify the host name
+ if (sslConfiguration.isVerifyHostName()) {
+ // Allowed endpoint identification algorithms: HTTPS and LDAPS.
+ // https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html#endpoint-identification-algorithms
+ final SSLParameters sslParameters = socket.getSSLParameters();
+ sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ // Literal IPv4 and IPv6 addresses are not permitted in "HostName".
+ // https://www.rfc-editor.org/rfc/rfc6066.html#section-3
+ if (!InetAddressValidator.isValid(hostName)) {
+ sslParameters.setServerNames(Collections.singletonList(new SNIHostName(hostName)));
+ }
+ socket.setSSLParameters(sslParameters);
}
+
+ // Force the handshake right after `connect()` instead of waiting for read/write to trigger it indirectly at a
+ // later stage
+ socket.startHandshake();
+
return socket;
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
index 41e2fc1031..a27febcabb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
@@ -132,8 +132,8 @@ public class SslConfiguration {
@Nullable final TrustStoreConfiguration trustStoreConfig) {
try {
final SSLContext sslContext = SSLContext.getInstance(protocol);
- final KeyManager[] keyManagers = loadKeyManagers(keyStoreConfig);
- final TrustManager[] trustManagers = loadTrustManagers(trustStoreConfig);
+ @Nullable final KeyManager[] keyManagers = loadKeyManagers(keyStoreConfig);
+ @Nullable final TrustManager[] trustManagers = loadTrustManagers(trustStoreConfig);
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
} catch (final Exception error) {
@@ -144,9 +144,11 @@ public class SslConfiguration {
}
}
+ @Nullable
+ @NullUnmarked
private static KeyManager[] loadKeyManagers(@Nullable final KeyStoreConfiguration config) throws Exception {
if (config == null) {
- return new KeyManager[0];
+ return null;
}
final KeyManagerFactory factory = KeyManagerFactory.getInstance(config.getKeyManagerFactoryAlgorithm());
final char[] password = config.getPasswordAsCharArray();
@@ -158,9 +160,11 @@ public class SslConfiguration {
return factory.getKeyManagers();
}
+ @Nullable
+ @NullUnmarked
private static TrustManager[] loadTrustManagers(@Nullable final TrustStoreConfiguration config) throws Exception {
if (config == null) {
- return new TrustManager[0];
+ return null;
}
final TrustManagerFactory factory = TrustManagerFactory.getInstance(config.getTrustManagerFactoryAlgorithm());
factory.init(config.getKeyStore());
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java
new file mode 100644
index 0000000000..133c8a4043
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/internal/InetAddressValidator.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.logging.log4j.core.net.ssl.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * {@link java.net.InetAddress} literal validator.
+ *
+ * @implNote
+ * IP address validation is hard.
+ * IPv6 validation is copied from Apache Commons Validator.
+ * This is an internal class with a very limited usage, and should stay that way.
+ * This class should be replaced with {@code java.net.InetAddress#ofLiteral(String)} introduced in Java 22.
+ *
+ * @see <a href="https://github.com/apache/commons-validator/blob/7c27355d86f7dc5a4a548658745b85c9f0d5b99f/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java"><code>InetAddressValidator</code> of Apache Commons Validator</a>
+ */
+public final class InetAddressValidator {
+
+ private static final Pattern IPV4_PATTERN = Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
+
+ /** Max number of hex groups (separated by {@code :}) in an IPV6 address */
+ private static final int IPV6_MAX_HEX_GROUPS = 8;
+
+ /** Max hex digits in each IPv6 group */
+ private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
+
+ private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
+
+ private static final Pattern ID_CHECK_PATTERN = Pattern.compile("[^\\s/%]+");
+
+ private InetAddressValidator() {}
+
+ /**
+ * {@return {@code true} if the provided string is a valid IPv4 or IPv6 address, {@code false} otherwise}.
+ * Verification is performed without any name resolution.
+ *
+ * @param inetAddress the string to validate
+ */
+ public static boolean isValid(final String inetAddress) {
+ return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress);
+ }
+
+ static boolean isValidInet4Address(final String inet4Address) {
+ final Matcher m = IPV4_PATTERN.matcher(inet4Address);
+ if (!m.matches()) {
+ return false;
+ }
+ for (int i = 1; i <= 4; i++) {
+ final String g = m.group(i);
+ if (g.length() > 1 && g.startsWith("0")) {
+ return false;
+ }
+ final int n;
+ try {
+ n = Integer.parseInt(g);
+ } catch (final NumberFormatException ignored) {
+ return false;
+ }
+ if (n > 0xFF) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static boolean isValidInet6Address(String inet6Address) {
+ String[] parts;
+ // remove prefix size. This will appear after the zone id (if any)
+ parts = inet6Address.split("/", -1);
+ if (parts.length > 2) {
+ return false; // can only have one prefix specifier
+ }
+ if (parts.length == 2) {
+ if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
+ return false; // not a valid number
+ }
+ final int bits = Integer.parseInt(parts[1]); // cannot fail because of RE check
+ if (bits < 0 || bits > 128) {
+ return false; // out of range
+ }
+ }
+ // remove zone-id
+ parts = parts[0].split("%", -1);
+ // The id syntax is implementation independent, but it presumably cannot allow:
+ // whitespace, '/' or '%'
+ if (parts.length > 2
+ || parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
+ return false; // invalid id
+ }
+ inet6Address = parts[0];
+ final boolean containsCompressedZeroes = inet6Address.contains("::");
+ if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
+ return false;
+ }
+ final boolean startsWithCompressed = inet6Address.startsWith("::");
+ final boolean endsWithCompressed = inet6Address.endsWith("::");
+ final boolean endsWithSep = inet6Address.endsWith(":");
+ if (inet6Address.startsWith(":") && !startsWithCompressed || endsWithSep && !endsWithCompressed) {
+ return false;
+ }
+ String[] octets = inet6Address.split(":");
+ if (containsCompressedZeroes) {
+ final List<String> octetList = new ArrayList<>(Arrays.asList(octets));
+ if (endsWithCompressed) {
+ // String.split() drops ending empty segments
+ octetList.add("");
+ } else if (startsWithCompressed && !octetList.isEmpty()) {
+ octetList.remove(0);
+ }
+ octets = octetList.toArray(new String[0]);
+ }
+ if (octets.length > IPV6_MAX_HEX_GROUPS) {
+ return false;
+ }
+ int validOctets = 0;
+ int emptyOctets = 0; // consecutive empty chunks
+ for (int index = 0; index < octets.length; index++) {
+ final String octet = octets[index];
+ if (Strings.isBlank(octet)) {
+ emptyOctets++;
+ if (emptyOctets > 1) {
+ return false;
+ }
+ } else {
+ emptyOctets = 0;
+ // Is last chunk an IPv4 address?
+ if (index == octets.length - 1 && octet.contains(".")) {
+ if (!isValidInet4Address(octet)) {
+ return false;
+ }
+ validOctets += 2;
+ continue;
+ }
+ if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
+ return false;
+ }
+ int octetInt = 0;
+ try {
+ octetInt = Integer.parseInt(octet, 16);
+ } catch (final NumberFormatException e) {
+ return false;
+ }
+ if (octetInt < 0 || octetInt > 0xffff) {
+ return false;
+ }
+ }
+ validOctets++;
+ }
+ return validOctets <= IPV6_MAX_HEX_GROUPS && (validOctets >= IPV6_MAX_HEX_GROUPS || containsCompressedZeroes);
+ }
+}