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/11/26 06:33:03 UTC

[02/10] mina-sshd git commit: [SSHD-599] Allow per-session override of KEX and authentication related configuration

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
index 8ea0788..0e2fe5c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
@@ -23,7 +23,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.ClientAuthenticationManager;
 import org.apache.sshd.client.auth.UserAuth;
 import org.apache.sshd.client.auth.UserInteraction;
 import org.apache.sshd.client.future.AuthFuture;
@@ -70,18 +70,19 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
         }
         session = (ClientSessionImpl) s;
         authFuture = new DefaultAuthFuture(session.getLock());
-        ClientFactoryManager manager = session.getFactoryManager();
-        authFactories = manager.getUserAuthFactories();
+        authFactories = session.getUserAuthFactories();
         clientMethods = new ArrayList<>();
 
-        String prefs = PropertyResolverUtils.getString(session, ClientFactoryManager.PREFERRED_AUTHS);
+        String prefs = PropertyResolverUtils.getString(session, ClientAuthenticationManager.PREFERRED_AUTHS);
         if (!GenericUtils.isEmpty(prefs)) {
             for (String pref : prefs.split(",")) {
                 NamedFactory<UserAuth> factory = NamedResource.Utils.findByName(pref, String.CASE_INSENSITIVE_ORDER, authFactories);
                 if (factory != null) {
                     clientMethods.add(pref);
                 } else {
-                    log.debug("Skip unknown prefered authentication method: {}", pref);
+                    if (log.isDebugEnabled()) {
+                        log.debug("ClientUserAuthService({}) skip unknown prefered authentication method: {}", s, pref);
+                    }
                 }
             }
         } else {
@@ -107,11 +108,12 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
     }
 
     public AuthFuture auth(List<Object> identities, String service) throws IOException {
-        log.debug("Start authentication");
         this.identities = new ArrayList<>(identities);
         this.service = service;
 
-        log.debug("Send SSH_MSG_USERAUTH_REQUEST for none");
+        if (log.isDebugEnabled()) {
+            log.debug("auth({})[{}] Send SSH_MSG_USERAUTH_REQUEST for 'none'", getClientSession(), service);
+        }
         String username = session.getUsername();
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, username.length() + service.length() + Integer.SIZE);
         buffer.putString(session.getUsername());
@@ -128,16 +130,19 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
             throw new IllegalStateException("UserAuth message delivered to authenticated client");
         } else if (this.authFuture.isDone()) {
             if (log.isDebugEnabled()) {
-                log.debug("Ignoring random message - cmd={}", cmd);
+                log.debug("process({}) Ignoring random message - cmd={}",
+                          session, SshConstants.getCommandMessageName(cmd));
             }
             // ignore for now; TODO: random packets
         } else if (cmd == SshConstants.SSH_MSG_USERAUTH_BANNER) {
             String welcome = buffer.getString();
             String lang = buffer.getString();
-            log.debug("Welcome banner(lang={}): {}", lang, welcome);
+            if (log.isDebugEnabled()) {
+                log.debug("process({}) Welcome banner(lang={}): {}", session, lang, welcome);
+            }
 
-            UserInteraction ui = UserInteraction.Utils.resolveUserInteraction(session);
-            if (ui != null) {
+            UserInteraction ui = session.getUserInteraction();
+            if ((ui != null) && ui.isInteractionAllowed(session)) {
                 ui.welcome(session, welcome, lang);
             }
         } else {
@@ -147,15 +152,18 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
     }
 
     /**
-     * execute one step in user authentication.
+     * Execute one step in user authentication.
      *
-     * @param buffer
-     * @throws java.io.IOException
+     * @param buffer The input {@link Buffer}
+     * @throws Exception If failed to process
      */
-    private void processUserAuth(Buffer buffer) throws Exception {
+    protected void processUserAuth(Buffer buffer) throws Exception {
         int cmd = buffer.getUByte();
         if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-            log.debug("SSH_MSG_USERAUTH_SUCCESS Succeeded with {}", userAuth);
+            if (log.isDebugEnabled()) {
+                log.debug("processUserAuth({}) SSH_MSG_USERAUTH_SUCCESS Succeeded with {}",
+                          getClientSession(), userAuth);
+            }
             if (userAuth != null) {
                 userAuth.destroy();
                 userAuth = null;
@@ -170,7 +178,8 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
             String mths = buffer.getString();
             boolean partial = buffer.getBoolean();
             if (log.isDebugEnabled()) {
-                log.debug("Received SSH_MSG_USERAUTH_FAILURE - partial={}, methods={}", partial, mths);
+                log.debug("processUserAuth({}) Received SSH_MSG_USERAUTH_FAILURE - partial={}, methods={}",
+                          getClientSession(), partial, mths);
             }
             if (partial || (serverMethods == null)) {
                 serverMethods = Arrays.asList(GenericUtils.split(mths, ','));
@@ -191,7 +200,7 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
         }
     }
 
-    private void tryNext() throws Exception {
+    protected void tryNext() throws Exception {
         // Loop until we find something to try
         while (true) {
             if (userAuth == null) {
@@ -202,19 +211,29 @@ public class ClientUserAuthService extends AbstractCloseable implements Service,
             } else {
                 return;
             }
+
             while (currentMethod < clientMethods.size() && !serverMethods.contains(clientMethods.get(currentMethod))) {
                 currentMethod++;
             }
+
             if (currentMethod >= clientMethods.size()) {
-                // Failure
+                if (log.isDebugEnabled()) {
+                    log.debug("tryNext({}) exhausted all methods", getClientSession());
+                }
+
                 authFuture.setAuthed(false);
                 return;
             }
+
             String method = clientMethods.get(currentMethod);
             userAuth = NamedFactory.Utils.create(authFactories, method);
             if (userAuth == null) {
                 throw new UnsupportedOperationException("Failed to find a user-auth factory for method=" + method);
             }
+            if (log.isDebugEnabled()) {
+                log.debug("tryNext({}) attempting method={}", getClientSession(), method);
+            }
+
             userAuth.init(session, service, identities);
         }
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 3cd9a19..ffb3883 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
@@ -31,27 +31,20 @@ import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.common.channel.Channel;
 import org.apache.sshd.common.channel.ChannelListener;
 import org.apache.sshd.common.channel.RequestHandler;
-import org.apache.sshd.common.cipher.Cipher;
-import org.apache.sshd.common.compression.Compression;
 import org.apache.sshd.common.config.VersionProperties;
 import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.forward.TcpipForwarderFactory;
 import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
-import org.apache.sshd.common.kex.KeyExchange;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProviderHolder;
-import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.kex.AbstractKexFactoryManager;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.session.AbstractSessionFactory;
 import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.session.SessionListener;
 import org.apache.sshd.common.session.SessionTimeoutListener;
-import org.apache.sshd.common.signature.Signature;
 import org.apache.sshd.common.util.EventListenerUtils;
 import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
 import org.apache.sshd.common.util.threads.ThreadUtils;
 import org.apache.sshd.server.forward.ForwardingFilter;
 
@@ -60,17 +53,10 @@ import org.apache.sshd.server.forward.ForwardingFilter;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public abstract class AbstractFactoryManager
-        extends AbstractInnerCloseable
-        implements FactoryManager, KeyPairProviderHolder {
+public abstract class AbstractFactoryManager extends AbstractKexFactoryManager implements FactoryManager {
 
     protected IoServiceFactoryFactory ioServiceFactoryFactory;
     protected IoServiceFactory ioServiceFactory;
-    protected List<NamedFactory<KeyExchange>> keyExchangeFactories;
-    protected List<NamedFactory<Cipher>> cipherFactories;
-    protected List<NamedFactory<Compression>> compressionFactories;
-    protected List<NamedFactory<Mac>> macFactories;
-    protected List<NamedFactory<Signature>> signatureFactories;
     protected Factory<Random> randomFactory;
     protected List<NamedFactory<Channel>> channelFactories;
     protected SshAgentFactory agentFactory;
@@ -89,7 +75,6 @@ public abstract class AbstractFactoryManager
     protected final ChannelListener channelListenerProxy;
 
     private final Map<String, Object> properties = new ConcurrentHashMap<>();
-    private KeyPairProvider keyPairProvider;
 
     protected AbstractFactoryManager() {
         ClassLoader loader = getClass().getClassLoader();
@@ -116,51 +101,6 @@ public abstract class AbstractFactoryManager
     }
 
     @Override
-    public List<NamedFactory<KeyExchange>> getKeyExchangeFactories() {
-        return keyExchangeFactories;
-    }
-
-    public void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
-        this.keyExchangeFactories = keyExchangeFactories;
-    }
-
-    @Override
-    public List<NamedFactory<Cipher>> getCipherFactories() {
-        return cipherFactories;
-    }
-
-    public void setCipherFactories(List<NamedFactory<Cipher>> cipherFactories) {
-        this.cipherFactories = cipherFactories;
-    }
-
-    @Override
-    public List<NamedFactory<Compression>> getCompressionFactories() {
-        return compressionFactories;
-    }
-
-    public void setCompressionFactories(List<NamedFactory<Compression>> compressionFactories) {
-        this.compressionFactories = compressionFactories;
-    }
-
-    @Override
-    public List<NamedFactory<Mac>> getMacFactories() {
-        return macFactories;
-    }
-
-    public void setMacFactories(List<NamedFactory<Mac>> macFactories) {
-        this.macFactories = macFactories;
-    }
-
-    @Override
-    public List<NamedFactory<Signature>> getSignatureFactories() {
-        return signatureFactories;
-    }
-
-    public void setSignatureFactories(List<NamedFactory<Signature>> signatureFactories) {
-        this.signatureFactories = signatureFactories;
-    }
-
-    @Override
     public Factory<Random> getRandomFactory() {
         return randomFactory;
     }
@@ -170,15 +110,6 @@ public abstract class AbstractFactoryManager
     }
 
     @Override
-    public KeyPairProvider getKeyPairProvider() {
-        return keyPairProvider;
-    }
-
-    public void setKeyPairProvider(KeyPairProvider keyPairProvider) {
-        this.keyPairProvider = keyPairProvider;
-    }
-
-    @Override
     public Map<String, Object> getProperties() {
         return properties;
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 14f688c..0e2ff1f 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
@@ -26,17 +26,13 @@ import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.common.channel.Channel;
 import org.apache.sshd.common.channel.ChannelListenerManager;
 import org.apache.sshd.common.channel.RequestHandler;
-import org.apache.sshd.common.cipher.Cipher;
-import org.apache.sshd.common.compression.Compression;
 import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.forward.TcpipForwarderFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
-import org.apache.sshd.common.kex.KeyExchange;
-import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.kex.KexFactoryManager;
 import org.apache.sshd.common.random.Random;
 import org.apache.sshd.common.session.ConnectionService;
 import org.apache.sshd.common.session.SessionListenerManager;
-import org.apache.sshd.common.signature.Signature;
 import org.apache.sshd.server.forward.ForwardingFilter;
 
 /**
@@ -45,7 +41,7 @@ import org.apache.sshd.server.forward.ForwardingFilter;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public interface FactoryManager extends SessionListenerManager, ChannelListenerManager, PropertyResolver {
+public interface FactoryManager extends KexFactoryManager, SessionListenerManager, ChannelListenerManager, PropertyResolver {
 
     /**
      * Key used to retrieve the value of the channel window size in the
@@ -213,41 +209,6 @@ public interface FactoryManager extends SessionListenerManager, ChannelListenerM
     IoServiceFactory getIoServiceFactory();
 
     /**
-     * Retrieve the list of named factories for <code>KeyExchange</code>.
-     *
-     * @return a list of named <code>KeyExchange</code> factories, never {@code null}
-     */
-    List<NamedFactory<KeyExchange>> getKeyExchangeFactories();
-
-    /**
-     * Retrieve the list of named factories for <code>Cipher</code>.
-     *
-     * @return a list of named <code>Cipher</code> factories, never {@code null}
-     */
-    List<NamedFactory<Cipher>> getCipherFactories();
-
-    /**
-     * Retrieve the list of named factories for <code>Compression</code>.
-     *
-     * @return a list of named <code>Compression</code> factories, never {@code null}
-     */
-    List<NamedFactory<Compression>> getCompressionFactories();
-
-    /**
-     * Retrieve the list of named factories for <code>Mac</code>.
-     *
-     * @return a list of named <code>Mac</code> factories, never {@code null}
-     */
-    List<NamedFactory<Mac>> getMacFactories();
-
-    /**
-     * Retrieve the list of named factories for <code>Signature</code>.
-     *
-     * @return a list of named <code>Signature</code> factories, never {@code null}
-     */
-    List<NamedFactory<Signature>> getSignatureFactories();
-
-    /**
      * Retrieve the <code>Random</code> factory to be used.
      *
      * @return the <code>Random</code> factory, never {@code null}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/auth/AbstractUserAuthMethodFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/auth/AbstractUserAuthMethodFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/auth/AbstractUserAuthMethodFactory.java
index cb9cefe..73e8015 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/auth/AbstractUserAuthMethodFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/auth/AbstractUserAuthMethodFactory.java
@@ -37,4 +37,9 @@ public abstract class AbstractUserAuthMethodFactory<M> extends AbstractLoggingBe
     public final String getName() {
         return name;
     }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getName() + "]";
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
new file mode 100644
index 0000000..e86e579
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/AbstractKexFactoryManager.java
@@ -0,0 +1,137 @@
+/*
+ * 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.kex;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.signature.Signature;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractKexFactoryManager
+              extends AbstractInnerCloseable
+              implements KexFactoryManager {
+    private KexFactoryManager parent;
+    private List<NamedFactory<KeyExchange>> keyExchangeFactories;
+    private List<NamedFactory<Cipher>> cipherFactories;
+    private List<NamedFactory<Compression>> compressionFactories;
+    private List<NamedFactory<Mac>> macFactories;
+    private List<NamedFactory<Signature>> signatureFactories;
+    private KeyPairProvider keyPairProvider;
+
+    protected AbstractKexFactoryManager() {
+        this(null);
+    }
+
+    protected AbstractKexFactoryManager(KexFactoryManager parent) {
+        this.parent = parent;
+    }
+
+    @Override
+    public List<NamedFactory<KeyExchange>> getKeyExchangeFactories() {
+        return resolveEffectiveFactories(KeyExchange.class, keyExchangeFactories,
+                (parent == null) ? Collections.<NamedFactory<KeyExchange>>emptyList() : parent.getKeyExchangeFactories());
+    }
+
+    @Override
+    public void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+        this.keyExchangeFactories = keyExchangeFactories;
+    }
+
+    @Override
+    public List<NamedFactory<Cipher>> getCipherFactories() {
+        return resolveEffectiveFactories(Cipher.class, cipherFactories,
+                (parent == null) ? Collections.<NamedFactory<Cipher>>emptyList() : parent.getCipherFactories());
+    }
+
+    @Override
+    public void setCipherFactories(List<NamedFactory<Cipher>> cipherFactories) {
+        this.cipherFactories = cipherFactories;
+    }
+
+    @Override
+    public List<NamedFactory<Compression>> getCompressionFactories() {
+        return resolveEffectiveFactories(Compression.class, compressionFactories,
+                (parent == null) ? Collections.<NamedFactory<Compression>>emptyList() : parent.getCompressionFactories());
+    }
+
+    @Override
+    public void setCompressionFactories(List<NamedFactory<Compression>> compressionFactories) {
+        this.compressionFactories = compressionFactories;
+    }
+
+    @Override
+    public List<NamedFactory<Mac>> getMacFactories() {
+        return resolveEffectiveFactories(Mac.class, macFactories,
+                (parent == null) ? Collections.<NamedFactory<Mac>>emptyList() : parent.getMacFactories());
+    }
+
+    @Override
+    public void setMacFactories(List<NamedFactory<Mac>> macFactories) {
+        this.macFactories = macFactories;
+    }
+
+    @Override
+    public List<NamedFactory<Signature>> getSignatureFactories() {
+        return resolveEffectiveFactories(Signature.class, signatureFactories,
+                (parent == null) ? Collections.<NamedFactory<Signature>>emptyList() : parent.getSignatureFactories());
+    }
+
+    @Override
+    public void setSignatureFactories(List<NamedFactory<Signature>> signatureFactories) {
+        this.signatureFactories = signatureFactories;
+    }
+
+    @Override
+    public KeyPairProvider getKeyPairProvider() {
+        return resolveEffectiveProvider(KeyPairProvider.class, keyPairProvider,
+                (parent == null) ? null : parent.getKeyPairProvider());
+    }
+
+    @Override
+    public void setKeyPairProvider(KeyPairProvider keyPairProvider) {
+        this.keyPairProvider = keyPairProvider;
+    }
+
+    protected <V> List<NamedFactory<V>> resolveEffectiveFactories(Class<V> factoryType, List<NamedFactory<V>> local, List<NamedFactory<V>> inherited) {
+        if (GenericUtils.isEmpty(local)) {
+            return inherited;
+        } else {
+            return local;
+        }
+    }
+
+    protected <V> V resolveEffectiveProvider(Class<V> providerType, V local, V inherited) {
+        if (local == null) {
+            return inherited;
+        } else {
+            return local;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
new file mode 100644
index 0000000..60dcf57
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/KexFactoryManager.java
@@ -0,0 +1,75 @@
+/*
+ * 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.kex;
+
+import java.util.List;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.keyprovider.KeyPairProviderHolder;
+import org.apache.sshd.common.mac.Mac;
+import org.apache.sshd.common.signature.Signature;
+
+/**
+ * Holds KEX negotiation stage configuration
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface KexFactoryManager extends KeyPairProviderHolder {
+    /**
+     * Retrieve the list of named factories for <code>KeyExchange</code>.
+     *
+     * @return a list of named <code>KeyExchange</code> factories, never {@code null}
+     */
+    List<NamedFactory<KeyExchange>> getKeyExchangeFactories();
+    void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories);
+
+    /**
+     * Retrieve the list of named factories for <code>Cipher</code>.
+     *
+     * @return a list of named <code>Cipher</code> factories, never {@code null}
+     */
+    List<NamedFactory<Cipher>> getCipherFactories();
+    void setCipherFactories(List<NamedFactory<Cipher>> cipherFactories);
+
+    /**
+     * Retrieve the list of named factories for <code>Compression</code>.
+     *
+     * @return a list of named <code>Compression</code> factories, never {@code null}
+     */
+    List<NamedFactory<Compression>> getCompressionFactories();
+    void setCompressionFactories(List<NamedFactory<Compression>> compressionFactories);
+
+    /**
+     * Retrieve the list of named factories for <code>Mac</code>.
+     *
+     * @return a list of named <code>Mac</code> factories, never {@code null}
+     */
+    List<NamedFactory<Mac>> getMacFactories();
+    void setMacFactories(List<NamedFactory<Mac>> macFactories);
+
+    /**
+     * Retrieve the list of named factories for <code>Signature</code>.
+     *
+     * @return a list of named <code>Signature</code> factories, never {@code null}
+     */
+    List<NamedFactory<Signature>> getSignatureFactories();
+    void setSignatureFactories(List<NamedFactory<Signature>> signatureFactories);
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProviderHolder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProviderHolder.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProviderHolder.java
index fbd5d22..b5826f6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProviderHolder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyPairProviderHolder.java
@@ -30,4 +30,5 @@ public interface KeyPairProviderHolder {
      * @return the <code>KeyPairProvider</code>, never {@code null}
      */
     KeyPairProvider getKeyPairProvider();
+    void setKeyPairProvider(KeyPairProvider keyPairProvider);
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 e092a32..ad1e74b 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
@@ -54,6 +54,7 @@ import org.apache.sshd.common.future.KeyExchangeFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.kex.AbstractKexFactoryManager;
 import org.apache.sshd.common.kex.KexProposalOption;
 import org.apache.sshd.common.kex.KexState;
 import org.apache.sshd.common.kex.KeyExchange;
@@ -67,7 +68,6 @@ import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
-import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
 
 /**
  * <P>
@@ -84,7 +84,7 @@ import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public abstract class AbstractSession extends AbstractInnerCloseable implements Session {
+public abstract class AbstractSession extends AbstractKexFactoryManager implements Session {
     /**
      * Name of the property where this session is stored in the attributes of the
      * underlying MINA session. See {@link #getSession(IoSession, boolean)}
@@ -196,15 +196,19 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
      * @param ioSession      the underlying MINA session
      */
     protected AbstractSession(boolean isServer, FactoryManager factoryManager, IoSession ioSession) {
+        super(ValidateUtils.checkNotNull(factoryManager, "No factory manager provided"));
         this.isServer = isServer;
-        this.factoryManager = ValidateUtils.checkNotNull(factoryManager, "No factory manager provided", GenericUtils.EMPTY_OBJECT_ARRAY);
+        this.factoryManager = factoryManager;
         this.ioSession = ioSession;
 
         ClassLoader loader = getClass().getClassLoader();
         sessionListenerProxy = EventListenerUtils.proxyWrapper(SessionListener.class, loader, sessionListeners);
         channelListenerProxy = EventListenerUtils.proxyWrapper(ChannelListener.class, loader, channelListeners);
-
         random = ValidateUtils.checkNotNull(factoryManager.getRandomFactory(), "No random factory").create();
+
+        // Delegate the task of further notifications to the session
+        addSessionListener(factoryManager.getSessionListenerProxy());
+        addChannelListener(factoryManager.getChannelListenerProxy());
     }
 
     /**
@@ -507,7 +511,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
 
         Map<KexProposalOption, String> result = negotiate();
         String kexAlgorithm = result.get(KexProposalOption.ALGORITHMS);
-        kex = ValidateUtils.checkNotNull(NamedFactory.Utils.create(factoryManager.getKeyExchangeFactories(), kexAlgorithm),
+        kex = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getKeyExchangeFactories(), kexAlgorithm),
                 "Unknown negotiated KEX algorithm: %s",
                 kexAlgorithm);
         kex.init(this, serverVersion.getBytes(StandardCharsets.UTF_8), clientVersion.getBytes(StandardCharsets.UTF_8), i_s, i_c);
@@ -689,7 +693,9 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
                 @Override
                 public void run() {
                     Throwable t = new TimeoutException("Timeout writing packet: " + timeout + " " + unit);
-                    log.info(t.getMessage());
+                    if (log.isDebugEnabled()) {
+                        log.debug(t.getMessage());
+                    }
                     future.setValue(t);
                 }
             }, timeout, unit);
@@ -787,7 +793,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
             if (buffer.rpos() < 5) {
                 log.warn("Performance cost: when sending a packet, ensure that "
                         + "5 bytes are available in front of the buffer");
-                Buffer nb = new ByteArrayBuffer();
+                Buffer nb = new ByteArrayBuffer(buffer.available() + Long.SIZE);
                 nb.wpos(5);
                 nb.putBuffer(buffer);
                 buffer = nb;
@@ -800,7 +806,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
                 log.trace("Sending packet #{}: {}", Long.valueOf(seqo), buffer.printHex());
             }
             // Compress the packet if needed
-            if (outCompression != null && (authed || !outCompression.isDelayed())) {
+            if ((outCompression != null) && (authed || !outCompression.isDelayed())) {
                 outCompression.compress(buffer);
                 len = buffer.available();
             }
@@ -1026,18 +1032,23 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
      */
     protected Map<KexProposalOption, String> createProposal(String hostKeyTypes) {
         Map<KexProposalOption, String> proposal = new EnumMap<>(KexProposalOption.class);
-        proposal.put(KexProposalOption.ALGORITHMS, NamedResource.Utils.getNames(factoryManager.getKeyExchangeFactories()));
+        proposal.put(KexProposalOption.ALGORITHMS,
+                NamedResource.Utils.getNames(
+                        ValidateUtils.checkNotNullAndNotEmpty(getKeyExchangeFactories(), "No KEX factories")));
         proposal.put(KexProposalOption.SERVERKEYS, hostKeyTypes);
 
-        String ciphers = NamedResource.Utils.getNames(factoryManager.getCipherFactories());
+        String ciphers = NamedResource.Utils.getNames(
+                ValidateUtils.checkNotNullAndNotEmpty(getCipherFactories(), "No cipher factories"));
         proposal.put(KexProposalOption.S2CENC, ciphers);
         proposal.put(KexProposalOption.C2SENC, ciphers);
 
-        String macs = NamedResource.Utils.getNames(factoryManager.getMacFactories());
+        String macs = NamedResource.Utils.getNames(
+                ValidateUtils.checkNotNullAndNotEmpty(getMacFactories(), "No MAC factories"));
         proposal.put(KexProposalOption.S2CMAC, macs);
         proposal.put(KexProposalOption.C2SMAC, macs);
 
-        String compressions = NamedResource.Utils.getNames(factoryManager.getCompressionFactories());
+        String compressions = NamedResource.Utils.getNames(
+                ValidateUtils.checkNotNullAndNotEmpty(getCompressionFactories(), "No compression factories"));
         proposal.put(KexProposalOption.S2CCOMP, compressions);
         proposal.put(KexProposalOption.C2SCOMP, compressions);
 
@@ -1209,30 +1220,30 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
         String value;
 
         value = getNegotiatedKexParameter(KexProposalOption.S2CENC);
-        s2ccipher = ValidateUtils.checkNotNull(NamedFactory.Utils.create(factoryManager.getCipherFactories(), value), "Unknown s2c cipher: %s", value);
+        s2ccipher = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getCipherFactories(), value), "Unknown s2c cipher: %s", value);
         e_s2c = resizeKey(e_s2c, s2ccipher.getBlockSize(), hash, k, h);
         s2ccipher.init(isServer ? Cipher.Mode.Encrypt : Cipher.Mode.Decrypt, e_s2c, iv_s2c);
 
         value = getNegotiatedKexParameter(KexProposalOption.S2CMAC);
-        s2cmac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(factoryManager.getMacFactories(), value), "Unknown s2c mac: %s", value);
+        s2cmac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getMacFactories(), value), "Unknown s2c mac: %s", value);
         mac_s2c = resizeKey(mac_s2c, s2cmac.getBlockSize(), hash, k, h);
         s2cmac.init(mac_s2c);
 
         value = getNegotiatedKexParameter(KexProposalOption.S2CCOMP);
-        s2ccomp = NamedFactory.Utils.create(factoryManager.getCompressionFactories(), value);
+        s2ccomp = NamedFactory.Utils.create(getCompressionFactories(), value);
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SENC);
-        c2scipher = ValidateUtils.checkNotNull(NamedFactory.Utils.create(factoryManager.getCipherFactories(), value), "Unknown c2s cipher: %s", value);
+        c2scipher = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getCipherFactories(), value), "Unknown c2s cipher: %s", value);
         e_c2s = resizeKey(e_c2s, c2scipher.getBlockSize(), hash, k, h);
         c2scipher.init(isServer ? Cipher.Mode.Decrypt : Cipher.Mode.Encrypt, e_c2s, iv_c2s);
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SMAC);
-        c2smac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(factoryManager.getMacFactories(), value), "Unknown c2s mac: %s", value);
+        c2smac = ValidateUtils.checkNotNull(NamedFactory.Utils.create(getMacFactories(), value), "Unknown c2s mac: %s", value);
         mac_c2s = resizeKey(mac_c2s, c2smac.getBlockSize(), hash, k, h);
         c2smac.init(mac_c2s);
 
         value = getNegotiatedKexParameter(KexProposalOption.C2SCOMP);
-        c2scomp = NamedFactory.Utils.create(factoryManager.getCompressionFactories(), value);
+        c2scomp = NamedFactory.Utils.create(getCompressionFactories(), value);
 
         if (isServer) {
             outCipher = s2ccipher;
@@ -1521,7 +1532,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements
     @Override
     public KeyExchangeFuture reExchangeKeys() throws IOException {
         if (kexState.compareAndSet(KexState.DONE, KexState.INIT)) {
-            log.info("Initiating key re-exchange");
+            log.info("reExchangeKeys({}) Initiating key re-exchange", this);
             sendKexInit();
 
             DefaultKeyExchangeFuture kexFuture = kexFutureHolder.getAndSet(new DefaultKeyExchangeFuture(null));

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSessionFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSessionFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSessionFactory.java
index c4afdfd..5dc01d8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSessionFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSessionFactory.java
@@ -48,13 +48,6 @@ public abstract class AbstractSessionFactory<M extends FactoryManager, S extends
     protected abstract S doCreateSession(IoSession ioSession) throws Exception;
 
     protected S setupSession(S session) throws Exception {
-        FactoryManager listenersManager = getFactoryManager();
-        SessionListener sessionListener = listenersManager.getSessionListenerProxy();
-        // Inform the listener of the newly created session
-        sessionListener.sessionCreated(session);
-        // Delegate the task of further notifications to the session
-        session.addSessionListener(sessionListener);
-        session.addChannelListener(listenersManager.getChannelListenerProxy());
         return session;
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 f16949a..0ac2705 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
@@ -30,6 +30,7 @@ import org.apache.sshd.common.channel.ChannelListenerManager;
 import org.apache.sshd.common.future.KeyExchangeFuture;
 import org.apache.sshd.common.io.IoSession;
 import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.kex.KexFactoryManager;
 import org.apache.sshd.common.kex.KexProposalOption;
 import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.util.buffer.Buffer;
@@ -41,7 +42,8 @@ import org.apache.sshd.common.util.buffer.Buffer;
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
 public interface Session
-        extends SessionListenerManager,
+        extends KexFactoryManager,
+                SessionListenerManager,
                 ChannelListenerManager,
                 PropertyResolver,
                 Closeable,

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 db8a930..39c08d2 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
@@ -565,4 +565,24 @@ public final class GenericUtils {
         current.addSuppressed(extra);
         return current;
     }
+
+    /**
+     * Wraps a value into a {@link Supplier}
+     * @param <T>   Type of value being supplied
+     * @param value The value to be supplied
+     * @return The supplier wrapper
+     */
+    public static <T> Supplier<T> supplierOf(final T value) {
+        return new Supplier<T>() {
+            @Override
+            public T get() {
+                return value;
+            }
+
+            @Override
+            public String toString() {
+                return Supplier.class.getSimpleName() + "[" + value + "]";
+            }
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/common/util/Supplier.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/Supplier.java b/sshd-core/src/main/java/org/apache/sshd/common/util/Supplier.java
new file mode 100644
index 0000000..c40a175
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/Supplier.java
@@ -0,0 +1,29 @@
+/*
+ * 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.util;
+
+/**
+ * Same as in Java 8
+ * @param <T> Type of object being supplied
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface Supplier<T> {
+    T get();
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
new file mode 100644
index 0000000..e889392
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerAuthenticationManager.java
@@ -0,0 +1,166 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.server.auth.UserAuth;
+import org.apache.sshd.server.auth.UserAuthKeyboardInteractiveFactory;
+import org.apache.sshd.server.auth.UserAuthPasswordFactory;
+import org.apache.sshd.server.auth.UserAuthPublicKeyFactory;
+import org.apache.sshd.server.auth.gss.GSSAuthenticator;
+import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
+import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
+import org.apache.sshd.server.auth.password.PasswordAuthenticator;
+import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
+
+/**
+ * Holds providers and helpers related to the server side authentication process
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ServerAuthenticationManager {
+    /**
+     * 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.
+     * @see #DEFAULT_MAX_AUTH_REQUESTS
+     */
+    String MAX_AUTH_REQUESTS = "max-auth-requests";
+
+    /**
+     * Default value for {@link #MAX_AUTH_REQUESTS} if none configured
+     */
+    int DEFAULT_MAX_AUTH_REQUESTS = 20;
+
+    /**
+     * Retrieve the list of named factories for <code>UserAuth</code> objects.
+     *
+     * @return a list of named <code>UserAuth</code> factories, never {@code null}/empty
+     */
+    List<NamedFactory<UserAuth>> getUserAuthFactories();
+    void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories);
+
+    /**
+     * Retrieve the <code>PublickeyAuthenticator</code> to be used by SSH server.
+     * If no authenticator has been configured (i.e. this method returns
+     * {@code null}), then client authentication requests based on keys will be
+     * rejected.
+     *
+     * @return the <code>PublickeyAuthenticator</code> or {@code null}
+     */
+    PublickeyAuthenticator getPublickeyAuthenticator();
+    void setPasswordAuthenticator(PasswordAuthenticator passwordAuthenticator);
+
+    /**
+     * Retrieve the <code>PasswordAuthenticator</code> to be used by the SSH server.
+     * If no authenticator has been configured (i.e. this method returns
+     * {@code null}), then client authentication requests based on passwords
+     * will be rejected.
+     *
+     * @return the <code>PasswordAuthenticator</code> or {@code null}
+     */
+    PasswordAuthenticator getPasswordAuthenticator();
+    void setPublickeyAuthenticator(PublickeyAuthenticator publickeyAuthenticator);
+
+    /**
+     * Retrieve the <code>KeyboardInteractiveAuthenticator</code> to be used by
+     * the SSH server. If no authenticator has been configured (i.e. this method returns
+     * {@code null}), then client authentication requests based on this method
+     * will be rejected.
+     *
+     * @return The {@link KeyboardInteractiveAuthenticator} or {@code null}
+     */
+    KeyboardInteractiveAuthenticator getKeyboardInteractiveAuthenticator();
+    void setKeyboardInteractiveAuthenticator(KeyboardInteractiveAuthenticator interactiveAuthenticator);
+
+    /**
+     * Retrieve the <code>GSSAuthenticator</code> to be used by the SSH server.
+     * If no authenticator has been configured (i.e. this method returns
+     * {@code null}), then client authentication requests based on gssapi
+     * will be rejected.
+     *
+     * @return the <code>GSSAuthenticator</code> or {@code null}
+     */
+    GSSAuthenticator getGSSAuthenticator();
+    void setGSSAuthenticator(GSSAuthenticator gssAuthenticator);
+
+    // CHECKSTYLE:OFF
+    final class Utils {
+    // CHECKSTYLE:ON
+        public static final UserAuthPublicKeyFactory DEFAULT_USER_AUTH_PUBLIC_KEY_FACTORY =
+                UserAuthPublicKeyFactory.INSTANCE;
+
+        public static final UserAuthGSSFactory DEFAULT_USER_AUTH_GSS_FACTORY =
+                UserAuthGSSFactory.INSTANCE;
+
+        public static final UserAuthPasswordFactory DEFAULT_USER_AUTH_PASSWORD_FACTORY =
+                UserAuthPasswordFactory.INSTANCE;
+
+        public static final UserAuthKeyboardInteractiveFactory DEFAULT_USER_AUTH_KB_INTERACTIVE_FACTORY =
+                UserAuthKeyboardInteractiveFactory.INSTANCE;
+
+        private Utils() {
+            throw new UnsupportedOperationException("No instance allowed");
+        }
+
+        /**
+         * If user authentication factories already set, then simply returns them. Otherwise,
+         * builds the factories list from the individual authenticators set - password,
+         * public key, keyboard-interactive, GSS, etc...
+         *
+         * @param manager The {@link ServerAuthenticationManager} - ignored if {@code null}
+         * @return The resolved {@link List} of {@link NamedFactory} for the {@link UserAuth}s
+         */
+        public static List<NamedFactory<UserAuth>> resolveUserAuthFactories(ServerAuthenticationManager manager) {
+            if (manager == null) {
+                return Collections.emptyList();
+            } else {
+                return resolveUserAuthFactories(manager, manager.getUserAuthFactories());
+            }
+        }
+
+        public static List<NamedFactory<UserAuth>> resolveUserAuthFactories(
+                ServerAuthenticationManager manager, List<NamedFactory<UserAuth>> userFactories) {
+            if (GenericUtils.size(userFactories) > 0) {
+                return userFactories;
+            }
+
+            List<NamedFactory<UserAuth>> factories = new ArrayList<>();
+            if (manager.getPasswordAuthenticator() != null) {
+                factories.add(DEFAULT_USER_AUTH_PASSWORD_FACTORY);
+                factories.add(DEFAULT_USER_AUTH_KB_INTERACTIVE_FACTORY);
+            }
+
+            if (manager.getPublickeyAuthenticator() != null) {
+                factories.add(DEFAULT_USER_AUTH_PUBLIC_KEY_FACTORY);
+            }
+
+            if (manager.getGSSAuthenticator() != null) {
+                factories.add(DEFAULT_USER_AUTH_GSS_FACTORY);
+            }
+
+            return factories;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 ca806fd..92fd295 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
@@ -24,12 +24,6 @@ import java.util.concurrent.TimeUnit;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.keyprovider.KeyPairProviderHolder;
-import org.apache.sshd.server.auth.UserAuth;
-import org.apache.sshd.server.auth.gss.GSSAuthenticator;
-import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
-import org.apache.sshd.server.auth.password.PasswordAuthenticator;
-import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
 
 /**
  * The <code>ServerFactoryManager</code> enable the retrieval of additional
@@ -37,7 +31,7 @@ import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public interface ServerFactoryManager extends FactoryManager, KeyPairProviderHolder {
+public interface ServerFactoryManager extends FactoryManager, ServerAuthenticationManager {
     /**
      * Key used to retrieve the value of the maximum concurrent open session count per username.
      * If not set, then unlimited
@@ -50,19 +44,6 @@ public interface ServerFactoryManager extends FactoryManager, KeyPairProviderHol
     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.
-     * @see #DEFAULT_MAX_AUTH_REQUESTS
-     */
-    String MAX_AUTH_REQUESTS = "max-auth-requests";
-
-    /**
-     * Default value for {@link #MAX_AUTH_REQUESTS} if none configured
-     */
-    int DEFAULT_MAX_AUTH_REQUESTS = 20;
-
-    /**
      * Key used to retrieve the value of welcome banner that will be displayed
      * when a user connects to the server. If {@code null}/empty then no banner
      * will be sent.
@@ -130,53 +111,6 @@ public interface ServerFactoryManager extends FactoryManager, KeyPairProviderHol
     String MODULI_URL = "moduli-url";
 
     /**
-     * Retrieve the list of named factories for <code>UserAuth</code> objects.
-     *
-     * @return a list of named <code>UserAuth</code> factories, never {@code null}
-     */
-    List<NamedFactory<UserAuth>> getUserAuthFactories();
-
-    /**
-     * Retrieve the <code>PublickeyAuthenticator</code> to be used by SSH server.
-     * If no authenticator has been configured (i.e. this method returns
-     * {@code null}), then client authentication requests based on keys will be
-     * rejected.
-     *
-     * @return the <code>PublickeyAuthenticato</code> or {@code null}
-     */
-    PublickeyAuthenticator getPublickeyAuthenticator();
-
-    /**
-     * Retrieve the <code>PasswordAuthenticator</code> to be used by the SSH server.
-     * If no authenticator has been configured (i.e. this method returns
-     * {@code null}), then client authentication requests based on passwords
-     * will be rejected.
-     *
-     * @return the <code>PasswordAuthenticator</code> or {@code null}
-     */
-    PasswordAuthenticator getPasswordAuthenticator();
-
-    /**
-     * Retrieve the <code>KeyboardInteractiveAuthenticator</code> to be used by
-     * the SSH server. If no authenticator has been configured (i.e. this method returns
-     * {@code null}), then client authentication requests based on this method
-     * will be rejected.
-     *
-     * @return The {@link KeyboardInteractiveAuthenticator} or {@code null}
-     */
-    KeyboardInteractiveAuthenticator getKeyboardInteractiveAuthenticator();
-
-    /**
-     * Retrieve the <code>GSSAuthenticator</code> to be used by the SSH server.
-     * If no authenticator has been configured (i.e. this method returns
-     * {@code null}), then client authentication requests based on gssapi
-     * will be rejected.
-     *
-     * @return the <code>GSSAuthenticator</code> or {@code null}
-     */
-    GSSAuthenticator getGSSAuthenticator();
-
-    /**
      * Retrieve the <code>ShellFactory</code> object to be used to create shells.
      *
      * @return a valid <code>ShellFactory</code> object or {@code null} if shells

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
index 6a50428..5df5346 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java
@@ -45,11 +45,7 @@ import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.server.auth.UserAuth;
-import org.apache.sshd.server.auth.UserAuthKeyboardInteractiveFactory;
-import org.apache.sshd.server.auth.UserAuthPasswordFactory;
-import org.apache.sshd.server.auth.UserAuthPublicKeyFactory;
 import org.apache.sshd.server.auth.gss.GSSAuthenticator;
-import org.apache.sshd.server.auth.gss.UserAuthGSSFactory;
 import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
 import org.apache.sshd.server.auth.password.PasswordAuthenticator;
 import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
@@ -107,31 +103,20 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
                     ServerUserAuthServiceFactory.INSTANCE,
                     ServerConnectionServiceFactory.INSTANCE
             ));
-    public static final UserAuthPublicKeyFactory DEFAULT_USER_AUTH_PUBLIC_KEY_FACTORY =
-            UserAuthPublicKeyFactory.INSTANCE;
-
-    public static final UserAuthGSSFactory DEFAULT_USER_AUTH_GSS_FACTORY =
-            UserAuthGSSFactory.INSTANCE;
-
-    public static final UserAuthPasswordFactory DEFAULT_USER_AUTH_PASSWORD_FACTORY =
-            UserAuthPasswordFactory.INSTANCE;
-
-    public static final UserAuthKeyboardInteractiveFactory DEFAULT_USER_AUTH_KB_INTERACTIVE_FACTORY =
-            UserAuthKeyboardInteractiveFactory.INSTANCE;
 
 
     protected IoAcceptor acceptor;
     protected String host;
     protected int port;
-    protected List<NamedFactory<UserAuth>> userAuthFactories;
-    protected Factory<Command> shellFactory;
-    protected SessionFactory sessionFactory;
-    protected CommandFactory commandFactory;
-    protected List<NamedFactory<Command>> subsystemFactories;
-    protected PasswordAuthenticator passwordAuthenticator;
-    protected PublickeyAuthenticator publickeyAuthenticator;
-    protected KeyboardInteractiveAuthenticator interactiveAuthenticator;
-    protected GSSAuthenticator gssAuthenticator;
+    private Factory<Command> shellFactory;
+    private SessionFactory sessionFactory;
+    private CommandFactory commandFactory;
+    private List<NamedFactory<Command>> subsystemFactories;
+    private List<NamedFactory<UserAuth>> userAuthFactories;
+    private PasswordAuthenticator passwordAuthenticator;
+    private PublickeyAuthenticator publickeyAuthenticator;
+    private KeyboardInteractiveAuthenticator interactiveAuthenticator;
+    private GSSAuthenticator gssAuthenticator;
 
     public SshServer() {
         super();
@@ -163,6 +148,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return userAuthFactories;
     }
 
+    @Override
     public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
         this.userAuthFactories = userAuthFactories;
     }
@@ -207,6 +193,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return passwordAuthenticator;
     }
 
+    @Override
     public void setPasswordAuthenticator(PasswordAuthenticator passwordAuthenticator) {
         this.passwordAuthenticator = passwordAuthenticator;
     }
@@ -216,6 +203,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return publickeyAuthenticator;
     }
 
+    @Override
     public void setPublickeyAuthenticator(PublickeyAuthenticator publickeyAuthenticator) {
         this.publickeyAuthenticator = publickeyAuthenticator;
     }
@@ -225,6 +213,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return interactiveAuthenticator;
     }
 
+    @Override
     public void setKeyboardInteractiveAuthenticator(KeyboardInteractiveAuthenticator interactiveAuthenticator) {
         this.interactiveAuthenticator = interactiveAuthenticator;
     }
@@ -234,6 +223,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         return gssAuthenticator;
     }
 
+    @Override
     public void setGSSAuthenticator(GSSAuthenticator gssAuthenticator) {
         this.gssAuthenticator = gssAuthenticator;
     }
@@ -249,24 +239,8 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
 
         ValidateUtils.checkTrue(getPort() >= 0 /* zero means not set yet */, "Bad port number: %d", Integer.valueOf(getPort()));
 
-        if (GenericUtils.isEmpty(getUserAuthFactories())) {
-            List<NamedFactory<UserAuth>> factories = new ArrayList<>();
-            if (getPasswordAuthenticator() != null) {
-                factories.add(DEFAULT_USER_AUTH_PASSWORD_FACTORY);
-                factories.add(DEFAULT_USER_AUTH_KB_INTERACTIVE_FACTORY);
-            }
-
-            if (getPublickeyAuthenticator() != null) {
-                factories.add(DEFAULT_USER_AUTH_PUBLIC_KEY_FACTORY);
-            }
-
-            if (getGSSAuthenticator() != null) {
-                factories.add(DEFAULT_USER_AUTH_GSS_FACTORY);
-            }
-
-            ValidateUtils.checkTrue(factories.size() > 0, "UserAuthFactories not set");
-            setUserAuthFactories(factories);
-        }
+        List<NamedFactory<UserAuth>> authFactories = ServerAuthenticationManager.Utils.resolveUserAuthFactories(this);
+        setUserAuthFactories(ValidateUtils.checkNotNullAndNotEmpty(authFactories, "UserAuthFactories not set"));
 
         ValidateUtils.checkNotNullAndNotEmpty(getChannelFactories(), "ChannelFactories not set");
         ValidateUtils.checkNotNull(getKeyPairProvider(), "HostKeyProvider not set");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 f9b8737..a384520 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
@@ -24,10 +24,8 @@ import java.util.List;
 
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
-import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.BufferUtils;
-import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.auth.keyboard.InteractiveChallenge;
 import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
 import org.apache.sshd.server.session.ServerSession;
@@ -47,8 +45,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
     @Override
     protected Boolean doAuth(Buffer buffer, boolean init) throws Exception {
         ServerSession session = getServerSession();
-        ServerFactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
-        KeyboardInteractiveAuthenticator auth = manager.getKeyboardInteractiveAuthenticator();
+        KeyboardInteractiveAuthenticator auth = session.getKeyboardInteractiveAuthenticator();
         if (init) {
             String lang = buffer.getString();
             String subMethods = buffer.getString();
@@ -75,7 +72,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
         } else {
             int cmd = buffer.getUByte();
             if (cmd != SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE) {
-                throw new SshException("Received unexpected message: " + cmd);
+                throw new SshException("Received unexpected message: " + SshConstants.getCommandMessageName(cmd));
             }
 
             int num = buffer.getInt();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 3dc7fd5..d59720b 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
@@ -21,7 +21,6 @@ package org.apache.sshd.server.auth;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
-import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.auth.password.PasswordAuthenticator;
 import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
 import org.apache.sshd.server.session.ServerSession;
@@ -69,10 +68,7 @@ public class UserAuthPassword extends AbstractUserAuth {
      * @see #handleServerPasswordChangeRequest(Buffer, ServerSession, String, String, PasswordChangeRequiredException)
      */
     protected Boolean checkPassword(Buffer buffer, ServerSession session, String username, String password) throws Exception {
-        ServerFactoryManager manager = ValidateUtils.checkNotNull(
-                session.getFactoryManager(),
-                "No ServerFactoryManager configured");
-        PasswordAuthenticator auth = manager.getPasswordAuthenticator();
+        PasswordAuthenticator auth = session.getPasswordAuthenticator();
         if (auth == null) {
             if (log.isDebugEnabled()) {
                 log.debug("checkPassword({}) no password authenticator", session);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 5285e40..5299a84 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
@@ -22,12 +22,12 @@ import java.security.PublicKey;
 
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.signature.Signature;
 import org.apache.sshd.common.util.ValidateUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.buffer.BufferUtils;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
-import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
 import org.apache.sshd.server.session.ServerSession;
 
@@ -55,17 +55,21 @@ public class UserAuthPublicKey extends AbstractUserAuth {
         buffer.wpos(buffer.rpos() + len);
 
         ServerSession session = getServerSession();
-        ServerFactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
         PublicKey key = buffer.getRawPublicKey();
+        if (log.isDebugEnabled()) {
+            log.debug("doAuth({}) verify key type={}, fingerprint={}",
+                      session, alg, KeyUtils.getFingerPrint(key));
+        }
+
         Signature verifier = ValidateUtils.checkNotNull(
-                NamedFactory.Utils.create(manager.getSignatureFactories(), alg),
+                NamedFactory.Utils.create(session.getSignatureFactories(), alg),
                 "No verifier located for algorithm=%s",
                 alg);
         verifier.initVerifier(key);
         buffer.wpos(oldLim);
 
         byte[] sig = hasSig ? buffer.getBytes() : null;
-        PublickeyAuthenticator authenticator = manager.getPublickeyAuthenticator();
+        PublickeyAuthenticator authenticator = session.getPublickeyAuthenticator();
         if (authenticator == null) {
             if (log.isDebugEnabled()) {
                 log.debug("doAuth({}) no authenticator", session);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 3a96e00..706b278 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
@@ -24,7 +24,6 @@ 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.auth.AbstractUserAuth;
 import org.apache.sshd.server.session.ServerSession;
 import org.ietf.jgss.GSSContext;
@@ -63,7 +62,7 @@ public class UserAuthGSS extends AbstractUserAuth {
     @Override
     protected Boolean doAuth(Buffer buffer, boolean initial) throws Exception {
         ServerSession session = getServerSession();
-        GSSAuthenticator auth = getAuthenticator(session);
+        GSSAuthenticator auth = ValidateUtils.checkNotNull(session.getGSSAuthenticator(), "No GSSAuthenticator configured");
 
         if (initial) {
             // Get mechanism count from buffer and look for Kerberos 5.
@@ -74,7 +73,9 @@ public class UserAuthGSS extends AbstractUserAuth {
                 Oid oid = new Oid(buffer.getBytes());
 
                 if (oid.equals(KRB5_MECH)) {
-                    log.debug("UserAuthGSS: found Kerberos 5");
+                    if (log.isDebugEnabled()) {
+                        log.debug("doAuth({}@{}) found Kerberos 5", getUsername(), session);
+                    }
 
                     // Validate initial user before proceeding
 
@@ -110,11 +111,11 @@ public class UserAuthGSS extends AbstractUserAuth {
             if (!((msg == SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE)
                     || (msg == SshConstants.SSH_MSG_USERAUTH_GSSAPI_MIC) && context.isEstablished())) {
                 throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR,
-                        "Packet not supported by user authentication method: " + msg);
+                        "Packet not supported by user authentication method: " + SshConstants.getCommandMessageName(msg));
             }
 
             if (log.isDebugEnabled()) {
-                log.debug("doAuth({}@{}) In krb5.next: msg = {}", getUsername(), session, msg);
+                log.debug("doAuth({}@{}) In krb5.next: msg = {}", getUsername(), session, SshConstants.getCommandMessageName(msg));
             }
 
             // If the context is established, this must be a MIC message
@@ -145,7 +146,10 @@ public class UserAuthGSS extends AbstractUserAuth {
                     }
                     return Boolean.TRUE;
                 } catch (GSSException e) {
-                    log.info("doAuth({}@{}) GSS verification error: {}", getUsername(), session, e.toString());
+                    if (log.isDebugEnabled()) {
+                        log.debug("doAuth({}@{}) GSS verification {} error: {}",
+                                  getUsername(), session, e.getClass().getSimpleName(), e.getMessage());
+                    }
                     return Boolean.FALSE;
                 }
             } else {
@@ -161,7 +165,7 @@ public class UserAuthGSS extends AbstractUserAuth {
                 if (established && (identity == null)) {
                     identity = context.getSrcName().toString();
                     if (log.isDebugEnabled()) {
-                        log.info("GSS identity is {}", identity);
+                        log.debug("doAuth({}@{}) GSS identity is {}", getUsername(), session, identity);
                     }
 
                     if (!auth.validateIdentity(session, identity)) {
@@ -208,24 +212,12 @@ 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 {@link ServerSession}
-     * @return The {@link GSSAuthenticator} - never {@code null}
-     * @throws Exception If no GSS authenticator is defined
-     */
-    protected GSSAuthenticator getAuthenticator(ServerSession session) throws Exception {
-        ServerFactoryManager manager = session.getFactoryManager();
-        return ValidateUtils.checkNotNull(manager.getGSSAuthenticator(), "No GSSAuthenticator configured");
-    }
-
-    /**
      * Utility to construct an Oid from a string, ignoring the annoying exception.
      *
      * @param rep The string form
      * @return The Oid
      */
-    private static Oid createOID(String rep) {
+    public static Oid createOID(String rep) {
         try {
             return new Oid(rep);
         } catch (GSSException e) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java
index 0e3f971..92bf59b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java
@@ -24,9 +24,7 @@ import java.util.List;
 import org.apache.sshd.common.PropertyResolverUtils;
 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.logging.AbstractLoggingBean;
-import org.apache.sshd.server.ServerFactoryManager;
 import org.apache.sshd.server.auth.password.PasswordAuthenticator;
 import org.apache.sshd.server.session.ServerSession;
 
@@ -59,8 +57,7 @@ public class DefaultKeyboardInteractiveAuthenticator
 
     @Override
     public InteractiveChallenge generateChallenge(ServerSession session, String username, String lang, String subMethods) {
-        ServerFactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
-        PasswordAuthenticator auth = manager.getPasswordAuthenticator();
+        PasswordAuthenticator auth = session.getPasswordAuthenticator();
         if (auth == null) {
             if (log.isDebugEnabled()) {
                 log.debug("generateChallenge({}) no password authenticator", session);
@@ -78,8 +75,7 @@ public class DefaultKeyboardInteractiveAuthenticator
 
     @Override
     public boolean authenticate(ServerSession session, String username, List<String> responses) throws Exception {
-        ServerFactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
-        PasswordAuthenticator auth = manager.getPasswordAuthenticator();
+        PasswordAuthenticator auth = session.getPasswordAuthenticator();
         if (auth == null) {
             if (log.isDebugEnabled()) {
                 log.debug("authenticate({}) no password authenticator", session);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/KeyboardInteractiveAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/KeyboardInteractiveAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/KeyboardInteractiveAuthenticator.java
index 80c94f1..cdf2928 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/KeyboardInteractiveAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/KeyboardInteractiveAuthenticator.java
@@ -31,6 +31,26 @@ import org.apache.sshd.server.session.ServerSession;
  */
 public interface KeyboardInteractiveAuthenticator {
     /**
+     * An authenticator that rejects any attempt to use it
+     */
+    KeyboardInteractiveAuthenticator NONE = new KeyboardInteractiveAuthenticator() {
+        @Override
+        public InteractiveChallenge generateChallenge(ServerSession session, String username, String lang, String subMethods) {
+            return null;
+        }
+
+        @Override
+        public boolean authenticate(ServerSession session, String username, List<String> responses) throws Exception {
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "NONE";
+        }
+    };
+
+    /**
      * Generates the interactive &quot;challenge&quot; to send to the client
      *
      * @param session The {@link ServerSession} through which the request was received

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 3a0c4c5..4509ae5 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
@@ -171,9 +171,8 @@ public class DHGEXServer extends AbstractDHServerKeyExchange {
             byte[] k_s;
             KeyPair kp = ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available");
             String algo = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
-            FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
             Signature sig = ValidateUtils.checkNotNull(
-                    NamedFactory.Utils.create(manager.getSignatureFactories(), algo),
+                    NamedFactory.Utils.create(session.getSignatureFactories(), algo),
                     "Unknown negotiated server keys: %s",
                     algo);
             sig.initSigner(kp.getPrivate());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 4a45cd5..7e1757c 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
@@ -20,7 +20,6 @@ package org.apache.sshd.server.kex;
 
 import java.security.KeyPair;
 
-import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.SshException;
@@ -98,9 +97,8 @@ public class DHGServer extends AbstractDHServerKeyExchange {
 
         KeyPair kp = ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available");
         String algo = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS);
-        FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager");
         Signature sig = ValidateUtils.checkNotNull(
-                NamedFactory.Utils.create(manager.getSignatureFactories(), algo),
+                NamedFactory.Utils.create(session.getSignatureFactories(), algo),
                 "Unknown negotiated server keys: %s",
                 algo);
         sig.initSigner(kp.getPrivate());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
new file mode 100644
index 0000000..2e76a7a
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
@@ -0,0 +1,107 @@
+/*
+ * 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 java.util.List;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.server.ServerFactoryManager;
+import org.apache.sshd.server.auth.UserAuth;
+import org.apache.sshd.server.auth.gss.GSSAuthenticator;
+import org.apache.sshd.server.auth.keyboard.KeyboardInteractiveAuthenticator;
+import org.apache.sshd.server.auth.password.PasswordAuthenticator;
+import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractServerSession extends AbstractSession implements ServerSession {
+    private PasswordAuthenticator passwordAuthenticator;
+    private PublickeyAuthenticator publickeyAuthenticator;
+    private KeyboardInteractiveAuthenticator interactiveAuthenticator;
+    private GSSAuthenticator gssAuthenticator;
+    private List<NamedFactory<UserAuth>> userAuthFactories;
+
+    protected AbstractServerSession(ServerFactoryManager factoryManager, IoSession ioSession) {
+        super(true, factoryManager, ioSession);
+    }
+
+    @Override
+    public ServerFactoryManager getFactoryManager() {
+        return (ServerFactoryManager) super.getFactoryManager();
+    }
+
+    @Override
+    public PasswordAuthenticator getPasswordAuthenticator() {
+        return resolveEffectiveProvider(PasswordAuthenticator.class, passwordAuthenticator, getFactoryManager().getPasswordAuthenticator());
+    }
+
+    @Override
+    public void setPasswordAuthenticator(PasswordAuthenticator passwordAuthenticator) {
+        this.passwordAuthenticator = passwordAuthenticator; // OK if null - inherit from parent
+    }
+
+    @Override
+    public PublickeyAuthenticator getPublickeyAuthenticator() {
+        return resolveEffectiveProvider(PublickeyAuthenticator.class, publickeyAuthenticator, getFactoryManager().getPublickeyAuthenticator());
+    }
+
+    @Override
+    public void setPublickeyAuthenticator(PublickeyAuthenticator publickeyAuthenticator) {
+        this.publickeyAuthenticator = publickeyAuthenticator; // OK if null - inherit from parent
+    }
+
+    @Override
+    public KeyboardInteractiveAuthenticator getKeyboardInteractiveAuthenticator() {
+        return resolveEffectiveProvider(KeyboardInteractiveAuthenticator.class, interactiveAuthenticator, getFactoryManager().getKeyboardInteractiveAuthenticator());
+    }
+
+    @Override
+    public void setKeyboardInteractiveAuthenticator(KeyboardInteractiveAuthenticator interactiveAuthenticator) {
+        this.interactiveAuthenticator = interactiveAuthenticator; // OK if null - inherit from parent
+    }
+
+    @Override
+    public GSSAuthenticator getGSSAuthenticator() {
+        return resolveEffectiveProvider(GSSAuthenticator.class, gssAuthenticator, getFactoryManager().getGSSAuthenticator());
+    }
+
+    @Override
+    public void setGSSAuthenticator(GSSAuthenticator gssAuthenticator) {
+        this.gssAuthenticator = gssAuthenticator; // OK if null - inherit from parent
+    }
+
+    @Override
+    public List<NamedFactory<UserAuth>> getUserAuthFactories() {
+        return resolveEffectiveFactories(UserAuth.class, userAuthFactories, getFactoryManager().getUserAuthFactories());
+    }
+
+    @Override
+    public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
+        this.userAuthFactories = userAuthFactories; // OK if null/empty - inherit from parent
+    }
+
+    @Override
+    protected void checkKeys() {
+        // nothing
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e9dd7f47/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 a53d2ba..bf85c97 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
@@ -22,12 +22,13 @@ package org.apache.sshd.server.session;
 import java.security.KeyPair;
 
 import org.apache.sshd.common.session.Session;
+import org.apache.sshd.server.ServerAuthenticationManager;
 import org.apache.sshd.server.ServerFactoryManager;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public interface ServerSession extends Session {
+public interface ServerSession extends Session, ServerAuthenticationManager {
     /**
      * @return The {@link ServerFactoryManager} for this session
      */