You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/06/22 15:54:36 UTC

[2/2] mina-sshd git commit: [SSHD-499] Consolidate similar logic for client and server sessions

[SSHD-499] Consolidate similar logic for client and server sessions


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

Branch: refs/heads/master
Commit: 6f8507a10afbb4314ac7714bfc52b0702e102bbc
Parents: 612a2f4
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Mon Jun 22 16:54:21 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Mon Jun 22 16:54:21 2015 +0300

----------------------------------------------------------------------
 .../sshd/client/future/DefaultAuthFuture.java   |   6 +-
 .../client/future/DefaultConnectFuture.java     |  10 +-
 .../sshd/client/future/DefaultOpenFuture.java   |   6 +-
 .../org/apache/sshd/client/kex/DHGClient.java   |   5 +-
 .../org/apache/sshd/client/kex/DHGEXClient.java |   2 +-
 .../sshd/client/session/ClientSession.java      |  12 +-
 .../sshd/client/session/ClientSessionImpl.java  |  73 +++---
 .../client/sftp/SftpFileSystemProvider.java     |  94 ++++---
 .../apache/sshd/common/file/util/BasePath.java  |  11 +-
 .../sshd/common/future/DefaultSshFuture.java    |  38 +--
 .../common/kex/dh/AbstractDHKeyExchange.java    |   1 -
 .../sshd/common/session/AbstractSession.java    | 119 ++++++---
 .../org/apache/sshd/common/session/Session.java |  42 +++-
 .../apache/sshd/common/util/GenericUtils.java   |   8 +
 .../apache/sshd/common/util/ValidateUtils.java  |   6 +
 .../sshd/server/ServerFactoryManager.java       |  18 +-
 .../org/apache/sshd/server/SessionAware.java    |   4 +-
 .../sshd/server/auth/AbstractUserAuth.java      |   4 +
 .../auth/UserAuthKeyboardInteractive.java       |  20 +-
 .../apache/sshd/server/auth/UserAuthNone.java   |   4 +
 .../sshd/server/auth/UserAuthPassword.java      |  21 +-
 .../sshd/server/auth/UserAuthPublicKey.java     |   8 +-
 .../sshd/server/auth/gss/UserAuthGSS.java       |  20 +-
 .../sshd/server/channel/ChannelSession.java     |  53 ++--
 .../keys/AuthorizedKeysAuthenticator.java       |   3 +-
 .../server/jaas/JaasPasswordAuthenticator.java  |   2 +-
 .../server/kex/AbstractDHServerKeyExchange.java |   8 +-
 .../org/apache/sshd/server/kex/DHGEXServer.java |   2 +-
 .../org/apache/sshd/server/kex/DHGServer.java   |   2 +-
 .../server/session/ServerConnectionService.java |   9 +-
 .../sshd/server/session/ServerSession.java      | 213 ++--------------
 .../sshd/server/session/ServerSessionImpl.java  | 250 +++++++++++++++++++
 .../server/session/ServerUserAuthService.java   |  10 +-
 .../sshd/server/session/SessionFactory.java     |  18 +-
 .../org/apache/sshd/AuthenticationTest.java     |   8 +-
 .../apache/sshd/SinglePublicKeyAuthTest.java    |   6 +-
 .../java/org/apache/sshd/client/ClientTest.java |   9 +-
 .../client/session/ClientSessionImplTest.java   |   5 +-
 .../common/session/AbstractSessionTest.java     |  19 +-
 .../java/org/apache/sshd/git/util/Utils.java    |  14 +-
 40 files changed, 675 insertions(+), 488 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultAuthFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultAuthFuture.java b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultAuthFuture.java
index a9043d4..4fc29c6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultAuthFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultAuthFuture.java
@@ -22,6 +22,8 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.DefaultSshFuture;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 
 /**
@@ -88,9 +90,7 @@ public class DefaultAuthFuture extends DefaultSshFuture<AuthFuture> implements A
 
     @Override
     public void setException(Throwable exception) {
-        if (exception == null) {
-            throw new NullPointerException("exception");
-        }
+        ValidateUtils.checkNotNull(exception, "No exception provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         setValue(exception);
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultConnectFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultConnectFuture.java b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultConnectFuture.java
index 9dd3a12..bd02880 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultConnectFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultConnectFuture.java
@@ -21,6 +21,8 @@ package org.apache.sshd.client.future;
 import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.common.RuntimeSshException;
 import org.apache.sshd.common.future.DefaultSshFuture;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 /**
  * A default implementation of {@link ConnectFuture}.
@@ -66,17 +68,13 @@ public class DefaultConnectFuture extends DefaultSshFuture<ConnectFuture> implem
 
     @Override
     public void setSession(ClientSession session) {
-        if (session == null) {
-            throw new NullPointerException("session");
-        }
+        ValidateUtils.checkNotNull(session, "No client session provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         setValue(session);
     }
 
     @Override
     public void setException(Throwable exception) {
-        if (exception == null) {
-            throw new NullPointerException("exception");
-        }
+        ValidateUtils.checkNotNull(exception, "No exception provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         setValue(exception);
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultOpenFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultOpenFuture.java b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultOpenFuture.java
index 9baab23..7dc401f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultOpenFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/future/DefaultOpenFuture.java
@@ -22,6 +22,8 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.DefaultSshFuture;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 /**
  * A default implementation of {@link OpenFuture}.
@@ -80,9 +82,7 @@ public class DefaultOpenFuture extends DefaultSshFuture<OpenFuture> implements O
 
     @Override
     public void setException(Throwable exception) {
-        if (exception == null) {
-            throw new NullPointerException("exception");
-        }
+        ValidateUtils.checkNotNull(exception, "No exception provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         setValue(exception);
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
index f4a21f9..0f1c1f8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGClient.java
@@ -107,7 +107,7 @@ public class DHGClient extends AbstractDHClientKeyExchange {
         buffer = new ByteArrayBuffer(K_S);
         serverKey = buffer.getRawPublicKey();
         final String keyAlg = KeyUtils.getKeyType(serverKey);
-        if (keyAlg == null) {
+        if (GenericUtils.isEmpty(keyAlg)) {
             throw new SshException("Unsupported server key type");
         }
 
@@ -130,8 +130,7 @@ public class DHGClient extends AbstractDHClientKeyExchange {
         verif.initVerifier(serverKey);
         verif.update(H);
         if (!verif.verify(sig)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
-                                   "KeyExchange signature verification failed");
+            throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, "KeyExchange signature verification failed");
         }
         return true;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
index bcf4ba9..bd3f222 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/kex/DHGEXClient.java
@@ -124,7 +124,7 @@ public class DHGEXClient extends AbstractDHClientKeyExchange {
             buffer = new ByteArrayBuffer(K_S);
             serverKey = buffer.getRawPublicKey();
             final String keyAlg = KeyUtils.getKeyType(serverKey);
-            if (keyAlg == null) {
+            if (GenericUtils.isEmpty(keyAlg)) {
                 throw new SshException("Unsupported server key type");
             }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
index 6a885d4..d694b75 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
@@ -35,7 +35,6 @@ import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.client.scp.ScpClient;
 import org.apache.sshd.client.sftp.SftpClient;
 import org.apache.sshd.common.SshdSocketAddress;
-import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.scp.ScpTransferEventListener;
 import org.apache.sshd.common.session.Session;
@@ -238,21 +237,14 @@ public interface ClientSession extends Session {
     int waitFor(int mask, long timeout);
 
     /**
-     * Close this session.
-     */
-    @Override
-    CloseFuture close(boolean immediately);
-
-    /**
      * Access to the metadata.
      */
     Map<Object, Object> getMetadataMap();
 
     /**
-     * Return ClientFactoryManager for this session.
+     * @return The ClientFactoryManager for this session.
      */
-    @Override
-    ClientFactoryManager getFactoryManager();
+    @Override ClientFactoryManager getFactoryManager();
 
     /**
      * Switch to a none cipher for performance.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/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 bc7cf74..50c0d5a 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
@@ -24,6 +24,7 @@ import java.nio.file.FileSystem;
 import java.security.KeyPair;
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -240,8 +241,10 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
         if (username == null) {
             throw new IllegalStateException("No username specified when the session was created");
         }
+        
+        ClientUserAuthService authService = getUserAuthService();
         synchronized (lock) {
-            return authFuture = getUserAuthService().auth(identities, nextServiceName());
+            return authFuture = authService.auth(identities, nextServiceName());
         }
     }
 
@@ -268,19 +271,27 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
     @SuppressWarnings("rawtypes")
     public SshFuture switchToNoneCipher() throws IOException {
         if (!(currentService instanceof AbstractConnectionService)
-                || !((AbstractConnectionService) currentService).getChannels().isEmpty()) {
+         || !((AbstractConnectionService) currentService).getChannels().isEmpty()) {
             throw new IllegalStateException("The switch to the none cipher must be done immediately after authentication");
         }
         if (kexState.compareAndSet(KexState.DONE, KexState.INIT)) {
             reexchangeFuture = new DefaultSshFuture(null);
             
-            String c2sEncServer = serverProposal.get(KexProposalOption.C2SENC);
+            String c2sEncServer, s2cEncServer;
+            synchronized(serverProposal) {
+                c2sEncServer = serverProposal.get(KexProposalOption.C2SENC);
+                s2cEncServer  = serverProposal.get(KexProposalOption.S2CENC);
+            }
             boolean c2sEncServerNone = BuiltinCiphers.Constants.isNoneCipherIncluded(c2sEncServer);
-            String s2cEncServer = serverProposal.get(KexProposalOption.S2CENC);
             boolean s2cEncServerNone = BuiltinCiphers.Constants.isNoneCipherIncluded(s2cEncServer);
-            String c2sEncClient = clientProposal.get(KexProposalOption.C2SENC);
+
+            String c2sEncClient, s2cEncClient;
+            synchronized(clientProposal) {
+                c2sEncClient = clientProposal.get(KexProposalOption.C2SENC);
+                s2cEncClient = clientProposal.get(KexProposalOption.S2CENC);
+            }
+
             boolean c2sEncClientNone = BuiltinCiphers.Constants.isNoneCipherIncluded(c2sEncClient);
-            String s2cEncClient = clientProposal.get(KexProposalOption.S2CENC);
             boolean s2cEncClientNone = BuiltinCiphers.Constants.isNoneCipherIncluded(s2cEncClient);
 
             if ((!c2sEncServerNone) || (!s2cEncServerNone)) {
@@ -289,9 +300,17 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
                 reexchangeFuture.setValue(new SshException("Client does not support none cipher"));
             } else {
                 log.info("Switching to none cipher");
-                clientProposal.put(KexProposalOption.C2SENC, BuiltinCiphers.Constants.NONE);
-                clientProposal.put(KexProposalOption.S2CENC, BuiltinCiphers.Constants.NONE);
-                I_C = sendKexInit(clientProposal);
+                
+                Map<KexProposalOption,String> proposal = new EnumMap<KexProposalOption, String>(KexProposalOption.class);
+                synchronized(clientProposal) {
+                    proposal.putAll(clientProposal);
+                }
+
+                proposal.put(KexProposalOption.C2SENC, BuiltinCiphers.Constants.NONE);
+                proposal.put(KexProposalOption.S2CENC, BuiltinCiphers.Constants.NONE);
+
+                byte[] seed = sendKexInit(proposal);
+                setKexSeed(seed);
             }
             return reexchangeFuture;
         } else {
@@ -494,27 +513,26 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
     }
 
     @Override
-    protected void sendKexInit() throws IOException {
-        FactoryManager manager = getFactoryManager();
-        String algs = NamedResource.Utils.getNames(manager.getSignatureFactories());
-        Map<KexProposalOption,String> proposal = createProposal(algs);
-        synchronized(clientProposal) {
-            if (!clientProposal.isEmpty()) {
-                clientProposal.clear(); // debug breakpoint
-            }
-            
-            clientProposal.putAll(proposal);
-        }
+    protected byte[] sendKexInit(Map<KexProposalOption,String> proposal) throws IOException {
+        mergeProposals(clientProposal, proposal);
+        return super.sendKexInit(proposal);
+    }
 
-        I_C = sendKexInit(proposal);
+    @Override
+    protected void setKexSeed(byte... seed) {
+        I_C = ValidateUtils.checkNotNullAndNotEmpty(seed, "No KEX seed", GenericUtils.EMPTY_OBJECT_ARRAY);
     }
 
     @Override
-    protected void receiveKexInit(Buffer buffer) throws IOException {
-        if (!serverProposal.isEmpty()) {
-            serverProposal.clear(); // debug breakpoint
-        }
-        I_S = receiveKexInit(buffer, serverProposal);
+    protected String resolveAvailableSignaturesProposal(FactoryManager manager) {
+        // the client does not have to provide keys for the available signatures
+        return NamedResource.Utils.getNames(manager.getSignatureFactories());
+    }
+
+    @Override
+    protected void receiveKexInit(Map<KexProposalOption,String> proposal, byte[] seed) throws IOException {
+        mergeProposals(serverProposal, proposal);
+        I_S = seed;
     }
 
     @Override
@@ -557,12 +575,11 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
 
     @Override
     public void startService(String name) throws Exception {
-        throw new IllegalStateException("Starting services is not supported on the client side");
+        throw new IllegalStateException("Starting services is not supported on the client side: " + name);
     }
 
     @Override
     public Map<Object, Object> getMetadataMap() {
         return metadataMap;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
index 4f7b693..4c041bd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
@@ -44,6 +44,7 @@ import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.FileStore;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystemAlreadyExistsException;
+import java.nio.file.FileSystemException;
 import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.LinkOption;
 import java.nio.file.NoSuchFileException;
@@ -180,7 +181,8 @@ public class SftpFileSystemProvider extends FileSystemProvider {
 
     @Override
     public Path getPath(URI uri) {
-        return getFileSystem(uri).getPath(uri.getPath());
+        FileSystem fs = getFileSystem(uri);
+        return fs.getPath(uri.getPath());
     }
 
     @Override
@@ -229,12 +231,16 @@ public class SftpFileSystemProvider extends FileSystemProvider {
     public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) throws IOException {
         final SftpPath p = toSftpPath(dir);
         return new DirectoryStream<Path>() {
-            final SftpClient sftp = p.getFileSystem().getClient();
-            final Iterable<SftpClient.DirEntry> iter = sftp.readDir(p.toString());
+            private final SftpFileSystem fs = p.getFileSystem();
+            private final SftpClient sftp = fs.getClient();
+            private final Iterable<SftpClient.DirEntry> iter = sftp.readDir(p.toString());
+
             @Override
             public Iterator<Path> iterator() {
                 return new Iterator<Path>() {
-                    final Iterator<SftpClient.DirEntry> it = iter.iterator();
+                    @SuppressWarnings("synthetic-access")
+                    private final Iterator<SftpClient.DirEntry> it = iter.iterator();
+
                     @Override
                     public boolean hasNext() {
                         return it.hasNext();
@@ -263,7 +269,8 @@ public class SftpFileSystemProvider extends FileSystemProvider {
     @Override
     public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
         SftpPath p = toSftpPath(dir);
-        try (SftpClient sftp = p.getFileSystem().getClient()) {
+        SftpFileSystem fs = p.getFileSystem();
+        try (SftpClient sftp = fs.getClient()) {
             try {
                 sftp.mkdir(dir.toString());
             } catch (SftpException e) {
@@ -293,7 +300,9 @@ public class SftpFileSystemProvider extends FileSystemProvider {
     public void delete(Path path) throws IOException {
         SftpPath p = toSftpPath(path);
         checkAccess(p, AccessMode.WRITE);
-        try (SftpClient sftp = p.getFileSystem().getClient()) {
+        
+        SftpFileSystem fs = p.getFileSystem();
+        try (SftpClient sftp = fs.getClient()) {
             BasicFileAttributes attributes = readAttributes(path, BasicFileAttributes.class);
             if (attributes.isDirectory()) {
                 sftp.rmdir(path.toString());
@@ -308,7 +317,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         SftpPath src = toSftpPath(source);
         SftpPath dst = toSftpPath(target);
         if (src.getFileSystem() != dst.getFileSystem()) {
-            throw new ProviderMismatchException("Mismatched file system providers");
+            throw new ProviderMismatchException("Mismatched file system providers for " + src + " vs. " + dst);
         }
         checkAccess(src);
 
@@ -323,9 +332,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         LinkOption[] linkOptions = IoUtils.getLinkOptions(!noFollowLinks);
 
         // attributes of source file
-        BasicFileAttributes attrs = readAttributes(source,
-                BasicFileAttributes.class,
-                linkOptions);
+        BasicFileAttributes attrs = readAttributes(source, BasicFileAttributes.class, linkOptions);
         if (attrs.isSymbolicLink())
             throw new IOException("Copying of symbolic links not supported");
 
@@ -357,9 +364,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         if (copyAttributes) {
             BasicFileAttributeView view = getFileAttributeView(target, BasicFileAttributeView.class, linkOptions);
             try {
-                view.setTimes(attrs.lastModifiedTime(),
-                        attrs.lastAccessTime(),
-                        attrs.creationTime());
+                view.setTimes(attrs.lastModifiedTime(), attrs.lastAccessTime(), attrs.creationTime());
             } catch (Throwable x) {
                 // rollback
                 try {
@@ -375,9 +380,11 @@ public class SftpFileSystemProvider extends FileSystemProvider {
     @Override
     public void move(Path source, Path target, CopyOption... options) throws IOException {
         SftpPath src = toSftpPath(source);
+        SftpFileSystem fsSrc = src.getFileSystem(); 
         SftpPath dst = toSftpPath(target);
+        
         if (src.getFileSystem() != dst.getFileSystem()) {
-            throw new ProviderMismatchException();
+            throw new ProviderMismatchException("Mismatched file system providers for " + src + " vs. " + dst);
         }
         checkAccess(src);
 
@@ -392,11 +399,10 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         LinkOption[] linkOptions = IoUtils.getLinkOptions(noFollowLinks);
 
         // attributes of source file
-        BasicFileAttributes attrs = readAttributes(source,
-                BasicFileAttributes.class,
-                linkOptions);
-        if (attrs.isSymbolicLink())
+        BasicFileAttributes attrs = readAttributes(source, BasicFileAttributes.class, linkOptions);
+        if (attrs.isSymbolicLink()) {
             throw new IOException("Copying of symbolic links not supported");
+        }
 
         // delete target if it exists and REPLACE_EXISTING is specified
         Boolean status=IoUtils.checkFileExists(target, linkOptions);
@@ -406,10 +412,11 @@ public class SftpFileSystemProvider extends FileSystemProvider {
 
         if (replaceExisting) {
             deleteIfExists(target);
-        } else if (status.booleanValue())
+        } else if (status.booleanValue()) {
             throw new FileAlreadyExistsException(target.toString());
+        }
 
-        try (SftpClient sftp = src.getFileSystem().getClient()) {
+        try (SftpClient sftp = fsSrc.getClient()) {
             sftp.rename(src.toString(), dst.toString());
         }
 
@@ -417,9 +424,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         if (copyAttributes) {
             BasicFileAttributeView view = getFileAttributeView(target, BasicFileAttributeView.class, linkOptions);
             try {
-                view.setTimes(attrs.lastModifiedTime(),
-                        attrs.lastAccessTime(),
-                        attrs.creationTime());
+                view.setTimes(attrs.lastModifiedTime(), attrs.lastAccessTime(), attrs.creationTime());
             } catch (Throwable x) {
                 // rollback
                 try {
@@ -437,7 +442,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         SftpPath p1 = toSftpPath(path1);
         SftpPath p2 = toSftpPath(path2);
         if (p1.getFileSystem() != p2.getFileSystem()) {
-            throw new ProviderMismatchException();
+            throw new ProviderMismatchException("Mismatched file system providers for " + p1 + " vs. " + p2);
         }
         checkAccess(p1);
         checkAccess(p2);
@@ -451,17 +456,18 @@ public class SftpFileSystemProvider extends FileSystemProvider {
 
     @Override
     public FileStore getFileStore(Path path) throws IOException {
-        throw new UnsupportedOperationException("getFileStore(" + path + ") N/A");
+        throw new FileSystemException(path.toString(), path.toString(), "getFileStore(" + path + ") N/A");
     }
 
     @Override
     public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException {
         SftpPath l = toSftpPath(link);
+        SftpFileSystem fsLink = l.getFileSystem();
         SftpPath t = toSftpPath(target);
-        if (l.getFileSystem() != t.getFileSystem()) {
-            throw new ProviderMismatchException();
+        if (fsLink != t.getFileSystem()) {
+            throw new ProviderMismatchException("Mismatched file system providers for " + l + " vs. " + t);
         }
-        try (SftpClient client = l.getFileSystem().getClient()) {
+        try (SftpClient client = fsLink.getClient()) {
             client.symLink(l.toString(), t.toString());
         }
     }
@@ -469,8 +475,9 @@ public class SftpFileSystemProvider extends FileSystemProvider {
     @Override
     public Path readSymbolicLink(Path link) throws IOException {
         SftpPath l = toSftpPath(link);
-        try (SftpClient client = l.getFileSystem().getClient()) {
-            return l.getFileSystem().getPath(client.readLink(l.toString()));
+        SftpFileSystem fsLink = l.getFileSystem();
+        try (SftpClient client = fsLink.getClient()) {
+            return fsLink.getPath(client.readLink(l.toString()));
         }
     }
 
@@ -500,7 +507,9 @@ public class SftpFileSystemProvider extends FileSystemProvider {
         if ((attrs == null) && !(p.isAbsolute() && p.getNameCount() == 0)) {
             throw new NoSuchFileException(path.toString());
         }
-        if (x || (w && p.getFileSystem().isReadOnly())) {
+        
+        SftpFileSystem fs = p.getFileSystem();
+        if (x || (w && fs.isReadOnly())) {
             throw new AccessDeniedException(path.toString());
         }
     }
@@ -519,8 +528,9 @@ public class SftpFileSystemProvider extends FileSystemProvider {
                 @Override
                 public PosixFileAttributes readAttributes() throws IOException {
                     SftpPath p = toSftpPath(path);
+                    SftpFileSystem fs = p.getFileSystem();
                     final SftpClient.Attributes attributes;
-                    try (SftpClient client = p.getFileSystem().getClient()) {
+                    try (SftpClient client =fs.getClient()) {
                         try {
                             if (followLinks(options)) {
                                 attributes = client.stat(p.toString());
@@ -658,8 +668,10 @@ public class SftpFileSystemProvider extends FileSystemProvider {
             attrs = attributes.substring(i);
         }
         SftpPath p = toSftpPath(path);
-        if (!p.getFileSystem().supportedFileAttributeViews().contains(view)) {
-            throw new UnsupportedOperationException("readAttributes(" + path + ")[" + attributes + "] view not supported: " + view);
+        SftpFileSystem fs = p.getFileSystem();
+        Collection<String> views = fs.supportedFileAttributeViews();
+        if (GenericUtils.isEmpty(views) || (!views.contains(view))) {
+            throw new UnsupportedOperationException("readAttributes(" + path + ")[" + attributes + "] view " + view + " not supported: " + views);
         }
 
         PosixFileAttributes v = readAttributes(path, PosixFileAttributes.class, options);
@@ -727,8 +739,10 @@ public class SftpFileSystemProvider extends FileSystemProvider {
             attr = attribute.substring(i);
         }
         SftpPath p = toSftpPath(path);
-        if (!p.getFileSystem().supportedFileAttributeViews().contains(view)) {
-            throw new UnsupportedOperationException("setAttribute(" + path + ")[" + attribute + "=" + value + "] view not supported: " + view);
+        SftpFileSystem fs = p.getFileSystem();
+        Collection<String> views = fs.supportedFileAttributeViews();
+        if (GenericUtils.isEmpty(views) || (!view.contains(view))) {
+            throw new UnsupportedOperationException("setAttribute(" + path + ")[" + attribute + "=" + value + "] view " + view + " not supported: " + views);
         }
 
         SftpClient.Attributes attributes = new SftpClient.Attributes();
@@ -770,17 +784,15 @@ public class SftpFileSystemProvider extends FileSystemProvider {
                 }
         }
 
-        try (SftpClient client = p.getFileSystem().getClient()) {
+        try (SftpClient client = fs.getClient()) {
             client.setStat(p.toString(), attributes);
         }
     }
 
     private SftpPath toSftpPath(Path path) {
-        if (path == null) {
-            throw new NullPointerException();
-        }
+        ValidateUtils.checkNotNull(path, "No path provided", GenericUtils.EMPTY_OBJECT_ARRAY);
         if (!(path instanceof SftpPath)) {
-            throw new ProviderMismatchException();
+            throw new ProviderMismatchException("Path is not SFTP: " + path);
         }
         return (SftpPath) path;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/file/util/BasePath.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/util/BasePath.java b/sshd-core/src/main/java/org/apache/sshd/common/file/util/BasePath.java
index a74b1c0..3286a8d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/file/util/BasePath.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/util/BasePath.java
@@ -38,6 +38,7 @@ import java.util.List;
 import java.util.Objects;
 
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 public abstract class BasePath<T extends BasePath<T, FS>, FS extends BaseFileSystem<T>> implements Path {
 
@@ -238,9 +239,7 @@ public abstract class BasePath<T extends BasePath<T, FS>, FS extends BaseFileSys
 
     @Override
     public Path resolveSibling(Path other) {
-        if (other == null) {
-            throw new NullPointerException("Missing sibling path argument");
-        }
+        ValidateUtils.checkNotNull(other, "Missing sibling path argument", GenericUtils.EMPTY_OBJECT_ARRAY);
         T parent = getParent();
         return parent == null ? other : parent.resolve(other);
     }
@@ -357,11 +356,9 @@ public abstract class BasePath<T extends BasePath<T, FS>, FS extends BaseFileSys
 
     @SuppressWarnings("unchecked")
     private T checkPath(Path paramPath) {
-        if (paramPath == null) {
-            throw new NullPointerException();
-        }
+        ValidateUtils.checkNotNull(paramPath, "Missing path argument", GenericUtils.EMPTY_OBJECT_ARRAY);
         if (paramPath.getClass() != getClass()) {
-            throw new ProviderMismatchException();
+            throw new ProviderMismatchException("Path is not of this class: " + paramPath + "[" + paramPath.getClass().getSimpleName() + "]");
         }
         T t = (T) paramPath;
         

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java
index 0ee8afe..39ae862 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java
@@ -21,6 +21,8 @@ package org.apache.sshd.common.future;
 import java.lang.reflect.Array;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.logging.AbstractLoggingBean;
 
 /**
@@ -46,9 +48,6 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         this.lock = lock != null ? lock : this;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public T await() throws InterruptedException {
         if (await0(Long.MAX_VALUE, true) == null) {
@@ -58,25 +57,16 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         return asT();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
         return await(unit.toMillis(timeout));
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean await(long timeoutMillis) throws InterruptedException {
         return await0(timeoutMillis, true) != null;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public T awaitUninterruptibly() {
         try {
@@ -88,17 +78,11 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         return asT();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
         return awaitUninterruptibly(unit.toMillis(timeout));
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean awaitUninterruptibly(long timeoutMillis) {
         try {
@@ -144,9 +128,6 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean isDone() {
         synchronized (lock) {
@@ -180,15 +161,9 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public T addListener(SshFutureListener<T> listener) {
-        if (listener == null) {
-            throw new NullPointerException("listener");
-        }
-
+        ValidateUtils.checkNotNull(listener, "Missing listener argument", GenericUtils.EMPTY_OBJECT_ARRAY);
         boolean notifyNow = false;
         synchronized (lock) {
             if (result != null) {
@@ -215,14 +190,9 @@ public class DefaultSshFuture<T extends SshFuture> extends AbstractLoggingBean i
         return asT();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public T removeListener(SshFutureListener<T> listener) {
-        if (listener == null) {
-            throw new NullPointerException("listener");
-        }
+        ValidateUtils.checkNotNull(listener, "No listener provided", GenericUtils.EMPTY_OBJECT_ARRAY);
 
         synchronized (lock) {
             if (result == null) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
index 9abbaa4..67078b0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java
@@ -64,5 +64,4 @@ public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implemen
     public byte[] getK() {
         return K;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/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 5b60279..1874494 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
@@ -239,30 +239,22 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         return clientVersion;
     }
 
+    @Override
     public KeyExchange getKex() {
         return kex;
     }
 
-    public byte [] getSessionId() {
-        return sessionId;
+    @Override
+    public byte[] getSessionId() {
+        // return a clone to avoid anyone changing the internal value
+        return GenericUtils.isEmpty(sessionId) ? sessionId : sessionId.clone();
     }
 
-
-    /**
-     * Retrieve the mina session
-     *  
-     * @return the mina session
-     */
     @Override
     public IoSession getIoSession() {
         return ioSession;
     }
 
-    /**
-     * Retrieve the factory manager
-     *
-     * @return the factory manager for this session
-     */
     @Override
     public FactoryManager getFactoryManager() {
         return factoryManager;
@@ -277,14 +269,12 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
     	}
     }
 
+    @Override
     public boolean isAuthenticated() {
         return authed;
     }
 
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
+    @Override
     public void setAuthenticated() throws IOException {
         this.authed = true;
         sendEvent(SessionListener.Event.Authenticated);
@@ -1183,21 +1173,13 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         return E;
     }
 
-    /**
-     * Send a disconnect packet with the given reason and message.
-     * Once the packet has been sent, the session will be closed
-     * asynchronously.
-     *
-     * @param reason the reason code for this disconnect
-     * @param msg the text message
-     * @throws IOException if an error occured sending the packet
-     */
+    @Override
     public void disconnect(int reason, String msg) throws IOException {
-        log.info("Disconnecting: {}", msg);
+        log.info("Disconnecting: {} - {}", Integer.valueOf(reason), msg);
         Buffer buffer = createBuffer(SshConstants.SSH_MSG_DISCONNECT);
         buffer.putInt(reason);
         buffer.putString(msg);
-        buffer.putString("");
+        buffer.putString("");   // language...
         // Write the packet with a timeout to ensure a timely close of the session
         // in case the consumer does not read packets anymore.
         writePacket(buffer, disconnectTimeoutMs, TimeUnit.MILLISECONDS).addListener(new SshFutureListener<IoWriteFuture>() {
@@ -1366,22 +1348,21 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         return username;
     }
 
+    @Override
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
     public Object getLock() {
         return lock;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void addListener(SessionListener listener) {
         ValidateUtils.checkNotNull(listener, "addListener(%s) null instance", this);
         this.listeners.add(listener);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void removeListener(SessionListener listener) {
         this.listeners.remove(listener);
@@ -1406,18 +1387,80 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         // nothing
     }
 
-    protected abstract void sendKexInit() throws IOException;
+    protected byte[] sendKexInit() throws IOException {
+        String resolvedAlgorithms = resolveAvailableSignaturesProposal();
+        if (GenericUtils.isEmpty(resolvedAlgorithms)) {
+            throw new SshException(SshConstants.SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE,
+                                   "sendKexInit() no resolved signatures available");
+        }
+
+        Map<KexProposalOption,String> proposal = createProposal(resolvedAlgorithms); 
+        byte[] seed = sendKexInit(proposal);
+        if (log.isDebugEnabled()) {
+            log.debug("sendKexInit(" + proposal + ") seed: " + BufferUtils.printHex(':', seed));
+        }
+        setKexSeed(seed);
+        return seed;
+    }
+
+    /**
+     * @param seed The result of the KEXINIT handshake - required for correct
+     * session key establishment
+     */
+    protected abstract void setKexSeed(byte ... seed);
+
+    /**
+     * @return A comma-separated list of all the signature protocols to be
+     * included in the proposal - {@code null}/empty if no proposal
+     * @see #getFactoryManager()
+     * @see #resolveAvailableSignaturesProposal(FactoryManager)
+     */
+    protected String resolveAvailableSignaturesProposal() {
+        return resolveAvailableSignaturesProposal(getFactoryManager());
+    }
+
+    /**
+     * @param manager The {@link FactoryManager}
+     * @return A comma-separated list of all the signature protocols to be
+     * included in the proposal - {@code null}/empty if no proposal
+     */
+    protected abstract String resolveAvailableSignaturesProposal(FactoryManager manager);
 
     protected abstract void checkKeys() throws IOException;
 
-    protected abstract void receiveKexInit(Buffer buffer) throws IOException;
+    protected void receiveKexInit(Buffer buffer) throws IOException {
+        Map<KexProposalOption,String> proposal = new EnumMap<KexProposalOption, String>(KexProposalOption.class);
+        byte[] seed = receiveKexInit(buffer, proposal);
+        receiveKexInit(proposal, seed);
+    }
+    
+    protected abstract void receiveKexInit(Map<KexProposalOption,String> proposal, byte[] seed) throws IOException;
+
+    // returns the proposal argument
+    protected Map<KexProposalOption,String> mergeProposals(Map<KexProposalOption,String> current, Map<KexProposalOption,String> proposal) {
+        if (current == proposal) {
+            return proposal; // debug breakpoint
+        }
+
+        synchronized(current) {
+            if (!current.isEmpty()) {
+                current.clear();    // debug breakpoint
+            }
+            
+            if (GenericUtils.isEmpty(proposal)) {
+                return proposal; // debug breakpoint
+            }
+            
+            current.putAll(proposal);
+        }
+        
+        return proposal;
+    }
 
     protected void serviceAccept() throws IOException {
         // nothing
     }
 
-    public abstract void startService(String name) throws Exception;
-
     /**
      * 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.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
index 6bda1ec..ededad2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java
@@ -28,6 +28,7 @@ import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.IoWriteFuture;
 import org.apache.sshd.common.kex.KexProposalOption;
+import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.util.buffer.Buffer;
 
 /**
@@ -70,6 +71,7 @@ public interface Session extends Closeable {
      * @return the user name.
      */
     String getUsername();
+    void setUsername(String username);
 
     /**
      * Retrieve the client version for this session.
@@ -86,9 +88,7 @@ public interface Session extends Closeable {
     String getServerVersion();
 
     /**
-     * Retrieve the FactoryManager that has created this session
-     *
-     * @return the factory manager, can not be <tt>null</tt>.
+     * @return the {@link FactoryManager} that has created this session, can not be {@code null}
      */
     FactoryManager getFactoryManager();
 
@@ -237,24 +237,44 @@ public interface Session extends Closeable {
         }
     }
 
-    public void resetIdleTimeout();
+    void resetIdleTimeout();
 
     /**
      * Check if timeout has occurred.
      * @return the timeout status, never <code>null</code>
      */
-    public TimeoutStatus getTimeoutStatus();
+    TimeoutStatus getTimeoutStatus();
 
     /**
-     * What is timeout value in milliseconds for authentication stage
-     * @return
+     * @return Timeout value in milliseconds for authentication stage
      */
-    public long getAuthTimeout();
+    long getAuthTimeout();
 
     /**
-     * What is timeout value in milliseconds for communication
-     * @return
+     * @return Timeout value in milliseconds for communication
      */
+    long getIdleTimeout();
+    
+    boolean isAuthenticated();
+    void setAuthenticated() throws IOException;
+    
+    byte[] getSessionId();
+    KeyExchange getKex();
 
-    public long getIdleTimeout();
+    /**
+     * Send a disconnect packet with the given reason and message.
+     * Once the packet has been sent, the session will be closed
+     * asynchronously.
+     *
+     * @param reason the reason code for this disconnect
+     * @param msg the text message
+     * @throws IOException if an error occurred sending the packet
+     */
+    void disconnect(int reason, String msg) throws IOException;
+
+    /**
+     * @param name Service name
+     * @throws Exception If failed to start it
+     */
+    void startService(String name) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index 27cf000..a14bea8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -199,6 +199,14 @@ public final class GenericUtils {
         }
     }
 
+    public static final boolean isEmpty(byte[] a) {
+        if (length(a) <= 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     public static final int length(byte ... a) {
         if (a == null) {
             return 0;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
index 0009a14..4432aa4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
@@ -67,6 +67,12 @@ public final class ValidateUtils {
         return t;
     }
 
+    public static final byte[] checkNotNullAndNotEmpty(byte[] t, String message, Object ... args) {
+        t = checkNotNull(t, message, args);
+        checkTrue(GenericUtils.length(t) > 0, message, args);
+        return t;
+    }
+
     public static final <T> T[] checkNotNullAndNotEmpty(T[] t, String message, Object ... args) {
         t = checkNotNull(t, message, args);
         checkTrue(GenericUtils.length(t) > 0, message, args);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/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 99368f9..a86dce8 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
@@ -35,23 +35,23 @@ public interface ServerFactoryManager extends FactoryManager {
     /**
      * Key used to retrieve the value of the maximum concurrent open session count per username
      */
-    public static final String MAX_CONCURRENT_SESSIONS = "max-concurrent-sessions";
+    String MAX_CONCURRENT_SESSIONS = "max-concurrent-sessions";
     /**
      * Key used to retrieve the value of the server identification string if not default.
      */
-    public static final String SERVER_IDENTIFICATION = "server-identification";
+    String SERVER_IDENTIFICATION = "server-identification";
     /**
      * Key used to retrieve the value in the configuration properties map
      * of the maximum number of failed authentication requests before the
      * server closes the connection.
      */
-    public static final String MAX_AUTH_REQUESTS = "max-auth-requests";
+    String MAX_AUTH_REQUESTS = "max-auth-requests";
 
     /**
      * Key used to retrieve the value of welcome banner that will be displayed
      * when a user connects to the server.
      */
-    public static final String WELCOME_BANNER = "welcome-banner";
+    String WELCOME_BANNER = "welcome-banner";
 
     /**
      * This key is used when configuring multi-step authentications.
@@ -65,34 +65,34 @@ public interface ServerFactoryManager extends FactoryManager {
      * stage, so for this example, it would not be possible to attempt
      * password or keyboard-interactive authentication before public key.
      */
-    public static final String AUTH_METHODS = "auth-methods";
+    String AUTH_METHODS = "auth-methods";
 
     /**
      * Key used to configure the timeout used when receiving a close request
      * on a channel to wait until the command cleanly exits after setting
      * an EOF on the input stream. In milliseconds.
      */
-    public static final String COMMAND_EXIT_TIMEOUT = "command-exit-timeout";
+    String COMMAND_EXIT_TIMEOUT = "command-exit-timeout";
 
     /**
      * Key re-exchange will be automatically performed after the session
      * has sent or received the given amount of bytes.
      * The default value is 1 gigabyte.
      */
-    public static final String REKEY_BYTES_LIMIT = "rekey-bytes-limit";
+    String REKEY_BYTES_LIMIT = "rekey-bytes-limit";
 
     /**
      * Key re-exchange will be automatically performed after the specified
      * amount of time has elapsed since the last key exchange. In milliseconds.
      * The default value is 1 hour.
      */
-    public static final String REKEY_TIME_LIMIT = "rekey-time-limit";
+    String REKEY_TIME_LIMIT = "rekey-time-limit";
 
     /**
      * A URL pointing to the moduli file.
      * If not specified, the default internal file will be used.
      */
-    public static final String MODULI_URL = "moduli-url";
+    String MODULI_URL = "moduli-url";
 
     /**
      * Retrieve the list of named factories for <code>UserAuth</code> objects.

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/SessionAware.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SessionAware.java b/sshd-core/src/main/java/org/apache/sshd/server/SessionAware.java
index d133363..b5b6d86 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/SessionAware.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/SessionAware.java
@@ -27,9 +27,7 @@ import org.apache.sshd.server.session.ServerSession;
 public interface SessionAware {
 
     /**
-     * Set the server session in which this shell will be executed.
-     *
-     * @param session
+     * @param session The {@link ServerSession} in which this shell will be executed.
      */
     void setSession(ServerSession session);
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
index d334edb..c766310 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/AbstractUserAuth.java
@@ -30,6 +30,10 @@ public abstract class AbstractUserAuth extends AbstractLoggingBean implements Us
     protected String service;
     protected String username;
 
+    protected AbstractUserAuth() {
+        super();
+    }
+
     @Override
     public String getUserName() {
         return username;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
index 83db703..2972a9d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthKeyboardInteractive.java
@@ -21,8 +21,11 @@ package org.apache.sshd.server.auth;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.UserAuth;
 import org.apache.sshd.server.session.ServerSession;
 
@@ -51,6 +54,10 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
         }
     }
 
+    public UserAuthKeyboardInteractive() {
+        super();
+    }
+
     @Override
     protected Boolean doAuth(Buffer buffer, boolean init) throws Exception {
         if (init) {
@@ -78,12 +85,13 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
         }
     }
 
-    private boolean checkPassword(ServerSession session, String username, String password) throws Exception {
-        PasswordAuthenticator auth = session.getFactoryManager().getPasswordAuthenticator();
-        if (auth != null) {
-            return auth.authenticate(username, password, session);
-        }
-        throw new Exception("No PasswordAuthenticator configured");
+    protected boolean checkPassword(ServerSession session, String username, String password) throws Exception {
+        ServerFactoryManager manager = session.getFactoryManager();
+        PasswordAuthenticator auth = ValidateUtils.checkNotNull(
+                manager.getPasswordAuthenticator(),
+                "No PasswordAuthenticator configured",
+                GenericUtils.EMPTY_BYTE_ARRAY);
+        return auth.authenticate(username, password, session);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthNone.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthNone.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthNone.java
index 46d23f9..f25fd52 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthNone.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthNone.java
@@ -46,6 +46,10 @@ public class UserAuthNone extends AbstractUserAuth {
         }
     }
 
+    public UserAuthNone() {
+        super();
+    }
+
     @Override
     public Boolean doAuth(Buffer buffer, boolean init) {
         return Boolean.TRUE;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPassword.java
index 273b125..9168b99 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPassword.java
@@ -19,8 +19,11 @@
 package org.apache.sshd.server.auth;
 
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.UserAuth;
 import org.apache.sshd.server.session.ServerSession;
 
@@ -48,6 +51,10 @@ public class UserAuthPassword extends AbstractUserAuth {
         }
     }
 
+    public UserAuthPassword() {
+        super();
+    }
+
     @Override
     public Boolean doAuth(Buffer buffer, boolean init) throws Exception {
         if (!init) {
@@ -61,12 +68,12 @@ public class UserAuthPassword extends AbstractUserAuth {
         return Boolean.valueOf(checkPassword(session, username, password));
     }
 
-    private boolean checkPassword(ServerSession session, String username, String password) throws Exception {
-        PasswordAuthenticator auth = session.getFactoryManager().getPasswordAuthenticator();
-        if (auth != null) {
-            return auth.authenticate(username, password, session);
-        }
-        throw new Exception("No PasswordAuthenticator configured");
+    protected boolean checkPassword(ServerSession session, String username, String password) throws Exception {
+        ServerFactoryManager manager = session.getFactoryManager();
+        PasswordAuthenticator auth = ValidateUtils.checkNotNull(
+                manager.getPasswordAuthenticator(),
+                "No PasswordAuthenticator configured",
+                GenericUtils.EMPTY_OBJECT_ARRAY);
+        return auth.authenticate(username, password, session);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
index 9e7d269..1c468b3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuthPublicKey.java
@@ -57,11 +57,13 @@ public class UserAuthPublicKey extends AbstractUserAuth {
         }
     }
 
+    public UserAuthPublicKey() {
+        super();
+    }
+
     @Override
     public Boolean doAuth(Buffer buffer, boolean init) throws Exception {
-        if (!init) {
-            throw new IllegalStateException();
-        }
+        ValidateUtils.checkTrue(init, "Instance not initialized", GenericUtils.EMPTY_OBJECT_ARRAY);
         boolean hasSig = buffer.getBoolean();
         String alg = buffer.getString();
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
index 5422cf0..7ed9ec8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java
@@ -21,8 +21,11 @@ package org.apache.sshd.server.auth.gss;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.UserAuth;
 import org.apache.sshd.server.auth.AbstractUserAuth;
 import org.apache.sshd.server.session.ServerSession;
@@ -124,7 +127,7 @@ public class UserAuthGSS extends AbstractUserAuth {
 
                 Buffer msgbuf = new ByteArrayBuffer();
 
-                msgbuf.putBytes(session.getSessionId());
+                msgbuf.putBytes(ValidateUtils.checkNotNullAndNotEmpty(session.getSessionId(), "No current session ID", GenericUtils.EMPTY_OBJECT_ARRAY));
                 msgbuf.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
                 msgbuf.putString(username);
                 msgbuf.putString(service);
@@ -206,18 +209,13 @@ public class UserAuthGSS extends AbstractUserAuth {
     /**
      * Utility to get the configured GSS authenticator for the server, throwing an exception if none is available.
      *
-     * @param session The current session
-     * @return The GSS authenticator
+     * @param session The current {@link ServerSession}
+     * @return The {@link GSSAuthenticator} - never {@code null)
      * @throws Exception If no GSS authenticator is defined
      */
-    private GSSAuthenticator getAuthenticator(ServerSession session) throws Exception {
-        GSSAuthenticator ga = session.getFactoryManager().getGSSAuthenticator();
-
-        if (ga == null) {
-            throw new Exception("No GSSAuthenticator configured");
-        } else {
-            return ga;
-        }
+    protected GSSAuthenticator getAuthenticator(ServerSession session) throws Exception {
+        ServerFactoryManager manager = session.getFactoryManager();
+        return ValidateUtils.checkNotNull(manager.getGSSAuthenticator(), "No GSSAuthenticator configured", GenericUtils.EMPTY_OBJECT_ARRAY);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
index 44069cb..7edc72e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.sshd.agent.SshAgent;
 import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.common.Closeable;
+import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.FactoryManagerUtils;
 import org.apache.sshd.common.NamedFactory;
@@ -50,6 +51,7 @@ import org.apache.sshd.common.future.DefaultCloseFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.io.IoUtils;
@@ -57,6 +59,7 @@ import org.apache.sshd.common.util.io.LoggingFilterOutputStream;
 import org.apache.sshd.server.AsyncCommand;
 import org.apache.sshd.server.ChannelSessionAware;
 import org.apache.sshd.server.Command;
+import org.apache.sshd.server.CommandFactory;
 import org.apache.sshd.server.Environment;
 import org.apache.sshd.server.ExitCallback;
 import org.apache.sshd.server.ServerFactoryManager;
@@ -457,12 +460,22 @@ public class ChannelSession extends AbstractServerChannel {
     protected boolean handleShell(Buffer buffer) throws IOException {
         // If we're already closing, ignore incoming data
         if (isClosing()) {
+            log.debug("handleShell - closing");
             return false;
         }
-        if (((ServerSession) session).getFactoryManager().getShellFactory() == null) {
+        
+        ServerFactoryManager manager = ((ServerSession) session).getFactoryManager();
+        Factory<Command> factory = manager.getShellFactory();
+        if (factory == null) {
+            log.debug("handleShell - no shell factory");
             return false;
         }
-        command = ((ServerSession) session).getFactoryManager().getShellFactory().create();
+        
+        if ((command = factory.create()) == null) {
+            log.debug("handleShell - no shell command");
+            return false;
+        }
+
         prepareCommand();
         command.start(getEnvironment());
         return true;
@@ -474,17 +487,19 @@ public class ChannelSession extends AbstractServerChannel {
             return false;
         }
         String commandLine = buffer.getString();
-        if (((ServerSession) session).getFactoryManager().getCommandFactory() == null) {
-            log.warn("Unsupported command: {}", commandLine);
+        ServerFactoryManager manager = ((ServerSession) session).getFactoryManager();
+        CommandFactory factory = manager.getCommandFactory();
+        if (factory == null) {
+            log.warn("No command factory for command: {}", commandLine);
             return false;
         }
         if (log.isInfoEnabled()) {
             log.info("Executing command: {}", commandLine);
         }
         try {
-            command = ((ServerSession) session).getFactoryManager().getCommandFactory().createCommand(commandLine);
-        } catch (IllegalArgumentException iae) {
-            // TODO: Shouldn't we log errors on the server side?
+            command = factory.createCommand(commandLine);
+        } catch (RuntimeException iae) {
+            log.warn("Failed (" + iae.getClass().getSimpleName() + ") to execute " + commandLine + ": " + iae.getMessage());
             return false;
         }
         prepareCommand();
@@ -495,13 +510,14 @@ public class ChannelSession extends AbstractServerChannel {
 
     protected boolean handleSubsystem(Buffer buffer) throws IOException {
         String subsystem = buffer.getString();
-        List<NamedFactory<Command>> factories = ((ServerSession) session).getFactoryManager().getSubsystemFactories();
-        if (factories == null) {
-            log.warn("Unsupported subsystem: {}", subsystem);
+        ServerFactoryManager manager = ((ServerSession) session).getFactoryManager();
+        List<NamedFactory<Command>> factories = manager.getSubsystemFactories();
+        if (GenericUtils.isEmpty(factories)) {
+            log.warn("No factories for subsystem: {}", subsystem);
             return false;
         }
-        command = NamedFactory.Utils.create(factories, subsystem);
-        if (command == null) {
+
+        if ((command = NamedFactory.Utils.create(factories, subsystem)) == null) {
             log.warn("Unsupported subsystem: {}", subsystem);
             return false;
         }
@@ -596,11 +612,11 @@ public class ChannelSession extends AbstractServerChannel {
     }
 
     protected boolean handleAgentForwarding(Buffer buffer) throws IOException {
-        ServerSession server = (ServerSession) session;
-        FactoryManager manager = server.getFactoryManager();
+        ValidateUtils.checkTrue(session instanceof ServerSession, "Session not a server one", GenericUtils.EMPTY_OBJECT_ARRAY);
+        FactoryManager manager = session.getFactoryManager();
         ForwardingFilter filter = manager.getTcpipForwardingFilter();
         SshAgentFactory factory = manager.getAgentFactory();
-        if ((factory == null) || (filter == null) || (!filter.canForwardAgent(server))) {
+        if ((factory == null) || (filter == null) || (!filter.canForwardAgent(session))) {
             if (log.isDebugEnabled()) {
                 log.debug("handleAgentForwarding(" + session + ")[haveFactory=" + (factory != null) + ",haveFilter=" + (filter != null) + "] filtered out");
             }
@@ -613,9 +629,10 @@ public class ChannelSession extends AbstractServerChannel {
     }
 
     protected boolean handleX11Forwarding(Buffer buffer) throws IOException {
-        ServerSession server = (ServerSession) session;
-        ForwardingFilter filter = server.getFactoryManager().getTcpipForwardingFilter();
-        if ((filter == null) || (!filter.canForwardX11(server))) {
+        ValidateUtils.checkTrue(session instanceof ServerSession, "Session not a server one", GenericUtils.EMPTY_OBJECT_ARRAY);
+        FactoryManager manager = session.getFactoryManager();
+        ForwardingFilter filter = manager.getTcpipForwardingFilter();
+        if ((filter == null) || (!filter.canForwardX11(session))) {
             if (log.isDebugEnabled()) {
                 log.debug("handleX11Forwarding(" + session + ")[haveFilter=" + (filter != null) + "] filtered out");
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticator.java
index 69d7107..6125a63 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticator.java
@@ -96,7 +96,8 @@ public class AuthorizedKeysAuthenticator extends ModifiableFileWatcher implement
         }
     }
 
-    protected PublickeyAuthenticator resolvePublickeyAuthenticator(String username, ServerSession session) throws IOException, GeneralSecurityException {
+    protected PublickeyAuthenticator resolvePublickeyAuthenticator(String username, ServerSession session)
+            throws IOException, GeneralSecurityException {
         if (checkReloadRequired()) {
             /* Start fresh - NOTE: if there is any error then we want to reject all attempts
              * since we don't want to remain with the previous data - safer that way

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticator.java
index 0f4ea2a..266801c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticator.java
@@ -58,7 +58,7 @@ public class JaasPasswordAuthenticator extends AbstractLoggingBean implements Pa
     }
 
     @Override
-    public boolean authenticate(final String username, final String password, final ServerSession session) {
+    public boolean authenticate(String username, String password, ServerSession session) {
     	return authenticate(username, password);
     }
     

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
index 169efe6..0b7076b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java
@@ -23,6 +23,8 @@ import java.security.PublicKey;
 
 import org.apache.sshd.common.kex.dh.AbstractDHKeyExchange;
 import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.server.session.ServerSession;
 
 /**
@@ -39,14 +41,12 @@ public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange
     @Override
     public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
         super.init(s, V_S, V_C, I_S, I_C);
-        if (!(s instanceof ServerSession)) {
-            throw new IllegalStateException("Using a server side KeyExchange on a client");
-        }
+        ValidateUtils.checkTrue(s instanceof ServerSession, "Using a server side KeyExchange on a client", GenericUtils.EMPTY_OBJECT_ARRAY);
         session = (ServerSession) s;
     }
 
     @Override
     public PublicKey getServerKey() {
-        return session.getHostKey().getPublic();
+        return ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available", GenericUtils.EMPTY_OBJECT_ARRAY).getPublic();
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
index 7cc569e..3a8a194 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java
@@ -157,7 +157,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
 
 
             byte[] K_S;
-            KeyPair kp = session.getHostKey();
+            KeyPair kp = ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available", GenericUtils.EMPTY_OBJECT_ARRAY);
             String algo = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
             FactoryManager manager = session.getFactoryManager();
             Signature sig = ValidateUtils.checkNotNull(

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
index c88f902..b204615 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java
@@ -91,7 +91,7 @@ public class DHGServer extends AbstractDHServerKeyExchange {
         K = dh.getK();
 
         byte[] K_S;
-        KeyPair kp = session.getHostKey();
+        KeyPair kp = ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available", GenericUtils.EMPTY_OBJECT_ARRAY);
         String algo = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
         FactoryManager manager = session.getFactoryManager();
         Signature sig = ValidateUtils.checkNotNull(

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
index fa10296..8051eca 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
@@ -25,6 +25,8 @@ import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.session.AbstractConnectionService;
 import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
 
 /**
  * Server side <code>ssh-connection</code> service.
@@ -49,10 +51,9 @@ public class ServerConnectionService extends AbstractConnectionService {
 
     protected ServerConnectionService(Session s) throws SshException {
         super(s);
-        if (!(s instanceof ServerSession)) {
-            throw new IllegalStateException("Server side service used on client side");
-        }
-        ServerSession session = (ServerSession) s;
+        
+        ValidateUtils.checkTrue(s instanceof ServerSession, "Server side service used on client side", GenericUtils.EMPTY_OBJECT_ARRAY);
+
         if (!session.isAuthenticated()) {
             throw new SshException("Session is not authenticated");
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/6f8507a1/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 d5b8364..4e07afc 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
@@ -16,216 +16,33 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.sshd.server.session;
 
-import java.io.IOException;
 import java.security.KeyPair;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
 
-import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.FactoryManagerUtils;
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.ServiceFactory;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.future.SshFutureListener;
-import org.apache.sshd.common.io.IoService;
-import org.apache.sshd.common.io.IoSession;
-import org.apache.sshd.common.io.IoWriteFuture;
-import org.apache.sshd.common.kex.KexProposalOption;
-import org.apache.sshd.common.kex.KexState;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.buffer.Buffer;
-import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
+import org.apache.sshd.common.session.Session;
 import org.apache.sshd.server.ServerFactoryManager;
 
 /**
- *
- * TODO Add javadoc
- *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ServerSession extends AbstractSession {
-    public static final String  DEFAULT_SSH_VERSION_PREFIX="SSH-2.0-";
-
-    protected static final long MAX_PACKETS = (1l << 31);
-
-    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);
-        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());
-        sendServerIdentification();
-    }
-
-    @Override
-    public ServerFactoryManager getFactoryManager() {
-        return (ServerFactoryManager) factoryManager;
-    }
-
-    @Override
-    protected void checkKeys() {
-        // nothing
-    }
-
-    @Override
-    public void startService(String name) throws Exception {
-        currentService = ServiceFactory.Utils.create(getFactoryManager().getServiceFactories(), name, this);
-    }
-
-    @Override
-    protected void serviceAccept() throws IOException {
-        // TODO: can services be initiated by the server-side ?
-        disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Unsupported packet: SSH_MSG_SERVICE_ACCEPT");
-    }
-
-    @Override
-    protected void checkRekey() throws IOException {
-        if (KexState.DONE.equals(kexState.get())) {
-            if (   inPackets > MAX_PACKETS || outPackets > MAX_PACKETS
-                || inBytes > maxBytes || outBytes > maxBytes
-                || maxKeyInterval > 0 && System.currentTimeMillis() - lastKeyTime > maxKeyInterval)
-            {
-                reExchangeKeys();
-            }
-        }
-    }
-
-    private void sendServerIdentification() {
-        FactoryManager manager = getFactoryManager();
-        String ident = FactoryManagerUtils.getString(manager, ServerFactoryManager.SERVER_IDENTIFICATION);
-        if (GenericUtils.isEmpty(ident)) {
-            serverVersion = DEFAULT_SSH_VERSION_PREFIX + manager.getVersion();
-        } else {
-            serverVersion = DEFAULT_SSH_VERSION_PREFIX + ident;
-        }
-        sendIdentification(serverVersion);
-    }
-
-    @Override
-    protected void sendKexInit() throws IOException {
-    	/*
-    	 * Make sure that the provided host keys have at least one supported signature factory
-    	 */
-        FactoryManager manager = getFactoryManager();
-        KeyPairProvider kpp = manager.getKeyPairProvider();
-        List<String> supported = NamedResource.Utils.getNameList(manager.getSignatureFactories());
-        Iterable<String> provided = kpp.getKeyTypes();
-        StringBuilder resolvedHostKeys = null;
-        for (String keyType : provided) {
-            if (!supported.contains(keyType)) {
-                if (log.isDebugEnabled()) {
-                    log.debug("sendKexInit(" + provided + ") " + keyType + " not in list of supported: " + supported);
-                }
-                continue;
-            }
-
-            if (resolvedHostKeys == null) {
-                resolvedHostKeys = new StringBuilder(supported.size() * 16 /* ecdsa-sha2-xxxx */);
-            }
-
-            if (resolvedHostKeys.length() > 0) {
-                resolvedHostKeys.append(',');
-            }
-
-            resolvedHostKeys.append(keyType);
-        }
-
-        // make sure the new list has at least one supported AND provided key type
-        if (GenericUtils.isEmpty(resolvedHostKeys)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE,
-                                   "sendKexInit(" + provided + ") none of the keys appears in supported list: " + supported);
-        }
-
-        Map<KexProposalOption,String> proposal = createProposal(resolvedHostKeys.toString());
-        synchronized(serverProposal) {
-            if (!serverProposal.isEmpty()) {
-                serverProposal.clear(); // debug breakpoint
-            }
-            
-            serverProposal.putAll(proposal);
-        }
-
-        I_S = sendKexInit(proposal);
-    }
-
-    @Override
-    protected boolean readIdentification(Buffer buffer) throws IOException {
-        clientVersion = doReadIdentification(buffer, true);
-        if (GenericUtils.isEmpty(clientVersion)) {
-            return false;
-        }
-        log.debug("Client version string: {}", clientVersion);
-        if (!clientVersion.startsWith(DEFAULT_SSH_VERSION_PREFIX)) {
-            String msg = "Unsupported protocol version: " + clientVersion;
-            ioSession.write(new ByteArrayBuffer((msg + "\n").getBytes())).addListener(new SshFutureListener<IoWriteFuture>() {
-                @Override
-                public void operationComplete(IoWriteFuture future) {
-                    close(true);
-                }
-            });
-            throw new SshException(msg);
-        } else {
-            kexState.set(KexState.INIT);
-            sendKexInit();
-        }
-        return true;
-    }
-
-    @Override
-    protected void receiveKexInit(Buffer buffer) throws IOException {
-        if (!clientProposal.isEmpty()) {
-            clientProposal.clear(); // debug breakpoint
-        }
-        I_C = receiveKexInit(buffer, clientProposal);
-    }
-
-    public KeyPair getHostKey() {
-        String value = getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
-        return factoryManager.getKeyPairProvider().loadKey(value);
-    }
+public interface ServerSession extends Session {
+    /**
+     * @return The {@link ServerFactoryManager} for this session
+     */
+    @Override ServerFactoryManager getFactoryManager();
+    
+    /**
+     * @return The {@link KeyPair} representing the current session's used keys
+     * on KEX
+     */
+    KeyPair getHostKey();
 
     /**
      * Retrieve the current number of sessions active for a given username.
-     * @param userName The name of the user
+     * @param userName The name of the user - ignored if {@code null}/empty
      * @return The current number of live <code>SshSession</code> objects associated with the user
      */
-    protected int getActiveSessionCountForUser(String userName) {
-        IoService service = ioSession.getService();
-        Map<?, IoSession> sessionsMap = service.getManagedSessions();
-        if (GenericUtils.isEmpty(sessionsMap)) {
-            return 0;
-        }
-
-        int totalCount = 0;
-        for (IoSession is : sessionsMap.values()) {
-            ServerSession session = (ServerSession) getSession(is, true);
-            if (session == null) {
-                continue;
-            }
-            
-            String sessionUser = session.getUsername();
-            if ((!GenericUtils.isEmpty(sessionUser)) && Objects.equals(sessionUser, userName)) {
-                totalCount++;
-            }
-        }
-
-        return totalCount;
-    }
-
-	/**
-	 * Returns the session id.
-	 * 
-	 * @return The session id.
-	 */
-	public long getId() {
-		return ioSession.getId();
-	}
+    int getActiveSessionCountForUser(String userName);
 }