You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2014/11/18 09:50:10 UTC

[2/2] mina-sshd git commit: [SSHD-368] Add a timeout on the client to better handle the ssh server being slow to respond or some packets being lost

[SSHD-368] Add a timeout on the client to better handle the ssh server being slow to respond or some packets being lost

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/e3e808cb
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/e3e808cb
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/e3e808cb

Branch: refs/heads/master
Commit: e3e808cb1efef408c37d90832273125853703660
Parents: f52e200
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Nov 18 09:28:11 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Nov 18 09:28:11 2014 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshClient.java    |  8 +++
 .../main/java/org/apache/sshd/SshServer.java    | 34 +----------
 .../sshd/client/channel/ChannelSession.java     |  1 +
 .../sshd/client/session/ClientSessionImpl.java  |  4 --
 .../sshd/client/sftp/DefaultSftpClient.java     |  1 +
 .../sshd/common/AbstractFactoryManager.java     | 38 ++++++++++++
 .../org/apache/sshd/common/FactoryManager.java  | 14 ++++-
 .../java/org/apache/sshd/common/Session.java    | 29 +++++++++
 .../sshd/common/session/AbstractSession.java    | 63 +++++++++++++++++++-
 .../common/session/SessionTimeoutListener.java  | 63 ++++++++++++++++++++
 .../sshd/server/ServerFactoryManager.java       | 13 ----
 .../sshd/server/session/ServerSession.java      | 30 ----------
 .../session/ServerSessionTimeoutListener.java   | 63 --------------------
 13 files changed, 216 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index 33b7eeb..461b8ca 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -223,6 +223,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         if (sessionFactory == null) {
             sessionFactory = createSessionFactory();
         }
+
+        setupSessionTimeout(sessionFactory);
+
         sessionFactory.setClient(this);
         connector = createConnector();
     }
@@ -242,6 +245,11 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
     @Override
     protected Closeable getInnerCloseable() {
         return builder()
+                .run(new Runnable() {
+                    public void run() {
+                        removeSessionTimeout(sessionFactory);
+                    }
+                })
                 .sequential(connector, ioServiceFactory)
                 .run(new Runnable() {
                     public void run() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index 8d5d583..2424df4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -26,8 +26,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.List;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.common.AbstractFactoryManager;
 import org.apache.sshd.common.Closeable;
@@ -43,7 +41,6 @@ import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.mina.MinaServiceFactory;
 import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
 import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.OsUtils;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.ThreadUtils;
@@ -66,7 +63,6 @@ import org.apache.sshd.server.session.ServerSession;
 import org.apache.sshd.server.session.ServerUserAuthService;
 import org.apache.sshd.server.session.SessionFactory;
 import org.apache.sshd.server.sftp.SftpSubsystem;
-import org.apache.sshd.server.session.ServerSessionTimeoutListener;
 import org.apache.sshd.server.shell.ProcessShellFactory;
 
 /**
@@ -111,8 +107,6 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
     protected PasswordAuthenticator passwordAuthenticator;
     protected PublickeyAuthenticator publickeyAuthenticator;
     protected GSSAuthenticator gssAuthenticator;
-    protected ServerSessionTimeoutListener sessionTimeoutListener;
-    protected ScheduledFuture<?> timeoutListenerFuture;
 
     public SshServer() {
     }
@@ -281,12 +275,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         sessionFactory.setServer(this);
         acceptor = createAcceptor();
 
-        // set up the the session timeout listener and schedule it
-        sessionTimeoutListener = createSessionTimeoutListener();
-        sessionFactory.addListener(sessionTimeoutListener);
-
-        timeoutListenerFuture = getScheduledExecutorService()
-                .scheduleAtFixedRate(sessionTimeoutListener, 1, 1, TimeUnit.SECONDS);
+        setupSessionTimeout(sessionFactory);
 
         if (host != null) {
             String[] hosts = host.split(",");
@@ -327,7 +316,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return builder()
                 .run(new Runnable() {
                     public void run() {
-                        stopSessionTimeoutListener();
+                        removeSessionTimeout(sessionFactory);
                     }
                 })
                 .sequential(acceptor, ioServiceFactory)
@@ -366,25 +355,6 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return new SessionFactory();
     }
 
-    protected ServerSessionTimeoutListener createSessionTimeoutListener() {
-        return new ServerSessionTimeoutListener();
-    }
-
-    protected void stopSessionTimeoutListener() {
-        // cancel the timeout monitoring task
-        if (timeoutListenerFuture != null) {
-            timeoutListenerFuture.cancel(true);
-            timeoutListenerFuture = null;
-        }
-
-        // remove the sessionTimeoutListener completely; should the SSH server be restarted, a new one
-        // will be created.
-        if (sessionFactory != null && sessionTimeoutListener != null) {
-            sessionFactory.removeListener(sessionTimeoutListener);
-        }
-        sessionTimeoutListener = null;
-    }
-
     @Override
     public String toString() {
         return "SshServer[" + Integer.toHexString(hashCode()) + "]";

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
index 92555df..fe254fc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
@@ -102,6 +102,7 @@ public class ChannelSession extends AbstractClientChannel {
             byte[] buffer = new byte[remoteWindow.getPacketSize()];
             while (!closeFuture.isClosed()) {
                 int len = securedRead(in, buffer, 0, buffer.length);
+                session.resetIdleTimeout();
                 if (len > 0) {
                     invertedIn.write(buffer, 0, len);
                     invertedIn.flush();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
index e4c0258..76a8bca 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
@@ -386,10 +386,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
         throw new IllegalStateException("Starting services is not supported on the client side");
     }
 
-    @Override
-    public void resetIdleTimeout() {
-    }
-
     public Map<Object, Object> getMetadataMap() {
 		return metadataMap;
 	}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
index 8eb6b52..a0a9b2c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
@@ -164,6 +164,7 @@ public class DefaultSftpClient implements SftpClient {
     protected boolean receive(Buffer incoming) throws IOException {
         int rpos = incoming.rpos();
         int wpos = incoming.wpos();
+        clientSession.resetIdleTimeout();
         if (wpos - rpos > 4) {
             int length = incoming.getInt();
             if (length < 5) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index 515bc9e..f8404a6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -24,12 +24,16 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
+import org.apache.sshd.common.session.AbstractSessionFactory;
 import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.session.SessionTimeoutListener;
 import org.apache.sshd.common.util.CloseableUtils;
 
 /**
@@ -59,6 +63,8 @@ public abstract class AbstractFactoryManager extends CloseableUtils.AbstractInne
     protected FileSystemFactory fileSystemFactory;
     protected List<ServiceFactory> serviceFactories;
     protected List<RequestHandler<ConnectionService>> globalRequestHandlers;
+    protected SessionTimeoutListener sessionTimeoutListener;
+    protected ScheduledFuture<?> timeoutListenerFuture;
 
     protected AbstractFactoryManager() {
         loadVersion();
@@ -252,4 +258,36 @@ public abstract class AbstractFactoryManager extends CloseableUtils.AbstractInne
     public void setGlobalRequestHandlers(List<RequestHandler<ConnectionService>> globalRequestHandlers) {
         this.globalRequestHandlers = globalRequestHandlers;
     }
+
+    protected void setupSessionTimeout(final AbstractSessionFactory sessionFactory) {
+        // set up the the session timeout listener and schedule it
+        sessionTimeoutListener = createSessionTimeoutListener();
+        sessionFactory.addListener(sessionTimeoutListener);
+
+        timeoutListenerFuture = getScheduledExecutorService()
+                .scheduleAtFixedRate(sessionTimeoutListener, 1, 1, TimeUnit.SECONDS);
+    }
+
+    protected void removeSessionTimeout(final AbstractSessionFactory sessionFactory) {
+        stopSessionTimeoutListener(sessionFactory);
+    }
+
+    protected SessionTimeoutListener createSessionTimeoutListener() {
+        return new SessionTimeoutListener();
+    }
+
+    protected void stopSessionTimeoutListener(final AbstractSessionFactory sessionFactory) {
+        // cancel the timeout monitoring task
+        if (timeoutListenerFuture != null) {
+            timeoutListenerFuture.cancel(true);
+            timeoutListenerFuture = null;
+        }
+
+        // remove the sessionTimeoutListener completely; should the SSH server/client be restarted, a new one
+        // will be created.
+        if (sessionFactory != null && sessionTimeoutListener != null) {
+            sessionFactory.removeListener(sessionTimeoutListener);
+        }
+        sessionTimeoutListener = null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 3025271..037b718 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -25,7 +25,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
-import org.apache.sshd.common.io.IoServiceFactoryFactory;
 import org.apache.sshd.common.session.ConnectionService;
 
 /**
@@ -59,6 +58,19 @@ public interface FactoryManager {
     public static final int DEFAULT_NIO_WORKERS = Runtime.getRuntime().availableProcessors() + 1;
 
     /**
+     * Key used to retrieve the value of the timeout after which
+     * it will close the connection if the other side has not been
+     * authenticated.
+     */
+    public static final String AUTH_TIMEOUT = "auth-timeout";
+
+    /**
+     * Key used to retrieve the value of idle timeout after which
+     * it will close the connection.  In milliseconds.
+     */
+    public static final String IDLE_TIMEOUT = "idle-timeout";
+
+    /**
      * A map of properties that can be used to configure the SSH server
      * or client.  This map will never be changed by either the server or
      * client and is not supposed to be changed at runtime (changes are not

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/common/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
index 166ac41..f01edad 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
@@ -33,6 +33,15 @@ import org.apache.sshd.common.util.Buffer;
 public interface Session extends Closeable {
 
     /**
+     * Timeout status.
+     */
+    enum TimeoutStatus {
+        NoTimeout,
+        AuthTimeout,
+        IdleTimeout
+    }
+
+    /**
      * Returns the value of the user-defined attribute of this session.
      *
      * @param key the key of the attribute; must not be null.
@@ -196,4 +205,24 @@ public interface Session extends Closeable {
     public class AttributeKey<T> {
     }
 
+    public void resetIdleTimeout();
+
+    /**
+     * Check if timeout has occurred.
+     * @return the timeout status, never <code>null</code>
+     */
+    public TimeoutStatus getTimeoutStatus();
+
+    /**
+     * What is timeout value in milliseconds for authentication stage
+     * @return
+     */
+    public long getAuthTimeout();
+
+    /**
+     * What is timeout value in milliseconds for communication
+     * @return
+     */
+
+    public long getIdleTimeout();
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index d301e0a..91c0552 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -144,6 +145,13 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     protected final AtomicReference<Buffer> requestResult = new AtomicReference<Buffer>();
     protected final Map<AttributeKey<?>, Object> attributes = new ConcurrentHashMap<AttributeKey<?>, Object>();
 
+    // Session timeout
+    protected long authTimeoutTimestamp = 0L;
+    protected long idleTimeoutTimestamp = 0L;
+    protected long authTimeoutMs = TimeUnit.MINUTES.toMillis(2);    // 2 minutes in milliseconds
+    protected long idleTimeoutMs = TimeUnit.MINUTES.toMillis(10);   // 10 minutes in milliseconds
+    protected final AtomicReference<TimeoutStatus> timeoutStatus = new AtomicReference<TimeoutStatus>(TimeoutStatus.NoTimeout);
+
     //
     // Rekeying
     //
@@ -166,7 +174,10 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         this.isServer = isServer;
         this.factoryManager = factoryManager;
         this.ioSession = ioSession;
-        this.random = factoryManager.getRandomFactory().create();
+        random = factoryManager.getRandomFactory().create();
+        authTimeoutMs = getLongProperty(FactoryManager.AUTH_TIMEOUT, authTimeoutMs);
+        authTimeoutTimestamp = System.currentTimeMillis() + authTimeoutMs;
+        idleTimeoutMs = getLongProperty(FactoryManager.IDLE_TIMEOUT, idleTimeoutMs);
     }
 
     /**
@@ -1131,6 +1142,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     protected void requestSuccess(Buffer buffer) throws Exception{
         synchronized (requestResult) {
             requestResult.set(new Buffer(buffer.getCompactData()));
+            resetIdleTimeout();
             requestResult.notify();
         }
     }
@@ -1138,6 +1150,7 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     protected void requestFailure(Buffer buffer) throws Exception{
         synchronized (requestResult) {
             requestResult.set(null);
+            resetIdleTimeout();
             requestResult.notify();
         }
     }
@@ -1254,7 +1267,53 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
 
     public abstract void startService(String name) throws Exception;
 
-    public abstract void resetIdleTimeout();
+    /**
+     * Checks whether the session has timed out (both auth and idle timeouts are checked). If the session has
+     * timed out, a DISCONNECT message will be sent.
+     *
+     * @throws IOException
+     */
+    protected void checkForTimeouts() throws IOException {
+        if (!isClosing()) {
+            long now = System.currentTimeMillis();
+            if (!authed && authTimeoutMs > 0 && now > authTimeoutTimestamp) {
+                timeoutStatus.set(TimeoutStatus.AuthTimeout);
+                disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Session has timed out waiting for authentication after " + authTimeoutMs + " ms.");
+            }
+            if (idleTimeoutMs > 0 && idleTimeoutTimestamp > 0 && now > idleTimeoutTimestamp) {
+                timeoutStatus.set(TimeoutStatus.AuthTimeout);
+                disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User session has timed out idling after " + idleTimeoutMs + " ms.");
+            }
+        }
+    }
+
+    public void resetIdleTimeout() {
+        this.idleTimeoutTimestamp = System.currentTimeMillis() + idleTimeoutMs;
+    }
+
+    /**
+     * Check if timeout has occurred.
+     * @return
+     */
+    public TimeoutStatus getTimeoutStatus() {
+        return timeoutStatus.get();
+    }
+
+    /**
+     * What is timeout value in milliseconds for authentication stage
+     * @return
+     */
+    public long getAuthTimeout() {
+        return authTimeoutMs;
+    }
+
+    /**
+     * What is timeout value in milliseconds for communication
+     * @return
+     */
+    public long getIdleTimeout() {
+        return idleTimeoutMs;
+    }
 
     /**
      * Future holding a packet pending key exchange termination.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/common/session/SessionTimeoutListener.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/SessionTimeoutListener.java b/sshd-core/src/main/java/org/apache/sshd/common/session/SessionTimeoutListener.java
new file mode 100644
index 0000000..74091ff
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/SessionTimeoutListener.java
@@ -0,0 +1,63 @@
+/*
+ * 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.sshd.common.session;
+
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Task that iterates over all currently open {@link AbstractSession}s and checks each of them for timeouts. If
+ * the {@link AbstractSession} has timed out (either auth or idle timeout), the session will be disconnected.
+ *
+ * @see org.apache.sshd.common.session.AbstractSession#checkForTimeouts()
+ */
+public class SessionTimeoutListener implements SessionListener, Runnable {
+
+    private final Logger log = LoggerFactory.getLogger(SessionTimeoutListener.class);
+    
+    private final Set<AbstractSession> sessions = new CopyOnWriteArraySet<AbstractSession>();
+
+    public void sessionCreated(Session session) {
+        if (session instanceof AbstractSession && (session.getAuthTimeout() > 0 || session.getIdleTimeout() > 0)) {
+            sessions.add((AbstractSession) session);
+        }
+    }
+
+    public void sessionEvent(Session session, Event event) {
+    }
+
+    public void sessionClosed(Session s) {
+        sessions.remove(s);
+    }
+
+    public void run() {
+        for (AbstractSession session : sessions) {
+            try {
+                session.checkForTimeouts();
+            } catch (Exception e) {
+                log.warn("An error occurred while checking session timeouts", e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
index e7fd556..99368f9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
@@ -48,19 +48,6 @@ public interface ServerFactoryManager extends FactoryManager {
     public static final String MAX_AUTH_REQUESTS = "max-auth-requests";
 
     /**
-     * Key used to retrieve the value of the timeout after which
-     * the server will close the connection if the client has not been
-     * authenticated.
-     */
-    public static final String AUTH_TIMEOUT = "auth-timeout";
-
-    /**
-     * Key used to retrieve the value of idle timeout after which
-     * the server will close the connection.  In milliseconds.
-     */
-    public static final String IDLE_TIMEOUT = "idle-timeout";
-
-    /**
      * Key used to retrieve the value of welcome banner that will be displayed
      * when a user connects to the server.
      */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
index 7e54933..377171c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
@@ -43,19 +43,11 @@ public class ServerSession extends AbstractSession {
 
     protected static final long MAX_PACKETS = (1l << 31);
 
-    private long authTimeoutTimestamp;
-    private long idleTimeoutTimestamp = 0L;
-    private int authTimeoutMs = 2 * 60 * 1000;    // 2 minutes in milliseconds
-    private int idleTimeoutMs = 10 * 60 * 1000;   // 10 minutes in milliseconds
     private long maxBytes = 1024 * 1024 * 1024;   // 1 GB
     private long maxKeyInterval = 60 * 60 * 1000; // 1 hour
 
-
     public ServerSession(ServerFactoryManager server, IoSession ioSession) throws Exception {
         super(true, server, ioSession);
-        authTimeoutMs = getIntProperty(ServerFactoryManager.AUTH_TIMEOUT, authTimeoutMs);
-        authTimeoutTimestamp = System.currentTimeMillis() + authTimeoutMs;
-        idleTimeoutMs = getIntProperty(ServerFactoryManager.IDLE_TIMEOUT, idleTimeoutMs);
         maxBytes = Math.max(32, getLongProperty(ServerFactoryManager.REKEY_BYTES_LIMIT, maxBytes));
         maxKeyInterval = getLongProperty(ServerFactoryManager.REKEY_TIME_LIMIT, maxKeyInterval);
         log.info("Server session created from {}", ioSession.getRemoteAddress());
@@ -85,24 +77,6 @@ public class ServerSession extends AbstractSession {
         disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Unsupported packet: SSH_MSG_SERVICE_ACCEPT");
     }
 
-    /**
-     * Checks whether the server session has timed out (both auth and idle timeouts are checked). If the session has
-     * timed out, a DISCONNECT message will be sent to the client.
-     *
-     * @throws IOException
-     */
-    protected void checkForTimeouts() throws IOException {
-        if (!isClosing()) {
-            long now = System.currentTimeMillis();
-            if (!authed && now > authTimeoutTimestamp) {
-                disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Session has timed out waiting for authentication after " + authTimeoutMs + " ms.");
-            }
-            if (idleTimeoutTimestamp > 0 && now > idleTimeoutTimestamp) {
-                disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User session has timed out idling after " + idleTimeoutMs + " ms.");
-            }
-        }
-    }
-
     protected void checkRekey() throws IOException {
         if (kexState.get() == KEX_STATE_DONE) {
             if (   inPackets > MAX_PACKETS || outPackets > MAX_PACKETS
@@ -114,10 +88,6 @@ public class ServerSession extends AbstractSession {
         }
     }
 
-    public void resetIdleTimeout() {
-        this.idleTimeoutTimestamp = System.currentTimeMillis() + idleTimeoutMs;
-    }
-
     private void sendServerIdentification() {
         if (getFactoryManager().getProperties() != null && getFactoryManager().getProperties().get(ServerFactoryManager.SERVER_IDENTIFICATION) != null) {
             serverVersion = "SSH-2.0-" + getFactoryManager().getProperties().get(ServerFactoryManager.SERVER_IDENTIFICATION);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e3e808cb/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionTimeoutListener.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionTimeoutListener.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionTimeoutListener.java
deleted file mode 100644
index bb28f96..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionTimeoutListener.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.sshd.server.session;
-
-import org.apache.sshd.common.Session;
-import org.apache.sshd.common.SessionListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-/**
- * Task that iterates over all currently open {@link ServerSession}s and checks each of them for timeouts. If 
- * the {@link ServerSession} has timed out (either auth or idle timeout), the session will be disconnected.
- *
- * @see org.apache.sshd.server.session.ServerSession#checkForTimeouts()
- */
-public class ServerSessionTimeoutListener implements SessionListener, Runnable {
-
-    private final Logger log = LoggerFactory.getLogger(ServerSessionTimeoutListener.class);
-    
-    private final Set<ServerSession> sessions = new CopyOnWriteArraySet<ServerSession>();
-
-    public void sessionCreated(Session session) {
-        if (session instanceof ServerSession) {
-            sessions.add((ServerSession) session);
-        }
-    }
-
-    public void sessionEvent(Session session, Event event) {
-    }
-
-    public void sessionClosed(Session s) {
-        sessions.remove(s);
-    }
-
-    public void run() {
-        for (ServerSession session : sessions) {
-            try {
-                session.checkForTimeouts();
-            } catch (Exception e) {
-                log.warn("An error occurred while checking session timeouts", e);
-            }
-        }
-    }
-}