This is an automated email from the ASF dual-hosted git repository. lgoldstein pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit 42b2e7d45934fa79e0249b14fd95ebfef6f73ace Author: Lyor Goldstein <lgoldst...@apache.org> AuthorDate: Wed Jul 29 08:56:59 2020 +0300 Moved some common CLI support utilities from SshClientCliSupport to CliSupport --- .../main/java/org/apache/sshd/cli/CliSupport.java | 116 ++++++++++++++++- .../sshd/cli/client/SshClientCliSupport.java | 107 ---------------- .../org/apache/sshd/cli/server/SshServerMain.java | 1 + .../sshd/common/config/SshConfigFileReader.java | 137 +++++++++++---------- 4 files changed, 189 insertions(+), 172 deletions(-) diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java index 3c3863a..aafce0c 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java @@ -22,17 +22,27 @@ import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.logging.Level; import org.apache.sshd.common.AttributeRepository; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.auth.UserAuthFactoriesManager; import org.apache.sshd.common.auth.UserAuthInstance; import org.apache.sshd.common.auth.UserAuthMethodFactory; +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.ConfigFileReaderSupport; import org.apache.sshd.common.config.LogLevelValue; import org.apache.sshd.common.helpers.AbstractFactoryManager; @@ -42,13 +52,15 @@ import org.apache.sshd.common.io.IoConnector; import org.apache.sshd.common.io.IoServiceEventListener; import org.apache.sshd.common.io.IoServiceFactoryFactory; import org.apache.sshd.common.kex.KexProposalOption; +import org.apache.sshd.common.mac.BuiltinMacs; +import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.session.SessionListener; import org.apache.sshd.common.util.GenericUtils; /** - * TODO Add javadoc + * Provides common utilities for SSH client/server execution from the CLI * * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ @@ -340,4 +352,106 @@ public abstract class CliSupport { return level.getLoggingLevel(); } + + public static List<NamedFactory<Compression>> setupCompressions(PropertyResolver options, PrintStream stderr) { + String argVal = PropertyResolverUtils.getString( + options, ConfigFileReaderSupport.COMPRESSION_PROP); + if (GenericUtils.isEmpty(argVal)) { + return Collections.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.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("WARNING: Ignored unsupported compressions: ") + .println(GenericUtils.join(unsupported, ',')); + } + + return new ArrayList<>(available); + } + + public static List<NamedFactory<Mac>> setupMacs(PropertyResolver options, PrintStream stderr) { + String argVal = PropertyResolverUtils.getString( + options, ConfigFileReaderSupport.MACS_CONFIG_PROP); + return GenericUtils.isEmpty(argVal) + ? Collections.emptyList() + : CliSupport.setupMacs(ConfigFileReaderSupport.MACS_CONFIG_PROP, argVal, null, stderr); + } + + public static List<NamedFactory<Mac>> setupMacs( + String argName, String argVal, List<NamedFactory<Mac>> current, PrintStream stderr) { + if (GenericUtils.size(current) > 0) { + showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); + return null; + } + + BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(argVal); + Collection<? extends NamedFactory<Mac>> available = result.getParsedFactories(); + if (GenericUtils.isEmpty(available)) { + showError(stderr, "No known MACs in " + argVal); + return null; + } + + Collection<String> unsupported = result.getUnsupportedFactories(); + if (GenericUtils.size(unsupported) > 0) { + stderr.append("WARNING: Ignored unsupported MACs: ") + .println(GenericUtils.join(unsupported, ',')); + } + + return new ArrayList<>(available); + } + + public static List<NamedFactory<Cipher>> setupCiphers(PropertyResolver options, PrintStream stderr) { + String argVal = PropertyResolverUtils.getString( + options, ConfigFileReaderSupport.CIPHERS_CONFIG_PROP); + return GenericUtils.isEmpty(argVal) + ? Collections.emptyList() + : CliSupport.setupCiphers(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, argVal, null, stderr); + } + + // returns null - e.g., re-specified or no supported cipher found + public static List<NamedFactory<Cipher>> setupCiphers( + String argName, String argVal, List<NamedFactory<Cipher>> current, PrintStream stderr) { + if (GenericUtils.size(current) > 0) { + showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); + return null; + } + + BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(argVal); + Collection<? extends NamedFactory<Cipher>> available = result.getParsedFactories(); + if (GenericUtils.isEmpty(available)) { + showError(stderr, "WARNING: No known ciphers in " + argVal); + return null; + } + + Collection<String> unsupported = result.getUnsupportedFactories(); + if (GenericUtils.size(unsupported) > 0) { + stderr.append("WARNING: Ignored unsupported ciphers: ") + .println(GenericUtils.join(unsupported, ',')); + } + + return new ArrayList<>(available); + } } diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java index c7ab0e3..5f34586 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java @@ -57,18 +57,14 @@ import org.apache.sshd.client.keyverifier.KnownHostsServerKeyVerifier; import org.apache.sshd.client.keyverifier.ServerKeyVerifier; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.PtyChannelConfiguration; import org.apache.sshd.common.channel.PtyChannelConfigurationMutator; import org.apache.sshd.common.channel.PtyMode; -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.ConfigFileReaderSupport; import org.apache.sshd.common.config.SshConfigFileReader; import org.apache.sshd.common.config.keys.BuiltinIdentities; @@ -78,7 +74,6 @@ import org.apache.sshd.common.kex.KexFactoryManager; import org.apache.sshd.common.kex.extension.DefaultClientKexExtensionHandler; import org.apache.sshd.common.kex.extension.KexExtensionHandler; import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.apache.sshd.common.mac.BuiltinMacs; import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.OsUtils; @@ -656,108 +651,6 @@ public abstract class SshClientCliSupport extends CliSupport { return stderr; } - public static List<NamedFactory<Compression>> setupCompressions(PropertyResolver options, PrintStream stderr) { - String argVal = PropertyResolverUtils.getString( - options, ConfigFileReaderSupport.COMPRESSION_PROP); - if (GenericUtils.isEmpty(argVal)) { - return Collections.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.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("WARNING: Ignored unsupported compressions: ") - .println(GenericUtils.join(unsupported, ',')); - } - - return new ArrayList<>(available); - } - - public static List<NamedFactory<Mac>> setupMacs(PropertyResolver options, PrintStream stderr) { - String argVal = PropertyResolverUtils.getString( - options, ConfigFileReaderSupport.MACS_CONFIG_PROP); - return GenericUtils.isEmpty(argVal) - ? Collections.emptyList() - : setupMacs(ConfigFileReaderSupport.MACS_CONFIG_PROP, argVal, null, stderr); - } - - public static List<NamedFactory<Mac>> setupMacs( - String argName, String argVal, List<NamedFactory<Mac>> current, PrintStream stderr) { - if (GenericUtils.size(current) > 0) { - showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); - return null; - } - - BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(argVal); - Collection<? extends NamedFactory<Mac>> available = result.getParsedFactories(); - if (GenericUtils.isEmpty(available)) { - showError(stderr, "No known MACs in " + argVal); - return null; - } - - Collection<String> unsupported = result.getUnsupportedFactories(); - if (GenericUtils.size(unsupported) > 0) { - stderr.append("WARNING: Ignored unsupported MACs: ") - .println(GenericUtils.join(unsupported, ',')); - } - - return new ArrayList<>(available); - } - - public static List<NamedFactory<Cipher>> setupCiphers(PropertyResolver options, PrintStream stderr) { - String argVal = PropertyResolverUtils.getString( - options, ConfigFileReaderSupport.CIPHERS_CONFIG_PROP); - return GenericUtils.isEmpty(argVal) - ? Collections.emptyList() - : setupCiphers(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, argVal, null, stderr); - } - - // returns null - e.g., re-specified or no supported cipher found - public static List<NamedFactory<Cipher>> setupCiphers( - String argName, String argVal, List<NamedFactory<Cipher>> current, PrintStream stderr) { - if (GenericUtils.size(current) > 0) { - showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); - return null; - } - - BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(argVal); - Collection<? extends NamedFactory<Cipher>> available = result.getParsedFactories(); - if (GenericUtils.isEmpty(available)) { - showError(stderr, "WARNING: No known ciphers in " + argVal); - return null; - } - - Collection<String> unsupported = result.getUnsupportedFactories(); - if (GenericUtils.size(unsupported) > 0) { - stderr.append("WARNING: Ignored unsupported ciphers: ") - .println(GenericUtils.join(unsupported, ',')); - } - - return new ArrayList<>(available); - } - public static Handler setupLogging( Level level, PrintStream stdout, PrintStream stderr, OutputStream outputStream) { Handler fh = new ConsoleHandler() { diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java index 64b6a86..1646e08 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java @@ -173,6 +173,7 @@ public class SshServerMain extends SshServerCliSupport { System.err.println( "usage: sshd [-p port] [-io mina|nio2|netty] [-key-type RSA|DSA|EC] [-key-size NNNN] [-key-file <path>] [-o option=value]"); System.exit(-1); + return; // just in case... } Map<String, Object> props = sshd.getProperties(); diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java index 163fe57..e4244a1 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java @@ -169,18 +169,19 @@ public final class SshConfigFileReader { public static <M extends AbstractFactoryManager> M configureCiphers( M manager, String value, boolean lenient, boolean ignoreUnsupported) { Objects.requireNonNull(manager, "No manager to configure"); + if (GenericUtils.isEmpty(value)) { + return manager; + } - if (!GenericUtils.isEmpty(value)) { - BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(value); - Collection<String> unsupported = result.getUnsupportedFactories(); - ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), - "Unsupported cipher(s) (%s) in %s", unsupported, value); + BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(value); + Collection<String> unsupported = result.getUnsupportedFactories(); + ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), + "Unsupported cipher(s) (%s) in %s", unsupported, value); - List<NamedFactory<Cipher>> factories - = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); - manager.setCipherFactories( - ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/unsupported ciphers(s): %s", value)); - } + List<NamedFactory<Cipher>> factories + = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); + manager.setCipherFactories( + ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/unsupported ciphers(s): %s", value)); return manager; } @@ -195,18 +196,19 @@ public final class SshConfigFileReader { public static <M extends AbstractFactoryManager> M configureSignatures( M manager, String value, boolean lenient, boolean ignoreUnsupported) { Objects.requireNonNull(manager, "No manager to configure"); + if (GenericUtils.isEmpty(value)) { + return manager; + } - if (!GenericUtils.isEmpty(value)) { - BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(value); - Collection<String> unsupported = result.getUnsupportedFactories(); - ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), - "Unsupported signatures (%s) in %s", unsupported, value); + BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(value); + Collection<String> unsupported = result.getUnsupportedFactories(); + ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), + "Unsupported signatures (%s) in %s", unsupported, value); - List<NamedFactory<Signature>> factories - = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); - manager.setSignatureFactories( - ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported signatures: %s", value)); - } + List<NamedFactory<Signature>> factories + = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); + manager.setSignatureFactories( + ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported signatures: %s", value)); return manager; } @@ -221,17 +223,18 @@ public final class SshConfigFileReader { public static <M extends AbstractFactoryManager> M configureMacs( M manager, String value, boolean lenient, boolean ignoreUnsupported) { Objects.requireNonNull(manager, "No manager to configure"); + if (GenericUtils.isEmpty(value)) { + return manager; + } - if (!GenericUtils.isEmpty(value)) { - BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(value); - Collection<String> unsupported = result.getUnsupportedFactories(); - ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), - "Unsupported MAC(s) (%s) in %s", unsupported, value); + BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(value); + Collection<String> unsupported = result.getUnsupportedFactories(); + ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), + "Unsupported MAC(s) (%s) in %s", unsupported, value); - List<NamedFactory<Mac>> factories = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); - manager.setMacFactories( - ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported MAC(s): %s", value)); - } + List<NamedFactory<Mac>> factories = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); + manager.setMacFactories( + ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported MAC(s): %s", value)); return manager; } @@ -263,18 +266,19 @@ public final class SshConfigFileReader { Function<? super DHFactory, ? extends KeyExchangeFactory> xformer, boolean ignoreUnsupported) { Objects.requireNonNull(manager, "No manager to configure"); Objects.requireNonNull(xformer, "No DHFactory transformer"); + if (GenericUtils.isEmpty(value)) { + return manager; + } - if (!GenericUtils.isEmpty(value)) { - BuiltinDHFactories.ParseResult result = BuiltinDHFactories.parseDHFactoriesList(value); - Collection<String> unsupported = result.getUnsupportedFactories(); - ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), - "Unsupported KEX(s) (%s) in %s", unsupported, value); + BuiltinDHFactories.ParseResult result = BuiltinDHFactories.parseDHFactoriesList(value); + Collection<String> unsupported = result.getUnsupportedFactories(); + ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), + "Unsupported KEX(s) (%s) in %s", unsupported, value); - List<KeyExchangeFactory> factories - = NamedFactory.setUpTransformedFactories(ignoreUnsupported, result.getParsedFactories(), xformer); - manager.setKeyExchangeFactories( - ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported KEXS(s): %s", value)); - } + List<KeyExchangeFactory> factories + = NamedFactory.setUpTransformedFactories(ignoreUnsupported, result.getParsedFactories(), xformer); + manager.setKeyExchangeFactories( + ValidateUtils.checkNotNullAndNotEmpty(factories, "No known/supported KEXS(s): %s", value)); return manager; } @@ -295,13 +299,16 @@ public final class SshConfigFileReader { Objects.requireNonNull(props, "No properties to configure"); String value = props.getString(ConfigFileReaderSupport.COMPRESSION_PROP); - if (!GenericUtils.isEmpty(value)) { - CompressionFactory factory = CompressionConfigValue.fromName(value); - ValidateUtils.checkTrue(lenient || (factory != null), "Unsupported compression value: %s", value); - if ((factory != null) && factory.isSupported()) { - manager.setCompressionFactories(Collections.singletonList(factory)); - } + if (GenericUtils.isEmpty(value)) { + return manager; } + + CompressionFactory factory = CompressionConfigValue.fromName(value); + ValidateUtils.checkTrue(lenient || (factory != null), "Unsupported compression value: %s", value); + if ((factory != null) && factory.isSupported()) { + manager.setCompressionFactories(Collections.singletonList(factory)); + } + return manager; } @@ -309,28 +316,30 @@ public final class SshConfigFileReader { public static <M extends AbstractFactoryManager> M configureCompression( M manager, String value, boolean lenient, boolean ignoreUnsupported) { Objects.requireNonNull(manager, "No manager to configure"); + if (GenericUtils.isEmpty(value)) { + return manager; + } - if (!GenericUtils.isEmpty(value)) { - CompressionFactory factory = CompressionConfigValue.fromName(value); - if (factory != null) { - // SSH can work without compression - if (ignoreUnsupported || factory.isSupported()) { - manager.setCompressionFactories(Collections.singletonList(factory)); - } - } else { - BuiltinCompressions.ParseResult result = BuiltinCompressions.parseCompressionsList(value); - Collection<String> unsupported = result.getUnsupportedFactories(); - ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported compressions(s) (%s) in %s", - unsupported, value); - - List<NamedFactory<Compression>> factories - = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); - // SSH can work without compression - if (GenericUtils.size(factories) > 0) { - manager.setCompressionFactories(factories); - } + CompressionFactory factory = CompressionConfigValue.fromName(value); + if (factory != null) { + // SSH can work without compression + if (ignoreUnsupported || factory.isSupported()) { + manager.setCompressionFactories(Collections.singletonList(factory)); + } + } else { + BuiltinCompressions.ParseResult result = BuiltinCompressions.parseCompressionsList(value); + Collection<String> unsupported = result.getUnsupportedFactories(); + ValidateUtils.checkTrue(lenient || GenericUtils.isEmpty(unsupported), "Unsupported compressions(s) (%s) in %s", + unsupported, value); + + List<NamedFactory<Compression>> factories + = BuiltinFactory.setUpFactories(ignoreUnsupported, result.getParsedFactories()); + // SSH can work without compression + if (GenericUtils.size(factories) > 0) { + manager.setCompressionFactories(factories); } } + return manager; } }