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

[1/3] [SSHD-235][SSHD-287] Refactor client side authentication API, support partial authentication

Updated Branches:
  refs/heads/master d5b96d9fe -> 8f7dff123


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
new file mode 100644
index 0000000..389fe39
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
@@ -0,0 +1,189 @@
+/*
+ * 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.client.session;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.auth.deprecated.UserAuth;
+import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.DefaultAuthFuture;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client side <code>ssh-auth</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientUserAuthServiceOld implements Service {
+
+    /** Our logger */
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * When !authFuture.isDone() the current authentication
+     */
+    private UserAuth userAuth;
+
+    /**
+     * The AuthFuture that is being used by the current auth request.  This encodes the state.
+     * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
+     */
+    private volatile AuthFuture authFuture;
+
+    protected final ClientSessionImpl session;
+    protected final Object lock;
+
+    public ClientUserAuthServiceOld(Session s) {
+        if (!(s instanceof ClientSessionImpl)) {
+            throw new IllegalStateException("Client side service used on server side");
+        }
+        session = (ClientSessionImpl) s;
+        lock = session.getLock();
+        // Maintain the current auth status in the authFuture.
+        authFuture = new DefaultAuthFuture(lock);
+    }
+
+    public ClientSessionImpl getSession() {
+        return session;
+    }
+
+    public void start() {
+        synchronized (lock) {
+            log.debug("accepted");
+            // kick start the authentication process by failing the pending auth.
+            this.authFuture.setAuthed(false);
+        }
+    }
+
+    public void process(byte cmd, Buffer buffer) throws Exception {
+        if (this.authFuture.isSuccess()) {
+            throw new IllegalStateException("UserAuth message delivered to authenticated client");
+        } else if (this.authFuture.isDone()) {
+            log.debug("Ignoring random message");
+            // 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: {}", welcome);
+            UserInteraction ui = session.getFactoryManager().getUserInteraction();
+            if (ui != null) {
+                ui.welcome(welcome);
+            }
+        } else {
+            buffer.rpos(buffer.rpos() - 1);
+            processUserAuth(buffer);
+        }
+    }
+
+    /**
+     * return true if/when ready for auth; false if never ready.
+     * @return server is ready and waiting for auth
+     */
+    private boolean readyForAuth(UserAuth userAuth) {
+        // isDone indicates that the last auth finished and a new one can commence.
+        while (!this.authFuture.isDone()) {
+            log.debug("waiting to send authentication");
+            try {
+                this.authFuture.await();
+            } catch (InterruptedException e) {
+                log.debug("Unexpected interrupt", e);
+                throw new RuntimeException(e);
+            }
+        }
+        if (this.authFuture.isSuccess()) {
+            log.debug("already authenticated");
+            throw new IllegalStateException("Already authenticated");
+        }
+        if (this.authFuture.getException() != null) {
+            log.debug("probably closed", this.authFuture.getException());
+            return false;
+        }
+        if (!this.authFuture.isFailure()) {
+            log.debug("unexpected state");
+            throw new IllegalStateException("Unexpected authentication state");
+        }
+        if (this.userAuth != null) {
+            log.debug("authentication already in progress");
+            throw new IllegalStateException("Authentication already in progress?");
+        }
+        // Set up the next round of authentication.  Each round gets a new lock.
+        this.userAuth = userAuth;
+        // The new future !isDone() - i.e., in progress blocking out other waits.
+        this.authFuture = new DefaultAuthFuture(lock);
+        log.debug("ready to try authentication with new lock");
+        return true;
+    }
+
+    /**
+     * execute one step in user authentication.
+     * @param buffer
+     * @throws java.io.IOException
+     */
+    private void processUserAuth(Buffer buffer) throws IOException {
+        log.debug("processing {}", userAuth);
+        switch (userAuth.next(buffer)) {
+            case Success:
+                log.debug("succeeded with {}", userAuth);
+                session.setAuthenticated();
+                session.switchToNextService();
+                // Will wake up anyone sitting in waitFor
+                authFuture.setAuthed(true);
+                break;
+            case Failure:
+                log.debug("failed with {}", userAuth);
+                this.userAuth = null;
+                // Will wake up anyone sitting in waitFor
+                this.authFuture.setAuthed(false);
+                break;
+            case Continued:
+                // Will wake up anyone sitting in waitFor
+                log.debug("continuing with {}", userAuth);
+                break;
+        }
+    }
+
+    public CloseFuture close(boolean immediately) {
+        if (!authFuture.isDone()) {
+            authFuture.setException(new SshException("Session is closed"));
+        }
+        CloseFuture future = new DefaultCloseFuture(lock);
+        future.setClosed();
+        return future;
+    }
+
+    public AuthFuture auth(UserAuth userAuth) throws IOException {
+        log.debug("Trying authentication with {}", userAuth);
+        synchronized (lock) {
+            if (readyForAuth(userAuth)) {
+                processUserAuth(null);
+            }
+            return authFuture;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/common/KeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/KeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/KeyPairProvider.java
index 63b87c2..70a379e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/KeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/KeyPairProvider.java
@@ -54,6 +54,13 @@ public interface KeyPairProvider {
     String ECDSA_SHA2_NISTP521 = "ecdsa-sha2-nistp521";
 
     /**
+     * Load available keys.
+     *
+     * @return an array of available keys, never <code>null</code>
+     */
+    KeyPair[] loadKeys();
+
+    /**
      * Load a key of the specified type which can be "ssh-rsa", "ssh-dss", or
      * "ecdsa-sha2-nistp{256,384,521}". If there is no key of this type, return
      * <code>null</code>

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/common/SshConstants.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/SshConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/SshConstants.java
index bb0cf45..0cb5f3e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/SshConstants.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/SshConstants.java
@@ -53,10 +53,14 @@ public interface SshConstants {
     static final byte SSH_MSG_USERAUTH_FAILURE=               51;
     static final byte SSH_MSG_USERAUTH_SUCCESS=               52;
     static final byte SSH_MSG_USERAUTH_BANNER=                53;
+
     static final byte SSH_MSG_USERAUTH_INFO_REQUEST=          60;
     static final byte SSH_MSG_USERAUTH_INFO_RESPONSE=         61;
+
     static final byte SSH_MSG_USERAUTH_PK_OK=                 60;
 
+    static final byte SSH_MSG_USERAUTH_PASSWD_CHANGEREQ=      60;
+
     static final byte SSH_MSG_USERAUTH_GSSAPI_MIC=            66;
 
     static final byte SSH_MSG_GLOBAL_REQUEST=                 80;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java
index 0337e87..bf6650b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java
@@ -19,10 +19,6 @@
 package org.apache.sshd.common.keyprovider;
 
 import java.security.KeyPair;
-import java.security.interfaces.DSAKey;
-import java.security.interfaces.ECKey;
-import java.security.interfaces.RSAKey;
-import java.security.spec.ECParameterSpec;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,6 +26,8 @@ import org.apache.sshd.common.KeyPairProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sshd.common.util.KeyUtils.getKeyType;
+
 /**
  * TODO Add javadoc
  *
@@ -69,30 +67,5 @@ public abstract class AbstractKeyPairProvider implements KeyPairProvider {
         return sb.toString();
     }
 
-    protected String getKeyType(KeyPair kp) {
-        Object key = kp.getPrivate() != null ? kp.getPrivate() : kp.getPublic();
-        if (key instanceof DSAKey) {
-            return SSH_DSS;
-        } else if (key instanceof RSAKey) {
-            return SSH_RSA;
-        } else if (key instanceof ECKey) {
-            ECKey ecKey = (ECKey) key;
-            ECParameterSpec ecSpec = ecKey.getParams();
-            /*
-             * TODO make this more robust by checking the actual parameters instead of
-             * just the field size.
-             */
-            switch (ecSpec.getCurve().getField().getFieldSize()) {
-            case 256:
-                return ECDSA_SHA2_NISTP256;
-            case 384:
-                return ECDSA_SHA2_NISTP384;
-            case 521:
-                return ECDSA_SHA2_NISTP521;
-            }
-        }
-        return null;
-    }
-
-    protected abstract KeyPair[] loadKeys();
+    public abstract KeyPair[] loadKeys();
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 cc050e2..e6d1639 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
@@ -255,9 +255,12 @@ public abstract class AbstractSession implements Session {
         return authed;
     }
 
-    public void setAuthenticated(String username) throws IOException {
-        this.authed = true;
+    public void setUsername(String username) {
         this.username = username;
+    }
+
+    public void setAuthenticated() throws IOException {
+        this.authed = true;
         sendEvent(SessionListener.Event.Authenticated);
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
index cd9fd65..123d594 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/KeyUtils.java
@@ -18,8 +18,15 @@
  */
 package org.apache.sshd.common.util;
 
+import java.security.Key;
+import java.security.KeyPair;
 import java.security.PublicKey;
+import java.security.interfaces.DSAKey;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.spec.ECParameterSpec;
 
+import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.digest.MD5;
 
 /**
@@ -49,6 +56,46 @@ public class KeyUtils {
         }
     }
 
+    /**
+     * Retrieve the key type
+     *
+     * @param kp a key pair
+     * @return the key type
+     */
+    public static String getKeyType(KeyPair kp) {
+        return getKeyType(kp.getPrivate() != null ? kp.getPrivate() : kp.getPublic());
+    }
+
+    /**
+     * Retrieve the key type
+     *
+     * @param key a public or private key
+     * @return the key type
+     */
+    public static String getKeyType(Key key) {
+        if (key instanceof DSAKey) {
+            return KeyPairProvider.SSH_DSS;
+        } else if (key instanceof RSAKey) {
+            return KeyPairProvider.SSH_RSA;
+        } else if (key instanceof ECKey) {
+            ECKey ecKey = (ECKey) key;
+            ECParameterSpec ecSpec = ecKey.getParams();
+            /*
+             * TODO make this more robust by checking the actual parameters instead of
+             * just the field size.
+             */
+            switch (ecSpec.getCurve().getField().getFieldSize()) {
+                case 256:
+                    return KeyPairProvider.ECDSA_SHA2_NISTP256;
+                case 384:
+                    return KeyPairProvider.ECDSA_SHA2_NISTP384;
+                case 521:
+                    return KeyPairProvider.ECDSA_SHA2_NISTP521;
+            }
+        }
+        return null;
+    }
+
     private KeyUtils() {
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 94cfdba..e0e7152 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
@@ -44,9 +44,6 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
 
     @Override
     protected Boolean doAuth(Buffer buffer, boolean init) throws Exception {
-        if (!"ssh-connection".equals(service)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Unsupported service '" + service + "'");
-        }
         if (init) {
             // Prompt for password
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_INFO_REQUEST, 0);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 50754ac..6219c3a 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
@@ -46,9 +46,6 @@ public class UserAuthPassword extends AbstractUserAuth {
         if (!init) {
             throw new IllegalStateException();
         }
-        if (!"ssh-connection".equals(service)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Unsupported service '" + service + "'");
-        }
         boolean newPassword = buffer.getBoolean();
         if (newPassword) {
             throw new IllegalStateException("Password changes are not supported");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 0e4de86..3f4971a 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
@@ -50,9 +50,6 @@ public class UserAuthPublicKey extends AbstractUserAuth {
         if (!init) {
             throw new IllegalStateException();
         }
-        if (!"ssh-connection".equals(service)) {
-            throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Unsupported service '" + service + "'");
-        }
         boolean hasSig = buffer.getBoolean();
         String alg = buffer.getString();
 
@@ -88,7 +85,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
             buf.putString(session.getKex().getH());
             buf.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
             buf.putString(username);
-            buf.putString("ssh-connection");
+            buf.putString(service);
             buf.putString("publickey");
             buf.putByte((byte) 1);
             buf.putString(keyAlg);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index 49612e2..5f7dd19 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -129,6 +129,7 @@ public class ServerUserAuthService implements Service {
                                 + username + ", " + service + ")");
                 return;
             }
+            // TODO: verify that the service is supported
             this.authMethod = method;
             if (nbAuthRequests++ > maxAuthRequests) {
                 session.disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Too many authentication failures");
@@ -197,7 +198,8 @@ public class ServerUserAuthService implements Service {
 
                 buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_SUCCESS, 0);
                 session.writePacket(buffer);
-                session.setAuthenticated(username);
+                session.setUsername(username);
+                session.setAuthenticated();
                 session.startService(authService);
                 session.resetIdleTimeout();
                 log.info("Session {}@{} authenticated", username, session.getIoSession().getRemoteAddress());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
index 6fc48e5..6e0de51 100644
--- a/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
@@ -364,6 +364,26 @@ public class ClientTest {
     }
 
     @Test
+    public void testPublicKeyAuthNew() throws Exception {
+        SshClient client = SshClient.setUpDefaultClient();
+        client.start();
+        ClientSession session = client.connect("smx", "localhost", port).await().getSession();
+        KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+        session.addPublicKeyIdentity(pair);
+        session.auth().verify();
+    }
+
+    @Test
+    public void testPasswordAuthNew() throws Exception {
+        SshClient client = SshClient.setUpDefaultClient();
+        client.start();
+        ClientSession session = client.connect("smx", "localhost", port).await().getSession();
+        KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
+        session.addPasswordIdentity("smx");
+        session.auth().verify();
+    }
+
+    @Test
     public void testClientDisconnect() throws Exception {
         TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
         try


[2/3] git commit: [SSHD-235][SSHD-287] Refactor client side authentication API, support partial authentication

Posted by gn...@apache.org.
[SSHD-235][SSHD-287] Refactor client side authentication API, support partial authentication

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

Branch: refs/heads/master
Commit: 0824b93bdde6782ecb2669fed808c3137db74af8
Parents: d5b96d9
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Jan 31 11:50:32 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Jan 31 11:51:25 2014 +0100

----------------------------------------------------------------------
 .../java/org/apache/sshd/ClientSession.java     |  10 +
 .../main/java/org/apache/sshd/SshClient.java    |  33 ++-
 .../sshd/client/ClientFactoryManager.java       |  17 ++
 .../java/org/apache/sshd/client/UserAuth.java   |  13 +-
 .../sshd/client/auth/AbstractUserAuth.java      |  50 ----
 .../apache/sshd/client/auth/UserAuthAgent.java  | 117 ----------
 .../auth/UserAuthKeyboardInteractive.java       | 142 +++++++-----
 .../sshd/client/auth/UserAuthPassword.java      |  85 ++++---
 .../sshd/client/auth/UserAuthPublicKey.java     | 203 ++++++++++++-----
 .../auth/deprecated/AbstractUserAuth.java       |  43 ++++
 .../sshd/client/auth/deprecated/UserAuth.java   |  40 ++++
 .../client/auth/deprecated/UserAuthAgent.java   | 117 ++++++++++
 .../deprecated/UserAuthKeyboardInteractive.java | 111 +++++++++
 .../auth/deprecated/UserAuthPassword.java       |  72 ++++++
 .../auth/deprecated/UserAuthPublicKey.java      | 107 +++++++++
 .../apache/sshd/client/future/AuthFuture.java   |   8 +
 .../sshd/client/future/DefaultAuthFuture.java   |  13 ++
 .../sshd/client/session/ClientSessionImpl.java  |  41 +++-
 .../client/session/ClientUserAuthService.java   | 156 ++++---------
 .../session/ClientUserAuthServiceNew.java       | 227 +++++++++++++++++++
 .../session/ClientUserAuthServiceOld.java       | 189 +++++++++++++++
 .../org/apache/sshd/common/KeyPairProvider.java |   7 +
 .../org/apache/sshd/common/SshConstants.java    |   4 +
 .../keyprovider/AbstractKeyPairProvider.java    |  33 +--
 .../sshd/common/session/AbstractSession.java    |   7 +-
 .../org/apache/sshd/common/util/KeyUtils.java   |  47 ++++
 .../auth/UserAuthKeyboardInteractive.java       |   3 -
 .../sshd/server/auth/UserAuthPassword.java      |   3 -
 .../sshd/server/auth/UserAuthPublicKey.java     |   5 +-
 .../server/session/ServerUserAuthService.java   |   4 +-
 .../test/java/org/apache/sshd/ClientTest.java   |  20 ++
 31 files changed, 1435 insertions(+), 492 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/ClientSession.java b/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
index 96068cb..15b0005 100644
--- a/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
@@ -31,6 +31,7 @@ import org.apache.sshd.client.channel.ChannelShell;
 import org.apache.sshd.client.channel.ChannelSubsystem;
 import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.future.CloseFuture;
 
@@ -62,24 +63,33 @@ public interface ClientSession extends Session {
     int WAIT_AUTH =   0x0004;
     int AUTHED =      0x0008;
 
+    void addPasswordIdentity(String password);
+    void addPublicKeyIdentity(KeyPair key);
+
+    AuthFuture auth() throws IOException;
+
     /**
      * Authenticate the session with the given username using an ssh agent.
      */
+    @Deprecated
     AuthFuture authAgent(String username) throws IOException;
 
     /**
      * Authenticate the session with the given username and password.
      */
+    @Deprecated
     AuthFuture authPassword(String username, String password) throws IOException;
 
     /**
      * Authenticate the session with the given username and password.
      */
+    @Deprecated
     AuthFuture authInteractive(String username, String password) throws IOException;
 
     /**
      * Authenticate the session with the given username and public key.
      */
+    @Deprecated
     AuthFuture authPublicKey(String username, KeyPair key) throws IOException;
 
     /**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index 8d4e169..f0858eb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -38,7 +38,11 @@ import java.util.concurrent.Executors;
 import org.apache.sshd.client.ClientFactoryManager;
 import org.apache.sshd.client.ServerKeyVerifier;
 import org.apache.sshd.client.SessionFactory;
+import org.apache.sshd.client.UserAuth;
 import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
+import org.apache.sshd.client.auth.UserAuthPassword;
+import org.apache.sshd.client.auth.UserAuthPublicKey;
 import org.apache.sshd.client.channel.ChannelShell;
 import org.apache.sshd.client.future.AuthFuture;
 import org.apache.sshd.client.future.ConnectFuture;
@@ -149,6 +153,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
     protected SessionFactory sessionFactory;
     protected UserInteraction userInteraction;
     protected Factory<IoConnector> connectorFactory;
+    protected List<NamedFactory<UserAuth>> userAuthFactories;
 
     private ServerKeyVerifier serverKeyVerifier;
 
@@ -179,6 +184,14 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         this.userInteraction = userInteraction;
     }
 
+    public List<NamedFactory<UserAuth>> getUserAuthFactories() {
+        return userAuthFactories;
+    }
+
+    public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
+        this.userAuthFactories = userAuthFactories;
+    }
+
     protected void checkConfig() {
         if (getKeyExchangeFactories() == null) {
             throw new IllegalArgumentException("KeyExchangeFactories not set");
@@ -224,6 +237,13 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                     new ClientConnectionService.Factory()
             ));
         }
+        if (getUserAuthFactories() == null) {
+            setUserAuthFactories(Arrays.asList(
+                    new UserAuthPublicKey.Factory(),
+                    new UserAuthKeyboardInteractive.Factory(),
+                    new UserAuthPassword.Factory()
+            ));
+        }
     }
 
     public void start() {
@@ -244,17 +264,27 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         }
     }
 
+    @Deprecated
     public ConnectFuture connect(String host, int port) throws IOException {
+        return connect(null, host, port);
+    }
+
+    public ConnectFuture connect(String username, String host, int port) throws IOException {
         assert host != null;
         assert port >= 0;
         if (connector == null) {
             throw new IllegalStateException("SshClient not started. Please call start() method before connecting to a server");
         }
         SocketAddress address = new InetSocketAddress(host, port);
-        return connect(address);
+        return connect(username, address);
     }
 
+    @Deprecated
     public ConnectFuture connect(SocketAddress address) {
+        return connect(null, address);
+    }
+
+    public ConnectFuture connect(final String username, SocketAddress address) {
         assert address != null;
         if (connector == null) {
             throw new IllegalStateException("SshClient not started. Please call start() method before connecting to a server");
@@ -268,6 +298,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                     connectFuture.setException(future.getException());
                 } else {
                     ClientSessionImpl session = (ClientSessionImpl) AbstractSession.getSession(future.getSession());
+                    session.setUsername(username);
                     connectFuture.setSession(session);
                 }
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
index 8375ffa..595dc93 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
@@ -18,7 +18,10 @@
  */
 package org.apache.sshd.client;
 
+import java.util.List;
+
 import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.TcpipForwarderFactory;
 
 /**
@@ -40,6 +43,12 @@ public interface ClientFactoryManager extends FactoryManager {
     public static final String HEARTBEAT_REQUEST = "heartbeat-request";
 
     /**
+     * Ordered comma separated list of authentications methods.
+     * Authentications methods accepted by the server will be tried in the given order.
+     */
+    public static final String PREFERRED_AUTHS = "preferred-auths";
+
+    /**
      * Retrieve the server key verifier to be used to check the key when connecting
      * to an ssh server.
      *
@@ -61,4 +70,12 @@ public interface ClientFactoryManager extends FactoryManager {
      * @return A <code>UserInteraction</code> or <code>null</code>
      */
     UserInteraction getUserInteraction();
+
+    /**
+     * Retrieve a list of UserAuth factories.
+     *
+     * @return a list of named <code>UserAuth</code> factories, never <code>null</code>
+     */
+    List<NamedFactory<UserAuth>> getUserAuthFactories();
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/UserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/UserAuth.java b/sshd-core/src/main/java/org/apache/sshd/client/UserAuth.java
index f508509..a2e8cb7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/UserAuth.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/UserAuth.java
@@ -18,8 +18,9 @@
  */
 package org.apache.sshd.client;
 
-import java.io.IOException;
+import java.util.List;
 
+import org.apache.sshd.ClientSession;
 import org.apache.sshd.common.util.Buffer;
 
 /**
@@ -29,14 +30,10 @@ import org.apache.sshd.common.util.Buffer;
  */
 public interface UserAuth {
 
-    enum Result {
-        Success,
-        Failure,
-        Continued
-    }
+    void init(ClientSession session, String service, List<Object> identities) throws Exception;
 
-    String getUsername();
+    boolean process(Buffer buffer) throws Exception;
 
-    Result next(Buffer buffer) throws IOException;
+    void destroy();
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/AbstractUserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/AbstractUserAuth.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/AbstractUserAuth.java
deleted file mode 100644
index 5f9a346..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/AbstractUserAuth.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.client.auth;
-
-import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.session.ClientSessionImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public abstract class AbstractUserAuth implements UserAuth {
-
-    protected final Logger log = LoggerFactory.getLogger(this.getClass());
-
-    protected final ClientSessionImpl session;
-    protected final String service;
-    protected final String username;
-
-    protected AbstractUserAuth(ClientSessionImpl session, String service, String username) {
-        this.session = session;
-        this.username = username;
-        this.service = service;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
deleted file mode 100644
index 7ceac6a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.client.auth;
-
-import java.io.IOException;
-import java.security.PublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Iterator;
-
-import org.apache.sshd.agent.SshAgent;
-import org.apache.sshd.client.session.ClientSessionImpl;
-import org.apache.sshd.common.KeyPairProvider;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.util.Buffer;
-
-/**
- * Authentication delegating to an SSH agent
- */
-public class UserAuthAgent extends AbstractUserAuth {
-
-    private final SshAgent agent;
-    private final Iterator<SshAgent.Pair<PublicKey, String>> keys;
-
-    public UserAuthAgent(ClientSessionImpl session, String service, String username) throws IOException {
-        super(session, service, username);
-        if (session.getFactoryManager().getAgentFactory() == null) {
-            throw new IllegalStateException("No ssh agent factory has been configured");
-        }
-        this.agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
-        this.keys = agent.getIdentities().iterator();
-    }
-
-    protected void sendNextKey(PublicKey key) throws IOException {
-        try {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
-            Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
-            int pos1 = buffer.wpos() - 1;
-            buffer.putString(username);
-            buffer.putString(service);
-            buffer.putString("publickey");
-            buffer.putByte((byte) 1);
-            buffer.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-            int pos2 = buffer.wpos();
-            buffer.putPublicKey(key);
-
-
-            Buffer bs = new Buffer();
-            bs.putString(session.getKex().getH());
-            bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
-            bs.putString(username);
-            bs.putString(service);
-            bs.putString("publickey");
-            bs.putByte((byte) 1);
-            bs.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-            bs.putPublicKey(key);
-
-            Buffer bs2 = new Buffer();
-            bs2.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-            bs2.putBytes(agent.sign(key, bs.getCompactData()));
-            buffer.putBytes(bs2.array(), bs2.rpos(), bs2.available());
-
-            session.writePacket(buffer);
-        } catch (IOException e) {
-            throw e;
-        } catch (Exception e) {
-            throw (IOException) new IOException("Error performing public key authentication").initCause(e);
-        }
-    }
-
-    public Result next(Buffer buffer) throws IOException {
-        if (buffer == null) {
-            if (keys.hasNext()) {
-                sendNextKey(keys.next().getFirst());
-                return Result.Continued;
-            } else {
-                agent.close();
-                return Result.Failure;
-            }
-        } else {
-            byte cmd = buffer.getByte();
-            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
-                agent.close();
-                return Result.Success;
-            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
-                log.info("Received SSH_MSG_USERAUTH_FAILURE");
-                if (keys.hasNext()) {
-                    sendNextKey(keys.next().getFirst());
-                    return Result.Continued;
-                } else {
-                    agent.close();
-                    return Result.Failure;
-                }
-            } else {
-                // TODO: check packets
-                log.info("Received unknown packet: {}", cmd);
-                return Result.Continued;
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
index 374ac36..d25b133 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
@@ -18,94 +18,110 @@
  */
 package org.apache.sshd.client.auth;
 
-import java.io.IOException;
+import java.util.List;
 
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.client.UserAuth;
 import org.apache.sshd.client.UserInteraction;
-import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.ClientUserAuthServiceNew;
+import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.session.AbstractSession;
 import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import static org.apache.sshd.common.SshConstants.*;
+import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_INFO_REQUEST;
+import static org.apache.sshd.common.SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE;
 
 /**
- * Userauth with keyboard-interactive method.
+ * TODO Add javadoc
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @author <a href="mailto:j.kapitza@schwarze-allianz.de">Jens Kapitza</a>
  */
-public class UserAuthKeyboardInteractive extends AbstractUserAuth {
+public class UserAuthKeyboardInteractive implements UserAuth {
 
-    private final String password;
+    public static class Factory implements NamedFactory<UserAuth> {
+        public String getName() {
+            return "keyboard-interactive";
+        }
+        public UserAuth create() {
+            return new UserAuthKeyboardInteractive();
+        }
+    }
 
-    public UserAuthKeyboardInteractive(ClientSessionImpl session, String service, String username, String password) {
-        super(session, service, username);
-        this.password = password;
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    private ClientSession session;
+    private String service;
+    private String password;
+
+    public void init(ClientSession session, String service, List<Object> identities) throws Exception {
+        this.session = session;
+        this.service = service;
+        for (Object o : identities) {
+            if (o instanceof String) {
+                password = (String) o;
+                break;
+            }
+        }
     }
 
-    public Result next(Buffer buffer) throws IOException {
+    public boolean process(Buffer buffer) throws Exception {
         if (buffer == null) {
             log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
-            buffer.putString(username);
+            buffer.putString(session.getUsername());
             buffer.putString(service);
             buffer.putString("keyboard-interactive");
             buffer.putString("");
             buffer.putString("");
             session.writePacket(buffer);
-            return Result.Continued;
-        } else {
-            byte cmd = buffer.getByte();
-            switch (cmd) {
-                case SSH_MSG_USERAUTH_INFO_REQUEST:
-                    log.info("Received SSH_MSG_USERAUTH_INFO_REQUEST");
-                    String name = buffer.getString();
-                    String instruction = buffer.getString();
-                    String language_tag = buffer.getString();
-                    log.info("Received {} {} {}", new Object[]{name, instruction, language_tag});
-                    int num = buffer.getInt();
-                    String[] prompt = new String[num];
-                    boolean[] echo = new boolean[num];
-                    for (int i = 0; i < num; i++) {
-                        prompt[i] = buffer.getString();
-                        echo[i] = (buffer.getByte() != 0);
-                    }
-                    log.info("Promt: {}", prompt);
-                    log.info("Echo: {}", echo);
+            return true;
+        }
+        byte cmd = buffer.getByte();
+        if (cmd == SSH_MSG_USERAUTH_INFO_REQUEST) {
+            log.info("Received SSH_MSG_USERAUTH_INFO_REQUEST");
+            String name = buffer.getString();
+            String instruction = buffer.getString();
+            String language_tag = buffer.getString();
+            log.info("Received {} {} {}", new Object[]{name, instruction, language_tag});
+            int num = buffer.getInt();
+            String[] prompt = new String[num];
+            boolean[] echo = new boolean[num];
+            for (int i = 0; i < num; i++) {
+                prompt[i] = buffer.getString();
+                echo[i] = (buffer.getByte() != 0);
+            }
+            log.info("Promt: {}", prompt);
+            log.info("Echo: {}", echo);
 
-                    String[] rep = null;
-                    if (num == 0) {
-                        rep = new String[0];
-                    } else if (num == 1 && password != null && !echo[0] && prompt[0].toLowerCase().startsWith("password:")) {
-                        rep = new String[] { password };
-                    } else {
-                        UserInteraction ui = session.getFactoryManager().getUserInteraction();
-                        if (ui != null) {
-                            String dest = username + "@" + session.getIoSession().getRemoteAddress().toString();
-                            rep = ui.interactive(dest, name, instruction, prompt, echo);
-                        }
-                    }
-                    if (rep == null) {
-                        return Result.Failure;
-                    }
+            String[] rep = null;
+            if (num == 0) {
+                rep = new String[0];
+            } else if (num == 1 && password != null && !echo[0] && prompt[0].toLowerCase().startsWith("password:")) {
+                rep = new String[] { password };
+            } else {
+                UserInteraction ui = session.getFactoryManager().getUserInteraction();
+                if (ui != null) {
+                    String dest = session.getUsername() + "@" + ((AbstractSession) session).getIoSession().getRemoteAddress().toString();
+                    rep = ui.interactive(dest, name, instruction, prompt, echo);
+                }
+            }
+            if (rep == null) {
+                return false;
+            }
 
-                    buffer = session.createBuffer(SSH_MSG_USERAUTH_INFO_RESPONSE, 0);
-                    buffer.putInt(rep.length);
-                    for (String r : rep) {
-                        buffer.putString(r);
-                    }
-                    session.writePacket(buffer);
-                    return Result.Continued;
-                case SSH_MSG_USERAUTH_SUCCESS:
-                    log.info("Received SSH_MSG_USERAUTH_SUCCESS");
-                    return Result.Success;
-                case SSH_MSG_USERAUTH_FAILURE:
-                    log.info("Received SSH_MSG_USERAUTH_FAILURE");
-                    return Result.Failure;
-                default:
-                    log.info("Received unknown packet {}", cmd);
-                    return Result.Continued;
+            buffer = session.createBuffer(SSH_MSG_USERAUTH_INFO_RESPONSE, 0);
+            buffer.putInt(rep.length);
+            for (String r : rep) {
+                buffer.putString(r);
             }
+            session.writePacket(buffer);
+            return true;
         }
+        throw new IllegalStateException("Received unknown packet");
     }
 
-}
\ No newline at end of file
+    public void destroy() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
index 900e36c..114bdcd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
@@ -18,10 +18,14 @@
  */
 package org.apache.sshd.client.auth;
 
-import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
+import org.apache.sshd.ClientSession;
 import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.ClientUserAuthServiceNew;
+import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.util.Buffer;
 import org.slf4j.Logger;
@@ -32,42 +36,63 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class UserAuthPassword extends AbstractUserAuth {
+public class UserAuthPassword implements UserAuth {
 
-    protected final Logger log = LoggerFactory.getLogger(getClass());
+    public static class Factory implements NamedFactory<UserAuth> {
+        public String getName() {
+            return "password";
+        }
+        public UserAuth create() {
+            return new UserAuthPassword();
+        }
+    }
 
-    private final String password;
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    private ClientSession session;
+    private String service;
+    private Iterator<String> passwords;
+    private String current;
 
-    public UserAuthPassword(ClientSessionImpl session, String service, String username, String password) {
-        super(session, service, username);
-        this.password = password;
+    public void init(ClientSession session, String service, List<Object> identities) throws Exception {
+        this.session = session;
+        this.service = service;
+        List<String> pwds = new ArrayList<String>();
+        for (Object o : identities) {
+            if (o instanceof String) {
+                pwds.add((String) o);
+            }
+        }
+        this.passwords = pwds.iterator();
     }
 
-    public Result next(Buffer buffer) throws IOException {
+    public boolean process(Buffer buffer) throws Exception {
+        // Send next key
         if (buffer == null) {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
-            buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
-            buffer.putString(username);
-            buffer.putString(service);
-            buffer.putString("password");
-            buffer.putByte((byte) 0);
-            buffer.putString(password);
-            session.writePacket(buffer);
-            return Result.Continued;
-        } else {
-            byte cmd = buffer.getByte();
-            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
-                return Result.Success;
-            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
-                log.info("Received SSH_MSG_USERAUTH_FAILURE");
-                return Result.Failure;
-            } else {
-                log.info("Received unkown packet {}", cmd);
-                // TODO: check packets
-                return Result.Continued;
+            if (passwords.hasNext()) {
+                current = passwords.next();
+                log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+                buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+                buffer.putString(session.getUsername());
+                buffer.putString(service);
+                buffer.putString("password");
+                buffer.putByte((byte) 0);
+                buffer.putString(current);
+                session.writePacket(buffer);
+                return true;
             }
+            return false;
         }
+        byte cmd = buffer.getByte();
+        if (cmd == SshConstants.SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) {
+            String prompt = buffer.getString();
+            String lang = buffer.getString();
+            // TODO: prompt user for password change
+            log.warn("Password change requested, but not supported");
+            return false;
+        }
+        throw new IllegalStateException("Received unknown packet");
     }
 
+    public void destroy() {
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
index 9804d2f..a24c7b5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
@@ -18,89 +18,182 @@
  */
 package org.apache.sshd.client.auth;
 
-import java.io.IOException;
 import java.security.KeyPair;
-import java.security.interfaces.RSAPublicKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.agent.SshAgent;
+import org.apache.sshd.agent.SshAgentFactory;
 import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.ClientUserAuthServiceNew;
+import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Signature;
 import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.session.AbstractSession;
 import org.apache.sshd.common.util.Buffer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sshd.common.util.KeyUtils.getKeyType;
+
 /**
  * TODO Add javadoc
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class UserAuthPublicKey extends AbstractUserAuth {
+public class UserAuthPublicKey implements UserAuth {
 
-    protected final Logger log = LoggerFactory.getLogger(getClass());
+    public static class Factory implements NamedFactory<UserAuth> {
+        public String getName() {
+            return "publickey";
+        }
+        public UserAuth create() {
+            return new UserAuthPublicKey();
+        }
+    }
 
-    private final KeyPair key;
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+    private ClientSession session;
+    private String service;
+    private SshAgent agent;
+    private Iterator<PublicKeyIdentity> keys;
+    private PublicKeyIdentity current;
 
-    public UserAuthPublicKey(ClientSessionImpl session, String service, String username, KeyPair key) {
-        super(session, service, username);
-        this.key = key;
+    public void init(ClientSession session, String service, List<Object> identities) throws Exception {
+        this.session = session;
+        this.service = service;
+        List<PublicKeyIdentity> ids = new ArrayList<PublicKeyIdentity>();
+        for (Object o : identities) {
+            if (o instanceof KeyPair) {
+                ids.add(new KeyPairIdentity(session.getFactoryManager(), (KeyPair) o));
+            }
+        }
+        KeyPairProvider provider = session.getFactoryManager().getKeyPairProvider();
+        if (provider != null) {
+            for (KeyPair pair : provider.loadKeys()) {
+                ids.add(new KeyPairIdentity(session.getFactoryManager(), pair));
+            }
+        }
+        SshAgentFactory factory = session.getFactoryManager().getAgentFactory();
+        if (factory != null) {
+            this.agent = factory.createClient(session.getFactoryManager());
+            for (SshAgent.Pair<PublicKey, String> pair : agent.getIdentities()) {
+                ids.add(new KeyAgentIdentity(agent, pair.getFirst()));
+            }
+        } else {
+            this.agent = null;
+        }
+        this.keys = ids.iterator();
     }
 
-    public Result next(Buffer buffer) throws IOException {
+    public boolean process(Buffer buffer) throws Exception {
+        // Send next key
         if (buffer == null) {
-            try {
+            if (keys.hasNext()) {
+                current = keys.next();
+                PublicKey key = current.getPublicKey();
+                String algo = getKeyType(key);
                 log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
                 buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
-                int pos1 = buffer.wpos() - 1;
-                buffer.putString(username);
+                buffer.putString(session.getUsername());
                 buffer.putString(service);
                 buffer.putString("publickey");
-                buffer.putByte((byte) 1);
-                buffer.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-                int pos2 = buffer.wpos();
-                buffer.putPublicKey(key.getPublic());
-
-                Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), (key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-                verif.init(key.getPublic(), key.getPrivate());
-
-                Buffer bs = new Buffer();
-                bs.putString(session.getKex().getH());
-                bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
-                bs.putString(username);
-                bs.putString(service);
-                bs.putString("publickey");
-                bs.putByte((byte) 1);
-                bs.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-                bs.putPublicKey(key.getPublic());
-                verif.update(bs.array(), bs.rpos(), bs.available());
-
-                bs = new Buffer();
-                bs.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
-                bs.putBytes(verif.sign());
-                buffer.putBytes(bs.array(), bs.rpos(), bs.available());
-
+                buffer.putByte((byte) 0);
+                buffer.putString(algo);
+                buffer.putPublicKey(key);
                 session.writePacket(buffer);
-                return Result.Continued;
-            } catch (IOException e) {
-                throw e;
-            } catch (Exception e) {
-                throw (IOException) new IOException("Error performing public key authentication").initCause(e);
-            }
-        } else {
-            byte cmd = buffer.getByte();
-            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
-                return Result.Success;
-            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
-                log.info("Received SSH_MSG_USERAUTH_FAILURE");
-                return Result.Failure;
-            } else {
-                log.info("Received unknown packet {}", cmd);
-                // TODO: check packets
-                return Result.Continued;
+                return true;
             }
+            return false;
+        }
+        byte cmd = buffer.getByte();
+        if (cmd == SshConstants.SSH_MSG_USERAUTH_PK_OK) {
+            PublicKey key = current.getPublicKey();
+            String algo = getKeyType(key);
+            log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+            buffer.putString(session.getUsername());
+            buffer.putString(service);
+            buffer.putString("publickey");
+            buffer.putByte((byte) 1);
+            buffer.putString(algo);
+            buffer.putPublicKey(key);
+
+            Buffer bs = new Buffer();
+            bs.putString(((AbstractSession) session).getKex().getH());
+            bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
+            bs.putString(session.getUsername());
+            bs.putString(service);
+            bs.putString("publickey");
+            bs.putByte((byte) 1);
+            bs.putString(algo);
+            bs.putPublicKey(key);
+            byte[] sig = current.sign(bs.getCompactData());
+
+            bs = new Buffer();
+            bs.putString(algo);
+            bs.putBytes(sig);
+            buffer.putBytes(bs.array(), bs.rpos(), bs.available());
+
+            session.writePacket(buffer);
+            return true;
+        }
+
+        throw new IllegalStateException("Received unknown packet");
+    }
+
+    public void destroy() {
+        if (agent != null) {
+            agent.close();
+        }
+    }
+
+    interface PublicKeyIdentity {
+        PublicKey getPublicKey();
+        byte[] sign(byte[] data) throws Exception;
+    }
+
+    static class KeyAgentIdentity implements PublicKeyIdentity {
+        private final SshAgent agent;
+        private final PublicKey key;
+
+        KeyAgentIdentity(SshAgent agent, PublicKey key) {
+            this.agent = agent;
+            this.key = key;
+        }
+
+        public PublicKey getPublicKey() {
+            return key;
+        }
+
+        public byte[] sign(byte[] data) throws Exception {
+            return agent.sign(key, data);
+        }
+    }
+
+    static class KeyPairIdentity implements PublicKeyIdentity {
+        private final KeyPair pair;
+        private final FactoryManager manager;
+
+        KeyPairIdentity(FactoryManager manager, KeyPair pair) {
+            this.manager = manager;
+            this.pair = pair;
+        }
+
+        public PublicKey getPublicKey() {
+            return pair.getPublic();
+        }
+
+        public byte[] sign(byte[] data) throws Exception {
+            Signature verif = NamedFactory.Utils.create(manager.getSignatureFactories(), getKeyType(pair));
+            verif.init(pair.getPublic(), pair.getPrivate());
+            verif.update(data, 0, data.length);
+            return verif.sign();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/AbstractUserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/AbstractUserAuth.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/AbstractUserAuth.java
new file mode 100644
index 0000000..d847283
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/AbstractUserAuth.java
@@ -0,0 +1,43 @@
+/*
+ * 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.client.auth.deprecated;
+
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public abstract class AbstractUserAuth implements UserAuth {
+
+    protected final Logger log = LoggerFactory.getLogger(this.getClass());
+
+    protected final ClientSessionImpl session;
+    protected final String service;
+
+    protected AbstractUserAuth(ClientSessionImpl session, String service) {
+        this.session = session;
+        this.service = service;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuth.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuth.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuth.java
new file mode 100644
index 0000000..af354ee
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuth.java
@@ -0,0 +1,40 @@
+/*
+ * 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.client.auth.deprecated;
+
+import java.io.IOException;
+
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface UserAuth {
+
+    enum Result {
+        Success,
+        Failure,
+        Continued
+    }
+
+    Result next(Buffer buffer) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
new file mode 100644
index 0000000..7ef6234
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
@@ -0,0 +1,117 @@
+/*
+ * 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.client.auth.deprecated;
+
+import java.io.IOException;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Iterator;
+
+import org.apache.sshd.agent.SshAgent;
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * Authentication delegating to an SSH agent
+ */
+public class UserAuthAgent extends AbstractUserAuth {
+
+    private final SshAgent agent;
+    private final Iterator<SshAgent.Pair<PublicKey, String>> keys;
+
+    public UserAuthAgent(ClientSessionImpl session, String service) throws IOException {
+        super(session, service);
+        if (session.getFactoryManager().getAgentFactory() == null) {
+            throw new IllegalStateException("No ssh agent factory has been configured");
+        }
+        this.agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
+        this.keys = agent.getIdentities().iterator();
+    }
+
+    protected void sendNextKey(PublicKey key) throws IOException {
+        try {
+            log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+            Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+            int pos1 = buffer.wpos() - 1;
+            buffer.putString(session.getUsername());
+            buffer.putString(service);
+            buffer.putString("publickey");
+            buffer.putByte((byte) 1);
+            buffer.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+            int pos2 = buffer.wpos();
+            buffer.putPublicKey(key);
+
+
+            Buffer bs = new Buffer();
+            bs.putString(session.getKex().getH());
+            bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
+            bs.putString(session.getUsername());
+            bs.putString(service);
+            bs.putString("publickey");
+            bs.putByte((byte) 1);
+            bs.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+            bs.putPublicKey(key);
+
+            Buffer bs2 = new Buffer();
+            bs2.putString((key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+            bs2.putBytes(agent.sign(key, bs.getCompactData()));
+            buffer.putBytes(bs2.array(), bs2.rpos(), bs2.available());
+
+            session.writePacket(buffer);
+        } catch (IOException e) {
+            throw e;
+        } catch (Exception e) {
+            throw (IOException) new IOException("Error performing public key authentication").initCause(e);
+        }
+    }
+
+    public Result next(Buffer buffer) throws IOException {
+        if (buffer == null) {
+            if (keys.hasNext()) {
+                sendNextKey(keys.next().getFirst());
+                return Result.Continued;
+            } else {
+                agent.close();
+                return Result.Failure;
+            }
+        } else {
+            byte cmd = buffer.getByte();
+            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
+                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                agent.close();
+                return Result.Success;
+            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
+                log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                if (keys.hasNext()) {
+                    sendNextKey(keys.next().getFirst());
+                    return Result.Continued;
+                } else {
+                    agent.close();
+                    return Result.Failure;
+                }
+            } else {
+                // TODO: check packets
+                log.info("Received unknown packet: {}", cmd);
+                return Result.Continued;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
new file mode 100644
index 0000000..cd9df71
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
@@ -0,0 +1,111 @@
+/*
+ * 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.client.auth.deprecated;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.util.Buffer;
+
+import static org.apache.sshd.common.SshConstants.*;
+
+/**
+ * Userauth with keyboard-interactive method.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @author <a href="mailto:j.kapitza@schwarze-allianz.de">Jens Kapitza</a>
+ */
+public class UserAuthKeyboardInteractive extends AbstractUserAuth {
+
+    private final String password;
+
+    public UserAuthKeyboardInteractive(ClientSessionImpl session, String service, String password) {
+        super(session, service);
+        this.password = password;
+    }
+
+    public Result next(Buffer buffer) throws IOException {
+        if (buffer == null) {
+            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+            buffer.putString(session.getUsername());
+            buffer.putString(service);
+            buffer.putString("keyboard-interactive");
+            buffer.putString("");
+            buffer.putString("");
+            session.writePacket(buffer);
+            return Result.Continued;
+        } else {
+            byte cmd = buffer.getByte();
+            switch (cmd) {
+                case SSH_MSG_USERAUTH_INFO_REQUEST:
+                    log.info("Received SSH_MSG_USERAUTH_INFO_REQUEST");
+                    String name = buffer.getString();
+                    String instruction = buffer.getString();
+                    String language_tag = buffer.getString();
+                    log.info("Received {} {} {}", new Object[]{name, instruction, language_tag});
+                    int num = buffer.getInt();
+                    String[] prompt = new String[num];
+                    boolean[] echo = new boolean[num];
+                    for (int i = 0; i < num; i++) {
+                        prompt[i] = buffer.getString();
+                        echo[i] = (buffer.getByte() != 0);
+                    }
+                    log.info("Promt: {}", prompt);
+                    log.info("Echo: {}", echo);
+
+                    String[] rep = null;
+                    if (num == 0) {
+                        rep = new String[0];
+                    } else if (num == 1 && password != null && !echo[0] && prompt[0].toLowerCase().startsWith("password:")) {
+                        rep = new String[] { password };
+                    } else {
+                        UserInteraction ui = session.getFactoryManager().getUserInteraction();
+                        if (ui != null) {
+                            String dest = session.getUsername() + "@" + session.getIoSession().getRemoteAddress().toString();
+                            rep = ui.interactive(dest, name, instruction, prompt, echo);
+                        }
+                    }
+                    if (rep == null) {
+                        return Result.Failure;
+                    }
+
+                    buffer = session.createBuffer(SSH_MSG_USERAUTH_INFO_RESPONSE, 0);
+                    buffer.putInt(rep.length);
+                    for (String r : rep) {
+                        buffer.putString(r);
+                    }
+                    session.writePacket(buffer);
+                    return Result.Continued;
+                case SSH_MSG_USERAUTH_SUCCESS:
+                    log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                    return Result.Success;
+                case SSH_MSG_USERAUTH_FAILURE:
+                    log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                    return Result.Failure;
+                default:
+                    log.info("Received unknown packet {}", cmd);
+                    return Result.Continued;
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
new file mode 100644
index 0000000..d2b5c9f
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
@@ -0,0 +1,72 @@
+/*
+ * 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.client.auth.deprecated;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class UserAuthPassword extends AbstractUserAuth {
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    private final String password;
+
+    public UserAuthPassword(ClientSessionImpl session, String service, String password) {
+        super(session, service);
+        this.password = password;
+    }
+
+    public Result next(Buffer buffer) throws IOException {
+        if (buffer == null) {
+            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+            buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+            buffer.putString(session.getUsername());
+            buffer.putString(service);
+            buffer.putString("password");
+            buffer.putByte((byte) 0);
+            buffer.putString(password);
+            session.writePacket(buffer);
+            return Result.Continued;
+        } else {
+            byte cmd = buffer.getByte();
+            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
+                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                return Result.Success;
+            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
+                log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                return Result.Failure;
+            } else {
+                log.info("Received unkown packet {}", cmd);
+                // TODO: check packets
+                return Result.Continued;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
new file mode 100644
index 0000000..9535066
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.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.client.auth.deprecated;
+
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.interfaces.RSAPublicKey;
+
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class UserAuthPublicKey extends AbstractUserAuth {
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    private final KeyPair key;
+
+    public UserAuthPublicKey(ClientSessionImpl session, String service, KeyPair key) {
+        super(session, service);
+        this.key = key;
+    }
+
+    public Result next(Buffer buffer) throws IOException {
+        if (buffer == null) {
+            try {
+                log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+                buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+                int pos1 = buffer.wpos() - 1;
+                buffer.putString(session.getUsername());
+                buffer.putString(service);
+                buffer.putString("publickey");
+                buffer.putByte((byte) 1);
+                buffer.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+                int pos2 = buffer.wpos();
+                buffer.putPublicKey(key.getPublic());
+
+                // TODO: support elliptic keys
+                Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), (key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+                verif.init(key.getPublic(), key.getPrivate());
+
+                Buffer bs = new Buffer();
+                bs.putString(session.getKex().getH());
+                bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
+                bs.putString(session.getUsername());
+                bs.putString(service);
+                bs.putString("publickey");
+                bs.putByte((byte) 1);
+                bs.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+                bs.putPublicKey(key.getPublic());
+                verif.update(bs.array(), bs.rpos(), bs.available());
+
+                bs = new Buffer();
+                bs.putString((key.getPublic() instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS);
+                bs.putBytes(verif.sign());
+                buffer.putBytes(bs.array(), bs.rpos(), bs.available());
+
+                session.writePacket(buffer);
+                return Result.Continued;
+            } catch (IOException e) {
+                throw e;
+            } catch (Exception e) {
+                throw (IOException) new IOException("Error performing public key authentication").initCause(e);
+            }
+        } else {
+            byte cmd = buffer.getByte();
+            if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
+                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                return Result.Success;
+            } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
+                log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                return Result.Failure;
+            } else {
+                log.info("Received unknown packet {}", cmd);
+                // TODO: check packets
+                return Result.Continued;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/future/AuthFuture.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/future/AuthFuture.java b/sshd-core/src/main/java/org/apache/sshd/client/future/AuthFuture.java
index 6b8bdb8..081474a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/future/AuthFuture.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/future/AuthFuture.java
@@ -18,6 +18,7 @@
  */
 package org.apache.sshd.client.future;
 
+import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.SshFuture;
 
 /**
@@ -28,6 +29,13 @@ import org.apache.sshd.common.future.SshFuture;
 public interface AuthFuture extends SshFuture<AuthFuture> {
 
     /**
+     * Wait and verify that the authentication succeeded.
+     *
+     * @throws SshException if the authentication failed for any reason
+     */
+    void verify() throws SshException;
+
+    /**
      * Returns the cause of the connection failure.
      *
      * @return <tt>null</tt> if the connect operation is not finished yet,

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 528bed3..176eadc 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
@@ -18,6 +18,7 @@
  */
 package org.apache.sshd.client.future;
 
+import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.DefaultSshFuture;
 
 
@@ -32,6 +33,18 @@ public class DefaultAuthFuture extends DefaultSshFuture<AuthFuture> implements A
         super(lock);
     }
 
+    public void verify() throws SshException {
+        try {
+            await();
+        }
+        catch (InterruptedException e) {
+            throw new SshException("Authentication interrupted", e);
+        }
+        if (!isSuccess()) {
+            throw new SshException("Authentication failed", getException());
+        }
+    }
+
     public Throwable getException() {
         Object v = getValue();
         if (v instanceof Throwable) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 720ce4b..bed1e36 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
@@ -21,6 +21,7 @@ package org.apache.sshd.client.session;
 import java.io.IOException;
 import java.net.SocketAddress;
 import java.security.KeyPair;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -31,11 +32,11 @@ import org.apache.sshd.client.ClientFactoryManager;
 import org.apache.sshd.client.ScpClient;
 import org.apache.sshd.client.ServerKeyVerifier;
 import org.apache.sshd.client.SftpClient;
-import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.auth.UserAuthAgent;
-import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
-import org.apache.sshd.client.auth.UserAuthPassword;
-import org.apache.sshd.client.auth.UserAuthPublicKey;
+import org.apache.sshd.client.auth.deprecated.UserAuth;
+import org.apache.sshd.client.auth.deprecated.UserAuthAgent;
+import org.apache.sshd.client.auth.deprecated.UserAuthKeyboardInteractive;
+import org.apache.sshd.client.auth.deprecated.UserAuthPassword;
+import org.apache.sshd.client.auth.deprecated.UserAuthPublicKey;
 import org.apache.sshd.client.channel.ChannelDirectTcpip;
 import org.apache.sshd.client.channel.ChannelExec;
 import org.apache.sshd.client.channel.ChannelShell;
@@ -105,23 +106,43 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
         return (ClientFactoryManager) factoryManager;
     }
 
+    private final List<Object> identities = new ArrayList<Object>();
+
+    public void addPasswordIdentity(String password) {
+        identities.add(password);
+    }
+
+    public void addPublicKeyIdentity(KeyPair key) {
+        identities.add(key);
+    }
+
+    public AuthFuture auth() throws IOException {
+        if (username == null) {
+            throw new IllegalStateException("No username specified when the session was created");
+        }
+        synchronized (lock) {
+            return authFuture = getUserAuthService().auth(identities, nextServiceName());
+        }
+    }
+
     public AuthFuture authAgent(String user) throws IOException {
-        return tryAuth(new UserAuthAgent(this, nextServiceName(), user));
+        return tryAuth(user, new UserAuthAgent(this, nextServiceName()));
     }
 
     public AuthFuture authPassword(String user, String password) throws IOException {
-        return tryAuth(new UserAuthPassword(this, nextServiceName(), user, password));
+        return tryAuth(user, new UserAuthPassword(this, nextServiceName(), password));
     }
 
     public AuthFuture authInteractive(String user, String password) throws IOException {
-        return tryAuth(new UserAuthKeyboardInteractive(this, nextServiceName(), user, password));
+        return tryAuth(user, new UserAuthKeyboardInteractive(this, nextServiceName(), password));
    }
 
     public AuthFuture authPublicKey(String user, KeyPair key) throws IOException {
-        return tryAuth(new UserAuthPublicKey(this, nextServiceName(), user, key));
+        return tryAuth(user, new UserAuthPublicKey(this, nextServiceName(), key));
     }
 
-    private AuthFuture tryAuth(UserAuth auth) throws IOException {
+    private AuthFuture tryAuth(String user, UserAuth auth) throws IOException {
+        this.username = user;
         synchronized (lock) {
             return authFuture = getUserAuthService().auth(auth);
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/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 9612b9b..d5c0b27 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
@@ -19,16 +19,13 @@
 package org.apache.sshd.client.session;
 
 import java.io.IOException;
+import java.util.List;
 
-import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.auth.deprecated.UserAuth;
 import org.apache.sshd.client.future.AuthFuture;
-import org.apache.sshd.client.future.DefaultAuthFuture;
 import org.apache.sshd.common.Service;
 import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.Session;
-import org.apache.sshd.common.SshConstants;
-import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultCloseFuture;
 import org.apache.sshd.common.util.Buffer;
@@ -56,28 +53,16 @@ public class ClientUserAuthService implements Service {
     /** Our logger */
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
-    /**
-     * When !authFuture.isDone() the current authentication
-     */
-    private UserAuth userAuth;
-
-    /**
-     * The AuthFuture that is being used by the current auth request.  This encodes the state.
-     * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
-     */
-    private volatile AuthFuture authFuture;
-
     protected final ClientSessionImpl session;
-    protected final Object lock;
+    protected ClientUserAuthServiceNew delegateNew;
+    protected ClientUserAuthServiceOld delegateOld;
+    protected boolean started;
 
     public ClientUserAuthService(Session s) {
         if (!(s instanceof ClientSessionImpl)) {
             throw new IllegalStateException("Client side service used on server side");
         }
         session = (ClientSessionImpl) s;
-        lock = session.getLock();
-        // Maintain the current auth status in the authFuture.
-        authFuture = new DefaultAuthFuture(lock);
     }
 
     public ClientSessionImpl getSession() {
@@ -85,117 +70,58 @@ public class ClientUserAuthService implements Service {
     }
 
     public void start() {
-        synchronized (lock) {
-            log.debug("accepted");
-            // kick start the authentication process by failing the pending auth.
-            this.authFuture.setAuthed(false);
+        if (delegateNew != null) {
+            delegateNew.start();
+        } else if (delegateOld != null) {
+            delegateOld.start();
         }
+        started = true;
     }
 
     public void process(byte cmd, Buffer buffer) throws Exception {
-        if (this.authFuture.isSuccess()) {
-            throw new IllegalStateException("UserAuth message delivered to authenticated client");
-        } else if (this.authFuture.isDone()) {
-            log.debug("Ignoring random message");
-            // 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: {}", welcome);
-            UserInteraction ui = session.getFactoryManager().getUserInteraction();
-            if (ui != null) {
-                ui.welcome(welcome);
-            }
+        if (delegateNew != null) {
+            delegateNew.process(cmd, buffer);
+        } else if (delegateOld != null) {
+            delegateOld.process(cmd, buffer);
         } else {
-            buffer.rpos(buffer.rpos() - 1);
-            processUserAuth(buffer);
+            throw new IllegalStateException();
         }
     }
 
-    /**
-     * return true if/when ready for auth; false if never ready.
-     * @return server is ready and waiting for auth
-     */
-    private boolean readyForAuth(UserAuth userAuth) {
-        // isDone indicates that the last auth finished and a new one can commence.
-        while (!this.authFuture.isDone()) {
-            log.debug("waiting to send authentication");
-            try {
-                this.authFuture.await();
-            } catch (InterruptedException e) {
-                log.debug("Unexpected interrupt", e);
-                throw new RuntimeException(e);
-            }
-        }
-        if (this.authFuture.isSuccess()) {
-            log.debug("already authenticated");
-            throw new IllegalStateException("Already authenticated");
-        }
-        if (this.authFuture.getException() != null) {
-            log.debug("probably closed", this.authFuture.getException());
-            return false;
-        }
-        if (!this.authFuture.isFailure()) {
-            log.debug("unexpected state");
-            throw new IllegalStateException("Unexpected authentication state");
-        }
-        if (this.userAuth != null) {
-            log.debug("authentication already in progress");
-            throw new IllegalStateException("Authentication already in progress?");
+    public CloseFuture close(boolean immediately) {
+        if (delegateNew != null) {
+            return delegateNew.close(immediately);
+        } else if (delegateOld != null) {
+            return delegateOld.close(immediately);
+        } else {
+            CloseFuture future = new DefaultCloseFuture(session.getLock());
+            future.setClosed();
+            return future;
         }
-        // Set up the next round of authentication.  Each round gets a new lock.
-        this.userAuth = userAuth;
-        // The new future !isDone() - i.e., in progress blocking out other waits.
-        this.authFuture = new DefaultAuthFuture(lock);
-        log.debug("ready to try authentication with new lock");
-        return true;
     }
 
-    /**
-     * execute one step in user authentication.
-     * @param buffer
-     * @throws IOException
-     */
-    private void processUserAuth(Buffer buffer) throws IOException {
-        log.debug("processing {}", userAuth);
-        switch (userAuth.next(buffer)) {
-            case Success:
-                log.debug("succeeded with {}", userAuth);
-                session.setAuthenticated(userAuth.getUsername());
-                session.switchToNextService();
-                // Will wake up anyone sitting in waitFor
-                authFuture.setAuthed(true);
-                break;
-            case Failure:
-                log.debug("failed with {}", userAuth);
-                this.userAuth = null;
-                // Will wake up anyone sitting in waitFor
-                this.authFuture.setAuthed(false);
-                break;
-            case Continued:
-                // Will wake up anyone sitting in waitFor
-                log.debug("continuing with {}", userAuth);
-                break;
+    public AuthFuture auth(UserAuth userAuth) throws IOException {
+        if (delegateNew != null) {
+            throw new IllegalStateException();
         }
-    }
-
-    public CloseFuture close(boolean immediately) {
-        if (!authFuture.isDone()) {
-            authFuture.setException(new SshException("Session is closed"));
+        if (delegateOld == null) {
+            delegateOld = new ClientUserAuthServiceOld(session);
+            if (started) {
+                delegateOld.start();
+            }
         }
-        CloseFuture future = new DefaultCloseFuture(lock);
-        future.setClosed();
-        return future;
+        return delegateOld.auth(userAuth);
     }
 
-    public AuthFuture auth(UserAuth userAuth) throws IOException {
-        log.debug("Trying authentication with {}", userAuth);
-        synchronized (lock) {
-            if (readyForAuth(userAuth)) {
-                processUserAuth(null);
-            }
-            return authFuture;
+    public AuthFuture auth(List<Object> identities, String service) throws IOException {
+        if (delegateOld != null || delegateNew != null) {
+            throw new IllegalStateException();
+        }
+        delegateNew = new ClientUserAuthServiceNew(session);
+        if (started) {
+            delegateNew.start();
         }
+        return delegateNew.auth(identities, service);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/0824b93b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
new file mode 100644
index 0000000..96d8208
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
@@ -0,0 +1,227 @@
+/*
+ * 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.client.session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.UserAuth;
+import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
+import org.apache.sshd.client.auth.UserAuthPassword;
+import org.apache.sshd.client.auth.UserAuthPublicKey;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.DefaultAuthFuture;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.sshd.common.util.KeyUtils.getKeyType;
+
+/**
+ * Client side <code>ssh-auth</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientUserAuthServiceNew implements Service {
+
+    /** Our logger */
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * The AuthFuture that is being used by the current auth request.  This encodes the state.
+     * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
+     */
+    private final AuthFuture authFuture;
+
+    protected final ClientSessionImpl session;
+
+    private List<Object> identities;
+    private String service;
+
+    List<NamedFactory<UserAuth>> authFactories;
+    List<String> clientMethods;
+    List<String> serverMethods;
+    UserAuth userAuth;
+
+    public ClientUserAuthServiceNew(Session s) {
+        if (!(s instanceof ClientSessionImpl)) {
+            throw new IllegalStateException("Client side service used on server side");
+        }
+        session = (ClientSessionImpl) s;
+        authFuture = new DefaultAuthFuture(session.getLock());
+        authFactories = session.getFactoryManager().getUserAuthFactories();
+        clientMethods = new ArrayList<String>();
+        String prefs = session.getFactoryManager().getProperties().get(ClientFactoryManager.PREFERRED_AUTHS);
+        if (prefs != null) {
+            for (String pref : prefs.split(",")) {
+                if (NamedFactory.Utils.get(authFactories, pref) != null) {
+                    clientMethods.add(pref);
+                }
+            }
+        } else {
+            for (NamedFactory<UserAuth> factory : authFactories) {
+                clientMethods.add(factory.getName());
+            }
+        }
+    }
+
+    public ClientSessionImpl getSession() {
+        return session;
+    }
+
+    public void start() {
+    }
+
+    public AuthFuture auth(List<Object> identities, String service) throws IOException {
+        log.debug("Start authentication");
+        this.identities = new ArrayList<Object>(identities);
+        this.service = service;
+
+        log.debug("Send SSH_MSG_USERAUTH_REQUEST for none");
+        Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
+        buffer.putString(session.getUsername());
+        buffer.putString(service);
+        buffer.putString("none");
+        session.writePacket(buffer);
+
+        return authFuture;
+    }
+
+    public void process(byte cmd, Buffer buffer) throws Exception {
+        if (this.authFuture.isSuccess()) {
+            throw new IllegalStateException("UserAuth message delivered to authenticated client");
+        } else if (this.authFuture.isDone()) {
+            log.debug("Ignoring random message");
+            // 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: {}", welcome);
+            UserInteraction ui = session.getFactoryManager().getUserInteraction();
+            if (ui != null) {
+                ui.welcome(welcome);
+            }
+        } else {
+            buffer.rpos(buffer.rpos() - 1);
+            processUserAuth(buffer);
+        }
+    }
+
+    int currentMethod;
+
+    /**
+     * execute one step in user authentication.
+     * @param buffer
+     * @throws java.io.IOException
+     */
+    private void processUserAuth(Buffer buffer) throws Exception {
+        byte cmd = buffer.getByte();
+        if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
+            log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+            log.debug("Succeeded with {}", userAuth);
+            if (userAuth != null) {
+                userAuth.destroy();
+                userAuth = null;
+            }
+            session.setAuthenticated();
+            session.switchToNextService();
+            // Will wake up anyone sitting in waitFor
+            authFuture.setAuthed(true);
+            return;
+        }
+        if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
+            log.info("Received SSH_MSG_USERAUTH_FAILURE");
+            String mths = buffer.getString();
+            boolean partial = buffer.getBoolean();
+            if (partial || serverMethods == null) {
+                serverMethods = Arrays.asList(mths.split(","));
+                if (log.isDebugEnabled()) {
+                    StringBuilder sb = new StringBuilder("Authentications that can continue: ");
+                    for (int i = 0; i < serverMethods.size(); i++) {
+                        if (i > 0) {
+                            sb.append(", ");
+                        }
+                        sb.append(serverMethods.get(i));
+                    }
+                    log.debug(sb.toString());
+                }
+                if (userAuth != null) {
+                    userAuth.destroy();
+                    userAuth = null;
+                }
+            }
+            tryNext();
+            return;
+        }
+        if (userAuth == null) {
+            throw new IllegalStateException("Received unknown packet");
+        }
+        buffer.rpos(buffer.rpos() - 1);
+        if (!userAuth.process(buffer)) {
+            tryNext();
+        }
+    }
+
+    private void tryNext() throws Exception {
+        // Loop until we find something to try
+        while (true) {
+            if (userAuth == null) {
+                currentMethod = 0;
+            } else if (!userAuth.process(null)) {
+                userAuth.destroy();
+                currentMethod++;
+            } else {
+                return;
+            }
+            while (currentMethod < clientMethods.size() && !serverMethods.contains(clientMethods.get(currentMethod))) {
+                currentMethod++;
+            }
+            if (currentMethod >= clientMethods.size()) {
+                // Failure
+                authFuture.setAuthed(false);
+                return;
+            }
+            String method = clientMethods.get(currentMethod);
+            userAuth = NamedFactory.Utils.create(authFactories, method);
+            assert userAuth != null;
+            userAuth.init(session, service, identities);
+        }
+    }
+
+    public CloseFuture close(boolean immediately) {
+        if (!authFuture.isDone()) {
+            authFuture.setException(new SshException("Session is closed"));
+        }
+        CloseFuture future = new DefaultCloseFuture(session.getLock());
+        future.setClosed();
+        return future;
+    }
+
+}


[3/3] git commit: Trim down log a bit

Posted by gn...@apache.org.
Trim down log a bit

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

Branch: refs/heads/master
Commit: 8f7dff123f4dcaa8f35b024432f2c9a76069be46
Parents: 0824b93
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Jan 31 11:51:54 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Jan 31 11:51:54 2014 +0100

----------------------------------------------------------------------
 .../sshd/client/auth/UserAuthKeyboardInteractive.java |  8 ++++----
 .../org/apache/sshd/client/auth/UserAuthPassword.java |  2 +-
 .../apache/sshd/client/auth/UserAuthPublicKey.java    |  4 ++--
 .../sshd/client/auth/deprecated/UserAuthAgent.java    |  2 +-
 .../auth/deprecated/UserAuthKeyboardInteractive.java  | 14 +++++++-------
 .../sshd/client/auth/deprecated/UserAuthPassword.java |  8 ++++----
 .../client/auth/deprecated/UserAuthPublicKey.java     |  8 ++++----
 .../sshd/client/channel/AbstractClientChannel.java    |  2 +-
 .../org/apache/sshd/client/channel/ChannelExec.java   |  2 +-
 .../org/apache/sshd/client/channel/ChannelShell.java  |  8 ++++----
 .../apache/sshd/client/channel/ChannelSubsystem.java  |  2 +-
 .../apache/sshd/client/session/ClientSessionImpl.java |  4 ++--
 .../org/apache/sshd/server/session/ServerSession.java |  2 +-
 13 files changed, 33 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
index d25b133..db74e73 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthKeyboardInteractive.java
@@ -68,7 +68,7 @@ public class UserAuthKeyboardInteractive implements UserAuth {
 
     public boolean process(Buffer buffer) throws Exception {
         if (buffer == null) {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+            log.debug("Send SSH_MSG_USERAUTH_REQUEST for password");
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
             buffer.putString(session.getUsername());
             buffer.putString(service);
@@ -80,7 +80,7 @@ public class UserAuthKeyboardInteractive implements UserAuth {
         }
         byte cmd = buffer.getByte();
         if (cmd == SSH_MSG_USERAUTH_INFO_REQUEST) {
-            log.info("Received SSH_MSG_USERAUTH_INFO_REQUEST");
+            log.debug("Received SSH_MSG_USERAUTH_INFO_REQUEST");
             String name = buffer.getString();
             String instruction = buffer.getString();
             String language_tag = buffer.getString();
@@ -92,8 +92,8 @@ public class UserAuthKeyboardInteractive implements UserAuth {
                 prompt[i] = buffer.getString();
                 echo[i] = (buffer.getByte() != 0);
             }
-            log.info("Promt: {}", prompt);
-            log.info("Echo: {}", echo);
+            log.debug("Promt: {}", prompt);
+            log.debug("Echo: {}", echo);
 
             String[] rep = null;
             if (num == 0) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
index 114bdcd..10266ac 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPassword.java
@@ -70,7 +70,7 @@ public class UserAuthPassword implements UserAuth {
         if (buffer == null) {
             if (passwords.hasNext()) {
                 current = passwords.next();
-                log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+                log.debug("Send SSH_MSG_USERAUTH_REQUEST for password");
                 buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
                 buffer.putString(session.getUsername());
                 buffer.putString(service);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
index a24c7b5..5ec1eeb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthPublicKey.java
@@ -98,7 +98,7 @@ public class UserAuthPublicKey implements UserAuth {
                 current = keys.next();
                 PublicKey key = current.getPublicKey();
                 String algo = getKeyType(key);
-                log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+                log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
                 buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
                 buffer.putString(session.getUsername());
                 buffer.putString(service);
@@ -115,7 +115,7 @@ public class UserAuthPublicKey implements UserAuth {
         if (cmd == SshConstants.SSH_MSG_USERAUTH_PK_OK) {
             PublicKey key = current.getPublicKey();
             String algo = getKeyType(key);
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+            log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
             buffer.putString(session.getUsername());
             buffer.putString(service);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
index 7ef6234..9879d72 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthAgent.java
@@ -48,7 +48,7 @@ public class UserAuthAgent extends AbstractUserAuth {
 
     protected void sendNextKey(PublicKey key) throws IOException {
         try {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+            log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
             Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
             int pos1 = buffer.wpos() - 1;
             buffer.putString(session.getUsername());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
index cd9df71..44b3cd5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthKeyboardInteractive.java
@@ -44,7 +44,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
 
     public Result next(Buffer buffer) throws IOException {
         if (buffer == null) {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+            log.debug("Send SSH_MSG_USERAUTH_REQUEST for password");
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
             buffer.putString(session.getUsername());
             buffer.putString(service);
@@ -57,7 +57,7 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
             byte cmd = buffer.getByte();
             switch (cmd) {
                 case SSH_MSG_USERAUTH_INFO_REQUEST:
-                    log.info("Received SSH_MSG_USERAUTH_INFO_REQUEST");
+                    log.debug("Received SSH_MSG_USERAUTH_INFO_REQUEST");
                     String name = buffer.getString();
                     String instruction = buffer.getString();
                     String language_tag = buffer.getString();
@@ -69,8 +69,8 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
                         prompt[i] = buffer.getString();
                         echo[i] = (buffer.getByte() != 0);
                     }
-                    log.info("Promt: {}", prompt);
-                    log.info("Echo: {}", echo);
+                    log.debug("Promt: {}", prompt);
+                    log.debug("Echo: {}", echo);
 
                     String[] rep = null;
                     if (num == 0) {
@@ -96,13 +96,13 @@ public class UserAuthKeyboardInteractive extends AbstractUserAuth {
                     session.writePacket(buffer);
                     return Result.Continued;
                 case SSH_MSG_USERAUTH_SUCCESS:
-                    log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                    log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                     return Result.Success;
                 case SSH_MSG_USERAUTH_FAILURE:
-                    log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                    log.debug("Received SSH_MSG_USERAUTH_FAILURE");
                     return Result.Failure;
                 default:
-                    log.info("Received unknown packet {}", cmd);
+                    log.debug("Received unknown packet {}", cmd);
                     return Result.Continued;
             }
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
index d2b5c9f..182e6b3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPassword.java
@@ -44,7 +44,7 @@ public class UserAuthPassword extends AbstractUserAuth {
 
     public Result next(Buffer buffer) throws IOException {
         if (buffer == null) {
-            log.info("Send SSH_MSG_USERAUTH_REQUEST for password");
+            log.debug("Send SSH_MSG_USERAUTH_REQUEST for password");
             buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
             buffer.putString(session.getUsername());
             buffer.putString(service);
@@ -56,13 +56,13 @@ public class UserAuthPassword extends AbstractUserAuth {
         } else {
             byte cmd = buffer.getByte();
             if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                 return Result.Success;
             } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
-                log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                log.debug("Received SSH_MSG_USERAUTH_FAILURE");
                 return Result.Failure;
             } else {
-                log.info("Received unkown packet {}", cmd);
+                log.debug("Received unkown packet {}", cmd);
                 // TODO: check packets
                 return Result.Continued;
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
index 9535066..bbbb337 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/deprecated/UserAuthPublicKey.java
@@ -50,7 +50,7 @@ public class UserAuthPublicKey extends AbstractUserAuth {
     public Result next(Buffer buffer) throws IOException {
         if (buffer == null) {
             try {
-                log.info("Send SSH_MSG_USERAUTH_REQUEST for publickey");
+                log.debug("Send SSH_MSG_USERAUTH_REQUEST for publickey");
                 buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, 0);
                 int pos1 = buffer.wpos() - 1;
                 buffer.putString(session.getUsername());
@@ -91,13 +91,13 @@ public class UserAuthPublicKey extends AbstractUserAuth {
         } else {
             byte cmd = buffer.getByte();
             if (cmd == SshConstants.SSH_MSG_USERAUTH_SUCCESS) {
-                log.info("Received SSH_MSG_USERAUTH_SUCCESS");
+                log.debug("Received SSH_MSG_USERAUTH_SUCCESS");
                 return Result.Success;
             } if (cmd == SshConstants.SSH_MSG_USERAUTH_FAILURE) {
-                log.info("Received SSH_MSG_USERAUTH_FAILURE");
+                log.debug("Received SSH_MSG_USERAUTH_FAILURE");
                 return Result.Failure;
             } else {
-                log.info("Received unknown packet {}", cmd);
+                log.debug("Received unknown packet {}", cmd);
                 // TODO: check packets
                 return Result.Continued;
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
index 43c38d4..a721da2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
@@ -187,7 +187,7 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
             throw new SshException("Session has been closed");
         }
         openFuture = new DefaultOpenFuture(lock);
-        log.info("Send SSH_MSG_CHANNEL_OPEN on channel {}", id);
+        log.debug("Send SSH_MSG_CHANNEL_OPEN on channel {}", id);
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN, 0);
         buffer.putString(type);
         buffer.putInt(id);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
index 0708b2d..943b631 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelExec.java
@@ -40,7 +40,7 @@ public class ChannelExec extends ChannelSession {
     }
 
     protected void doOpen() throws IOException {
-        log.info("Send SSH_MSG_CHANNEL_REQUEST exec");
+        log.debug("Send SSH_MSG_CHANNEL_REQUEST exec");
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
         buffer.putInt(recipient);
         buffer.putString("exec");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
index f05a9af..1404a08 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
@@ -152,7 +152,7 @@ public class ChannelShell extends ChannelSession {
         Buffer buffer;
 
         if (agentForwarding) {
-            log.info("Send agent forwarding request");
+            log.debug("Send agent forwarding request");
             buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
             buffer.putInt(recipient);
             buffer.putString("auth-agent-req@openssh.com");
@@ -161,7 +161,7 @@ public class ChannelShell extends ChannelSession {
         }
 
         if (usePty) {
-            log.info("Send SSH_MSG_CHANNEL_REQUEST pty-req");
+            log.debug("Send SSH_MSG_CHANNEL_REQUEST pty-req");
             buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
             buffer.putInt(recipient);
             buffer.putString("pty-req");
@@ -182,7 +182,7 @@ public class ChannelShell extends ChannelSession {
         }
 
         if (!env.isEmpty()) {
-            log.info("Send SSH_MSG_CHANNEL_REQUEST env");
+            log.debug("Send SSH_MSG_CHANNEL_REQUEST env");
             for (Map.Entry<String, String> entry : env.entrySet()) {
                 buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
                 buffer.putInt(recipient);
@@ -194,7 +194,7 @@ public class ChannelShell extends ChannelSession {
             }
         }
 
-        log.info("Send SSH_MSG_CHANNEL_REQUEST shell");
+        log.debug("Send SSH_MSG_CHANNEL_REQUEST shell");
         buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
         buffer.putInt(recipient);
         buffer.putString("shell");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
index 304ee49..62ada33 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSubsystem.java
@@ -42,7 +42,7 @@ public class ChannelSubsystem extends ChannelSession {
     }
 
     protected void doOpen() throws IOException {
-        log.info("Send SSH_MSG_CHANNEL_REQUEST exec");
+        log.debug("Send SSH_MSG_CHANNEL_REQUEST exec");
         Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, 0);
         buffer.putInt(recipient);
         buffer.putString("subsystem");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/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 bed1e36..5e99f7f 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
@@ -79,7 +79,7 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
 
     public ClientSessionImpl(ClientFactoryManager client, IoSession session) throws Exception {
         super(false, client, session);
-        log.info("Session created...");
+        log.info("Client session created");
         // Need to set the initial service early as calling code likes to start trying to
         // manipulate it before the connection has even been established.  For instance, to
         // set the authPassword.
@@ -346,7 +346,7 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
             return;
         }
         initialServiceRequestSent = true;
-        log.info("Send SSH_MSG_SERVICE_REQUEST for {}", currentServiceFactory.getName());
+        log.debug("Send SSH_MSG_SERVICE_REQUEST for {}", currentServiceFactory.getName());
         Buffer request = createBuffer(SshConstants.SSH_MSG_SERVICE_REQUEST, 0);
         request.putString(currentServiceFactory.getName());
         writePacket(request);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/8f7dff12/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 b92eea0..ea2a21a 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
@@ -60,7 +60,7 @@ public class ServerSession extends AbstractSession {
         idleTimeoutMs = getIntProperty(ServerFactoryManager.IDLE_TIMEOUT, idleTimeoutMs);
         maxBytes = Math.max(32, getLongProperty(ServerFactoryManager.REKEY_BYTES_LIMIT, maxBytes));
         maxKeyInterval = getLongProperty(ServerFactoryManager.REKEY_TIME_LIMIT, maxKeyInterval);
-        log.info("Session created from {}", ioSession.getRemoteAddress());
+        log.info("Server session created from {}", ioSession.getRemoteAddress());
         sendServerIdentification();
         kexState = KEX_STATE_INIT;
         sendKexInit();