29
29
import com .rabbitmq .client .impl .recovery .AutorecoveringConnection ;
30
30
import com .rabbitmq .client .impl .recovery .RetryHandler ;
31
31
import com .rabbitmq .client .impl .recovery .TopologyRecoveryFilter ;
32
+ import org .apache .http .conn .ssl .DefaultHostnameVerifier ;
32
33
33
34
import javax .net .SocketFactory ;
35
+ import javax .net .ssl .HostnameVerifier ;
34
36
import javax .net .ssl .SSLContext ;
35
37
import javax .net .ssl .SSLSocketFactory ;
36
38
import javax .net .ssl .TrustManager ;
@@ -188,6 +190,19 @@ public class ConnectionFactory implements Cloneable {
188
190
*/
189
191
private RetryHandler topologyRecoveryRetryHandler ;
190
192
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
+
191
206
/** @return the default host to use for connections */
192
207
public String getHost () {
193
208
return host ;
@@ -679,12 +694,19 @@ public void useSslProtocol(String protocol)
679
694
* Pass in the TLS protocol version to use, e.g. "TLSv1.2" or "TLSv1.1", and
680
695
* a desired {@link TrustManager}.
681
696
*
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
+ *
682
702
*
683
703
* The produced {@link SSLContext} instance will be shared with all
684
704
* the connections created by this connection factory.
685
705
* @param protocol the TLS protocol to use.
686
706
* @param trustManager the {@link TrustManager} implementation to use.
687
707
* @see #useSslProtocol(SSLContext)
708
+ * @see #enableHostnameVerification()
709
+ * @see #enableHostnameVerification(HostnameVerifier)
688
710
*/
689
711
public void useSslProtocol (String protocol , TrustManager trustManager )
690
712
throws NoSuchAlgorithmException , KeyManagementException
@@ -699,9 +721,16 @@ public void useSslProtocol(String protocol, TrustManager trustManager)
699
721
* for setting up the context with a {@link TrustManager} with suitable security guarantees,
700
722
* e.g. peer verification.
701
723
*
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
+ *
702
729
* The {@link SSLContext} instance will be shared with all
703
730
* the connections created by this connection factory.
704
731
* @param context An initialized SSLContext
732
+ * @see #enableHostnameVerification()
733
+ * @see #enableHostnameVerification(HostnameVerifier)
705
734
*/
706
735
public void useSslProtocol (SSLContext context ) {
707
736
setSocketFactory (context .getSocketFactory ());
@@ -716,6 +745,15 @@ public void useSslProtocol(SSLContext context) {
716
745
* <p>
717
746
* This can be called typically after setting the {@link SSLContext}
718
747
* 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)}.
719
757
*
720
758
* @see NioParams#enableHostnameVerification()
721
759
* @see NioParams#setSslEngineConfigurator(SslEngineConfigurator)
@@ -725,10 +763,43 @@ public void useSslProtocol(SSLContext context) {
725
763
* @see ConnectionFactory#useSslProtocol(SSLContext)
726
764
* @see ConnectionFactory#useSslProtocol()
727
765
* @see ConnectionFactory#useSslProtocol(String, TrustManager)
766
+ * @see ConnectionFactory#enableHostnameVerification(HostnameVerifier)
767
+ * @since 4.8.0
728
768
*/
729
769
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" );
732
803
}
733
804
734
805
protected void enableHostnameVerificationForNio () {
@@ -835,11 +906,11 @@ protected synchronized FrameHandlerFactory createFrameHandlerFactory() throws IO
835
906
if (this .nioParams .getNioExecutor () == null && this .nioParams .getThreadFactory () == null ) {
836
907
this .nioParams .setThreadFactory (getThreadFactory ());
837
908
}
838
- this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext );
909
+ this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext , connectionPostProcessor );
839
910
}
840
911
return this .frameHandlerFactory ;
841
912
} else {
842
- return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor );
913
+ return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor , connectionPostProcessor );
843
914
}
844
915
845
916
}
@@ -1483,4 +1554,15 @@ public void setTopologyRecoveryFilter(TopologyRecoveryFilter topologyRecoveryFil
1483
1554
public void setTopologyRecoveryRetryHandler (RetryHandler topologyRecoveryRetryHandler ) {
1484
1555
this .topologyRecoveryRetryHandler = topologyRecoveryRetryHandler ;
1485
1556
}
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
+ }
1486
1568
}
0 commit comments