Skip to content

Commit 01761d9

Browse files
committed
AMQP-830 Enable Hostname Verification by default
JIRA: https://jira.spring.io/browse/AMQP-830
1 parent ab0b9c7 commit 01761d9

File tree

2 files changed

+73
-14
lines changed

2 files changed

+73
-14
lines changed

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/RabbitConnectionFactoryBean.java

+67-14
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,19 @@
1616

1717
package org.springframework.amqp.rabbit.connection;
1818

19+
import java.lang.reflect.Method;
1920
import java.net.URI;
2021
import java.net.URISyntaxException;
2122
import java.security.KeyManagementException;
2223
import java.security.KeyStore;
23-
import java.security.KeyStoreException;
2424
import java.security.NoSuchAlgorithmException;
2525
import java.security.SecureRandom;
2626
import java.util.Arrays;
2727
import java.util.Map;
2828
import java.util.Properties;
2929
import java.util.concurrent.ExecutorService;
3030
import java.util.concurrent.ThreadFactory;
31+
import java.util.concurrent.atomic.AtomicReference;
3132

3233
import javax.net.SocketFactory;
3334
import javax.net.ssl.KeyManager;
@@ -42,6 +43,10 @@
4243
import org.springframework.beans.factory.config.AbstractFactoryBean;
4344
import org.springframework.core.io.Resource;
4445
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
46+
import org.springframework.util.Assert;
47+
import org.springframework.util.ReflectionUtils;
48+
import org.springframework.util.ReflectionUtils.MethodCallback;
49+
import org.springframework.util.ReflectionUtils.MethodFilter;
4550
import org.springframework.util.StringUtils;
4651

4752
import com.rabbitmq.client.ConnectionFactory;
@@ -75,6 +80,30 @@
7580
*/
7681
public class RabbitConnectionFactoryBean extends AbstractFactoryBean<ConnectionFactory> {
7782

83+
private static final Method enableHostnameVerificationNoArgMethod;
84+
85+
static {
86+
final AtomicReference<Method> method1 = new AtomicReference<Method>();
87+
ReflectionUtils.doWithMethods(ConnectionFactory.class, new MethodCallback() {
88+
89+
@Override
90+
public void doWith(Method m) throws IllegalArgumentException, IllegalAccessException {
91+
if (m.getParameterTypes().length == 0) {
92+
method1.set(m);
93+
}
94+
}
95+
96+
}, new MethodFilter() {
97+
98+
@Override
99+
public boolean matches(Method m) {
100+
return m.getName().equals("enableHostnameVerification");
101+
}
102+
103+
});
104+
enableHostnameVerificationNoArgMethod = method1.get();
105+
}
106+
78107
private final Log logger = LogFactory.getLog(getClass());
79108

80109
private static final String KEY_STORE = "keyStore";
@@ -103,30 +132,32 @@ public class RabbitConnectionFactoryBean extends AbstractFactoryBean<ConnectionF
103132

104133
private Resource sslPropertiesLocation;
105134

106-
private volatile String keyStore;
135+
private String keyStore;
107136

108-
private volatile String trustStore;
137+
private String trustStore;
109138

110-
private volatile Resource keyStoreResource;
139+
private Resource keyStoreResource;
111140

112-
private volatile Resource trustStoreResource;
141+
private Resource trustStoreResource;
113142

114-
private volatile String keyStorePassphrase;
143+
private String keyStorePassphrase;
115144

116-
private volatile String trustStorePassphrase;
145+
private String trustStorePassphrase;
117146

118-
private volatile String keyStoreType;
147+
private String keyStoreType;
119148

120-
private volatile String trustStoreType;
149+
private String trustStoreType;
121150

122-
private volatile String sslAlgorithm = TLS_V1_1;
151+
private String sslAlgorithm = TLS_V1_1;
123152

124-
private volatile boolean sslAlgorithmSet;
153+
private boolean sslAlgorithmSet;
125154

126-
private volatile SecureRandom secureRandom;
155+
private SecureRandom secureRandom;
127156

128157
private boolean skipServerCertificateValidation;
129158

159+
private boolean enableHostnameVerification;
160+
130161
public RabbitConnectionFactoryBean() {
131162
this.connectionFactory.setAutomaticRecoveryEnabled(false);
132163
}
@@ -604,6 +635,21 @@ public void setChannelRpcTimeout(int channelRpcTimeout) {
604635
this.connectionFactory.setChannelRpcTimeout(channelRpcTimeout);
605636
}
606637

638+
/**
639+
* Enable server hostname verification for TLS connections.
640+
* <p>
641+
* This enables hostname verification regardless of the IO mode used (blocking or
642+
* non-blocking IO).
643+
* Requires amqp-client 5.4.0 or later.
644+
* @param enable true to enable.
645+
* @since 1.7.10
646+
*/
647+
public void setEnableHostnameVerification(boolean enable) {
648+
Assert.notNull(enableHostnameVerificationNoArgMethod,
649+
"Host name verification requires amqp-client 5.4.0 or later");
650+
this.enableHostnameVerification = enable;
651+
}
652+
607653
@Override
608654
public Class<?> getObjectType() {
609655
return ConnectionFactory.class;
@@ -686,6 +732,7 @@ protected void setUpSSL() throws Exception {
686732
SSLContext context = createSSLContext();
687733
context.init(keyManagers, trustManagers, this.secureRandom);
688734
this.connectionFactory.useSslProtocol(context);
735+
checkHostVerification();
689736
}
690737
}
691738

@@ -701,14 +748,20 @@ protected SSLContext createSSLContext() throws NoSuchAlgorithmException {
701748
}
702749

703750

704-
private void useDefaultTrustStoreMechanism()
705-
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
751+
private void useDefaultTrustStoreMechanism() throws Exception {
706752
SSLContext sslContext = SSLContext.getInstance(this.sslAlgorithm);
707753
TrustManagerFactory trustManagerFactory =
708754
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
709755
trustManagerFactory.init((KeyStore) null);
710756
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
711757
this.connectionFactory.useSslProtocol(sslContext);
758+
checkHostVerification();
759+
}
760+
761+
private void checkHostVerification() throws Exception {
762+
if (this.enableHostnameVerification) {
763+
enableHostnameVerificationNoArgMethod.invoke(this.connectionFactory);
764+
}
712765
}
713766

714767
}

src/reference/asciidoc/whats-new.adoc

+6
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ Also the `ConnectionBlockedEvent` and `ConnectionUnblockedEvent` events are emit
179179

180180
See <<connections>> for more information.
181181

182+
===== Connection Factory Bean Changes
183+
184+
The `RabbitConnectionFactoryBean` now provides an `enabaleHostnameVerification` property; set it to `true` to enable host name verification.
185+
Also `setHostnameVerifier` is provided for when using Java 6; see the connection factory javadocs for more information.
186+
Host name verification requires overriding the `amqp-client` to 5.4.0 or later.
187+
182188
==== Earlier Releases
183189

184190
See <<previous-whats-new>> for changes in previous versions.

0 commit comments

Comments
 (0)