2929import com .rabbitmq .client .impl .recovery .AutorecoveringConnection ;
3030import com .rabbitmq .client .impl .recovery .RetryHandler ;
3131import com .rabbitmq .client .impl .recovery .TopologyRecoveryFilter ;
32+ import org .apache .http .conn .ssl .DefaultHostnameVerifier ;
3233
3334import javax .net .SocketFactory ;
35+ import javax .net .ssl .HostnameVerifier ;
3436import javax .net .ssl .SSLContext ;
3537import javax .net .ssl .SSLSocketFactory ;
3638import javax .net .ssl .TrustManager ;
@@ -188,6 +190,19 @@ public class ConnectionFactory implements Cloneable {
188190 */
189191 private RetryHandler topologyRecoveryRetryHandler ;
190192
193+ /**
194+ * Hook to post-process the freshly open TCP connection.
195+ *
196+ * @since 4.8.0
197+ */
198+ private ConnectionPostProcessor connectionPostProcessor = new ConnectionPostProcessor () {
199+
200+ @ Override
201+ public void postProcess (ConnectionContext context ) {
202+
203+ }
204+ };
205+
191206 /** @return the default host to use for connections */
192207 public String getHost () {
193208 return host ;
@@ -679,12 +694,19 @@ public void useSslProtocol(String protocol)
679694 * Pass in the TLS protocol version to use, e.g. "TLSv1.2" or "TLSv1.1", and
680695 * a desired {@link TrustManager}.
681696 *
697+ * Note <strong>you must explicitly enable hostname verification</strong> with the
698+ * {@link ConnectionFactory#enableHostnameVerification()} or the
699+ * {@link ConnectionFactory#enableHostnameVerification(HostnameVerifier)}
700+ * method.
701+ *
682702 *
683703 * The produced {@link SSLContext} instance will be shared with all
684704 * the connections created by this connection factory.
685705 * @param protocol the TLS protocol to use.
686706 * @param trustManager the {@link TrustManager} implementation to use.
687707 * @see #useSslProtocol(SSLContext)
708+ * @see #enableHostnameVerification()
709+ * @see #enableHostnameVerification(HostnameVerifier)
688710 */
689711 public void useSslProtocol (String protocol , TrustManager trustManager )
690712 throws NoSuchAlgorithmException , KeyManagementException
@@ -699,9 +721,16 @@ public void useSslProtocol(String protocol, TrustManager trustManager)
699721 * for setting up the context with a {@link TrustManager} with suitable security guarantees,
700722 * e.g. peer verification.
701723 *
724+ * Note <strong>you must explicitly enable hostname verification</strong> with the
725+ * {@link ConnectionFactory#enableHostnameVerification()} or the
726+ * {@link ConnectionFactory#enableHostnameVerification(HostnameVerifier)}
727+ * method.
728+ *
702729 * The {@link SSLContext} instance will be shared with all
703730 * the connections created by this connection factory.
704731 * @param context An initialized SSLContext
732+ * @see #enableHostnameVerification()
733+ * @see #enableHostnameVerification(HostnameVerifier)
705734 */
706735 public void useSslProtocol (SSLContext context ) {
707736 setSocketFactory (context .getSocketFactory ());
@@ -716,6 +745,15 @@ public void useSslProtocol(SSLContext context) {
716745 * <p>
717746 * This can be called typically after setting the {@link SSLContext}
718747 * with one of the <code>useSslProtocol</code> methods.
748+ * <p>
749+ * If <strong>using Java 7 or more</strong>, the hostname verification will be
750+ * performed by Java, as part of the TLS handshake.
751+ * <p>
752+ * If <strong>using Java 6</strong>, the hostname verification will be handled after
753+ * the TLS handshake, using the {@link HostnameVerifier} from the
754+ * Commons HttpClient project. This requires to add Commons HttpClient
755+ * and its dependencies to the classpath. To use a custom {@link HostnameVerifier},
756+ * use {@link ConnectionFactory#enableHostnameVerification(HostnameVerifier)}.
719757 *
720758 * @see NioParams#enableHostnameVerification()
721759 * @see NioParams#setSslEngineConfigurator(SslEngineConfigurator)
@@ -725,10 +763,43 @@ public void useSslProtocol(SSLContext context) {
725763 * @see ConnectionFactory#useSslProtocol(SSLContext)
726764 * @see ConnectionFactory#useSslProtocol()
727765 * @see ConnectionFactory#useSslProtocol(String, TrustManager)
766+ * @see ConnectionFactory#enableHostnameVerification(HostnameVerifier)
767+ * @since 4.8.0
728768 */
729769 public void enableHostnameVerification () {
730- enableHostnameVerificationForNio ();
731- enableHostnameVerificationForBlockingIo ();
770+ if (isJava6 ()) {
771+ enableHostnameVerification (new DefaultHostnameVerifier ());
772+ } else {
773+ enableHostnameVerificationForNio ();
774+ enableHostnameVerificationForBlockingIo ();
775+ }
776+ }
777+
778+ /**
779+ * Enable TLS hostname verification performed by the passed-in {@link HostnameVerifier}.
780+ * <p>
781+ * Using an {@link HostnameVerifier} is relevant only for Java 6, for Java 7 or more,
782+ * calling ConnectionFactory{@link #enableHostnameVerification()} is enough.
783+ *
784+ * @param hostnameVerifier
785+ * @since 4.8.0
786+ * @see ConnectionFactory#enableHostnameVerification()
787+ */
788+ public void enableHostnameVerification (HostnameVerifier hostnameVerifier ) {
789+ if (this .connectionPostProcessor == null ) {
790+ this .connectionPostProcessor = ConnectionPostProcessors .builder ()
791+ .enableHostnameVerification (hostnameVerifier )
792+ .build ();
793+ } else {
794+ this .connectionPostProcessor = ConnectionPostProcessors .builder ()
795+ .add (this .connectionPostProcessor )
796+ .enableHostnameVerification (hostnameVerifier )
797+ .build ();
798+ }
799+ }
800+
801+ protected boolean isJava6 () {
802+ return System .getProperty ("java.specification.version" ).startsWith ("1.6" );
732803 }
733804
734805 protected void enableHostnameVerificationForNio () {
@@ -835,11 +906,11 @@ protected synchronized FrameHandlerFactory createFrameHandlerFactory() throws IO
835906 if (this .nioParams .getNioExecutor () == null && this .nioParams .getThreadFactory () == null ) {
836907 this .nioParams .setThreadFactory (getThreadFactory ());
837908 }
838- this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext );
909+ this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext , connectionPostProcessor );
839910 }
840911 return this .frameHandlerFactory ;
841912 } else {
842- return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor );
913+ return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor , connectionPostProcessor );
843914 }
844915
845916 }
@@ -1483,4 +1554,15 @@ public void setTopologyRecoveryFilter(TopologyRecoveryFilter topologyRecoveryFil
14831554 public void setTopologyRecoveryRetryHandler (RetryHandler topologyRecoveryRetryHandler ) {
14841555 this .topologyRecoveryRetryHandler = topologyRecoveryRetryHandler ;
14851556 }
1557+
1558+ /**
1559+ * Hook to post-process the freshly open TCP connection.
1560+ *
1561+ * @param connectionPostProcessor
1562+ * @see #enableHostnameVerification()
1563+ * @see #enableHostnameVerification(HostnameVerifier)
1564+ */
1565+ public void setConnectionPostProcessor (ConnectionPostProcessor connectionPostProcessor ) {
1566+ this .connectionPostProcessor = connectionPostProcessor ;
1567+ }
14861568}
0 commit comments