Repository: flume Updated Branches: refs/heads/flume-1.5 d5fad3b00 -> a2175841e
FLUME-2520: HTTP Source should be able to block a prefixed set of protocols. (Hari Shreedharan via Jarek Jarcec Cecho) Project: http://git-wip-us.apache.org/repos/asf/flume/repo Commit: http://git-wip-us.apache.org/repos/asf/flume/commit/a2175841 Tree: http://git-wip-us.apache.org/repos/asf/flume/tree/a2175841 Diff: http://git-wip-us.apache.org/repos/asf/flume/diff/a2175841 Branch: refs/heads/flume-1.5 Commit: a2175841e46c44a317288b53c9d31dffcfbbfe3f Parents: d5fad3b Author: Jarek Jarcec Cecho <[email protected]> Authored: Mon Oct 27 16:27:00 2014 -0700 Committer: Jarek Jarcec Cecho <[email protected]> Committed: Mon Oct 27 16:27:42 2014 -0700 ---------------------------------------------------------------------- .../apache/flume/source/http/HTTPSource.java | 28 +++++- .../flume/source/http/TestHTTPSource.java | 98 ++++++++++++++++++-- 2 files changed, 116 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flume/blob/a2175841/flume-ng-core/src/main/java/org/apache/flume/source/http/HTTPSource.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/main/java/org/apache/flume/source/http/HTTPSource.java b/flume-ng-core/src/main/java/org/apache/flume/source/http/HTTPSource.java index 115b34f..4b2717c 100644 --- a/flume-ng-core/src/main/java/org/apache/flume/source/http/HTTPSource.java +++ b/flume-ng-core/src/main/java/org/apache/flume/source/http/HTTPSource.java @@ -35,13 +35,13 @@ import org.mortbay.jetty.servlet.ServletHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.SSLServerSocket; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.net.ServerSocket; +import java.util.*; /** * A source which accepts Flume Events by HTTP POST and GET. GET should be used @@ -172,7 +172,7 @@ public class HTTPSource extends AbstractSource implements if (sslEnabled) { - SslSocketConnector sslSocketConnector = new SslSocketConnector(); + SslSocketConnector sslSocketConnector = new HTTPSourceSocketConnector(); sslSocketConnector.setKeystore(keyStorePath); sslSocketConnector.setKeyPassword(keyStorePassword); sslSocketConnector.setReuseAddress(true); @@ -271,4 +271,24 @@ public class HTTPSource extends AbstractSource implements doPost(request, response); } } + + private static class HTTPSourceSocketConnector extends SslSocketConnector { + + @Override + public ServerSocket newServerSocket(String host, int port, + int backlog) throws IOException { + SSLServerSocket socket = (SSLServerSocket)super.newServerSocket(host, + port, backlog); + String[] protocols = socket.getEnabledProtocols(); + List<String> newProtocols = new ArrayList<String>(protocols.length); + for(String protocol: protocols) { + if (!(protocol.equals("SSLv3") || protocol.equals("SSLv2Hello"))) { + newProtocols.add(protocol); + } + } + socket.setEnabledProtocols( + newProtocols.toArray(new String[newProtocols.size()])); + return socket; + } + } } http://git-wip-us.apache.org/repos/asf/flume/blob/a2175841/flume-ng-core/src/test/java/org/apache/flume/source/http/TestHTTPSource.java ---------------------------------------------------------------------- diff --git a/flume-ng-core/src/test/java/org/apache/flume/source/http/TestHTTPSource.java b/flume-ng-core/src/test/java/org/apache/flume/source/http/TestHTTPSource.java index 5b07a6e..ec3bd50 100644 --- a/flume-ng-core/src/test/java/org/apache/flume/source/http/TestHTTPSource.java +++ b/flume-ng-core/src/test/java/org/apache/flume/source/http/TestHTTPSource.java @@ -45,9 +45,7 @@ import javax.net.ssl.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Type; -import java.net.HttpURLConnection; -import java.net.ServerSocket; -import java.net.URL; +import java.net.*; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.util.ArrayList; @@ -315,6 +313,20 @@ public class TestHTTPSource { @Test public void testHttps() throws Exception { + doTestHttps(null); + } + + @Test (expected = javax.net.ssl.SSLHandshakeException.class) + public void testHttpsSSLv3() throws Exception { + doTestHttps("SSLv3"); + } + + @Test (expected = javax.net.ssl.SSLHandshakeException.class) + public void testHttpsSSLv2Hello() throws Exception { + doTestHttps("SSLv2Hello"); + } + + public void doTestHttps(String protocol) throws Exception { Type listType = new TypeToken<List<JSONEvent>>() { }.getType(); List<JSONEvent> events = Lists.newArrayList(); @@ -361,7 +373,13 @@ public class TestHTTPSource { } }; sc.init(null, trustAllCerts, new SecureRandom()); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + javax.net.ssl.SSLSocketFactory factory = null; + if(protocol != null) { + factory = new TestSSLSocketFactory(sc.getSocketFactory(), protocol); + } else { + factory = sc.getSocketFactory(); + } + HttpsURLConnection.setDefaultSSLSocketFactory(factory); HttpsURLConnection.setDefaultHostnameVerifier( SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); URL sslUrl = new URL("https://0.0.0.0:" + sslPort); @@ -384,8 +402,6 @@ public class TestHTTPSource { transaction.commit(); transaction.close(); - } catch (Exception exception) { - Assert.fail("Exception not expected"); } finally { httpsURLConnection.disconnect(); } @@ -467,4 +483,74 @@ public class TestHTTPSource { this.events = events; } } + + private class TestSSLSocketFactory extends javax.net.ssl.SSLSocketFactory { + + private final javax.net.ssl.SSLSocketFactory socketFactory; + private final String[] protocols; + + TestSSLSocketFactory(javax.net.ssl.SSLSocketFactory factory, String protocol) { + this.socketFactory = factory; + if(protocol.equals("SSLv2Hello")) { + protocols = new String[2]; + protocols[0] = "TLSv1.2"; + protocols[1] = protocol; + } else { + protocols = new String[1]; + protocols[0] = protocol; + } + } + + @Override + public String[] getDefaultCipherSuites() { + return socketFactory.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return socketFactory.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket socket, String s, int i, boolean b) + throws IOException { + SSLSocket sc = (SSLSocket) socketFactory.createSocket(socket, s, i, b); + sc.setEnabledProtocols(protocols); + return sc; + } + + @Override + public Socket createSocket(String s, int i) + throws IOException, UnknownHostException { + SSLSocket sc = (SSLSocket)socketFactory.createSocket(s, i); + sc.setEnabledProtocols(protocols); + return sc; + } + + @Override + public Socket createSocket(String s, int i, InetAddress inetAddress, int i2) + throws IOException, UnknownHostException { + SSLSocket sc = (SSLSocket)socketFactory.createSocket(s, i, inetAddress, + i2); + sc.setEnabledProtocols(protocols); + return sc; + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i) + throws IOException { + SSLSocket sc = (SSLSocket)socketFactory.createSocket(inetAddress, i); + sc.setEnabledProtocols(protocols); + return sc; + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i, + InetAddress inetAddress2, int i2) throws IOException { + SSLSocket sc = (SSLSocket)socketFactory.createSocket(inetAddress, i, + inetAddress2, i2); + sc.setEnabledProtocols(protocols); + return sc; + } + } }
