diff --git a/gradle.properties b/gradle.properties index 30aa3f0a755a..4119558fc171 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,8 +11,8 @@ checkstyleToolVersion=10.12.4 commonsCodecVersion=1.21.0 graalVersion=25 hamcrestVersion=3.0 -jackson2Version=2.21.3 -jacksonVersion=3.1.3 +jackson2Version=2.21.4 +jacksonVersion=3.1.4 javaFormatVersion=0.0.47 junitJupiterVersion=6.0.3 kotlinVersion=2.3.21 diff --git a/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/InetAddressFilter.java b/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/InetAddressFilter.java index 2dfd54be6936..94ebc86ebe08 100644 --- a/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/InetAddressFilter.java +++ b/module/spring-boot-http-client/src/main/java/org/springframework/boot/http/client/InetAddressFilter.java @@ -185,12 +185,16 @@ default InetAddressFilter negate() { /** * Return a filter that will match external (non-private) IP addresses. External - * addresses are all non-{@link #internalAddresses() internal addresses} + * addresses are all {@link #routable() routable} addresses that are not: + * * @return a filter for external IP addresses * @see #internalAddresses() */ static InetAddressFilter externalAddresses() { - return routable().andNot(InternalInetAddressFilter.instance); + return routable().andNot(multicast(), specialPurpose()); } /** @@ -224,6 +228,27 @@ static InetAddressFilter routable() { }; } + /** + * Returns a filter that will match all multicast addresses. + * @return a filter for multicast IP addresses + */ + static InetAddressFilter multicast() { + return InetAddress::isMulticastAddress; + } + + /** + * Returns a filter that will match special purpose IP addresses as defined by + * RFC 6890. + * @return a filter for this network + */ + static InetAddressFilter specialPurpose() { + return of("0.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8", "169.254.0.0/16", "192.0.0.0/24", "192.0.0.0/29", + "192.0.2.0/24", "192.88.99.0/24", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", + "255.255.255.255/32", "::1/128", "::/128", "64:ff9b::/96", "100::/64", "2001::/23", "2001::/32", + "2001:2::/48", "2001:db8::/32", "2001:10::/28", "2002::/16", "fc00::/7", "fe80::/10") + .or(InternalInetAddressFilter.instance); + } + /** * Return a filter that is the negation of all the given addresses. * @param addresses the addresses to negate in any form supported by diff --git a/module/spring-boot-http-client/src/test/java/org/springframework/boot/http/client/InetAddressFilterTests.java b/module/spring-boot-http-client/src/test/java/org/springframework/boot/http/client/InetAddressFilterTests.java index 3eb8d4089138..31106bacb945 100644 --- a/module/spring-boot-http-client/src/test/java/org/springframework/boot/http/client/InetAddressFilterTests.java +++ b/module/spring-boot-http-client/src/test/java/org/springframework/boot/http/client/InetAddressFilterTests.java @@ -327,6 +327,65 @@ void ipv6NonRoutable() { assertThat(filter).doesNotMatch("::"); } + @Test + void ipv4CurrentLocalThisNetwork() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("0.0.0.4"); + } + + @Test + void ipv4Subnet() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("169.254.0.1"); + assertThat(filter).doesNotMatch("255.255.255.255"); + } + + @Test + void ipv4Documentation() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("192.0.2.1"); + assertThat(filter).doesNotMatch("203.0.113.1"); + } + + @Test + void ipv4Multicast() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("224.0.0.1"); + } + + @Test + void ipv4ReservedForFutureUse() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("240.0.0.1"); + } + + @Test + void ipv4SharedAddressSpace() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("100.64.0.1"); + assertThat(filter).doesNotMatch("100.127.255.254"); + } + + @Test + void ipv4PerformanceBenchmarking() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("198.18.0.1"); + assertThat(filter).doesNotMatch("198.19.255.255"); + } + + @Test + void ipv4AllHostsMulticastGroup() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("224.0.0.1"); + assertThat(filter).doesNotMatch("239.255.255.250"); + } + + @Test + void ipv6NodeLinkMulticastAddress() { + InetAddressFilter filter = InetAddressFilter.externalAddresses(); + assertThat(filter).doesNotMatch("ff02::1"); + } + } @Nested @@ -521,6 +580,163 @@ void routable() { } + @Nested + class Multicast { + + @Test + void multicast() { + InetAddressFilter filter = InetAddressFilter.multicast(); + assertThat(filter).matches("239.255.255.255"); + assertThat(filter).matches("FF00:0000:0000:0000:0000:0000:0000:0001"); + } + + } + + @Nested + class SpecialPurpose { + + @Test + void publicAddress() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).doesNotMatch("8.8.8.8"); + } + + @Test + void thisHostNetwork() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("0.0.0.1"); + } + + @Test + void privateUseNetwork() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("10.0.0.1"); + assertThat(filter).matches("172.16.0.1"); + assertThat(filter).matches("192.168.0.1"); + } + + @Test + void sharedAddressSpace() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("100.64.0.1"); + } + + @Test + void loopback() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("127.0.0.0"); + assertThat(filter).matches("::1"); + } + + @Test + void linkLocal() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("169.254.0.1"); + } + + @Test + void protocolAssignments() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("192.0.0.1"); + assertThat(filter).matches("2001:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void dsLite() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("192.0.0.1"); + } + + @Test + void documentation() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("192.0.2.1"); + assertThat(filter).matches("198.51.100.1"); + assertThat(filter).matches("203.0.113.1"); + assertThat(filter).matches("2001:0db8:0000:0000:0000:0000:0000:0001"); + } + + @Test + void SixToFourRelay() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("192.88.99.1"); + } + + @Test + void deviceBenchmarking() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("198.18.0.1"); + assertThat(filter).matches("2001:0002:0000:0000:0000:0000:0000:0001"); + } + + @Test + void futureUse() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("240.0.0.1"); + } + + @Test + void limitedBroadcast() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("255.255.255.255"); + } + + @Test + void unspecifiedAddress() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("0000:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void ipv4ToIpv6AddressTranslation() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("0064:ff9b:0000:0000:0000:0000:0000:0001"); + } + + @Test + void ipv4MappedAddress() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("0000:0000:0000:0000:0000:ffff:0000:0001"); + } + + @Test + void discardOnly() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("0100:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void teredo() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("2001:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void orchid() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("2001:10:0000:0000:0000:0000:0000:0001"); + } + + @Test + void sixToFour() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("2002:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void uniqueLocal() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("fc00:0000:0000:0000:0000:0000:0000:0001"); + } + + @Test + void linkedScopedUnicast() { + InetAddressFilter filter = InetAddressFilter.specialPurpose(); + assertThat(filter).matches("fe80:0000:0000:0000:0000:0000:0000:0001"); + } + + } + @Nested class NotTests { diff --git a/platform/spring-boot-dependencies/build.gradle b/platform/spring-boot-dependencies/build.gradle index c77954e2dcc4..ac109d51a86b 100644 --- a/platform/spring-boot-dependencies/build.gradle +++ b/platform/spring-boot-dependencies/build.gradle @@ -31,7 +31,7 @@ bom { ] } } - library("ActiveMQ", "6.2.5") { + library("ActiveMQ", "6.2.6") { group("org.apache.activemq") { modules = [ "activemq-console", @@ -186,7 +186,7 @@ bom { releaseNotes("https://github.com/mojohaus/build-helper-maven-plugin/releases/tag/{version}") } } - library("Byte Buddy", "1.18.8") { + library("Byte Buddy", "1.18.9") { group("net.bytebuddy") { modules = [ "byte-buddy", @@ -231,7 +231,7 @@ bom { releaseNotes("https://github.com/ben-manes/caffeine/releases/tag/v{version}") } } - library("Cassandra Driver", "4.19.2") { + library("Cassandra Driver", "4.19.3") { group("org.apache.cassandra") { bom("java-driver-bom") { permit("com.datastax.oss:native-protocol") @@ -401,7 +401,7 @@ bom { releaseNotes("https://github.com/ehcache/ehcache3/releases/tag/v{version}") } } - library("Elasticsearch Client", "9.4.1") { + library("Elasticsearch Client", "9.4.2") { prohibit { contains "-alpha" contains "-beta" @@ -484,7 +484,7 @@ bom { releaseNotes("https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v{version}") } } - library("Glassfish JAXB", "4.0.8") { + library("Glassfish JAXB", "4.0.9") { alignWith { dependencyManagementDeclaredIn("org.glassfish.jaxb:jaxb-bom") { excluding { candidate -> candidate.classifier().equals("sources") } @@ -854,7 +854,7 @@ bom { releaseNotes("https://github.com/jakartaee/jsonp-api/releases/tag/{version}-RELEASE") } } - library("Jakarta Json Bind", "3.0.1") { + library("Jakarta Json Bind", "3.0.2") { group("jakarta.json.bind") { modules = [ "jakarta.json.bind-api" @@ -1035,7 +1035,7 @@ bom { ] } } - library("Jaxen", "2.0.3") { + library("Jaxen", "2.0.5") { group("jaxen") { modules = [ "jaxen" @@ -1115,7 +1115,7 @@ bom { ] } } - library("Jetty", "12.1.8") { + library("Jetty", "12.1.10") { prohibit { contains ".alpha" because "we don't want alpha dependencies" @@ -1241,7 +1241,7 @@ bom { releaseNotes("https://junit.org/junit5/docs/{version}/release-notes") } } - library("Kafka", "4.2.0") { + library("Kafka", "4.2.1") { group("org.apache.kafka") { modules = [ "connect", @@ -1373,7 +1373,7 @@ bom { releaseNotes("https://github.com/apache/logging-log4j2/releases/tag/rel%2F{version}") } } - library("Logback", "1.5.32") { + library("Logback", "1.5.34") { group("ch.qos.logback") { modules = [ "logback-classic", @@ -1490,7 +1490,7 @@ bom { releaseNotes("https://github.com/apache/maven-enforcer/releases/tag/enforcer-{version}") } } - library("Maven Failsafe Plugin", "3.5.5") { + library("Maven Failsafe Plugin", "3.5.6") { group("org.apache.maven.plugins") { plugins = [ "maven-failsafe-plugin" @@ -1593,7 +1593,7 @@ bom { releaseNotes("https://github.com/apache/maven-source-plugin/releases/tag/maven-source-plugin-{version}") } } - library("Maven Surefire Plugin", "3.5.5") { + library("Maven Surefire Plugin", "3.5.6") { group("org.apache.maven.plugins") { plugins = [ "maven-surefire-plugin" @@ -1752,7 +1752,7 @@ bom { releaseNotes("https://github.com/neo4j/neo4j-java-driver/releases/tag/{version}") } } - library("Netty", "4.2.14.Final") { + library("Netty", "4.2.15.Final") { prohibit { contains ".Alpha" contains ".Beta" @@ -1791,7 +1791,7 @@ bom { releaseNotes("https://github.com/open-telemetry/opentelemetry-java/releases/tag/v{version}") } } - library("Oracle Database", "23.26.1.0.0") { + library("Oracle Database", "23.26.2.0.0") { alignWith { dependencyManagementDeclaredIn("com.oracle.database.jdbc:ojdbc-bom") }