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/02/07 23:54:16 UTC

[1/3] git commit: Change KeyPairProvider to return an Iterable to benefit from lazy loading

Updated Branches:
  refs/heads/master e737ae3fc -> 1a3aae3e0


Change KeyPairProvider to return an Iterable to benefit from lazy loading

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

Branch: refs/heads/master
Commit: 602ed3f4a3570029796bcc27500ca28c322040c7
Parents: e737ae3
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Feb 7 23:51:41 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Feb 7 23:51:41 2014 +0100

----------------------------------------------------------------------
 .../org/apache/sshd/common/KeyPairProvider.java |   2 +-
 .../keyprovider/AbstractKeyPairProvider.java    |   6 +-
 .../common/keyprovider/FileKeyPairProvider.java |  91 ++++++++++-----
 .../keyprovider/ResourceKeyPairProvider.java    | 114 ++++++++++++-------
 .../AbstractGeneratorHostKeyProvider.java       |   7 +-
 5 files changed, 146 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/602ed3f4/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 70a379e..1b52c17 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
@@ -58,7 +58,7 @@ public interface KeyPairProvider {
      *
      * @return an array of available keys, never <code>null</code>
      */
-    KeyPair[] loadKeys();
+    Iterable<KeyPair> loadKeys();
 
     /**
      * Load a key of the specified type which can be "ssh-rsa", "ssh-dss", or

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/602ed3f4/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 bf6650b..42982b6 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
@@ -39,7 +39,7 @@ public abstract class AbstractKeyPairProvider implements KeyPairProvider {
 
     public KeyPair loadKey(String type) {
         assert type != null;
-        KeyPair[] keys = loadKeys();
+        Iterable<KeyPair> keys = loadKeys();
         for (KeyPair key : keys) {
             if (type.equals(getKeyType(key))) {
                 return key;
@@ -50,7 +50,7 @@ public abstract class AbstractKeyPairProvider implements KeyPairProvider {
 
     public String getKeyTypes() {
         List<String> types = new ArrayList<String>();
-        KeyPair[] keys = loadKeys();
+        Iterable<KeyPair> keys = loadKeys();
         for (KeyPair key : keys) {
             String type = getKeyType(key);
             if (type != null && !types.contains(type)) {
@@ -67,5 +67,5 @@ public abstract class AbstractKeyPairProvider implements KeyPairProvider {
         return sb.toString();
     }
 
-    public abstract KeyPair[] loadKeys();
+    public abstract Iterable<KeyPair> loadKeys();
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/602ed3f4/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
index 8d2e979..bb00cd7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java
@@ -21,8 +21,9 @@ package org.apache.sshd.common.keyprovider;
 import java.io.FileInputStream;
 import java.io.InputStreamReader;
 import java.security.KeyPair;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 import org.apache.sshd.common.util.SecurityUtils;
 import org.bouncycastle.openssl.PEMDecryptorProvider;
@@ -74,39 +75,75 @@ public class FileKeyPairProvider extends AbstractKeyPairProvider {
         this.passwordFinder = passwordFinder;
     }
 
-    public KeyPair[] loadKeys() {
+    public Iterable<KeyPair> loadKeys() {
         if (!SecurityUtils.isBouncyCastleRegistered()) {
             throw new IllegalStateException("BouncyCastle must be registered as a JCE provider");
         }
-        List<KeyPair> keys = new ArrayList<KeyPair>();
-        for (int i = 0; i < files.length; i++) {
-            try {
-                PEMParser r = new PEMParser(new InputStreamReader(new FileInputStream(files[i])));
-                try {
-                    Object o = r.readObject();
-
-                    JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
-                    pemConverter.setProvider("BC");
-                    if (passwordFinder != null && o instanceof PEMEncryptedKeyPair) {
-                        JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
-                        PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(passwordFinder.getPassword());
-                        o = pemConverter.getKeyPair(((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor));
+        return new Iterable<KeyPair>() {
+            public Iterator<KeyPair> iterator() {
+                return new Iterator<KeyPair>() {
+                    private final Iterator<String> iterator = Arrays.asList(files).iterator();
+                    private KeyPair nextKeyPair;
+                    private boolean nextKeyPairSet = false;
+                    public boolean hasNext() {
+                        return nextKeyPairSet || setNextObject();
                     }
-
-                    if (o instanceof PEMKeyPair) {
-                        o = pemConverter.getKeyPair((PEMKeyPair)o);
-                        keys.add((KeyPair) o);
-                    } else if (o instanceof KeyPair) {
-                        keys.add((KeyPair) o);
+                    public KeyPair next() {
+                        if (!nextKeyPairSet) {
+                            if (!setNextObject()) {
+                                throw new NoSuchElementException();
+                            }
+                        }
+                        nextKeyPairSet = false;
+                        return nextKeyPair;
+                    }
+                    public void remove() {
+                        throw new UnsupportedOperationException();
                     }
-                } finally {
-                    r.close();
+                    private boolean setNextObject() {
+                        while (iterator.hasNext()) {
+                            String file = iterator.next();
+                            nextKeyPair = doLoadKey(file);
+                            if (nextKeyPair != null) {
+                                nextKeyPairSet = true;
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+
+                };
+            }
+        };
+    }
+
+    protected KeyPair doLoadKey(String file) {
+        try {
+            PEMParser r = new PEMParser(new InputStreamReader(new FileInputStream(file)));
+            try {
+                Object o = r.readObject();
+
+                JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+                pemConverter.setProvider("BC");
+                if (passwordFinder != null && o instanceof PEMEncryptedKeyPair) {
+                    JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
+                    PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(passwordFinder.getPassword());
+                    o = pemConverter.getKeyPair(((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor));
+                }
+
+                if (o instanceof PEMKeyPair) {
+                    o = pemConverter.getKeyPair((PEMKeyPair)o);
+                    return (KeyPair) o;
+                } else if (o instanceof KeyPair) {
+                    return (KeyPair) o;
                 }
-            } catch (Exception e) {
-                log.warn("Unable to read key {}: {}", files[i], e);
+            } finally {
+                r.close();
             }
+        } catch (Exception e) {
+            log.warn("Unable to read key " + file, e);
         }
-        return keys.toArray(new KeyPair[keys.size()]);
+        return null;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/602ed3f4/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ResourceKeyPairProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ResourceKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ResourceKeyPairProvider.java
index 0ed6335..0cd5d6c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ResourceKeyPairProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ResourceKeyPairProvider.java
@@ -22,7 +22,10 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.security.KeyPair;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 import org.apache.sshd.common.util.IoUtils;
 import org.apache.sshd.common.util.SecurityUtils;
@@ -143,48 +146,79 @@ public class ResourceKeyPairProvider extends AbstractKeyPairProvider {
     /**
      * {@inheritDoc}
      */
-    public KeyPair[] loadKeys() {
+    public Iterable<KeyPair> loadKeys() {
         if (!SecurityUtils.isBouncyCastleRegistered()) {
             throw new IllegalStateException("BouncyCastle must be registered as a JCE provider");
         } // end of if
+        return new Iterable<KeyPair>() {
+            public Iterator<KeyPair> iterator() {
+                return new Iterator<KeyPair>() {
+                    private final Iterator<String> iterator = Arrays.asList(resources).iterator();
+                    private KeyPair nextKeyPair;
+                    private boolean nextKeyPairSet = false;
+                    public boolean hasNext() {
+                        return nextKeyPairSet || setNextObject();
+                    }
+                    public KeyPair next() {
+                        if (!nextKeyPairSet) {
+                            if (!setNextObject()) {
+                                throw new NoSuchElementException();
+                            }
+                        }
+                        nextKeyPairSet = false;
+                        return nextKeyPair;
+                    }
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                    private boolean setNextObject() {
+                        while (iterator.hasNext()) {
+                            String file = iterator.next();
+                            nextKeyPair = doLoadKey(file);
+                            if (nextKeyPair != null) {
+                                nextKeyPairSet = true;
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+
+                };
+            }
+        };
+    }
+
+    protected KeyPair doLoadKey(String resource) {
+        PEMParser r = null;
+        InputStreamReader isr = null;
+        InputStream is = null;
+        try {
+            is = this.cloader.getResourceAsStream(resource);
+            isr = new InputStreamReader(is);
+            r = new PEMParser(isr);
+
+            Object o = r.readObject();
+
+            JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
+            pemConverter.setProvider("BC");
+            if (passwordFinder != null && o instanceof PEMEncryptedKeyPair) {
+                JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
+                PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(passwordFinder.getPassword());
+                o = pemConverter.getKeyPair(((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor));
+            }
+
+            if (o instanceof PEMKeyPair) {
+                o = pemConverter.getKeyPair((PEMKeyPair)o);
+                return (KeyPair) o;
+            } else if (o instanceof KeyPair) {
+                return (KeyPair) o;
+            } // end of if
+        } catch (Exception e) {
+            log.warn("Unable to read key " + resource, e);
+        } finally {
+            IoUtils.closeQuietly(r, is, isr);
+        } // end of finally
+        return null;
+    } // end of doLoadKey
 
-        // ---
-
-        final List<KeyPair> keys =
-                new ArrayList<KeyPair>(this.resources.length);
-
-        for (String resource : resources) {
-            PEMParser r = null;
-            InputStreamReader isr = null;
-            InputStream is = null;
-            try {
-                is = this.cloader.getResourceAsStream(resource);
-                isr = new InputStreamReader(is);
-                r = new PEMParser(isr);
-
-                Object o = r.readObject();
-
-                JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
-                pemConverter.setProvider("BC");
-                if (passwordFinder != null && o instanceof PEMEncryptedKeyPair) {
-                    JcePEMDecryptorProviderBuilder decryptorBuilder = new JcePEMDecryptorProviderBuilder();
-                    PEMDecryptorProvider pemDecryptor = decryptorBuilder.build(passwordFinder.getPassword());
-                    o = pemConverter.getKeyPair(((PEMEncryptedKeyPair) o).decryptKeyPair(pemDecryptor));
-                }
-
-                if (o instanceof PEMKeyPair) {
-                    o = pemConverter.getKeyPair((PEMKeyPair)o);
-                    keys.add((KeyPair) o);
-                } else if (o instanceof KeyPair) {
-                    keys.add((KeyPair) o);
-                } // end of if
-            } catch (Exception e) {
-                log.warn("Unable to read key", e);
-            } finally {
-                IoUtils.closeQuietly(r, is, isr);
-            } // end of finally
-        } // end of for
-
-        return keys.toArray(new KeyPair[keys.size()]);
-    } // end of loadKeys
 } // end of class ResourceKeyPairProvider

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/602ed3f4/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
index 7cd8333..282b8bc 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProvider.java
@@ -28,6 +28,7 @@ import java.io.OutputStream;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.spec.AlgorithmParameterSpec;
+import java.util.Collections;
 
 import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
 import org.apache.sshd.common.util.SecurityUtils;
@@ -99,7 +100,7 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
 
     protected abstract void doWriteKeyPair(KeyPair kp, OutputStream os) throws Exception;
 
-    public synchronized KeyPair[] loadKeys() {
+    public synchronized Iterable<KeyPair> loadKeys() {
         if (keyPair == null) {
             if (path != null) {
                 File f = new File(path);
@@ -114,10 +115,10 @@ public abstract class AbstractGeneratorHostKeyProvider extends AbstractKeyPairPr
                 }
             }
             if (keyPair == null) {
-                return new KeyPair[0];
+                return Collections.emptyList();
             }
         }
-        return new KeyPair[] { keyPair };
+        return Collections.singleton(keyPair);
     }
 
     private KeyPair readKeyPair(File f) {


[2/3] git commit: Use agent key pairs before the ones from the KeyPairProvider

Posted by gn...@apache.org.
Use agent key pairs before the ones from the KeyPairProvider

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

Branch: refs/heads/master
Commit: e0cbc8b2b08c5f5fb1f6acaa83397e6c9a0415e1
Parents: 602ed3f
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Feb 7 23:53:03 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Feb 7 23:53:03 2014 +0100

----------------------------------------------------------------------
 .../org/apache/sshd/client/auth/UserAuthPublicKey.java  | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e0cbc8b2/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 7dfe20b..6fdba21 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
@@ -73,12 +73,6 @@ public class UserAuthPublicKey implements UserAuth {
                 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());
@@ -88,6 +82,12 @@ public class UserAuthPublicKey implements UserAuth {
         } else {
             this.agent = null;
         }
+        KeyPairProvider provider = session.getFactoryManager().getKeyPairProvider();
+        if (provider != null) {
+            for (KeyPair pair : provider.loadKeys()) {
+                ids.add(new KeyPairIdentity(session.getFactoryManager(), pair));
+            }
+        }
         this.keys = ids.iterator();
     }
 


[3/3] git commit: Fix client main() to support logging, key pairs, password-interactive auth

Posted by gn...@apache.org.
Fix client main() to support logging, key pairs, password-interactive auth

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

Branch: refs/heads/master
Commit: 1a3aae3e0f98ac5a442d546b237f7b156b39da25
Parents: e0cbc8b
Author: Guillaume Nodet <gn...@apache.org>
Authored: Fri Feb 7 23:54:08 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Fri Feb 7 23:54:08 2014 +0100

----------------------------------------------------------------------
 assembly/pom.xml                                |   2 +-
 pom.xml                                         |   5 +
 .../main/java/org/apache/sshd/SshClient.java    | 223 +++++++++++--------
 sshd-git/README.txt                             |   2 +-
 4 files changed, 143 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a3aae3e/assembly/pom.xml
----------------------------------------------------------------------
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 403a2a4..9f04f1d 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -58,7 +58,7 @@
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>slf4j-jdk14</artifactId>
         </dependency>
         <dependency>
             <groupId>org.bouncycastle</groupId>

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a3aae3e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 07f4cda..d38e0c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -136,6 +136,11 @@
             </dependency>
             <dependency>
                 <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-jdk14</artifactId>
+                <version>1.6.4</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
                 <artifactId>slf4j-simple</artifactId>
                 <version>1.6.4</version>
             </dependency>

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a3aae3e/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 d784dba..fddc498 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -21,19 +21,29 @@ package org.apache.sshd;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.io.Writer;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.security.InvalidKeyException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Executors;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
 
 import org.apache.sshd.client.ClientFactoryManager;
 import org.apache.sshd.client.ServerKeyVerifier;
@@ -44,7 +54,6 @@ 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;
 import org.apache.sshd.client.future.DefaultConnectFuture;
 import org.apache.sshd.client.kex.DHG1;
@@ -65,6 +74,7 @@ import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.Compression;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.Mac;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.common.Signature;
@@ -86,6 +96,7 @@ import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.DefaultIoServiceFactory;
 import org.apache.sshd.common.io.IoConnectFuture;
 import org.apache.sshd.common.io.IoConnector;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
 import org.apache.sshd.common.mac.HMACMD5;
 import org.apache.sshd.common.mac.HMACMD596;
 import org.apache.sshd.common.mac.HMACSHA1;
@@ -99,10 +110,10 @@ import org.apache.sshd.common.session.AbstractSession;
 import org.apache.sshd.common.signature.SignatureDSA;
 import org.apache.sshd.common.signature.SignatureECDSA;
 import org.apache.sshd.common.signature.SignatureRSA;
-import org.apache.sshd.common.util.CloseableUtils;
 import org.apache.sshd.common.util.NoCloseInputStream;
 import org.apache.sshd.common.util.NoCloseOutputStream;
 import org.apache.sshd.common.util.SecurityUtils;
+import org.bouncycastle.openssl.PasswordFinder;
 
 /**
  * Entry point for the client side of the SSH protocol.
@@ -436,6 +447,35 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
      *=================================*/
 
     public static void main(String[] args) throws Exception {
+        Handler fh = new ConsoleHandler();
+        fh.setLevel(Level.FINEST);
+        fh.setFormatter(new Formatter() {
+            @Override
+            public String format(LogRecord record) {
+                String message = formatMessage(record);
+                String throwable = "";
+                if (record.getThrown() != null) {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);
+                    pw.println();
+                    record.getThrown().printStackTrace(pw);
+                    pw.close();
+                    throwable = sw.toString();
+                }
+                return String.format("%1$tY-%1$tm-%1$td: %2$-7.7s: %3$-32.32s: %4$s%5$s%n",
+                        new Date(record.getMillis()),
+                        record.getLevel().getName(),
+                        record.getLoggerName(),
+                        message,
+                        throwable);
+            }
+        });
+        Logger root = Logger.getLogger("");
+        for (Handler handler : root.getHandlers()) {
+            root.removeHandler(handler);
+        }
+        root.addHandler(fh);
+
         int port = 22;
         String host = null;
         String login = System.getProperty("user.name");
@@ -443,6 +483,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         List<String> command = null;
         int logLevel = 0;
         boolean error = false;
+        List<String> identities = new ArrayList<String>();
 
         for (int i = 0; i < args.length; i++) {
             if (command == null && "-p".equals(args[i])) {
@@ -460,15 +501,22 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                 }
                 login = args[++i];
             } else if (command == null && "-v".equals(args[i])) {
-                logLevel = 1;
+                logLevel += 1;
             } else if (command == null && "-vv".equals(args[i])) {
-                logLevel = 2;
+                logLevel += 2;
             } else if (command == null && "-vvv".equals(args[i])) {
-                logLevel = 3;
+                logLevel += 3;
             } else if ("-A".equals(args[i])) {
                 agentForward = true;
             } else if ("-a".equals(args[i])) {
                 agentForward = false;
+            } else if ("-i".equals(args[i])) {
+                if (i + 1 >= args.length) {
+                    System.err.println("option requires and argument: " + args[i]);
+                    error = true;
+                    break;
+                }
+                identities.add(args[++i]);
             } else if (command == null && args[i].startsWith("-")) {
                 System.err.println("illegal option: " + args[i]);
                 error = true;
@@ -492,103 +540,104 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
             System.err.println("usage: ssh [-A|-a] [-v[v][v]] [-l login] [-p port] hostname [command]");
             System.exit(-1);
         }
+        if (logLevel <= 0) {
+            root.setLevel(Level.WARNING);
+        } else if (logLevel == 1) {
+            root.setLevel(Level.INFO);
+        } else if (logLevel == 2) {
+            root.setLevel(Level.FINE);
+        } else {
+            root.setLevel(Level.FINEST);
+        }
 
         // TODO: handle log level
 
+        KeyPairProvider provider = null;
+        List<String> files = new ArrayList<String>();
+        File f = new File(System.getProperty("user.home"), ".ssh/id_dsa");
+        if (f.exists() && f.isFile() && f.canRead()) {
+            files.add(f.getAbsolutePath());
+        }
+        f = new File(System.getProperty("user.home"), ".ssh/id_rsa");
+        if (f.exists() && f.isFile() && f.canRead()) {
+            files.add(f.getAbsolutePath());
+        }
+        if (files.size() > 0) {
+            provider = new FileKeyPairProvider(files.toArray(new String[files.size()]), new PasswordFinder() {
+                public char[] getPassword() {
+                    try {
+                        System.out.println("Enter password for private key: ");
+                        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
+                        String password = r.readLine();
+                        return password.toCharArray();
+                    } catch (IOException e) {
+                        return null;
+                    }
+                }
+            });
+        }
+
         SshClient client = SshClient.setUpDefaultClient();
         client.start();
-
-        try {
-            boolean hasKeys = false;
-
-            /*
-            String authSock = System.getenv(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
-            if (authSock == null) {
-                KeyPair[] keys = null;
-                AgentServer server = new AgentServer();
-                authSock = server.start();
-                List<String> files = new ArrayList<String>();
-                File f = new File(System.getProperty("user.home"), ".ssh/id_dsa");
-                if (f.exists() && f.isFile() && f.canRead()) {
-                    files.add(f.getAbsolutePath());
-                }
-                f = new File(System.getProperty("user.home"), ".ssh/id_rsa");
-                if (f.exists() && f.isFile() && f.canRead()) {
-                    files.add(f.getAbsolutePath());
-                }
+        client.setKeyPairProvider(provider);
+        client.setUserInteraction(new UserInteraction() {
+            public void welcome(String banner) {
+                System.out.println(banner);
+            }
+            public String[] interactive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
+                String[] answers = new String[prompt.length];
                 try {
-                    if (files.size() > 0) {
-                        keys = new FileKeyPairProvider(files.toArray(new String[0]), new PasswordFinder() {
-                            public char[] getPassword() {
-                                try {
-                                    System.out.println("Enter password for private key: ");
-                                    BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
-                                    String password = r.readLine();
-                                    return password.toCharArray();
-                                } catch (IOException e) {
-                                    return null;
-                                }
-                            }
-                        }).loadKeys();
+                    for (int i = 0; i < prompt.length; i++) {
+                        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
+                        System.out.print(prompt[i] + " ");
+                        answers[i] = r.readLine();
                     }
-                } catch (Exception e) {
+                } catch (IOException e) {
                 }
-                SshAgent agent = new AgentClient(authSock);
-                for (KeyPair key : keys) {
-                    agent.addIdentity(key, "");
-                }
-                agent.close();
+                return answers;
             }
-            if (authSock != null) {
-                SshAgent agent = new AgentClient(authSock);
-                hasKeys = agent.getIdentities().size() > 0;
+        });
+
+        /*
+        String authSock = System.getenv(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
+        if (authSock == null && provider != null) {
+            Iterable<KeyPair> keys = provider.loadKeys();
+            AgentServer server = new AgentServer();
+            authSock = server.start();
+            SshAgent agent = new AgentClient(authSock);
+            for (KeyPair key : keys) {
+                agent.addIdentity(key, "");
             }
+            agent.close();
             client.getProperties().put(SshAgent.SSH_AUTHSOCKET_ENV_NAME, authSock);
-            */
+        }
+        */
 
-            ClientSession session = client.connect(host, port).await().getSession();
-            int ret = ClientSession.WAIT_AUTH;
+        ClientSession session = client.connect(login, host, port).await().getSession();
+        session.auth().verify();
 
-            AuthFuture authFuture;
-            do {
-                if (hasKeys) {
-                    authFuture = session.authAgent(login);
-                } else {
-                    System.out.print("Password:");
-                    BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
-                    String password = r.readLine();
-                    authFuture = session.authPassword(login, password);
-                }
-                authFuture.await();
-            } while (authFuture.isFailure());
-            if (!authFuture.isSuccess()) {
-                System.err.println("error");
-                System.exit(-1);
-            }
-            ClientChannel channel;
-            if (command == null) {
-                channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
-                ((ChannelShell) channel).setAgentForwarding(agentForward);
-                channel.setIn(new NoCloseInputStream(System.in));
-            } else {
-                channel = session.createChannel(ClientChannel.CHANNEL_EXEC);
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                Writer w = new OutputStreamWriter(baos);
-                for (String cmd : command) {
-                    w.append(cmd).append(" ");
-                }
-                w.append("\n");
-                w.close();
-                channel.setIn(new ByteArrayInputStream(baos.toByteArray()));
+        ClientChannel channel;
+        if (command == null) {
+            channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
+            ((ChannelShell) channel).setAgentForwarding(agentForward);
+            channel.setIn(new NoCloseInputStream(System.in));
+        } else {
+            channel = session.createChannel(ClientChannel.CHANNEL_EXEC);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            Writer w = new OutputStreamWriter(baos);
+            for (String cmd : command) {
+                w.append(cmd).append(" ");
             }
-            channel.setOut(new NoCloseOutputStream(System.out));
-            channel.setErr(new NoCloseOutputStream(System.err));
-            channel.open().await();
-            channel.waitFor(ClientChannel.CLOSED, 0);
-            session.close(false);
-        } finally {
-            client.stop();
+            w.append("\n");
+            w.close();
+            channel.setIn(new ByteArrayInputStream(baos.toByteArray()));
         }
+        channel.setOut(new NoCloseOutputStream(System.out));
+        channel.setErr(new NoCloseOutputStream(System.err));
+        channel.open().await();
+        channel.waitFor(ClientChannel.CLOSED, 0);
+        session.close(false);
+        client.stop();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1a3aae3e/sshd-git/README.txt
----------------------------------------------------------------------
diff --git a/sshd-git/README.txt b/sshd-git/README.txt
index 046f7c5..4977b98 100644
--- a/sshd-git/README.txt
+++ b/sshd-git/README.txt
@@ -1,4 +1,4 @@
 This module contains an SSHD CommandFactory to support git through SSH.
 The git commands are provided by a modified version of jgit-pgm
 available at:
-  https://github.com/gnodet/jgit/tree/%23413522
+  https://github.com/gnodet/jgit/tree/413522