Skip to content

Commit f88fd61

Browse files
committed
GH-5723: Refine SSL trust all configuration for http client builder
RDF4JHttpClientConfig - Added disableHostnameVerification boolean field (default false), getter, and builder method with security-warning Javadoc. ApacheHC5RDF4JHttpClientFactory - Added javax.net.ssl.SSLContext and NoopHostnameVerifier imports. - The TLS strategy block now covers both cases: if disableHostnameVerification is true, NoopHostnameVerifier.INSTANCE is passed to DefaultClientTlsStrategy; if only a custom SSLContext is set, the default verifier is used. If neither flag applies, no custom strategy is set. JdkRDF4JHttpClientFactory - Added javax.net.ssl.SSLParameters import. - When disableHostnameVerification is true, sets endpointIdentificationAlgorithm to null via SSLParameters, which is the JDK way to disable hostname checking. HttpClientBuilders.getSslTrustAllConfig() - Now calls .disableHostnameVerification(true) so the returned config disables both certificate validation and hostname verification, matching the "trust all" contract. - Updated Javadoc to accurately describe what the method does (both checks suppressed) and to include the production warning.
1 parent 2a5954f commit f88fd61

4 files changed

Lines changed: 68 additions & 5 deletions

File tree

core/http/client-apache5/src/main/java/org/eclipse/rdf4j/http/client/apache5/ApacheHC5RDF4JHttpClientFactory.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import java.util.List;
1616
import java.util.stream.Collectors;
1717

18+
import javax.net.ssl.SSLContext;
19+
1820
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
1921
import org.apache.hc.client5.http.config.ConnectionConfig;
2022
import org.apache.hc.client5.http.config.RequestConfig;
@@ -26,6 +28,7 @@
2628
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
2729
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
2830
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
31+
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
2932
import org.apache.hc.core5.http.ConnectionClosedException;
3033
import org.apache.hc.core5.http.HttpRequest;
3134
import org.apache.hc.core5.http.HttpResponse;
@@ -87,8 +90,19 @@ public RDF4JHttpClient create(RDF4JHttpClientConfig config) {
8790
.setConnectTimeout(Timeout.ofMilliseconds(config.getConnectTimeoutMs()))
8891
.build());
8992

90-
if (config.getSslContext().isPresent()) {
91-
cmBuilder.setTlsSocketStrategy(new DefaultClientTlsStrategy(config.getSslContext().get()));
93+
if (config.getSslContext().isPresent() || config.isDisableHostnameVerification()) {
94+
SSLContext sslContext = config.getSslContext().orElseGet(() -> {
95+
try {
96+
return SSLContext.getDefault();
97+
} catch (java.security.NoSuchAlgorithmException e) {
98+
throw new RuntimeException(e);
99+
}
100+
});
101+
if (config.isDisableHostnameVerification()) {
102+
cmBuilder.setTlsSocketStrategy(new DefaultClientTlsStrategy(sslContext, NoopHostnameVerifier.INSTANCE));
103+
} else {
104+
cmBuilder.setTlsSocketStrategy(new DefaultClientTlsStrategy(sslContext));
105+
}
92106
}
93107

94108
PoolingHttpClientConnectionManager connectionManager = cmBuilder.build();

core/http/client-api/src/main/java/org/eclipse/rdf4j/http/client/spi/RDF4JHttpClientConfig.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public final class RDF4JHttpClientConfig {
4747
private final boolean followRedirects;
4848
private final long idleConnectionTimeoutMs;
4949
private final SSLContext sslContext;
50+
private final boolean disableHostnameVerification;
5051
private final List<HttpHeader> defaultHeaders;
5152

5253
private RDF4JHttpClientConfig(Builder builder) {
@@ -59,6 +60,7 @@ private RDF4JHttpClientConfig(Builder builder) {
5960
this.followRedirects = builder.followRedirects;
6061
this.idleConnectionTimeoutMs = builder.idleConnectionTimeoutMs;
6162
this.sslContext = builder.sslContext;
63+
this.disableHostnameVerification = builder.disableHostnameVerification;
6264
this.defaultHeaders = List.copyOf(builder.defaultHeaders);
6365
}
6466

@@ -147,6 +149,20 @@ public Optional<SSLContext> getSslContext() {
147149
return Optional.ofNullable(sslContext);
148150
}
149151

152+
/**
153+
* Returns whether TLS hostname verification is disabled. When {@code true}, the client will accept certificates
154+
* even if the hostname does not match the certificate's CN/SAN fields.
155+
*
156+
* <p>
157+
* <strong>Warning:</strong> disabling hostname verification removes an important security check. Only use this in
158+
* controlled environments (e.g. testing against self-signed certificates).
159+
*
160+
* @return {@code true} if hostname verification is disabled, {@code false} otherwise
161+
*/
162+
public boolean isDisableHostnameVerification() {
163+
return disableHostnameVerification;
164+
}
165+
150166
/**
151167
* Returns the default HTTP headers to be sent with every request.
152168
*
@@ -189,6 +205,7 @@ public static Builder newBuilder() {
189205
* <li>{@code followRedirects} = {@code true}</li>
190206
* <li>{@code idleConnectionTimeoutMs} = 300,000 ms (5 minutes)</li>
191207
* <li>{@code sslContext} = none (uses JVM default)</li>
208+
* <li>{@code disableHostnameVerification} = {@code false}</li>
192209
* </ul>
193210
*/
194211
public static final class Builder {
@@ -201,6 +218,7 @@ public static final class Builder {
201218
private boolean followRedirects = true;
202219
private long idleConnectionTimeoutMs = 300_000L;
203220
private SSLContext sslContext;
221+
private boolean disableHostnameVerification = false;
204222
private List<HttpHeader> defaultHeaders = List.of();
205223

206224
private Builder() {
@@ -307,6 +325,22 @@ public Builder sslContext(SSLContext sslContext) {
307325
return this;
308326
}
309327

328+
/**
329+
* Disables TLS hostname verification. When set to {@code true}, the client will accept certificates even if the
330+
* hostname does not match the certificate's CN/SAN fields.
331+
*
332+
* <p>
333+
* <strong>Warning:</strong> disabling hostname verification removes an important security check. Only use this
334+
* in controlled environments (e.g. testing against self-signed certificates with hostname mismatches).
335+
*
336+
* @param disableHostnameVerification {@code true} to disable hostname verification
337+
* @return this builder
338+
*/
339+
public Builder disableHostnameVerification(boolean disableHostnameVerification) {
340+
this.disableHostnameVerification = disableHostnameVerification;
341+
return this;
342+
}
343+
310344
/**
311345
* Sets the default HTTP headers to be sent with every request.
312346
*

core/http/client-jdk/src/main/java/org/eclipse/rdf4j/http/client/jdk/JdkRDF4JHttpClientFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import java.net.http.HttpClient;
1717
import java.time.Duration;
1818

19+
import javax.net.ssl.SSLParameters;
20+
1921
import org.eclipse.rdf4j.http.client.spi.RDF4JHttpClient;
2022
import org.eclipse.rdf4j.http.client.spi.RDF4JHttpClientConfig;
2123
import org.eclipse.rdf4j.http.client.spi.RDF4JHttpClientFactory;
@@ -46,6 +48,12 @@ public RDF4JHttpClient create(RDF4JHttpClientConfig config) {
4648

4749
config.getSslContext().ifPresent(builder::sslContext);
4850

51+
if (config.isDisableHostnameVerification()) {
52+
SSLParameters sslParameters = new SSLParameters();
53+
sslParameters.setEndpointIdentificationAlgorithm(null);
54+
builder.sslParameters(sslParameters);
55+
}
56+
4957
builder.authenticator(new Authenticator() {
5058
@Override
5159
protected PasswordAuthentication getPasswordAuthentication() {

core/http/client/src/main/java/org/eclipse/rdf4j/http/client/util/HttpClientBuilders.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,15 @@
3030
public class HttpClientBuilders {
3131

3232
/**
33-
* Return an {@link RDF4JHttpClientConfig} configured to trust all SSL certificates, including self-signed
34-
* certificates.
33+
* Return an {@link RDF4JHttpClientConfig} configured to trust all SSL certificates and skip hostname verification.
34+
*
35+
* <p>
36+
* This installs a no-op {@link javax.net.ssl.TrustManager} that accepts any certificate chain, and disables TLS
37+
* endpoint identification so that hostname mismatches are also accepted. Both checks are suppressed, making this
38+
* suitable for self-signed certificates in controlled/test environments.
39+
*
40+
* <p>
41+
* <strong>Warning:</strong> this configuration is inherently insecure and must never be used in production.
3542
*
3643
* @return an {@link RDF4JHttpClientConfig} for <i>SSL trust all</i>
3744
*/
@@ -52,7 +59,7 @@ public X509Certificate[] getAcceptedIssuers() {
5259
return new X509Certificate[0];
5360
}
5461
} }, null);
55-
return RDF4JHttpClientConfig.newBuilder().sslContext(sslContext).build();
62+
return RDF4JHttpClientConfig.newBuilder().sslContext(sslContext).disableHostnameVerification(true).build();
5663
} catch (NoSuchAlgorithmException | KeyManagementException e) {
5764
throw new RuntimeException(e);
5865
}

0 commit comments

Comments
 (0)