Skip to content

Commit d64e7fa

Browse files
garyrussellartembilan
authored andcommitted
AMQP-830 Enable Hostname Verification
JIRA: https://jira.spring.io/browse/AMQP-830 * Fix typos and non-relevant sentences
1 parent ab0b9c7 commit d64e7fa

File tree

2 files changed

+63
-16
lines changed

2 files changed

+63
-16
lines changed

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

+58-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -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;
@@ -56,7 +61,7 @@
5661
* setter methods and optionally enabling SSL, with or without
5762
* certificate validation. When {@link #setSslPropertiesLocation(Resource) sslPropertiesLocation}
5863
* is not null, the default implementation loads a {@code PKCS12} keystore and a
59-
* {@code JKS} truststore using the supplied properties and intializes {@code SunX509} key
64+
* {@code JKS} truststore using the supplied properties and initializes {@code SunX509} key
6065
* and trust manager factories. These are then used to initialize an {@link SSLContext}
6166
* using the {@link #setSslAlgorithm(String) sslAlgorithm} (default TLSv1.1).
6267
* <p>
@@ -75,6 +80,19 @@
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<>();
87+
ReflectionUtils.doWithMethods(ConnectionFactory.class, m -> {
88+
if (m.getParameterTypes().length == 0) {
89+
method1.set(m);
90+
}
91+
}, m -> m.getName().equals("enableHostnameVerification"));
92+
93+
enableHostnameVerificationNoArgMethod = method1.get();
94+
}
95+
7896
private final Log logger = LogFactory.getLog(getClass());
7997

8098
private static final String KEY_STORE = "keyStore";
@@ -103,30 +121,32 @@ public class RabbitConnectionFactoryBean extends AbstractFactoryBean<ConnectionF
103121

104122
private Resource sslPropertiesLocation;
105123

106-
private volatile String keyStore;
124+
private String keyStore;
107125

108-
private volatile String trustStore;
126+
private String trustStore;
109127

110-
private volatile Resource keyStoreResource;
128+
private Resource keyStoreResource;
111129

112-
private volatile Resource trustStoreResource;
130+
private Resource trustStoreResource;
113131

114-
private volatile String keyStorePassphrase;
132+
private String keyStorePassphrase;
115133

116-
private volatile String trustStorePassphrase;
134+
private String trustStorePassphrase;
117135

118-
private volatile String keyStoreType;
136+
private String keyStoreType;
119137

120-
private volatile String trustStoreType;
138+
private String trustStoreType;
121139

122-
private volatile String sslAlgorithm = TLS_V1_1;
140+
private String sslAlgorithm = TLS_V1_1;
123141

124-
private volatile boolean sslAlgorithmSet;
142+
private boolean sslAlgorithmSet;
125143

126-
private volatile SecureRandom secureRandom;
144+
private SecureRandom secureRandom;
127145

128146
private boolean skipServerCertificateValidation;
129147

148+
private boolean enableHostnameVerification;
149+
130150
public RabbitConnectionFactoryBean() {
131151
this.connectionFactory.setAutomaticRecoveryEnabled(false);
132152
}
@@ -604,6 +624,21 @@ public void setChannelRpcTimeout(int channelRpcTimeout) {
604624
this.connectionFactory.setChannelRpcTimeout(channelRpcTimeout);
605625
}
606626

627+
/**
628+
* Enable server hostname verification for TLS connections.
629+
* <p>
630+
* This enables hostname verification regardless of the IO mode used (blocking or
631+
* non-blocking IO).
632+
* Requires amqp-client 5.4.0 or later.
633+
* @param enable true to enable.
634+
* @since 1.7.10
635+
*/
636+
public void setEnableHostnameVerification(boolean enable) {
637+
Assert.notNull(enableHostnameVerificationNoArgMethod,
638+
"Host name verification requires amqp-client 5.4.0 or later");
639+
this.enableHostnameVerification = enable;
640+
}
641+
607642
@Override
608643
public Class<?> getObjectType() {
609644
return ConnectionFactory.class;
@@ -686,6 +721,7 @@ protected void setUpSSL() throws Exception {
686721
SSLContext context = createSSLContext();
687722
context.init(keyManagers, trustManagers, this.secureRandom);
688723
this.connectionFactory.useSslProtocol(context);
724+
checkHostVerification();
689725
}
690726
}
691727

@@ -701,14 +737,20 @@ protected SSLContext createSSLContext() throws NoSuchAlgorithmException {
701737
}
702738

703739

704-
private void useDefaultTrustStoreMechanism()
705-
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
740+
private void useDefaultTrustStoreMechanism() throws Exception {
706741
SSLContext sslContext = SSLContext.getInstance(this.sslAlgorithm);
707742
TrustManagerFactory trustManagerFactory =
708743
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
709744
trustManagerFactory.init((KeyStore) null);
710745
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
711746
this.connectionFactory.useSslProtocol(sslContext);
747+
checkHostVerification();
748+
}
749+
750+
private void checkHostVerification() throws Exception {
751+
if (this.enableHostnameVerification) {
752+
enableHostnameVerificationNoArgMethod.invoke(this.connectionFactory);
753+
}
712754
}
713755

714756
}

src/reference/asciidoc/whats-new.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ 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 `enableHostnameVerification` property; set it to `true` to enable host name verification.
185+
Host name verification requires overriding the `amqp-client` to 5.4.0 or later.
186+
182187
==== Earlier Releases
183188

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

0 commit comments

Comments
 (0)