Initial fix for FTPSERVER-491
diff --git a/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java b/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java
index 401b7d3..4cbf62a 100644
--- a/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java
+++ b/core/src/main/java/org/apache/ftpserver/listener/nio/NioListener.java
@@ -74,148 +74,138 @@
private FtpServerContext context;
/**
- * @deprecated Use the constructor with IpFilter instead.
- * Constructor for internal use, do not use directly. Instead use {@link ListenerFactory}
+ * @deprecated Use the constructor with IpFilter instead. Constructor for internal use, do not use directly. Instead
+ * use {@link ListenerFactory}
*/
@Deprecated
- public NioListener(String serverAddress, int port,
- boolean implicitSsl,
- SslConfiguration sslConfiguration,
- DataConnectionConfiguration dataConnectionConfig,
- int idleTimeout, List<InetAddress> blockedAddresses, List<Subnet> blockedSubnets) {
- super(serverAddress, port, implicitSsl, sslConfiguration, dataConnectionConfig,
- idleTimeout, blockedAddresses, blockedSubnets);
+ public NioListener(String serverAddress, int port, boolean implicitSsl, SslConfiguration sslConfiguration, DataConnectionConfiguration dataConnectionConfig, int idleTimeout, List<InetAddress> blockedAddresses, List<Subnet> blockedSubnets) {
+ super(serverAddress, port, implicitSsl, sslConfiguration, dataConnectionConfig, idleTimeout, blockedAddresses, blockedSubnets);
}
/**
* Constructor for internal use, do not use directly. Instead use {@link ListenerFactory}
*/
- public NioListener(String serverAddress, int port, boolean implicitSsl,
- SslConfiguration sslConfiguration,
- DataConnectionConfiguration dataConnectionConfig, int idleTimeout,
- SessionFilter sessionFilter) {
- super(serverAddress, port, implicitSsl, sslConfiguration,
- dataConnectionConfig, idleTimeout, sessionFilter);
+ public NioListener(String serverAddress, int port, boolean implicitSsl, SslConfiguration sslConfiguration, DataConnectionConfiguration dataConnectionConfig, int idleTimeout, SessionFilter sessionFilter) {
+ super(serverAddress, port, implicitSsl, sslConfiguration, dataConnectionConfig, idleTimeout, sessionFilter);
}
/**
* @see Listener#start(FtpServerContext)
*/
public synchronized void start(FtpServerContext context) {
- if(!isStopped()) {
- // listener already started, don't allow
- throw new IllegalStateException("Listener already started");
- }
-
- try {
-
- this.context = context;
-
- acceptor = new NioSocketAcceptor(Runtime.getRuntime()
- .availableProcessors());
-
- if (getServerAddress() != null) {
- address = new InetSocketAddress(getServerAddress(), getPort());
- } else {
- address = new InetSocketAddress(getPort());
- }
-
- acceptor.setReuseAddress(true);
- acceptor.getSessionConfig().setReadBufferSize(2048);
- acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,
- getIdleTimeout());
- // Decrease the default receiver buffer size
- acceptor.getSessionConfig().setReceiveBufferSize(512);
-
- MdcInjectionFilter mdcFilter = new MdcInjectionFilter();
-
- acceptor.getFilterChain().addLast("mdcFilter", mdcFilter);
+ if (!isStopped()) {
+ // listener already started, don't allow
+ throw new IllegalStateException("Listener already started");
+ }
- SessionFilter sessionFilter = getSessionFilter();
- if (sessionFilter != null) {
- // add and IP filter to the filter chain.
- acceptor.getFilterChain().addLast("sessionFilter",
- new MinaSessionFilter(sessionFilter));
- }
-
- acceptor.getFilterChain().addLast("threadPool",
- new ExecutorFilter(context.getThreadPoolExecutor()));
- acceptor.getFilterChain().addLast("codec",
- new ProtocolCodecFilter(new FtpServerProtocolCodecFactory()));
- acceptor.getFilterChain().addLast("mdcFilter2", mdcFilter);
- acceptor.getFilterChain().addLast("logger", new FtpLoggingFilter());
-
- if (isImplicitSsl()) {
- SslConfiguration ssl = getSslConfiguration();
- SslFilter sslFilter;
- try {
- sslFilter = new SslFilter(ssl.getSSLContext());
- } catch (GeneralSecurityException e) {
- throw new FtpServerConfigurationException("SSL could not be initialized, check configuration");
- }
-
- if (ssl.getClientAuth() == ClientAuth.NEED) {
- sslFilter.setNeedClientAuth(true);
- } else if (ssl.getClientAuth() == ClientAuth.WANT) {
- sslFilter.setWantClientAuth(true);
- }
-
- if (ssl.getEnabledCipherSuites() != null) {
- sslFilter.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
- }
-
- acceptor.getFilterChain().addFirst("sslFilter", sslFilter);
- }
-
- handler.init(context, this);
- acceptor.setHandler(new FtpHandlerAdapter(context, handler));
-
- try {
- acceptor.bind(address);
- } catch (IOException e) {
- throw new FtpServerConfigurationException("Failed to bind to address " + address + ", check configuration", e);
- }
-
- updatePort();
-
- } catch(RuntimeException e) {
- // clean up if we fail to start
- stop();
-
- throw e;
- }
+ try {
+
+ this.context = context;
+
+ acceptor = new NioSocketAcceptor(Runtime.getRuntime().availableProcessors());
+
+ if (getServerAddress() != null) {
+ address = new InetSocketAddress(getServerAddress(), getPort());
+ } else {
+ address = new InetSocketAddress(getPort());
+ }
+
+ acceptor.setReuseAddress(true);
+ acceptor.getSessionConfig().setReadBufferSize(2048);
+ acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, getIdleTimeout());
+ // Decrease the default receiver buffer size
+ acceptor.getSessionConfig().setReceiveBufferSize(512);
+
+ MdcInjectionFilter mdcFilter = new MdcInjectionFilter();
+
+ acceptor.getFilterChain().addLast("mdcFilter", mdcFilter);
+
+ SessionFilter sessionFilter = getSessionFilter();
+ if (sessionFilter != null) {
+ // add and IP filter to the filter chain.
+ acceptor.getFilterChain().addLast("sessionFilter", new MinaSessionFilter(sessionFilter));
+ }
+
+ acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(context.getThreadPoolExecutor()));
+ acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FtpServerProtocolCodecFactory()));
+ acceptor.getFilterChain().addLast("mdcFilter2", mdcFilter);
+ acceptor.getFilterChain().addLast("logger", new FtpLoggingFilter());
+
+ if (isImplicitSsl()) {
+ SslConfiguration ssl_conf = getSslConfiguration();
+ SslFilter ssl_filter;
+ try {
+ ssl_filter = new SslFilter(ssl_conf.getSSLContext());
+ } catch (GeneralSecurityException e) {
+ throw new FtpServerConfigurationException("SSL could not be initialized, check configuration");
+ }
+
+ if (ssl_conf.getClientAuth() == ClientAuth.NEED) {
+ ssl_filter.setNeedClientAuth(true);
+ } else if (ssl_conf.getClientAuth() == ClientAuth.WANT) {
+ ssl_filter.setWantClientAuth(true);
+ }
+
+ if (ssl_conf.getEnabledProtocol() != null) {
+ ssl_filter.setEnabledProtocols(new String[] { ssl_conf.getEnabledProtocol() });
+ }
+
+ if (ssl_conf.getEnabledCipherSuites() != null) {
+ ssl_filter.setEnabledCipherSuites(ssl_conf.getEnabledCipherSuites());
+ }
+
+ acceptor.getFilterChain().addFirst("sslFilter", ssl_filter);
+ }
+
+ handler.init(context, this);
+ acceptor.setHandler(new FtpHandlerAdapter(context, handler));
+
+ try {
+ acceptor.bind(address);
+ } catch (IOException e) {
+ throw new FtpServerConfigurationException("Failed to bind to address " + address + ", check configuration", e);
+ }
+
+ updatePort();
+
+ } catch (RuntimeException e) {
+ // clean up if we fail to start
+ stop();
+
+ throw e;
+ }
}
-
+
private void updatePort() {
- // update the port to the real port bound by the listener
- setPort(acceptor.getLocalAddress().getPort());
+ // update the port to the real port bound by the listener
+ setPort(acceptor.getLocalAddress().getPort());
}
/**
* @see Listener#stop()
*/
public synchronized void stop() {
- // close server socket
- if (acceptor != null) {
- acceptor.unbind();
- acceptor.dispose();
- acceptor = null;
- }
- context = null;
+ // close server socket
+ if (acceptor != null) {
+ acceptor.unbind();
+ acceptor.dispose();
+ acceptor = null;
+ }
+ context = null;
}
/**
* @see Listener#isStopped()
*/
public boolean isStopped() {
- return acceptor == null;
+ return acceptor == null;
}
/**
* @see Listener#isSuspended()
*/
public boolean isSuspended() {
- return suspended;
+ return suspended;
}
@@ -223,44 +213,44 @@
* @see Listener#resume()
*/
public synchronized void resume() {
- if (acceptor != null && suspended) {
- try {
- LOG.debug("Resuming listener");
- acceptor.bind(address);
- LOG.debug("Listener resumed");
-
- updatePort();
-
- suspended = false;
- } catch (IOException e) {
- LOG.error("Failed to resume listener", e);
- }
- }
+ if (acceptor != null && suspended) {
+ try {
+ LOG.debug("Resuming listener");
+ acceptor.bind(address);
+ LOG.debug("Listener resumed");
+
+ updatePort();
+
+ suspended = false;
+ } catch (IOException e) {
+ LOG.error("Failed to resume listener", e);
+ }
+ }
}
/**
* @see Listener#suspend()
*/
public synchronized void suspend() {
- if (acceptor != null && !suspended) {
- LOG.debug("Suspending listener");
- acceptor.unbind();
-
- suspended = true;
- LOG.debug("Listener suspended");
- }
+ if (acceptor != null && !suspended) {
+ LOG.debug("Suspending listener");
+ acceptor.unbind();
+
+ suspended = true;
+ LOG.debug("Listener suspended");
+ }
}
-
+
/**
* @see Listener#getActiveSessions()
*/
public synchronized Set<FtpIoSession> getActiveSessions() {
- Map<Long, IoSession> sessions = acceptor.getManagedSessions();
+ Map<Long, IoSession> sessions = acceptor.getManagedSessions();
- Set<FtpIoSession> ftpSessions = new HashSet<FtpIoSession>();
- for (IoSession session : sessions.values()) {
- ftpSessions.add(new FtpIoSession(session, context));
- }
- return ftpSessions;
+ Set<FtpIoSession> ftpSessions = new HashSet<FtpIoSession>();
+ for (IoSession session : sessions.values()) {
+ ftpSessions.add(new FtpIoSession(session, context));
+ }
+ return ftpSessions;
}
}
diff --git a/core/src/main/java/org/apache/ftpserver/ssl/SslConfiguration.java b/core/src/main/java/org/apache/ftpserver/ssl/SslConfiguration.java
index 4b6213f..c4da591 100644
--- a/core/src/main/java/org/apache/ftpserver/ssl/SslConfiguration.java
+++ b/core/src/main/java/org/apache/ftpserver/ssl/SslConfiguration.java
@@ -30,17 +30,16 @@
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public interface SslConfiguration {
-
- /**
- * Returns the socket factory that can be used to create sockets using
- * this <code>SslConfiguration</code>.
- * @return the socket factory that can be used to create sockets using this
- * <code>SslConfiguration</code>.
- * @throws GeneralSecurityException if any error occurs while creating the
- * socket factory.
- *
- */
- SSLSocketFactory getSocketFactory() throws GeneralSecurityException;
+
+ /**
+ * Returns the socket factory that can be used to create sockets using this <code>SslConfiguration</code>.
+ *
+ * @return the socket factory that can be used to create sockets using this <code>SslConfiguration</code>.
+ * @throws GeneralSecurityException
+ * if any error occurs while creating the socket factory.
+ *
+ */
+ SSLSocketFactory getSocketFactory() throws GeneralSecurityException;
/**
* Return the SSL context for this configuration
@@ -51,8 +50,7 @@
SSLContext getSSLContext() throws GeneralSecurityException;
/**
- * Return the SSL context for this configuration given the specified
- * protocol
+ * Return the SSL context for this configuration given the specified protocol
*
* @param protocol
* The protocol, SSL or TLS must be supported
@@ -62,21 +60,25 @@
SSLContext getSSLContext(String protocol) throws GeneralSecurityException;
/**
- * Returns the cipher suites that should be enabled for this connection.
- * Must return null if the default (as decided by the JVM) cipher suites
- * should be used.
+ * Returns the cipher suites that should be enabled for this connection. Must return null if the default (as decided
+ * by the JVM) cipher suites should be used.
*
* @return An array of cipher suites, or null.
*/
String[] getEnabledCipherSuites();
/**
+ * Returns the default ssl protocol
+ *
+ * @return The name of the protocol as a String
+ */
+ String getEnabledProtocol();
+
+ /**
* Return the required client authentication setting
*
- * @return {@link ClientAuth#NEED} if client authentication is required,
- * {@link ClientAuth#WANT} is client authentication is wanted or
- * {@link ClientAuth#NONE} if no client authentication is the be
- * performed
+ * @return {@link ClientAuth#NEED} if client authentication is required, {@link ClientAuth#WANT} is client
+ * authentication is wanted or {@link ClientAuth#NONE} if no client authentication is the be performed
*/
ClientAuth getClientAuth();
}
diff --git a/core/src/main/java/org/apache/ftpserver/ssl/impl/DefaultSslConfiguration.java b/core/src/main/java/org/apache/ftpserver/ssl/impl/DefaultSslConfiguration.java
index 04e4ab0..b7f71e5 100644
--- a/core/src/main/java/org/apache/ftpserver/ssl/impl/DefaultSslConfiguration.java
+++ b/core/src/main/java/org/apache/ftpserver/ssl/impl/DefaultSslConfiguration.java
@@ -36,8 +36,7 @@
/**
* <strong>Internal class, do not use directly.</strong>
*
- * Used to configure the SSL settings for the control channel or the data
- * channel.
+ * Used to configure the SSL settings for the control channel or the data channel.
*
* <strong><strong>Internal class, do not use directly.</strong></strong>
*
@@ -49,93 +48,95 @@
private final TrustManagerFactory trustManagerFactory;
- private String sslProtocol = "TLS";
+ private String enabledProtocol = "TLS";
private final ClientAuth clientAuth;// = ClientAuth.NONE;
private final String keyAlias;
private final String[] enabledCipherSuites;
-
+
private final SSLContext sslContext;
-
+
private final SSLSocketFactory socketFactory;
-
+
/**
* Internal constructor, do not use directly. Instead, use {@link SslConfigurationFactory}
- * @throws GeneralSecurityException
+ *
+ * @throws GeneralSecurityException
*/
- public DefaultSslConfiguration(KeyManagerFactory keyManagerFactory,
- TrustManagerFactory trustManagerFactory, ClientAuth clientAuthReqd,
- String sslProtocol, String[] enabledCipherSuites, String keyAlias)
- throws GeneralSecurityException {
- super();
- this.clientAuth = clientAuthReqd;
- this.enabledCipherSuites = enabledCipherSuites;
- this.keyAlias = keyAlias;
- this.keyManagerFactory = keyManagerFactory;
- this.sslProtocol = sslProtocol;
- this.trustManagerFactory = trustManagerFactory;
- this.sslContext = initContext();
- this.socketFactory = sslContext.getSocketFactory();
+ public DefaultSslConfiguration(KeyManagerFactory keyManagerFactory, TrustManagerFactory trustManagerFactory, ClientAuth clientAuthReqd, String sslProtocol, String[] enabledCipherSuites, String keyAlias) throws GeneralSecurityException {
+ super();
+ this.clientAuth = clientAuthReqd;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.keyAlias = keyAlias;
+ this.keyManagerFactory = keyManagerFactory;
+ this.enabledProtocol = sslProtocol;
+ this.trustManagerFactory = trustManagerFactory;
+ this.sslContext = initContext();
+ this.socketFactory = sslContext.getSocketFactory();
}
-
+
public SSLSocketFactory getSocketFactory() throws GeneralSecurityException {
- return socketFactory;
+ return socketFactory;
}
/**
* @see SslConfiguration#getSSLContext(String)
*/
- public SSLContext getSSLContext(String protocol)
- throws GeneralSecurityException {
- return sslContext;
+ public SSLContext getSSLContext(String protocol) throws GeneralSecurityException {
+ return sslContext;
}
-
+
+ /**
+ * @see SslConfiguration#getEnabledProtocol()
+ */
+ public String getEnabledProtocol() {
+ return enabledProtocol;
+ }
+
/**
* @see SslConfiguration#getClientAuth()
*/
public ClientAuth getClientAuth() {
- return clientAuth;
+ return clientAuth;
}
/**
* @see SslConfiguration#getSSLContext()
*/
public SSLContext getSSLContext() throws GeneralSecurityException {
- return getSSLContext(sslProtocol);
+ return getSSLContext(enabledProtocol);
}
/**
* @see SslConfiguration#getEnabledCipherSuites()
*/
public String[] getEnabledCipherSuites() {
- if (enabledCipherSuites != null) {
- return enabledCipherSuites.clone();
- } else {
- return null;
- }
+ if (enabledCipherSuites != null) {
+ return enabledCipherSuites.clone();
+ } else {
+ return null;
+ }
}
-
+
private SSLContext initContext() throws GeneralSecurityException {
- KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
+ KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
- // wrap key managers to allow us to control their behavior
- // (FTPSERVER-93)
- for (int i = 0; i < keyManagers.length; i++) {
- if (ClassUtils.extendsClass(keyManagers[i].getClass(),
- "javax.net.ssl.X509ExtendedKeyManager")) {
- keyManagers[i] = new ExtendedAliasKeyManager(keyManagers[i],
- keyAlias);
- } else if (keyManagers[i] instanceof X509KeyManager) {
- keyManagers[i] = new AliasKeyManager(keyManagers[i], keyAlias);
- }
- }
+ // wrap key managers to allow us to control their behavior
+ // (FTPSERVER-93)
+ for (int i = 0; i < keyManagers.length; i++) {
+ if (ClassUtils.extendsClass(keyManagers[i].getClass(), "javax.net.ssl.X509ExtendedKeyManager")) {
+ keyManagers[i] = new ExtendedAliasKeyManager(keyManagers[i], keyAlias);
+ } else if (keyManagers[i] instanceof X509KeyManager) {
+ keyManagers[i] = new AliasKeyManager(keyManagers[i], keyAlias);
+ }
+ }
- // create and initialize the SSLContext
- SSLContext ctx = SSLContext.getInstance(sslProtocol);
- ctx.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
- //Create the socket factory
- return ctx;
+ // create and initialize the SSLContext
+ SSLContext ctx = SSLContext.getInstance(sslProtocol);
+ ctx.init(keyManagers, trustManagerFactory.getTrustManagers(), null);
+ // Create the socket factory
+ return ctx;
}
}