diff options
| author | Robert Godfrey <rgodfrey@apache.org> | 2014-10-16 12:18:05 +0000 |
|---|---|---|
| committer | Robert Godfrey <rgodfrey@apache.org> | 2014-10-16 12:18:05 +0000 |
| commit | c194b6913e73661c1da7de29e02b5b921e0eaf1e (patch) | |
| tree | 83b73910af3114d4a4a6bfa588fcb34c1f28deeb /qpid/java | |
| parent | 45e8fc964106fab73b4f750da59a5349853296ea (diff) | |
| download | qpid-python-c194b6913e73661c1da7de29e02b5b921e0eaf1e.tar.gz | |
QPID-6156 : [Java] Prevent downgrade to SSLv3 on secure connections
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1632285 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
19 files changed, 311 insertions, 42 deletions
diff --git a/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java index cb1701b2fb..02bf93664e 100644 --- a/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java +++ b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java @@ -71,7 +71,7 @@ class WebSocketProvider implements TransportProvider sslContextFactory.setSslContext(context); - + sslContextFactory.addExcludeProtocols("SSLv3"); factory.start(); return factory; diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java index 139ef8fbda..1cf270f930 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java @@ -26,6 +26,9 @@ import java.io.OutputStream; import java.net.Socket; import java.net.SocketTimeoutException; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; @@ -76,6 +79,13 @@ class TCPTransportProvier implements TransportProvider final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(address, port); + List<String> supportedProtocols = Arrays.asList(sslSocket.getSupportedProtocols()); + if(supportedProtocols.contains("SSLv3")) + { + List<String> allowedProtocols = new ArrayList<>(supportedProtocols); + allowedProtocols.remove("SSLv3"); + sslSocket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } sslSocket.startHandshake(); conn.setExternalPrincipal(sslSocket.getSession().getLocalPrincipal()); _socket=sslSocket; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java index f7eeca354a..a75e74f304 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java @@ -26,7 +26,6 @@ import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.ManagedAttribute; import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.virtualhost.VirtualHostImpl; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java index afe3c9a44e..02bd8d994d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java @@ -34,7 +34,6 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; -import org.apache.qpid.server.util.PortUtil; import org.codehaus.jackson.map.ObjectMapper; import org.apache.qpid.server.configuration.BrokerProperties; @@ -43,7 +42,6 @@ import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.ManagedAttributeField; -import org.apache.qpid.server.model.ManagedContextDefault; import org.apache.qpid.server.model.ManagedObjectFactoryConstructor; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; @@ -54,6 +52,7 @@ import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.TransportProviderFactory; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.transport.TransportProvider; +import org.apache.qpid.server.util.PortUtil; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; @@ -215,6 +214,7 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider< try { SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManager[] keyManagers = keyStore.getKeyManagers(); TrustManager[] trustManagers; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 0eabcd725e..ef45971858 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -45,6 +45,7 @@ import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.security.SSLStatus; import org.apache.qpid.transport.network.security.ssl.SSLBufferingSender; import org.apache.qpid.transport.network.security.ssl.SSLReceiver; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class MultiVersionProtocolEngine implements ServerProtocolEngine { @@ -480,6 +481,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine _engine = _sslContext.createSSLEngine(); _engine.setUseClientMode(false); + SSLUtil.removeSSLv3Support(_engine); if(_needClientAuth) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java index e6bf0c1f89..733382a375 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java @@ -42,13 +42,13 @@ class TCPandSSLTransport implements AcceptingTransport private Set<Transport> _transports; private SSLContext _sslContext; private InetSocketAddress _bindingSocketAddress; - private Port<?> _port; + private AmqpPort<?> _port; private Set<Protocol> _supported; private Protocol _defaultSupportedProtocolReply; TCPandSSLTransport(final Set<Transport> transports, final SSLContext sslContext, - final Port<?> port, + final AmqpPort<?> port, final Set<Protocol> supported, final Protocol defaultSupportedProtocolReply) { @@ -67,7 +67,7 @@ class TCPandSSLTransport implements AcceptingTransport { bindingAddress = null; } - Integer port = (Integer) _port.getAttribute(Port.PORT); + int port = _port.getPort(); if ( bindingAddress == null ) { _bindingSocketAddress = new InetSocketAddress(port); @@ -91,6 +91,11 @@ class TCPandSSLTransport implements AcceptingTransport _networkTransport.accept(settings, protocolEngineFactory, _transports.contains(Transport.TCP) ? null : _sslContext); } + public int getAcceptingPort() + { + return _networkTransport.getAcceptingPort(); + } + @Override public void close() { @@ -106,31 +111,31 @@ class TCPandSSLTransport implements AcceptingTransport @Override public boolean wantClientAuth() { - return (Boolean)_port.getAttribute(Port.WANT_CLIENT_AUTH); + return _port.getWantClientAuth(); } @Override public boolean needClientAuth() { - return (Boolean)_port.getAttribute(Port.NEED_CLIENT_AUTH); + return _port.getNeedClientAuth(); } @Override public Boolean getTcpNoDelay() { - return (Boolean)_port.getAttribute(Port.TCP_NO_DELAY); + return _port.isTcpNoDelay(); } @Override public Integer getSendBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.SEND_BUFFER_SIZE); + return _port.getSendBufferSize(); } @Override public Integer getReceiveBufferSize() { - return (Integer)_port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE); + return _port.getReceiveBufferSize(); } @Override diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java index 7c7d0ea9e6..fa0d9bfcff 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java @@ -24,16 +24,16 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; class TCPandSSLTransportProvider implements TransportProvider { @Override public AcceptingTransport createTransport(final Set<Transport> transports, final SSLContext sslContext, - final Port port, + final AmqpPort<?> port, final Set<Protocol> supported, final Protocol defaultSupportedProtocolReply) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java index 04b4b44c2e..24061562e5 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java @@ -24,15 +24,15 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; public interface TransportProvider { AcceptingTransport createTransport(Set<Transport> transports, SSLContext sslContext, - Port port, + AmqpPort<?> port, Set<Protocol> supported, Protocol defaultSupportedProtocolReply); } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java new file mode 100644 index 0000000000..d8471e5384 --- /dev/null +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/transport/TCPandSSLTransportTest.java @@ -0,0 +1,180 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.net.InetAddress; +import java.security.KeyStore; +import java.util.Arrays; +import java.util.HashSet; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManagerFactory; +import javax.xml.bind.DatatypeConverter; + +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; +import org.apache.qpid.test.utils.QpidTestCase; + +public class TCPandSSLTransportTest extends QpidTestCase +{ + + public void testNoSSLv3SupportOnSSLOnlyPort() throws Exception + { + try + { + checkSSLExcluded("SSLv3", Transport.SSL); + fail("Should not be able to connect using SSLv3"); + } + catch(SSLHandshakeException e) + { + // pass + } + } + + + public void testNoSSLv3SupportOnSharedPort() throws Exception + { + try + { + checkSSLExcluded("SSLv3", Transport.TCP, Transport.SSL); + fail("Should not be able to connect using SSLv3"); + } + catch(SSLHandshakeException e) + { + // pass + } + } + + + public void testTLSSupportOnSharedPort() throws Exception + { + try + { + checkSSLExcluded("TLSv1.1", Transport.TCP, Transport.SSL); + } + catch(SSLHandshakeException e) + { + // pass + fail("Should be able to connect using TLSv1.1"); + + } + } + + + + private void checkSSLExcluded(String clientProtocol, final Transport... transports) throws Exception + { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(keystoreString)), "password".toCharArray()); + + + final SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, "password".toCharArray()); + + sslContext.init(kmf.getKeyManagers(), null, null); + + + + final AmqpPort<?> port = mock(AmqpPort.class); + when(port.getPort()).thenReturn(0); + when(port.getSendBufferSize()).thenReturn(64*1024); + when(port.getReceiveBufferSize()).thenReturn(64*1024); + + TCPandSSLTransport transport = new TCPandSSLTransport(new HashSet<>(Arrays.asList(transports)), + sslContext, + port, + new HashSet<>(Arrays.asList(Protocol.AMQP_0_8, + Protocol.AMQP_0_9, + Protocol.AMQP_0_9_1, + Protocol.AMQP_0_10, + Protocol.AMQP_1_0)), + Protocol.AMQP_0_9_1); + + transport.start(); + + SSLContext clientContext = SSLContext.getInstance("TLS"); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(keyStore); + + clientContext.init(null, tmf.getTrustManagers(), null); + + + SSLSocket sslSocket = + (SSLSocket) clientContext.getSocketFactory().createSocket(InetAddress.getLoopbackAddress(), + transport.getAcceptingPort()); + + sslSocket.setEnabledProtocols(new String[] {clientProtocol}); + + sslSocket.startHandshake(); + transport.close(); + } + + // self signed cert keystore valid until Oct 2024 + private static String keystoreString = "/u3+7QAAAAIAAAABAAAAAQAKc2VsZnNpZ25lZAAAAUkYmo+uAAAFATCCBP0wDgYKKwYBBAEqAhEB" + + "AQUABIIE6bR+b7FHo2BRT/WG+zDIfO8zOXoGIbuNL2znNMnvEp9xwfMQOkhKxEbVtX8uJ7HSwi1V" + + "bV2it0CA59sgvRt9awmgg+W1CLgkGKNOB+kQZbjL8R8lXmKibw4yU/EFm5rqDqPEXBRBj40TF0aT" + + "GtCCmmLPsH2pGU1wH2Ne/tozk8q7hYK6XMH/i43ZXhS9V2CKzPWrzhXmvjFKCtmYHNLj5nLLE/n0" + + "snqAssBoFSAJKmqkqHQBJNQjm4oqJFSISB8pwDX++0kvOMM7j5ryjVwihsCYuHZ6lh5BntDGF41L" + + "f4XADfv3Fma6nZQKfKs0VU2kAWUmjPpyV1FFq/ua4x6SUdZKS22YIQ3t6iO76TDABbQNyUX+Ge4n" + + "k6clF8MFswKTT0ug7zjb17d36gwl+UznvFqMSE6Zkrr9nNAcSVlQS+JaazXveiVEXTBYCAZgsNw3" + + "3KqlLWliAegnwQCQLOguw7bgusnZ/E61/TL8GTryiwN1mltbnsWkCjMj1AGUBM3sYNwbj87Vdhij" + + "iHJbjcB7q3Dak68khrCTLmqoD43KHBB5g+UMlruXYbE0elWqYpXGjI5cvt4gzfh1V+ira5DOfa4B" + + "Qskv/dh1uj2xAe1YEvF3xmdO2F6Yuzd88VO0aaPGroYPfRmh2M6rEOlwc2Ku/p23FjSWrLyzori8" + + "8/OKV4PM2b/NtY51ztTKWR/eUdX6qTPUJMK5CJiOxKGxk9PDtmsbQY685H6QVDKzTkbaPlP97+Oa" + + "xv3/2RIWR7KJzsxbqiYhX0fevRJw/RY6ZY3NEE5RAmCjzxD+1qDtu0QM/LspgPxyv5oSInAtT23U" + + "BrcNIiQ8jO+6E+fDcVhFSrs6gLGe1BwKYHsosjvup8FETLZgqKY6g1mwECA/Un2agzhI4tGC0O8v" + + "lU4VEZKrXwgy/XQ5C2vwwgLvJh94OfE20Wuf7Jjq8IUPcdF201XeYREE/vSNcBnJf22yPouJMIPk" + + "yNxlAHcapeFUi00yC19FEIpdoW/8pX2k64jx63CwwVckWWOIWlg8N+z9jsiwdjvm5wL2aFU3+wtu" + + "8Nj6Soy7Y3QYAwx17q/nUOJOk5DqLedG+/DKXVs5jghmbQ9wyzqGjGs+xYvSCXtQJygETUU/ddoM" + + "/iK4hhnZL2uqZ0wamef4ibdBbhpoRO8C7mSbi7TbDtcfysZrMb6i5MugR+NwKKzN2DznXItvpgzc" + + "Xm9j7LP8HZcQANa+1o2aIGDqK1fMSAOmBbTWlYkHPDbpoE/lx32iBNL/Aj8aKbtkwy/J2JRvo9m2" + + "uBdLK4DoDeTjqG//AwISrwm9y6xxIIPNQq7GiftN6p9KCI87U5pxqs5yUQ1g/e9DCioLe8O3Vug7" + + "+1jS1ZHWFtb4BBEF3EhkKa1AOVKNu9+M8lcG9tKWUBjnIFTD68a++6B36ShRnIZNbmbRkLC6wWdB" + + "SdyI6FWPxsPvGSF+3wq+n+0bu75N3Xsta5tEOjc67DfnQlyZtP/BIZsKxgEueOcXkjzaXMPYcrlJ" + + "2BInovQSHnSHvQfaBKqj/nKcGaDyydfdxF5fyjRPFYF+fFCWXrFkbQgAst8ymJ//UpLomfw+Ni6f" + + "xx2XQGt3941zhRuXJI2tdvUb2Czzsp0tq+h46d0WOlYQ57Q70weUQRrtARqCKoSp/gNUzQsvd+FO" + + "sUUxKRoJltRYBwAAAAEABVguNTA5AAADdTCCA3EwggJZoAMCAQICBBAXeI4wDQYJKoZIhvcNAQEL" + + "BQAwaDELMAkGA1UEBhMCVUsxETAPBgNVBAgTCFNjb3RsYW5kMRAwDgYDVQQHEwdHbGFzZ293MQ8w" + + "DQYDVQQKEwZBcGFjaGUxDTALBgNVBAsTBFFwaWQxFDASBgNVBAMTC0FwYWNoZSBRcGlkMCAXDTE0" + + "MTAxNjEwNTY1NVoYDzIxMTMwNTEwMTA1NjU1WjBoMQswCQYDVQQGEwJVSzERMA8GA1UECBMIU2Nv" + + "dGxhbmQxEDAOBgNVBAcTB0dsYXNnb3cxDzANBgNVBAoTBkFwYWNoZTENMAsGA1UECxMEUXBpZDEU" + + "MBIGA1UEAxMLQXBhY2hlIFFwaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC520Yd" + + "1GuXh67h7HawvL5/pwTr46P45R0gx+LDGC1Equ9/wvvsVbCPL0JLDTSKl0qpgbJNMH/A740vSilb" + + "FDdqfyOuIkQZN1Ub9CkOaI5uR9RjaC2MfyNUJl7Gp64nSYk9iDX15ddZjsAijUDvET32XzfirlML" + + "dwLXv1Y5dLskV0r6xK4NdLtXi+Ndn+Uy4EllD7VMIFaLt6oG9Vo6mNl0jze7Yz/aYYtWns4x+uG8" + + "WbMgtcXo/VxCyp+4ji06XFerwfkS0zBS1wfvxd5Qb1+4dYovSn1v0AaPvZ0XwG4XErP2/svU01nc" + + "C43Z4neHdsj8Y/kmXLDD8Nc7Mpv/Wm6hAgMBAAGjITAfMB0GA1UdDgQWBBQfKBRPr/QD7PjpM3s4" + + "rD8u6ZxiijANBgkqhkiG9w0BAQsFAAOCAQEAFjyjJ8pbHf6MioZpOOlZh4lz6F+9dW1KyJR0OIc4" + + "FXnYnU/CNzjkwPminuZJoYgXBh+sVFN238YFS3I8ONEQJy8uSH33T81sklXhqnrSk9OlWk1v60wH" + + "NwwNFz5ZuGrGlvk9EFhbC8FgdkXJbz21drAl18i2oJHPdQQNwdc6mwqhpNfjqZ2opfJPbVscX1P/" + + "dbJjfcoZ01fy5687zjpN11G4egwsrya2FZiAw1WPI10OhrJgiGL5aDiDLjauNZmoM7QchUUD1cjE" + + "EwvRkU1MesliLg4y3UqDoV6ooHB4ClE2aKmIdbVB/eP1QrEEkey93ptt1z5fLk1l408AkXQtzyw7" + + "9WC+xnZta0IoYC/vO29IVsok"; +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index 936cc4789a..6e104f844f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -74,6 +74,7 @@ import org.apache.qpid.server.model.port.HttpPort; import org.apache.qpid.server.model.port.PortManager; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; @ManagedObject( category = false, type = "MANAGEMENT-HTTP" ) public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implements HttpManagementConfiguration<HttpManagement>, PortManager @@ -317,7 +318,7 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore"); } SslContextFactory factory = new SslContextFactory(); - + factory.addExcludeProtocols(SSLUtil.SSLV3_PROTOCOL); boolean needClientCert = port.getNeedClientAuth() || port.getWantClientAuth(); if (needClientCert && trustStores.isEmpty()) diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java index b0f5abd1a3..5c15a40427 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/QpidSslRMIServerSocketFactory.java @@ -30,6 +30,8 @@ import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; + public class QpidSslRMIServerSocketFactory extends SslRMIServerSocketFactory { private final SSLContext _sslContext; @@ -74,7 +76,7 @@ public class QpidSslRMIServerSocketFactory extends SslRMIServerSocketFactory socket.getPort(), true); sslSocket.setUseClientMode(false); - + SSLUtil.removeSSLv3Support(sslSocket); return sslSocket; } }; diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java index d989a73fa2..8e250ef669 100644 --- a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java +++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java @@ -32,8 +32,6 @@ import java.util.Set; import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; -import org.apache.qpid.server.model.port.AmqpPort; -import org.apache.qpid.server.model.port.HttpPort; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; @@ -48,11 +46,14 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; +import org.apache.qpid.server.model.port.HttpPort; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.util.ServerScopedRuntimeException; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; class WebSocketProvider implements AcceptingTransport { @@ -103,6 +104,7 @@ class WebSocketProvider implements AcceptingTransport { SslContextFactory factory = new SslContextFactory(); factory.setSslContext(_sslContext); + factory.addExcludeProtocols(SSLUtil.SSLV3_PROTOCOL); factory.setNeedClientAuth(true); connector = new SslSelectChannelConnector(factory); } diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java index 346e29e212..c7578adb91 100644 --- a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java +++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java @@ -24,9 +24,9 @@ import java.util.Set; import javax.net.ssl.SSLContext; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.port.AmqpPort; import org.apache.qpid.server.transport.AcceptingTransport; import org.apache.qpid.server.transport.TransportProvider; @@ -39,7 +39,7 @@ class WebSocketTransportProvider implements TransportProvider @Override public AcceptingTransport createTransport(final Set<Transport> transports, final SSLContext sslContext, - final Port port, + final AmqpPort<?> port, final Set<Protocol> supported, final Protocol defaultSupportedProtocolReply) { diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java index 8437ef1a94..e0cd9cac1a 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java @@ -20,14 +20,16 @@ */ package org.apache.qpid.transport.network; +import javax.net.ssl.SSLContext; + import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.transport.NetworkTransportConfiguration; -import javax.net.ssl.SSLContext; - public interface IncomingNetworkTransport extends NetworkTransport { public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext); -}
\ No newline at end of file + + public int getAcceptingPort(); +} diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java index 4ccb88bbf8..068e19fbc4 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java @@ -27,12 +27,12 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.nio.ByteBuffer; -import java.security.Principal; + import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; + +import org.slf4j.LoggerFactory; import org.apache.qpid.configuration.CommonProperties; import org.apache.qpid.protocol.ProtocolEngine; @@ -41,9 +41,11 @@ import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.NetworkTransportConfiguration; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.*; - -import org.slf4j.LoggerFactory; +import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.OutgoingNetworkTransport; +import org.apache.qpid.transport.network.TransportActivity; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport { @@ -150,6 +152,11 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } } + public int getAcceptingPort() + { + return _acceptor == null ? -1 : _acceptor.getPort(); + } + private class AcceptingThread extends Thread { private volatile boolean _closed = false; @@ -179,14 +186,19 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory(); _serverSocket = socketFactory.createServerSocket(); + SSLServerSocket sslServerSocket = (SSLServerSocket) _serverSocket; + + SSLUtil.removeSSLv3Support(sslServerSocket); + if(config.needClientAuth()) { - ((SSLServerSocket)_serverSocket).setNeedClientAuth(true); + sslServerSocket.setNeedClientAuth(true); } else if(config.wantClientAuth()) { - ((SSLServerSocket)_serverSocket).setWantClientAuth(true); + sslServerSocket.setWantClientAuth(true); } + } _serverSocket.setReuseAddress(true); @@ -215,6 +227,11 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } } + private int getPort() + { + return _serverSocket.getLocalPort(); + } + @Override public void run() { diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java index bfd1ae8181..2a2f3d8362 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java @@ -20,6 +20,11 @@ */ package org.apache.qpid.transport.network.security; +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; + import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Receiver; @@ -31,10 +36,6 @@ import org.apache.qpid.transport.network.security.ssl.SSLReceiver; import org.apache.qpid.transport.network.security.ssl.SSLSender; import org.apache.qpid.transport.network.security.ssl.SSLUtil; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import java.nio.ByteBuffer; - public class SecurityLayerFactory { private SecurityLayerFactory() @@ -100,6 +101,7 @@ public class SecurityLayerFactory { _engine = sslCtx.createSSLEngine(); _engine.setUseClientMode(true); + SSLUtil.removeSSLv3Support(_engine); } catch(Exception e) { diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java index 487b0c485b..0494f60e23 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java @@ -30,6 +30,8 @@ import java.security.Principal; import java.security.cert.Certificate; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; @@ -39,6 +41,8 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.util.Logger; @@ -47,6 +51,7 @@ public class SSLUtil { private static final Logger log = Logger.get(SSLUtil.class); private static final Integer DNS_NAME_TYPE = 2; + public static final String SSLV3_PROTOCOL = "SSLv3"; private SSLUtil() { @@ -242,4 +247,38 @@ public class SSLUtil } return ks; } + + public static void removeSSLv3Support(final SSLEngine engine) + { + List<String> supportedProtocols = Arrays.asList(engine.getSupportedProtocols()); + if(supportedProtocols.contains(SSLV3_PROTOCOL)) + { + List<String> allowedProtocols = new ArrayList<>(supportedProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + engine.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } + + public static void removeSSLv3Support(final SSLSocket socket) + { + List<String> supportedProtocols = Arrays.asList(socket.getSupportedProtocols()); + if(supportedProtocols.contains(SSLV3_PROTOCOL)) + { + List<String> allowedProtocols = new ArrayList<>(supportedProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + socket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } + + + public static void removeSSLv3Support(final SSLServerSocket socket) + { + List<String> supportedProtocols = Arrays.asList(socket.getSupportedProtocols()); + if(supportedProtocols.contains(SSLV3_PROTOCOL)) + { + List<String> allowedProtocols = new ArrayList<>(supportedProtocols); + allowedProtocols.remove(SSLV3_PROTOCOL); + socket.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); + } + } } diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java index bf9a5843d6..3071594be7 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java @@ -21,6 +21,10 @@ package org.apache.qpid.transport.network; +import java.nio.ByteBuffer; + +import javax.net.ssl.SSLContext; + import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.test.utils.QpidTestCase; @@ -30,9 +34,6 @@ import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.io.IoNetworkTransport; -import javax.net.ssl.SSLContext; -import java.nio.ByteBuffer; - public class TransportTest extends QpidTestCase { @@ -153,5 +154,11 @@ public class TransportTest extends QpidTestCase { throw new UnsupportedOperationException(); } + + @Override + public int getAcceptingPort() + { + return -1; + } } } diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java index eb61e5a084..3464051fc5 100644 --- a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java @@ -36,6 +36,9 @@ import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQTestConnection_0_10; import org.apache.qpid.jms.ConnectionURL; @@ -43,8 +46,6 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SSLTest extends QpidBrokerTestCase { |
