Skip to content

Commit 2b619b2

Browse files
committed
Add option to enable hostname verification
Fixes #55 (cherry picked from commit d31693b) Conflicts: src/main/java/com/rabbitmq/jms/admin/RMQConnectionFactory.java
1 parent d87bcf9 commit 2b619b2

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

src/main/java/com/rabbitmq/jms/admin/RMQConnectionFactory.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ public class RMQConnectionFactory implements ConnectionFactory, Referenceable, S
109109
private SSLContext sslContext;
110110
private boolean useDefaultSslContext = false;
111111

112+
/**
113+
* Whether to use hostname verification when TLS is on.
114+
*
115+
* @since 1.10.0
116+
*/
117+
private boolean hostnameVerification = false;
118+
119+
112120
/** The maximum number of messages to read on a queue browser, which must be non-negative;
113121
* 0 means unlimited and is the default; negative values are interpreted as 0. */
114122
private int queueBrowserReadMax = Math.max(0, Integer.getInteger("rabbit.jms.queueBrowserReadMax", 0));
@@ -154,8 +162,8 @@ public Connection createConnection(String username, String password) throws JMSE
154162
com.rabbitmq.client.ConnectionFactory factory = new com.rabbitmq.client.ConnectionFactory();
155163
setRabbitUri(logger, this, factory, this.getUri());
156164
maybeEnableTLS(factory);
157-
158165
factory.setMetricsCollector(this.metricsCollector);
166+
maybeEnableHostnameVerification(factory);
159167
com.rabbitmq.client.Connection rabbitConnection = instantiateNodeConnection(factory);
160168

161169
RMQConnection conn = new RMQConnection(new ConnectionParams()
@@ -181,6 +189,7 @@ public Connection createConnection(String username, String password, List<Addres
181189
this.password = password;
182190
com.rabbitmq.client.ConnectionFactory cf = new com.rabbitmq.client.ConnectionFactory();
183191
maybeEnableTLS(cf);
192+
cf.setMetricsCollector(this.metricsCollector);
184193
com.rabbitmq.client.Connection rabbitConnection = instantiateNodeConnection(cf, endpoints);
185194

186195
RMQConnection conn = new RMQConnection(new ConnectionParams()
@@ -340,6 +349,16 @@ private void maybeEnableTLS(com.rabbitmq.client.ConnectionFactory factory) {
340349
}
341350
}
342351

352+
private void maybeEnableHostnameVerification(com.rabbitmq.client.ConnectionFactory factory) {
353+
if (hostnameVerification) {
354+
if (this.ssl) {
355+
factory.enableHostnameVerification();
356+
} else {
357+
logger.warn("Hostname verification enabled, but not TLS, please enable TLS too.");
358+
}
359+
}
360+
}
361+
343362
public boolean isSsl() {
344363
return this.ssl;
345364
}
@@ -742,5 +761,17 @@ public void setAmqpPropertiesCustomiser(AmqpPropertiesCustomiser amqpPropertiesC
742761
public void setMetricsCollector(MetricsCollector metricsCollector) {
743762
this.metricsCollector = metricsCollector;
744763
}
764+
765+
/**
766+
* Enable or disable hostname verification when TLS is used.
767+
*
768+
* @param hostnameVerification
769+
* @see com.rabbitmq.client.ConnectionFactory#enableHostnameVerification()
770+
* @since 1.10.0
771+
*/
772+
public void setHostnameVerification(boolean hostnameVerification) {
773+
this.hostnameVerification = hostnameVerification;
774+
}
775+
745776
}
746777

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* Copyright (c) 2018 Pivotal Software, Inc. All rights reserved. */
2+
package com.rabbitmq.integration.tests;
3+
4+
import com.rabbitmq.jms.admin.RMQConnectionFactory;
5+
import org.junit.Before;
6+
import org.junit.BeforeClass;
7+
import org.junit.Test;
8+
9+
import javax.jms.Connection;
10+
import javax.jms.JMSException;
11+
import javax.jms.JMSSecurityException;
12+
import javax.net.ssl.KeyManagerFactory;
13+
import javax.net.ssl.SSLContext;
14+
import javax.net.ssl.TrustManagerFactory;
15+
import java.io.FileInputStream;
16+
import java.security.KeyStore;
17+
18+
import static org.junit.Assert.assertNotNull;
19+
20+
/**
21+
* Integration test for hostname verification with TLS.
22+
*/
23+
public class SSLHostnameVerificationIT {
24+
25+
static SSLContext sslContext;
26+
RMQConnectionFactory cf;
27+
28+
@BeforeClass
29+
public static void initCrypto() throws Exception {
30+
String keystorePath = System.getProperty("test-keystore.ca");
31+
assertNotNull(keystorePath);
32+
String keystorePasswd = System.getProperty("test-keystore.password");
33+
assertNotNull(keystorePasswd);
34+
char[] keystorePassword = keystorePasswd.toCharArray();
35+
36+
KeyStore tks = KeyStore.getInstance("JKS");
37+
tks.load(new FileInputStream(keystorePath), keystorePassword);
38+
39+
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
40+
tmf.init(tks);
41+
42+
String p12Path = System.getProperty("test-client-cert.path");
43+
assertNotNull(p12Path);
44+
String p12Passwd = System.getProperty("test-client-cert.password");
45+
assertNotNull(p12Passwd);
46+
47+
KeyStore ks = KeyStore.getInstance("PKCS12");
48+
char[] p12Password = p12Passwd.toCharArray();
49+
ks.load(new FileInputStream(p12Path), p12Password);
50+
51+
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
52+
kmf.init(ks, p12Password);
53+
54+
sslContext = SSLContext.getInstance("TLSv1.2");
55+
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
56+
}
57+
58+
@Before
59+
public void init() {
60+
cf = new RMQConnectionFactory();
61+
cf.useSslProtocol(sslContext);
62+
cf.setHostnameVerification(true);
63+
}
64+
65+
@Test
66+
public void hostnameVerificationEnabledShouldPassForLocalhost() throws JMSException {
67+
cf.setHost("localhost");
68+
Connection connection = null;
69+
try {
70+
connection = cf.createConnection();
71+
} finally {
72+
if (connection != null) {
73+
connection.close();
74+
}
75+
}
76+
}
77+
78+
@Test(expected = JMSSecurityException.class)
79+
public void hostnameVerificationEnabledShouldFailForLoopbackInterface() throws JMSException {
80+
cf.setHost("127.0.0.1");
81+
cf.createConnection();
82+
}
83+
}

0 commit comments

Comments
 (0)