diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java index 17e55a937a..bf34699708 100644 --- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java +++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyClientProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -53,4 +53,19 @@ public class NettyClientProperties { *

*/ public static final String MAX_CONNECTIONS = "jersey.config.client.maxConnections"; + + /** + *

+ * Sets the endpoint identification algorithm to HTTPS. + *

+ *

+ * The default value is {@code true} (for HTTPS uri scheme). + *

+ *

+ * The name of the configuration property is {@value}. + *

+ * @since 2.35 + * @see javax.net.ssl.SSLParameters#setEndpointIdentificationAlgorithm(String) + */ + public static final String ENABLE_SSL_HOSTNAME_VERIFICATION = "jersey.config.client.tls.enableHostnameVerification"; } diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java index 056ef31802..c97ea2e16c 100644 --- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java +++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -32,6 +32,9 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Client; import javax.ws.rs.core.Configuration; @@ -58,8 +61,11 @@ import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.proxy.HttpProxyHandler; +import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; +import io.netty.handler.ssl.IdentityCipherSuiteFilter; import io.netty.handler.ssl.JdkSslContext; +import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; @@ -216,15 +222,9 @@ protected CompletableFuture execute(final ClientRequest jerseyRe protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); - // Enable HTTPS if necessary. - if ("https".equals(requestUri.getScheme())) { - // making client authentication optional for now; it could be extracted to configurable property - JdkSslContext jdkSslContext = new JdkSslContext(client.getSslContext(), true, ClientAuth.NONE); - p.addLast(jdkSslContext.newHandler(ch.alloc())); - } + Configuration config = jerseyRequest.getConfiguration(); // http proxy - Configuration config = jerseyRequest.getConfiguration(); final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); if (proxyUri != null) { final URI u = getProxyUri(proxyUri); @@ -234,9 +234,37 @@ protected void initChannel(SocketChannel ch) throws Exception { final String password = ClientProperties.getValue( config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - p.addLast(new HttpProxyHandler(new InetSocketAddress(u.getHost(), - u.getPort() == -1 ? 8080 : u.getPort()), - userName, password)); + InetSocketAddress proxyAddr = new InetSocketAddress(u.getHost(), + u.getPort() == -1 ? 8080 : u.getPort()); + p.addLast(userName == null ? new HttpProxyHandler(proxyAddr) + : new HttpProxyHandler(proxyAddr, userName, password)); + } + + // Enable HTTPS if necessary. + if ("https".equals(requestUri.getScheme())) { + // making client authentication optional for now; it could be extracted to configurable property + JdkSslContext jdkSslContext = new JdkSslContext( + client.getSslContext(), + true, + (Iterable) null, + IdentityCipherSuiteFilter.INSTANCE, + (ApplicationProtocolConfig) null, + ClientAuth.NONE, + (String[]) null, /* enable default protocols */ + false /* true if the first write request shouldn't be encrypted */ + ); + int port = requestUri.getPort(); + SslHandler sslHandler = jdkSslContext.newHandler(ch.alloc(), requestUri.getHost(), + port <= 0 ? 443 : port, executorService); + if (ClientProperties.getValue(config.getProperties(), + NettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, true)) { + SSLEngine sslEngine = sslHandler.engine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + } + + p.addLast(sslHandler); } p.addLast(new HttpClientCodec());