You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2016/02/23 18:40:07 UTC

mina-sshd git commit: Added support for command line specification of compression mode

Repository: mina-sshd
Updated Branches:
  refs/heads/master 8803e1364 -> a4307d1cc


Added support for command line specification of compression mode


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

Branch: refs/heads/master
Commit: a4307d1cc508f651c6c40915316befbd1f4d4c04
Parents: 8803e13
Author: Lyor Goldstein <ly...@gmail.com>
Authored: Tue Feb 23 19:40:50 2016 +0200
Committer: Lyor Goldstein <ly...@gmail.com>
Committed: Tue Feb 23 19:40:50 2016 +0200

----------------------------------------------------------------------
 .../java/org/apache/sshd/client/SshClient.java  | 154 ++++++++++++++-----
 .../sshd/client/scp/DefaultScpClient.java       |   5 +-
 .../sshd/client/subsystem/sftp/SftpCommand.java |   2 +-
 .../ReservedSessionMessagesHandlerTest.java     |   2 +-
 4 files changed, 124 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a4307d1c/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
index 2fbdb11..6ae44d6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
@@ -97,6 +97,9 @@ import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.channel.Channel;
 import org.apache.sshd.common.cipher.BuiltinCiphers;
 import org.apache.sshd.common.cipher.Cipher;
+import org.apache.sshd.common.compression.BuiltinCompressions;
+import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.config.CompressionConfigValue;
 import org.apache.sshd.common.config.SshConfigFileReader;
 import org.apache.sshd.common.config.keys.FilePasswordProvider;
 import org.apache.sshd.common.config.keys.KeyUtils;
@@ -785,8 +788,8 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
 
     // NOTE: ClientSession#getFactoryManager is the SshClient
     public static ClientSession setupClientSession(
-            String portOption, final BufferedReader stdin, final PrintStream stdout, final PrintStream stderr, String... args)
-            throws Exception {
+            String portOption, BufferedReader stdin, PrintStream stdout, PrintStream stderr, String... args)
+                    throws Exception {
 
         int port = -1;
         String host = null;
@@ -797,6 +800,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         Map<String, String> options = new LinkedHashMap<>();
         List<NamedFactory<Cipher>> ciphers = null;
         List<NamedFactory<Mac>> macs = null;
+        List<NamedFactory<Compression>> compressions = null;
         int numArgs = GenericUtils.length(args);
         for (int i = 0; (!error) && (i < numArgs); i++) {
             String argName = args[i];
@@ -841,6 +845,16 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                 }
             } else if ("-i".equals(argName)) {
                 identities.add(new File(argVal));
+            } else if ("-C".equals(argName)) {
+                compressions = setupCompressions(argName,
+                        GenericUtils.join(
+                                Arrays.asList(
+                                        BuiltinCompressions.Constants.ZLIB, BuiltinCompressions.Constants.DELAYED_ZLIB), ','),
+                        compressions, stderr);
+                if (GenericUtils.isEmpty(compressions)) {
+                    error = true;
+                    break;
+                }
             } else if ("-o".equals(argName)) {
                 String opt = argVal;
                 int idx = opt.indexOf('=');
@@ -879,30 +893,71 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
             error = showError(stderr, "Hostname not specified");
         }
 
-        if ((!error) && GenericUtils.isEmpty(ciphers)) {
+        if (error) {
+            return null;
+        }
+
+        SshClient client = setupClient(options, ciphers, macs, compressions, identities, stdin, stdout, stderr);
+        if (client == null) {
+            return null;
+        }
+
+        try {
+            client.start();
+
+            if (login == null) {
+                login = OsUtils.getCurrentUser();
+            }
+
+            if (port <= 0) {
+                port = SshConfigFileReader.DEFAULT_PORT;
+            }
+
+            // TODO use a configurable wait time
+            ClientSession session = client.connect(login, host, port).verify().getSession();
+            try {
+                if (GenericUtils.length(password) > 0) {
+                    session.addPasswordIdentity(password);
+                }
+                session.auth().verify(FactoryManager.DEFAULT_AUTH_TIMEOUT);    // TODO use a configurable wait time
+                return session;
+            } catch (Exception e) {
+                session.close(true);
+                throw e;
+            }
+        } catch (Exception e) {
+            client.close();
+            throw e;
+        }
+    }
+
+    // returns null if error encountered
+    public static SshClient setupClient(
+            Map<String, ?> options,
+            List<NamedFactory<Cipher>> ciphers,
+            List<NamedFactory<Mac>> macs,
+            List<NamedFactory<Compression>> compressions,
+            Collection<File> identities,
+            BufferedReader stdin, PrintStream stdout, PrintStream stderr) throws Exception {
+        if (GenericUtils.isEmpty(ciphers)) {
             ciphers = setupCiphers(options, stderr);
             if (ciphers == null) {
-                error = true;
+                return null;
             }
         }
 
-        if ((!error) && GenericUtils.isEmpty(macs)) {
+        if (GenericUtils.isEmpty(macs)) {
             macs = setupMacs(options, stderr);
             if (macs == null) {
-                error = true;
+                return null;
             }
         }
 
-        if (login == null) {
-            login = OsUtils.getCurrentUser();
-        }
-
-        if (port <= 0) {
-            port = SshConfigFileReader.DEFAULT_PORT;
-        }
-
-        if (error) {
-            return null;
+        if (GenericUtils.isEmpty(compressions)) {
+            compressions = setupCompressions(options, stderr);
+            if (compressions == null) {
+                return null;
+            }
         }
 
         SshClient client = SshClient.setUpDefaultClient();
@@ -915,10 +970,14 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
                 client.setMacFactories(macs);
             }
 
+            if (GenericUtils.size(compressions) > 0) {
+                client.setCompressionFactories(compressions);
+            }
+
             try {
                 setupSessionIdentities(client, identities, stdin, stdout, stderr);
-            } catch (Throwable t) {
-                error = showError(stderr, t.getClass().getSimpleName() + " while loading user keys: " + t.getMessage());
+            } catch (Throwable t) { // show but do not fail the setup - maybe a password can be used
+                showError(stderr, t.getClass().getSimpleName() + " while loading user keys: " + t.getMessage());
             }
 
             setupServerKeyVerifier(client, options, stdin, stdout, stderr);
@@ -926,23 +985,11 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
 
             Map<String, Object> props = client.getProperties();
             props.putAll(options);
-            client.start();
-
-            // TODO use a configurable wait time
-            ClientSession session = client.connect(login, host, port).verify().getSession();
-            try {
-                if (GenericUtils.length(password) > 0) {
-                    session.addPasswordIdentity(password);
-                }
-                session.auth().verify(FactoryManager.DEFAULT_AUTH_TIMEOUT);    // TODO use a configurable wait time
-                return session;
-            } catch (Exception e) {
-                session.close(true);
-                throw e;
-            }
-        } catch (Exception e) {
+            return client;
+        } catch (Throwable t) {
+            showError(stderr, "Failed (" + t.getClass().getSimpleName() + ") to setup client: " + t.getMessage());
             client.close();
-            throw e;
+            return null;
         }
     }
 
@@ -1116,6 +1163,43 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
         return stderr;
     }
 
+    public static List<NamedFactory<Compression>> setupCompressions(Map<String, ?> options, PrintStream stderr) {
+        String argVal = PropertyResolverUtils.getString(options, SshConfigFileReader.COMPRESSION_PROP);
+        if (GenericUtils.isEmpty(argVal)) {
+            return Collections.<NamedFactory<Compression>>emptyList();
+        }
+
+        NamedFactory<Compression> value = CompressionConfigValue.fromName(argVal);
+        if (value == null) {
+            showError(stderr, "Unknown compression configuration value: " + argVal);
+            return null;
+        }
+
+        return Collections.singletonList(value);
+    }
+
+    public static List<NamedFactory<Compression>> setupCompressions(
+            String argName, String argVal, List<NamedFactory<Compression>> current, PrintStream stderr) {
+        if (GenericUtils.size(current) > 0) {
+            showError(stderr, argName + " option value re-specified: " + NamedResource.Utils.getNames(current));
+            return null;
+        }
+
+        BuiltinCompressions.ParseResult result = BuiltinCompressions.parseCompressionsList(argVal);
+        Collection<? extends NamedFactory<Compression>> available = result.getParsedFactories();
+        if (GenericUtils.isEmpty(available)) {
+            showError(stderr, "No known compressions in " + argVal);
+            return null;
+        }
+
+        Collection<String> unsupported = result.getUnsupportedFactories();
+        if (GenericUtils.size(unsupported) > 0) {
+            stderr.append("Ignored unsupported compressions: ").println(GenericUtils.join(unsupported, ','));
+        }
+
+        return new ArrayList<>(available);
+    }
+
     public static List<NamedFactory<Mac>> setupMacs(Map<String, ?> options, PrintStream stderr) {
         String argVal = PropertyResolverUtils.getString(options, SshConfigFileReader.MACS_CONFIG_PROP);
         return GenericUtils.isEmpty(argVal)
@@ -1300,7 +1384,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
             if (error) {
                 System.err.println("usage: ssh [-A|-a] [-v[v][v]] [-E logoutputfile] [-D socksPort]"
                         + " [-l login] [" + SSH_CLIENT_PORT_OPTION + " port] [-o option=value]"
-                        + " [-w password] [-c cipherslist] [-m maclist]"
+                        + " [-w password] [-c cipherslist] [-m maclist] [-C]"
                         + " hostname/user@host [command]");
                 System.exit(-1);
                 return;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a4307d1c/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
index 4617c84..e184f76 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
@@ -195,7 +195,8 @@ public class DefaultScpClient extends AbstractScpClient {
 
                 effective.add(argName);
                 effective.add(args[++index]);
-            } else if ("-r".equals(argName) || "-p".equals(argName) || "-q".equals(argName)
+            } else if ("-r".equals(argName) || "-p".equals(argName)
+                    || "-q".equals(argName) || "-C".equals(argName)
                     || "-v".equals(argName) || "-vv".equals(argName) || "-vvv".equals(argName)) {
                 effective.add(argName);
             } else if (argName.charAt(0) == '-') {
@@ -255,7 +256,7 @@ public class DefaultScpClient extends AbstractScpClient {
             if (session == null) {
                 stderr.println("usage: scp [" + SCP_PORT_OPTION + " port] [-i identity]"
                          + " [-v[v][v]] [-E logoutput] [-r] [-p] [-q] [-o option=value]"
-                         + " [-c cipherlist] [-m maclist] [-w password] <source> <target>");
+                         + " [-c cipherlist] [-m maclist] [-w password] [-C] <source> <target>");
                 stderr.println();
                 stderr.println("Where <source> or <target> are either 'user@host:file' or a local file path");
                 stderr.println("NOTE: exactly ONE of the source or target must be remote and the other one local");

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a4307d1c/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
index 0620b27..ff5cef4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java
@@ -260,7 +260,7 @@ public class SftpCommand implements Channel {
             if (session == null) {
                 System.err.println("usage: sftp [-v[v][v]] [-E logoutput] [-i identity]"
                         + " [-l login] [" + SFTP_PORT_OPTION + " port] [-o option=value]"
-                        + " [-w password] [-c cipherlist]  [-m maclist] hostname/user@host");
+                        + " [-w password] [-c cipherlist]  [-m maclist] [-C] hostname/user@host");
                 System.exit(-1);
                 return;
             }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a4307d1c/sshd-core/src/test/java/org/apache/sshd/common/session/ReservedSessionMessagesHandlerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/session/ReservedSessionMessagesHandlerTest.java b/sshd-core/src/test/java/org/apache/sshd/common/session/ReservedSessionMessagesHandlerTest.java
index 07e09e5..22f8cb3 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/session/ReservedSessionMessagesHandlerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/session/ReservedSessionMessagesHandlerTest.java
@@ -112,7 +112,7 @@ public class ReservedSessionMessagesHandlerTest extends BaseTestSupport {
                                     testReservedSessionMessagesHandler(session, handler);
                                     outputDebugMessage("Release test signal for %s", session);
                                     signal.release();
-                                } catch(Throwable t) {
+                                } catch (Throwable t) {
                                     outputDebugMessage("Failed (%s) to run test: %s", t.getClass().getSimpleName(), t.getMessage());
                                     session.exceptionCaught(t);
                                 }