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ı <[email protected]> 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); + } +}
