15
15
16
16
package com .rabbitmq .client ;
17
17
18
- import static java .util .concurrent .TimeUnit .*;
19
-
20
18
import com .rabbitmq .client .impl .AMQConnection ;
21
19
import com .rabbitmq .client .impl .ConnectionParams ;
22
20
import com .rabbitmq .client .impl .CredentialsProvider ;
31
29
import com .rabbitmq .client .impl .recovery .AutorecoveringConnection ;
32
30
import com .rabbitmq .client .impl .recovery .RetryHandler ;
33
31
import com .rabbitmq .client .impl .recovery .TopologyRecoveryFilter ;
32
+ import org .apache .http .conn .ssl .DefaultHostnameVerifier ;
34
33
34
+ import javax .net .SocketFactory ;
35
+ import javax .net .ssl .HostnameVerifier ;
36
+ import javax .net .ssl .SSLContext ;
37
+ import javax .net .ssl .SSLSocketFactory ;
38
+ import javax .net .ssl .TrustManager ;
35
39
import java .io .IOException ;
36
40
import java .net .URI ;
37
41
import java .net .URISyntaxException ;
49
53
import java .util .concurrent .ScheduledExecutorService ;
50
54
import java .util .concurrent .ThreadFactory ;
51
55
import java .util .concurrent .TimeoutException ;
52
- import javax .net .SocketFactory ;
53
- import javax .net .ssl .SSLContext ;
54
- import javax .net .ssl .SSLSocketFactory ;
55
- import javax .net .ssl .TrustManager ;
56
+
57
+ import static java .util .concurrent .TimeUnit .MINUTES ;
56
58
57
59
/**
58
60
* Convenience "factory" class to facilitate opening a {@link Connection} to an AMQP broker.
@@ -126,7 +128,7 @@ public class ConnectionFactory implements Cloneable {
126
128
// connections uses, see rabbitmq/rabbitmq-java-client#86
127
129
private ExecutorService shutdownExecutor ;
128
130
private ScheduledExecutorService heartbeatExecutor ;
129
- private SocketConfigurator socketConf = new DefaultSocketConfigurator ();
131
+ private SocketConfigurator socketConf = SocketConfigurators . defaultConfigurator ();
130
132
private ExceptionHandler exceptionHandler = new DefaultExceptionHandler ();
131
133
private CredentialsProvider credentialsProvider = new DefaultCredentialsProvider (DEFAULT_USER , DEFAULT_PASS );
132
134
@@ -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,15 +721,108 @@ 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 ());
708
737
this .sslContext = context ;
709
738
}
710
739
740
+ /**
741
+ * Enable server hostname verification for TLS connections.
742
+ * <p>
743
+ * This enables hostname verification regardless of the IO mode
744
+ * used (blocking or non-blocking IO).
745
+ * <p>
746
+ * This can be called typically after setting the {@link SSLContext}
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)}.
757
+ *
758
+ * @see NioParams#enableHostnameVerification()
759
+ * @see NioParams#setSslEngineConfigurator(SslEngineConfigurator)
760
+ * @see SslEngineConfigurators#ENABLE_HOSTNAME_VERIFICATION
761
+ * @see SocketConfigurators#ENABLE_HOSTNAME_VERIFICATION
762
+ * @see ConnectionFactory#useSslProtocol(String)
763
+ * @see ConnectionFactory#useSslProtocol(SSLContext)
764
+ * @see ConnectionFactory#useSslProtocol()
765
+ * @see ConnectionFactory#useSslProtocol(String, TrustManager)
766
+ * @see ConnectionFactory#enableHostnameVerification(HostnameVerifier)
767
+ * @since 4.8.0
768
+ */
769
+ public void enableHostnameVerification () {
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" );
803
+ }
804
+
805
+ protected void enableHostnameVerificationForNio () {
806
+ if (this .nioParams == null ) {
807
+ this .nioParams = new NioParams ();
808
+ }
809
+ this .nioParams = this .nioParams .enableHostnameVerification ();
810
+ }
811
+
812
+ protected void enableHostnameVerificationForBlockingIo () {
813
+ if (this .socketConf == null ) {
814
+ this .socketConf = SocketConfigurators .builder ()
815
+ .defaultConfigurator ()
816
+ .enableHostnameVerification ()
817
+ .build ();
818
+ } else {
819
+ this .socketConf = SocketConfigurators .builder ()
820
+ .add (this .socketConf )
821
+ .enableHostnameVerification ()
822
+ .build ();
823
+ }
824
+ }
825
+
711
826
public static String computeDefaultTlsProcotol (String [] supportedProtocols ) {
712
827
if (supportedProtocols != null ) {
713
828
for (String supportedProtocol : supportedProtocols ) {
@@ -791,11 +906,11 @@ protected synchronized FrameHandlerFactory createFrameHandlerFactory() throws IO
791
906
if (this .nioParams .getNioExecutor () == null && this .nioParams .getThreadFactory () == null ) {
792
907
this .nioParams .setThreadFactory (getThreadFactory ());
793
908
}
794
- this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext );
909
+ this .frameHandlerFactory = new SocketChannelFrameHandlerFactory (connectionTimeout , nioParams , isSSL (), sslContext , connectionPostProcessor );
795
910
}
796
911
return this .frameHandlerFactory ;
797
912
} else {
798
- return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor );
913
+ return new SocketFrameHandlerFactory (connectionTimeout , factory , socketConf , isSSL (), this .shutdownExecutor , connectionPostProcessor );
799
914
}
800
915
801
916
}
@@ -1439,4 +1554,15 @@ public void setTopologyRecoveryFilter(TopologyRecoveryFilter topologyRecoveryFil
1439
1554
public void setTopologyRecoveryRetryHandler (RetryHandler topologyRecoveryRetryHandler ) {
1440
1555
this .topologyRecoveryRetryHandler = topologyRecoveryRetryHandler ;
1441
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
+ }
1442
1568
}
0 commit comments