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 2018/09/06 16:03:33 UTC
[23/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common
utilities code from sshd-core into sshd-common (new artifact)
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
----------------------------------------------------------------------
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 c26a2d1..46f34a1 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
@@ -19,25 +19,11 @@
package org.apache.sshd.common.config;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamCorruptedException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
-import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.apache.sshd.common.BuiltinFactory;
@@ -52,17 +38,12 @@ import org.apache.sshd.common.helpers.AbstractFactoryManager;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchange;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.mac.BuiltinMacs;
import org.apache.sshd.common.mac.Mac;
import org.apache.sshd.common.signature.BuiltinSignatures;
import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseReader;
-import org.apache.sshd.common.util.net.SshdSocketAddress;
/**
* Reads and interprets some useful configurations from an OpenSSH
@@ -72,187 +53,10 @@ import org.apache.sshd.common.util.net.SshdSocketAddress;
* @see <a href="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">ssh_config(5)</a>
*/
public final class SshConfigFileReader {
-
- public static final char COMMENT_CHAR = '#';
-
- public static final String COMPRESSION_PROP = "Compression";
- public static final String DEFAULT_COMPRESSION = CompressionConfigValue.NO.getName();
- public static final String MAX_SESSIONS_CONFIG_PROP = "MaxSessions";
- public static final int DEFAULT_MAX_SESSIONS = 10;
- public static final String PASSWORD_AUTH_CONFIG_PROP = "PasswordAuthentication";
- public static final String DEFAULT_PASSWORD_AUTH = "no";
- public static final boolean DEFAULT_PASSWORD_AUTH_VALUE = parseBooleanValue(DEFAULT_PASSWORD_AUTH);
- public static final String LISTEN_ADDRESS_CONFIG_PROP = "ListenAddress";
- public static final String DEFAULT_BIND_ADDRESS = SshdSocketAddress.IPV4_ANYADDR;
- public static final String PORT_CONFIG_PROP = "Port";
- public static final int DEFAULT_PORT = 22;
- public static final String KEEP_ALIVE_CONFIG_PROP = "TCPKeepAlive";
- public static final boolean DEFAULT_KEEP_ALIVE = true;
- public static final String USE_DNS_CONFIG_PROP = "UseDNS";
- // NOTE: the usual default is TRUE
- public static final boolean DEFAULT_USE_DNS = true;
- public static final String PUBKEY_AUTH_CONFIG_PROP = "PubkeyAuthentication";
- public static final String DEFAULT_PUBKEY_AUTH = "yes";
- public static final boolean DEFAULT_PUBKEY_AUTH_VALUE = parseBooleanValue(DEFAULT_PUBKEY_AUTH);
- public static final String AUTH_KEYS_FILE_CONFIG_PROP = "AuthorizedKeysFile";
- public static final String MAX_AUTH_TRIES_CONFIG_PROP = "MaxAuthTries";
- public static final int DEFAULT_MAX_AUTH_TRIES = 6;
- public static final String MAX_STARTUPS_CONFIG_PROP = "MaxStartups";
- public static final int DEFAULT_MAX_STARTUPS = 10;
- public static final String LOGIN_GRACE_TIME_CONFIG_PROP = "LoginGraceTime";
- public static final long DEFAULT_LOGIN_GRACE_TIME = TimeUnit.SECONDS.toMillis(120);
- public static final String KEY_REGENERATE_INTERVAL_CONFIG_PROP = "KeyRegenerationInterval";
- public static final long DEFAULT_REKEY_TIME_LIMIT = TimeUnit.HOURS.toMillis(1L);
- // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
- public static final String CIPHERS_CONFIG_PROP = "Ciphers";
- public static final String DEFAULT_CIPHERS =
- "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour";
- // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
- public static final String MACS_CONFIG_PROP = "MACs";
- public static final String DEFAULT_MACS =
- "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-sha1-96,hmac-md5-96,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96";
- // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
- public static final String KEX_ALGORITHMS_CONFIG_PROP = "KexAlgorithms";
- public static final String DEFAULT_KEX_ALGORITHMS =
- "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521"
- + "," + "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1"
- // RFC-8268 groups
- + "," + "diffie-hellman-group18-sha512,diffie-hellman-group17-sha512"
- + "," + "diffie-hellman-group16-sha512,diffie-hellman-group15-sha512"
- + "," + "diffie-hellman-group14-sha256"
- // Legacy groups
- + "," + "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1";
- // see http://linux.die.net/man/5/ssh_config
- public static final String HOST_KEY_ALGORITHMS_CONFIG_PROP = "HostKeyAlgorithms";
- // see https://tools.ietf.org/html/rfc5656
- public static final String DEFAULT_HOST_KEY_ALGORITHMS =
- KeyPairProvider.SSH_RSA + "," + KeyPairProvider.SSH_DSS;
- // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
- public static final String LOG_LEVEL_CONFIG_PROP = "LogLevel";
- public static final LogLevelValue DEFAULT_LOG_LEVEL = LogLevelValue.INFO;
- // see https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5
- public static final String SYSLOG_FACILITY_CONFIG_PROP = "SyslogFacility";
- public static final SyslogFacilityValue DEFAULT_SYSLOG_FACILITY = SyslogFacilityValue.AUTH;
- public static final String SUBSYSTEM_CONFIG_PROP = "Subsystem";
-
private SshConfigFileReader() {
throw new UnsupportedOperationException("No instance allowed");
}
- public static Properties readConfigFile(File file) throws IOException {
- return readConfigFile(file.toPath(), IoUtils.EMPTY_OPEN_OPTIONS);
- }
-
- public static Properties readConfigFile(Path path, OpenOption... options) throws IOException {
- try (InputStream input = Files.newInputStream(path, options)) {
- return readConfigFile(input, true);
- }
- }
-
- public static Properties readConfigFile(URL url) throws IOException {
- try (InputStream input = url.openStream()) {
- return readConfigFile(input, true);
- }
- }
-
- public static Properties readConfigFile(String path) throws IOException {
- try (InputStream input = new FileInputStream(path)) {
- return readConfigFile(input, true);
- }
- }
-
- public static Properties readConfigFile(InputStream input, boolean okToClose) throws IOException {
- try (Reader reader = new InputStreamReader(NoCloseInputStream.resolveInputStream(input, okToClose), StandardCharsets.UTF_8)) {
- return readConfigFile(reader, true);
- }
- }
-
- public static Properties readConfigFile(Reader reader, boolean okToClose) throws IOException {
- try (BufferedReader buf = new BufferedReader(NoCloseReader.resolveReader(reader, okToClose))) {
- return readConfigFile(buf);
- }
- }
-
- /**
- * Reads the configuration file contents into a {@link Properties} instance.
- * <B>Note:</B> multiple keys value are concatenated using a comma - it is up to
- * the caller to know which keys are expected to have multiple values and handle
- * the split accordingly
- *
- * @param rdr The {@link BufferedReader} for reading the file
- * @return The read properties
- * @throws IOException If failed to read or malformed content
- */
- public static Properties readConfigFile(BufferedReader rdr) throws IOException {
- Properties props = new Properties();
- int lineNumber = 1;
- for (String line = rdr.readLine(); line != null; line = rdr.readLine(), lineNumber++) {
- line = GenericUtils.replaceWhitespaceAndTrim(line);
- if (GenericUtils.isEmpty(line)) {
- continue;
- }
-
- int pos = line.indexOf(COMMENT_CHAR);
- if (pos == 0) {
- continue;
- }
-
- if (pos > 0) {
- line = line.substring(0, pos);
- line = line.trim();
- }
-
- /*
- * Some options use '=', others use ' ' - try both
- * NOTE: we do not validate the format for each option separately
- */
- pos = line.indexOf(' ');
- if (pos < 0) {
- pos = line.indexOf('=');
- }
-
- if (pos < 0) {
- throw new StreamCorruptedException("No delimiter at line " + lineNumber + ": " + line);
- }
-
- String key = line.substring(0, pos);
- String value = line.substring(pos + 1).trim();
- // see if need to concatenate multi-valued keys
- String prev = props.getProperty(key);
- if (!GenericUtils.isEmpty(prev)) {
- value = prev + "," + value;
- }
-
- props.setProperty(key, value);
- }
-
- return props;
- }
-
- /**
- * @param v Checks if the value is "yes", "y"
- * or "on" or "true".
- * @return The result - <B>Note:</B> {@code null}/empty values are
- * interpreted as {@code false}
- */
- public static boolean parseBooleanValue(String v) {
- return "yes".equalsIgnoreCase(v)
- || "y".equalsIgnoreCase(v)
- || "on".equalsIgnoreCase(v)
- || "true".equalsIgnoreCase(v);
- }
-
- /**
- * Returns a "yes" or "no" value based on the input
- * parameter
- *
- * @param flag The required state
- * @return "yes" if {@code true}, "no" otherwise
- */
- public static String yesNoValueOf(boolean flag) {
- return flag ? "yes" : "no";
- }
-
/**
* @param props The {@link PropertyResolver} - ignored if {@code null}/empty
* @return A {@code ParseResult} of all the {@link NamedFactory}-ies
@@ -261,11 +65,12 @@ public final class SshConfigFileReader {
* is the same as the original order - bar the unknown ciphers.
* <B>Note:</B> it is up to caller to ensure that the lists do not
* contain duplicates
- * @see #CIPHERS_CONFIG_PROP
+ * @see ConfigFileReaderSupport#CIPHERS_CONFIG_PROP CIPHERS_CONFIG_PROP
* @see BuiltinCiphers#parseCiphersList(String)
*/
public static BuiltinCiphers.ParseResult getCiphers(PropertyResolver props) {
- return BuiltinCiphers.parseCiphersList((props == null) ? null : props.getString(CIPHERS_CONFIG_PROP));
+ return BuiltinCiphers.parseCiphersList(
+ (props == null) ? null : props.getString(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP));
}
/**
@@ -276,11 +81,12 @@ public final class SshConfigFileReader {
* is the same as the original order - bar the unknown MACs.
* <B>Note:</B> it is up to caller to ensure that the list does not
* contain duplicates
- * @see #MACS_CONFIG_PROP
+ * @see ConfigFileReaderSupport#MACS_CONFIG_PROP MACS_CONFIG_PROP
* @see BuiltinMacs#parseMacsList(String)
*/
public static BuiltinMacs.ParseResult getMacs(PropertyResolver props) {
- return BuiltinMacs.parseMacsList((props == null) ? null : props.getString(MACS_CONFIG_PROP));
+ return BuiltinMacs.parseMacsList(
+ (props == null) ? null : props.getString(ConfigFileReaderSupport.MACS_CONFIG_PROP));
}
/**
@@ -290,11 +96,12 @@ public final class SshConfigFileReader {
* unknown name is <U>ignored</U>. The order of the returned result is the
* same as the original order - bar the unknown signatures. <B>Note:</B> it
* is up to caller to ensure that the list does not contain duplicates
- * @see #HOST_KEY_ALGORITHMS_CONFIG_PROP
+ * @see ConfigFileReaderSupport#HOST_KEY_ALGORITHMS_CONFIG_PROP HOST_KEY_ALGORITHMS_CONFIG_PROP
* @see BuiltinSignatures#parseSignatureList(String)
*/
public static BuiltinSignatures.ParseResult getSignatures(PropertyResolver props) {
- return BuiltinSignatures.parseSignatureList((props == null) ? null : props.getString(HOST_KEY_ALGORITHMS_CONFIG_PROP));
+ return BuiltinSignatures.parseSignatureList(
+ (props == null) ? null : props.getString(ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP));
}
/**
@@ -304,30 +111,33 @@ public final class SshConfigFileReader {
* unknown name is <U>ignored</U>. The order of the returned result is the
* same as the original order - bar the unknown ones. <B>Note:</B> it is
* up to caller to ensure that the list does not contain duplicates
- * @see #KEX_ALGORITHMS_CONFIG_PROP
+ * @see ConfigFileReaderSupport#KEX_ALGORITHMS_CONFIG_PROP KEX_ALGORITHMS_CONFIG_PROP
* @see BuiltinDHFactories#parseDHFactoriesList(String)
*/
public static BuiltinDHFactories.ParseResult getKexFactories(PropertyResolver props) {
- return BuiltinDHFactories.parseDHFactoriesList((props == null) ? null : props.getString(KEX_ALGORITHMS_CONFIG_PROP));
+ return BuiltinDHFactories.parseDHFactoriesList(
+ (props == null) ? null : props.getString(ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP));
}
/**
* @param props The {@link PropertyResolver} - ignored if {@code null}/empty
* @return The matching {@link NamedFactory} for the configured value.
* {@code null} if no configuration or unknown name specified
+ * @see ConfigFileReaderSupport#COMPRESSION_PROP COMPRESSION_PROP
*/
public static CompressionFactory getCompression(PropertyResolver props) {
- return CompressionConfigValue.fromName((props == null) ? null : props.getString(COMPRESSION_PROP));
+ return CompressionConfigValue.fromName(
+ (props == null) ? null : props.getString(ConfigFileReaderSupport.COMPRESSION_PROP));
}
/**
* <P>Configures an {@link AbstractFactoryManager} with the values read from
* some configuration. Currently it configures:</P>
* <UL>
- * <LI>The {@link Cipher}s - via the {@link #CIPHERS_CONFIG_PROP}</LI>
- * <LI>The {@link Mac}s - via the {@link #MACS_CONFIG_PROP}</LI>
- * <LI>The {@link Signature}s - via the {@link #HOST_KEY_ALGORITHMS_CONFIG_PROP}</LI>
- * <LI>The {@link Compression} - via the {@link #COMPRESSION_PROP}</LI>
+ * <LI>The {@link Cipher}s - via the {@link ConfigFileReaderSupport#CIPHERS_CONFIG_PROP}</LI>
+ * <LI>The {@link Mac}s - via the {@link ConfigFileReaderSupport#MACS_CONFIG_PROP}</LI>
+ * <LI>The {@link Signature}s - via the {@link ConfigFileReaderSupport#HOST_KEY_ALGORITHMS_CONFIG_PROP}</LI>
+ * <LI>The {@link Compression} - via the {@link ConfigFileReaderSupport#COMPRESSION_PROP}</LI>
* </UL>
*
* @param <M> The generic factory manager
@@ -342,7 +152,8 @@ public final class SshConfigFileReader {
* or unsupported values there is an empty configuration exception is thrown
* @return The configured manager
*/
- public static <M extends AbstractFactoryManager> M configure(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configure(
+ M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
configureCiphers(manager, props, lenient, ignoreUnsupported);
configureSignatures(manager, props, lenient, ignoreUnsupported);
configureMacs(manager, props, lenient, ignoreUnsupported);
@@ -353,10 +164,13 @@ public final class SshConfigFileReader {
public static <M extends AbstractFactoryManager> M configureCiphers(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
- return configureCiphers(manager, props.getStringProperty(CIPHERS_CONFIG_PROP, DEFAULT_CIPHERS), lenient, ignoreUnsupported);
+ return configureCiphers(manager,
+ props.getStringProperty(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_CIPHERS),
+ lenient, ignoreUnsupported);
}
- public static <M extends AbstractFactoryManager> M configureCiphers(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureCiphers(
+ M manager, String value, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(manager, "No manager to configure");
BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(value);
@@ -371,10 +185,13 @@ public final class SshConfigFileReader {
public static <M extends AbstractFactoryManager> M configureSignatures(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
- return configureSignatures(manager, props.getStringProperty(HOST_KEY_ALGORITHMS_CONFIG_PROP, DEFAULT_HOST_KEY_ALGORITHMS), lenient, ignoreUnsupported);
+ return configureSignatures(manager,
+ props.getStringProperty(ConfigFileReaderSupport.HOST_KEY_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_HOST_KEY_ALGORITHMS),
+ lenient, ignoreUnsupported);
}
- public static <M extends AbstractFactoryManager> M configureSignatures(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureSignatures(
+ M manager, String value, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(manager, "No manager to configure");
BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(value);
@@ -387,12 +204,16 @@ public final class SshConfigFileReader {
return manager;
}
- public static <M extends AbstractFactoryManager> M configureMacs(M manager, PropertyResolver resolver, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureMacs(
+ M manager, PropertyResolver resolver, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(resolver, "No properties to configure");
- return configureMacs(manager, resolver.getStringProperty(MACS_CONFIG_PROP, DEFAULT_MACS), lenient, ignoreUnsupported);
+ return configureMacs(manager,
+ resolver.getStringProperty(ConfigFileReaderSupport.MACS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_MACS),
+ lenient, ignoreUnsupported);
}
- public static <M extends AbstractFactoryManager> M configureMacs(M manager, String value, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureMacs(
+ M manager, String value, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(manager, "No manager to configure");
BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(value);
@@ -417,13 +238,15 @@ public final class SshConfigFileReader {
* if after ignoring the unknown and un-supported values the result is an empty
* list of factories and exception is thrown
* @return The configured manager
- * @see #KEX_ALGORITHMS_CONFIG_PROP
- * @see #DEFAULT_KEX_ALGORITHMS
+ * @see ConfigFileReaderSupport#KEX_ALGORITHMS_CONFIG_PROP KEX_ALGORITHMS_CONFIG_PROP
+ * @see ConfigFileReaderSupport#DEFAULT_KEX_ALGORITHMS DEFAULT_KEX_ALGORITHMS
*/
public static <M extends AbstractFactoryManager> M configureKeyExchanges(
M manager, PropertyResolver props, boolean lenient, Function<? super DHFactory, ? extends NamedFactory<KeyExchange>> xformer, boolean ignoreUnsupported) {
Objects.requireNonNull(props, "No properties to configure");
- return configureKeyExchanges(manager, props.getStringProperty(KEX_ALGORITHMS_CONFIG_PROP, DEFAULT_KEX_ALGORITHMS), lenient, xformer, ignoreUnsupported);
+ return configureKeyExchanges(manager,
+ props.getStringProperty(ConfigFileReaderSupport.KEX_ALGORITHMS_CONFIG_PROP, ConfigFileReaderSupport.DEFAULT_KEX_ALGORITHMS),
+ lenient, xformer, ignoreUnsupported);
}
public static <M extends AbstractFactoryManager> M configureKeyExchanges(
@@ -454,11 +277,12 @@ public final class SshConfigFileReader {
* @return The configured manager - <B>Note:</B> if the result of filtering due
* to lenient mode or ignored unsupported value is empty then no factories are set
*/
- public static <M extends AbstractFactoryManager> M configureCompression(M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
+ public static <M extends AbstractFactoryManager> M configureCompression(
+ M manager, PropertyResolver props, boolean lenient, boolean ignoreUnsupported) {
Objects.requireNonNull(manager, "No manager to configure");
Objects.requireNonNull(props, "No properties to configure");
- String value = props.getStringProperty(COMPRESSION_PROP, DEFAULT_COMPRESSION);
+ String value = props.getStringProperty(ConfigFileReaderSupport.COMPRESSION_PROP, ConfigFileReaderSupport.DEFAULT_COMPRESSION);
CompressionFactory factory = CompressionConfigValue.fromName(value);
ValidateUtils.checkTrue(lenient || (factory != null), "Unsupported compression value: %s", value);
if ((factory != null) && factory.isSupported()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
deleted file mode 100644
index f52ae36..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
+++ /dev/null
@@ -1,51 +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.common.config;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5"><I>SyslogFacility</I> configuration value</A>
- */
-public enum SyslogFacilityValue {
- DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7;
-
- public static final Set<SyslogFacilityValue> VALUES =
- Collections.unmodifiableSet(EnumSet.allOf(SyslogFacilityValue.class));
-
- public static SyslogFacilityValue fromName(String n) {
- if (GenericUtils.isEmpty(n)) {
- return null;
- }
-
- for (SyslogFacilityValue f : VALUES) {
- if (n.equalsIgnoreCase(f.name())) {
- return f;
- }
- }
-
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java b/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
deleted file mode 100644
index 222cf84..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
+++ /dev/null
@@ -1,180 +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.common.config;
-
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="http://unixhelp.ed.ac.uk/CGI/man-cgi?sshd_config+5">Time formats for SSH configuration values</A>
- */
-public enum TimeValueConfig {
- SECONDS('s', 'S', TimeUnit.SECONDS.toMillis(1L)),
- MINUTES('m', 'M', TimeUnit.MINUTES.toMillis(1L)),
- HOURS('h', 'H', TimeUnit.HOURS.toMillis(1L)),
- DAYS('d', 'D', TimeUnit.DAYS.toMillis(1L)),
- WEEKS('w', 'W', TimeUnit.DAYS.toMillis(7L));
-
- public static final Set<TimeValueConfig> VALUES =
- Collections.unmodifiableSet(EnumSet.allOf(TimeValueConfig.class));
-
- private final char loChar;
- private final char hiChar;
- private final long interval;
-
- TimeValueConfig(char lo, char hi, long interval) {
- loChar = lo;
- hiChar = hi;
- this.interval = interval;
- }
-
- public final char getLowerCaseValue() {
- return loChar;
- }
-
- public final char getUpperCaseValue() {
- return hiChar;
- }
-
- public final long getInterval() {
- return interval;
- }
-
- public static TimeValueConfig fromValueChar(char ch) {
- if ((ch <= ' ') || (ch >= 0x7F)) {
- return null;
- }
-
- for (TimeValueConfig v : VALUES) {
- if ((v.getLowerCaseValue() == ch) || (v.getUpperCaseValue() == ch)) {
- return v;
- }
- }
-
- return null;
- }
-
- /**
- * @param s A time specification
- * @return The specified duration in milliseconds
- * @see #parse(String)
- * @see #durationOf(Map)
- */
- public static long durationOf(String s) {
- Map<TimeValueConfig, Long> spec = parse(s);
- return durationOf(spec);
- }
-
- /**
- * @param s An input time specification containing possibly mixed numbers
- * and units - e.g., {@code 3h10m} to indicate 3 hours and 10 minutes
- * @return A {@link Map} specifying for each time unit its count
- * @throws NumberFormatException If bad numbers found - e.g., negative counts
- * @throws IllegalArgumentException If bad format - e.g., unknown unit
- */
- public static Map<TimeValueConfig, Long> parse(String s) throws IllegalArgumentException {
- if (GenericUtils.isEmpty(s)) {
- return Collections.emptyMap();
- }
-
- int lastPos = 0;
- Map<TimeValueConfig, Long> spec = new EnumMap<>(TimeValueConfig.class);
- for (int curPos = 0; curPos < s.length(); curPos++) {
- char ch = s.charAt(curPos);
- if ((ch >= '0') && (ch <= '9')) {
- continue;
- }
-
- if (curPos <= lastPos) {
- throw new IllegalArgumentException("parse(" + s + ") missing count value at index=" + curPos);
- }
-
- TimeValueConfig c = fromValueChar(ch);
- if (c == null) {
- throw new IllegalArgumentException("parse(" + s + ") unknown time value character: '" + ch + "'");
- }
-
- String v = s.substring(lastPos, curPos);
- long count = Long.parseLong(v);
- if (count < 0L) {
- throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for " + c.name());
- }
-
- Long prev = spec.put(c, count);
- if (prev != null) {
- throw new IllegalArgumentException("parse(" + s + ") " + c.name() + " value re-specified: current=" + count + ", previous=" + prev);
- }
-
- lastPos = curPos + 1;
- if (lastPos >= s.length()) {
- break;
- }
- }
-
- if (lastPos < s.length()) {
- String v = s.substring(lastPos);
- long count = Long.parseLong(v);
- if (count < 0L) {
- throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for last component");
- }
-
- Long prev = spec.put(SECONDS, count);
- if (prev != null) {
- throw new IllegalArgumentException("parse(" + s + ") last component (" + SECONDS.name() + ") value re-specified: current=" + count + ", previous=" + prev);
- }
- }
-
- return spec;
- }
-
- /**
- * @param spec The {@link Map} specifying the count for each {@link TimeValueConfig}
- * @return The total duration in milliseconds
- * @throws IllegalArgumentException If negative count for a time unit
- */
- public static long durationOf(Map<TimeValueConfig, ? extends Number> spec) throws IllegalArgumentException {
- if (GenericUtils.isEmpty(spec)) {
- return -1L;
- }
-
- long total = 0L;
- // Cannot use forEach because the total value is not effectively final
- for (Map.Entry<TimeValueConfig, ? extends Number> se : spec.entrySet()) {
- TimeValueConfig v = se.getKey();
- Number c = se.getValue();
- long factor = c.longValue();
- if (factor < 0L) {
- throw new IllegalArgumentException("valueOf(" + spec + ") bad factor (" + c + ") for " + v.name());
- }
-
- long added = v.getInterval() * factor;
- total += added;
- }
-
- return total;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java b/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
deleted file mode 100644
index 0e351a8..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/VersionProperties.java
+++ /dev/null
@@ -1,98 +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.common.config;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Collections;
-import java.util.NavigableMap;
-import java.util.Properties;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.threads.ThreadUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class VersionProperties {
- private static final class LazyVersionPropertiesHolder {
- private static final NavigableMap<String, String> PROPERTIES =
- Collections.unmodifiableNavigableMap(loadVersionProperties(LazyVersionPropertiesHolder.class));
-
- private LazyVersionPropertiesHolder() {
- throw new UnsupportedOperationException("No instance allowed");
- }
-
- private static NavigableMap<String, String> loadVersionProperties(Class<?> anchor) {
- return loadVersionProperties(anchor, ThreadUtils.resolveDefaultClassLoader(anchor));
- }
-
- private static NavigableMap<String, String> loadVersionProperties(Class<?> anchor, ClassLoader loader) {
- NavigableMap<String, String> result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- try {
- InputStream input = loader.getResourceAsStream("org/apache/sshd/sshd-version.properties");
- if (input == null) {
- throw new FileNotFoundException("Version resource does not exist");
- }
-
- Properties props = new Properties();
- try {
- props.load(input);
- } finally {
- input.close();
- }
-
- for (String key : props.stringPropertyNames()) {
- String propValue = props.getProperty(key);
- String value = GenericUtils.trimToEmpty(propValue);
- if (GenericUtils.isEmpty(value)) {
- continue; // we have no need for empty values
- }
-
- String prev = result.put(key, value);
- if (prev != null) {
- Logger log = LoggerFactory.getLogger(anchor);
- log.warn("Multiple values for key=" + key + ": current=" + value + ", previous=" + prev);
- }
- }
- } catch (Exception e) {
- Logger log = LoggerFactory.getLogger(anchor);
- log.warn("Failed (" + e.getClass().getSimpleName() + ") to load version properties: " + e.getMessage());
- }
-
- return result;
- }
- }
-
- private VersionProperties() {
- throw new UnsupportedOperationException("No instance");
- }
-
- /**
- * @return A case <u>insensitive</u> un-modifiable {@link NavigableMap} of the {@code sshd-version.properties} data
- */
- @SuppressWarnings("synthetic-access")
- public static NavigableMap<String, String> getVersionProperties() {
- return LazyVersionPropertiesHolder.PROPERTIES;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
deleted file mode 100644
index a763903..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java
+++ /dev/null
@@ -1,492 +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.common.config.keys;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamCorruptedException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.PublicKey;
-import java.util.AbstractMap.SimpleImmutableEntry;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseReader;
-import org.apache.sshd.server.auth.pubkey.KeySetPublickeyAuthenticator;
-import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
-import org.apache.sshd.server.auth.pubkey.RejectAllPublickeyAuthenticator;
-
-/**
- * Represents an entry in the user's {@code authorized_keys} file according
- * to the <A HREF="http://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#.7E.2F.ssh.2Fauthorized_keys">OpenSSH format</A>.
- * <B>Note:</B> {@code equals/hashCode} check only the key type and data - the
- * comment and/or login options are not considered part of equality
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
- */
-public class AuthorizedKeyEntry extends PublicKeyEntry {
- public static final char BOOLEAN_OPTION_NEGATION_INDICATOR = '!';
-
- private static final long serialVersionUID = -9007505285002809156L;
-
- private String comment;
- // for options that have no value, "true" is used
- private Map<String, String> loginOptions = Collections.emptyMap();
-
- public AuthorizedKeyEntry() {
- super();
- }
-
- public String getComment() {
- return comment;
- }
-
- public void setComment(String value) {
- this.comment = value;
- }
-
- public Map<String, String> getLoginOptions() {
- return loginOptions;
- }
-
- public void setLoginOptions(Map<String, String> value) {
- if (value == null) {
- this.loginOptions = Collections.emptyMap();
- } else {
- this.loginOptions = value;
- }
- }
-
- @Override
- public PublicKey appendPublicKey(Appendable sb, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException {
- Map<String, String> options = getLoginOptions();
- if (!GenericUtils.isEmpty(options)) {
- int index = 0;
- // Cannot use forEach because the index value is not effectively final
- for (Map.Entry<String, String> oe : options.entrySet()) {
- String key = oe.getKey();
- String value = oe.getValue();
- if (index > 0) {
- sb.append(',');
- }
- sb.append(key);
- // TODO figure out a way to remember which options where quoted
- // TODO figure out a way to remember which options had no value
- if (!Boolean.TRUE.toString().equals(value)) {
- sb.append('=').append(value);
- }
- index++;
- }
-
- if (index > 0) {
- sb.append(' ');
- }
- }
-
- PublicKey key = super.appendPublicKey(sb, fallbackResolver);
- String kc = getComment();
- if (!GenericUtils.isEmpty(kc)) {
- sb.append(' ').append(kc);
- }
-
- return key;
- }
-
- @Override // to avoid Findbugs[EQ_DOESNT_OVERRIDE_EQUALS]
- public int hashCode() {
- return super.hashCode();
- }
-
- @Override // to avoid Findbugs[EQ_DOESNT_OVERRIDE_EQUALS]
- public boolean equals(Object obj) {
- return super.equals(obj);
- }
-
- @Override
- public String toString() {
- String entry = super.toString();
- String kc = getComment();
- Map<?, ?> ko = getLoginOptions();
- return (GenericUtils.isEmpty(ko) ? "" : ko.toString() + " ")
- + entry
- + (GenericUtils.isEmpty(kc) ? "" : " " + kc);
- }
-
- public static PublickeyAuthenticator fromAuthorizedEntries(PublicKeyEntryResolver fallbackResolver, Collection<? extends AuthorizedKeyEntry> entries)
- throws IOException, GeneralSecurityException {
- Collection<PublicKey> keys = resolveAuthorizedKeys(fallbackResolver, entries);
- if (GenericUtils.isEmpty(keys)) {
- return RejectAllPublickeyAuthenticator.INSTANCE;
- } else {
- return new KeySetPublickeyAuthenticator(keys);
- }
- }
-
- public static List<PublicKey> resolveAuthorizedKeys(PublicKeyEntryResolver fallbackResolver, Collection<? extends AuthorizedKeyEntry> entries)
- throws IOException, GeneralSecurityException {
- if (GenericUtils.isEmpty(entries)) {
- return Collections.emptyList();
- }
-
- List<PublicKey> keys = new ArrayList<>(entries.size());
- for (AuthorizedKeyEntry e : entries) {
- PublicKey k = e.resolvePublicKey(fallbackResolver);
- if (k != null) {
- keys.add(k);
- }
- }
-
- return keys;
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param url The {@link URL} to read from
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(InputStream, boolean)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(URL url) throws IOException {
- try (InputStream in = url.openStream()) {
- return readAuthorizedKeys(in, true);
- }
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param file The {@link File} to read from
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(InputStream, boolean)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(File file) throws IOException {
- try (InputStream in = new FileInputStream(file)) {
- return readAuthorizedKeys(in, true);
- }
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param path {@link Path} to read from
- * @param options The {@link OpenOption}s to use - if unspecified then appropriate
- * defaults assumed
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(InputStream, boolean)
- * @see Files#newInputStream(Path, OpenOption...)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(Path path, OpenOption... options) throws IOException {
- try (InputStream in = Files.newInputStream(path, options)) {
- return readAuthorizedKeys(in, true);
- }
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param filePath The file path to read from
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(InputStream, boolean)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(String filePath) throws IOException {
- try (InputStream in = new FileInputStream(filePath)) {
- return readAuthorizedKeys(in, true);
- }
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param in The {@link InputStream}
- * @param okToClose <code>true</code> if method may close the input stream
- * regardless of whether successful or failed
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(Reader, boolean)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(InputStream in, boolean okToClose) throws IOException {
- try (Reader rdr = new InputStreamReader(NoCloseInputStream.resolveInputStream(in, okToClose), StandardCharsets.UTF_8)) {
- return readAuthorizedKeys(rdr, true);
- }
- }
-
- /**
- * Reads read the contents of an <code>authorized_keys</code> file
- *
- * @param rdr The {@link Reader}
- * @param okToClose <code>true</code> if method may close the input stream
- * regardless of whether successful or failed
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #readAuthorizedKeys(BufferedReader)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(Reader rdr, boolean okToClose) throws IOException {
- try (BufferedReader buf = new BufferedReader(NoCloseReader.resolveReader(rdr, okToClose))) {
- return readAuthorizedKeys(buf);
- }
- }
-
- /**
- * @param rdr The {@link BufferedReader} to use to read the contents of
- * an <code>authorized_keys</code> file
- * @return A {@link List} of all the {@link AuthorizedKeyEntry}-ies found there
- * @throws IOException If failed to read or parse the entries
- * @see #parseAuthorizedKeyEntry(String)
- */
- public static List<AuthorizedKeyEntry> readAuthorizedKeys(BufferedReader rdr) throws IOException {
- List<AuthorizedKeyEntry> entries = null;
-
- for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
- AuthorizedKeyEntry entry;
- try {
- entry = parseAuthorizedKeyEntry(line);
- if (entry == null) { // null, empty or comment line
- continue;
- }
- } catch (RuntimeException | Error e) {
- throw new StreamCorruptedException("Failed (" + e.getClass().getSimpleName() + ")"
- + " to parse key entry=" + line + ": " + e.getMessage());
- }
-
- if (entries == null) {
- entries = new ArrayList<>();
- }
-
- entries.add(entry);
- }
-
- if (entries == null) {
- return Collections.emptyList();
- } else {
- return entries;
- }
- }
-
- /**
- * @param value Original line from an <code>authorized_keys</code> file
- * @return {@link AuthorizedKeyEntry} or {@code null} if the line is
- * {@code null}/empty or a comment line
- * @throws IllegalArgumentException If failed to parse/decode the line
- * @see #COMMENT_CHAR
- */
- public static AuthorizedKeyEntry parseAuthorizedKeyEntry(String value) throws IllegalArgumentException {
- String line = GenericUtils.replaceWhitespaceAndTrim(value);
- if (GenericUtils.isEmpty(line) || (line.charAt(0) == COMMENT_CHAR) /* comment ? */) {
- return null;
- }
-
- int startPos = line.indexOf(' ');
- if (startPos <= 0) {
- throw new IllegalArgumentException("Bad format (no key data delimiter): " + line);
- }
-
- int endPos = line.indexOf(' ', startPos + 1);
- if (endPos <= startPos) {
- endPos = line.length();
- }
-
- String keyType = line.substring(0, startPos);
- PublicKeyEntryDecoder<?, ?> decoder = KeyUtils.getPublicKeyEntryDecoder(keyType);
- AuthorizedKeyEntry entry;
- // assume this is due to the fact that it starts with login options
- if (decoder == null) {
- Map.Entry<String, String> comps = resolveEntryComponents(line);
- entry = parseAuthorizedKeyEntry(comps.getValue());
- ValidateUtils.checkTrue(entry != null, "Bad format (no key data after login options): %s", line);
- entry.setLoginOptions(parseLoginOptions(comps.getKey()));
- } else {
- String encData = (endPos < (line.length() - 1)) ? line.substring(0, endPos).trim() : line;
- String comment = (endPos < (line.length() - 1)) ? line.substring(endPos + 1).trim() : null;
- entry = parsePublicKeyEntry(new AuthorizedKeyEntry(), encData);
- entry.setComment(comment);
- }
-
- return entry;
- }
-
- /**
- * Parses a single line from an <code>authorized_keys</code> file that is <U>known</U>
- * to contain login options and separates it to the options and the rest of the line.
- *
- * @param entryLine The line to be parsed
- * @return A {@link SimpleImmutableEntry} representing the parsed data where key=login options part
- * and value=rest of the data - {@code null} if no data in line or line starts with comment character
- * @see <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
- */
- public static SimpleImmutableEntry<String, String> resolveEntryComponents(String entryLine) {
- String line = GenericUtils.replaceWhitespaceAndTrim(entryLine);
- if (GenericUtils.isEmpty(line) || (line.charAt(0) == COMMENT_CHAR) /* comment ? */) {
- return null;
- }
-
- for (int lastPos = 0; lastPos < line.length();) {
- int startPos = line.indexOf(' ', lastPos);
- if (startPos < lastPos) {
- throw new IllegalArgumentException("Bad format (no key data delimiter): " + line);
- }
-
- int quotePos = line.indexOf('"', startPos + 1);
- // If found quotes after the space then assume part of a login option
- if (quotePos > startPos) {
- lastPos = quotePos + 1;
- continue;
- }
-
- String loginOptions = line.substring(0, startPos).trim();
- String remainder = line.substring(startPos + 1).trim();
- return new SimpleImmutableEntry<>(loginOptions, remainder);
- }
-
- throw new IllegalArgumentException("Bad format (no key data contents): " + line);
- }
-
- /**
- * <P>
- * Parses login options line according to
- * <A HREF="http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT">sshd(8) - AUTHORIZED_KEYS_FILE_FORMAT</A>
- * guidelines. <B>Note:</B>
- * </P>
- *
- * <UL>
- * <P><LI>
- * Options that have a value are automatically stripped of any surrounding double quotes./
- * </LI></P>
- *
- * <P><LI>
- * Options that have no value are marked as {@code true/false} - according
- * to the {@link #BOOLEAN_OPTION_NEGATION_INDICATOR}.
- * </LI></P>
- *
- * <P><LI>
- * Options that appear multiple times are simply concatenated using comma as separator.
- * </LI></P>
- * </UL>
- *
- * @param options The options line to parse - ignored if {@code null}/empty/blank
- * @return A {@link NavigableMap} where key=case <U>insensitive</U> option name and value=the parsed value.
- * @see #addLoginOption(Map, String) addLoginOption
- */
- public static NavigableMap<String, String> parseLoginOptions(String options) {
- String line = GenericUtils.replaceWhitespaceAndTrim(options);
- int len = GenericUtils.length(line);
- if (len <= 0) {
- return Collections.emptyNavigableMap();
- }
-
- NavigableMap<String, String> optsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- int lastPos = 0;
- for (int curPos = 0; curPos < len; curPos++) {
- int nextPos = line.indexOf(',', curPos);
- if (nextPos < curPos) {
- break;
- }
-
- // check if "true" comma or one inside quotes
- int quotePos = line.indexOf('"', curPos);
- if ((quotePos >= lastPos) && (quotePos < nextPos)) {
- nextPos = line.indexOf('"', quotePos + 1);
- if (nextPos <= quotePos) {
- throw new IllegalArgumentException("Bad format (imbalanced quoted command): " + line);
- }
-
- // Make sure either comma or no more options follow the 2nd quote
- for (nextPos++; nextPos < len; nextPos++) {
- char ch = line.charAt(nextPos);
- if (ch == ',') {
- break;
- }
-
- if (ch != ' ') {
- throw new IllegalArgumentException("Bad format (incorrect list format): " + line);
- }
- }
- }
-
- addLoginOption(optsMap, line.substring(lastPos, nextPos));
- lastPos = nextPos + 1;
- curPos = lastPos;
- }
-
- // Any leftovers at end of line ?
- if (lastPos < len) {
- addLoginOption(optsMap, line.substring(lastPos));
- }
-
- return optsMap;
- }
-
- /**
- * Parses and adds a new option to the options map. If a valued option is re-specified then
- * its value(s) are concatenated using comma as separator.
- *
- * @param optsMap Options map to add to
- * @param option The option data to parse - ignored if {@code null}/empty/blank
- * @return The updated entry - {@code null} if no option updated in the map
- * @throws IllegalStateException If a boolean option is re-specified
- */
- public static SimpleImmutableEntry<String, String> addLoginOption(Map<String, String> optsMap, String option) {
- String p = GenericUtils.trimToEmpty(option);
- if (GenericUtils.isEmpty(p)) {
- return null;
- }
-
- int pos = p.indexOf('=');
- String name = (pos < 0) ? p : GenericUtils.trimToEmpty(p.substring(0, pos));
- CharSequence value = (pos < 0) ? null : GenericUtils.trimToEmpty(p.substring(pos + 1));
- value = GenericUtils.stripQuotes(value);
- if (value == null) {
- value = Boolean.toString(name.charAt(0) != BOOLEAN_OPTION_NEGATION_INDICATOR);
- }
-
- SimpleImmutableEntry<String, String> entry = new SimpleImmutableEntry<>(name, value.toString());
- String prev = optsMap.put(entry.getKey(), entry.getValue());
- if (prev != null) {
- if (pos < 0) {
- throw new IllegalStateException("Bad format (boolean option (" + name + ") re-specified): " + p);
- }
- optsMap.put(entry.getKey(), prev + "," + entry.getValue());
- }
-
- return entry;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
deleted file mode 100644
index 53b6b44..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/BuiltinIdentities.java
+++ /dev/null
@@ -1,212 +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.common.config.keys;
-
-import java.security.Key;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Objects;
-import java.util.Set;
-
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public enum BuiltinIdentities implements Identity {
- RSA(Constants.RSA, RSAPublicKey.class, RSAPrivateKey.class),
- DSA(Constants.DSA, DSAPublicKey.class, DSAPrivateKey.class),
- ECDSA(Constants.ECDSA, KeyUtils.EC_ALGORITHM, ECPublicKey.class, ECPrivateKey.class) {
- @Override
- public boolean isSupported() {
- return SecurityUtils.isECCSupported();
- }
- },
- ED25119(Constants.ED25519, SecurityUtils.EDDSA, SecurityUtils.getEDDSAPublicKeyType(), SecurityUtils.getEDDSAPrivateKeyType()) {
- @Override
- public boolean isSupported() {
- return SecurityUtils.isEDDSACurveSupported();
- }
- };
-
- public static final Set<BuiltinIdentities> VALUES =
- Collections.unmodifiableSet(EnumSet.allOf(BuiltinIdentities.class));
-
- public static final Set<String> NAMES =
- Collections.unmodifiableSet(
- GenericUtils.asSortedSet(
- String.CASE_INSENSITIVE_ORDER, NamedResource.getNameList(VALUES)));
-
- private final String name;
- private final String algorithm;
- private final Class<? extends PublicKey> pubType;
- private final Class<? extends PrivateKey> prvType;
-
- BuiltinIdentities(String type, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
- this(type, type, pubType, prvType);
- }
-
- BuiltinIdentities(String name, String algorithm, Class<? extends PublicKey> pubType, Class<? extends PrivateKey> prvType) {
- this.name = name.toLowerCase();
- this.algorithm = algorithm.toUpperCase();
- this.pubType = pubType;
- this.prvType = prvType;
- }
-
- @Override
- public final String getName() {
- return name;
- }
-
- @Override
- public boolean isSupported() {
- return true;
- }
-
- @Override
- public String getAlgorithm() {
- return algorithm;
- }
-
- @Override
- public final Class<? extends PublicKey> getPublicKeyType() {
- return pubType;
- }
-
- @Override
- public final Class<? extends PrivateKey> getPrivateKeyType() {
- return prvType;
- }
-
- /**
- * @param name The identity name - ignored if {@code null}/empty
- * @return The matching {@link BuiltinIdentities} whose {@link #getName()}
- * value matches case <U>insensitive</U> or {@code null} if no match found
- */
- public static BuiltinIdentities fromName(String name) {
- return NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES);
- }
-
- /**
- * @param algorithm The algorithm - ignored if {@code null}/empty
- * @return The matching {@link BuiltinIdentities} whose {@link #getAlgorithm()}
- * value matches case <U>insensitive</U> or {@code null} if no match found
- */
- public static BuiltinIdentities fromAlgorithm(String algorithm) {
- if (GenericUtils.isEmpty(algorithm)) {
- return null;
- }
-
- for (BuiltinIdentities id : VALUES) {
- if (algorithm.equalsIgnoreCase(id.getAlgorithm())) {
- return id;
- }
- }
-
- return null;
- }
-
- /**
- * @param kp The {@link KeyPair} - ignored if {@code null}
- * @return The matching {@link BuiltinIdentities} provided <U>both</U>
- * public and public keys are of the same type - {@code null} if no
- * match could be found
- * @see #fromKey(Key)
- */
- public static BuiltinIdentities fromKeyPair(KeyPair kp) {
- if (kp == null) {
- return null;
- }
-
- BuiltinIdentities i1 = fromKey(kp.getPublic());
- BuiltinIdentities i2 = fromKey(kp.getPrivate());
- if (Objects.equals(i1, i2)) {
- return i1;
- } else {
- return null; // some kind of mixed keys...
- }
- }
-
- /**
- * @param key The {@link Key} instance - ignored if {@code null}
- * @return The matching {@link BuiltinIdentities} whose either public or
- * private key type matches the requested one or {@code null} if no match found
- * @see #fromKeyType(Class)
- */
- public static BuiltinIdentities fromKey(Key key) {
- return fromKeyType((key == null) ? null : key.getClass());
- }
-
- /**
- * @param clazz The key type - ignored if {@code null} or not
- * a {@link Key} class
- * @return The matching {@link BuiltinIdentities} whose either public or
- * private key type matches the requested one or {@code null} if no match found
- * @see #getPublicKeyType()
- * @see #getPrivateKeyType()
- */
- public static BuiltinIdentities fromKeyType(Class<?> clazz) {
- if ((clazz == null) || (!Key.class.isAssignableFrom(clazz))) {
- return null;
- }
-
- for (BuiltinIdentities id : VALUES) {
- Class<?> pubType = id.getPublicKeyType();
- Class<?> prvType = id.getPrivateKeyType();
- // Ignore placeholder classes (e.g., if ed25519 is not supported)
- if ((prvType == null) || (pubType == null)) {
- continue;
- }
- if ((prvType == PrivateKey.class) || (pubType == PublicKey.class)) {
- continue;
- }
- if (pubType.isAssignableFrom(clazz) || prvType.isAssignableFrom(clazz)) {
- return id;
- }
- }
-
- return null;
- }
-
- /**
- * Contains the names of the identities
- */
- public static final class Constants {
- public static final String RSA = KeyUtils.RSA_ALGORITHM;
- public static final String DSA = KeyUtils.DSS_ALGORITHM;
- public static final String ECDSA = "ECDSA";
- public static final String ED25519 = "ED25519";
-
- private Constants() {
- throw new UnsupportedOperationException("No instance allowed");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
deleted file mode 100644
index 064f75c..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/FilePasswordProvider.java
+++ /dev/null
@@ -1,45 +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.common.config.keys;
-
-import java.io.IOException;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface FilePasswordProvider {
- /**
- * An "empty" provider that returns {@code null} - i.e., unprotected key file
- */
- FilePasswordProvider EMPTY = resourceKey -> null;
-
- /**
- * @param resourceKey The resource key representing the <U>private</U>
- * file
- * @return The password - if {@code null}/empty then no password is required
- * @throws IOException if cannot resolve password
- */
- String getPassword(String resourceKey) throws IOException;
-
- static FilePasswordProvider of(String password) {
- return r -> password;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
deleted file mode 100644
index eaec413..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/Identity.java
+++ /dev/null
@@ -1,42 +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.common.config.keys;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.OptionalFeature;
-
-/**
- * Represents an SSH key type
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface Identity extends NamedResource, OptionalFeature {
- /**
- * @return The key algorithm - e.g., RSA, DSA, EC
- */
- String getAlgorithm();
-
- Class<? extends PublicKey> getPublicKeyType();
-
- Class<? extends PrivateKey> getPrivateKeyType();
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
deleted file mode 100644
index d826821..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityResourceLoader.java
+++ /dev/null
@@ -1,49 +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.common.config.keys;
-
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.util.Collection;
-
-/**
- * @param <PUB> Type of {@link PublicKey}
- * @param <PRV> Type of {@link PrivateKey}
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface IdentityResourceLoader<PUB extends PublicKey, PRV extends PrivateKey> {
- /**
- * @return The {@link Class} of the {@link PublicKey} that is the result
- * of decoding
- */
- Class<PUB> getPublicKeyType();
-
- /**
- * @return The {@link Class} of the {@link PrivateKey} that matches the
- * public one
- */
- Class<PRV> getPrivateKeyType();
-
- /**
- * @return The {@link Collection} of {@code OpenSSH} key type names that
- * are supported by this decoder - e.g., ECDSA keys have several curve names.
- * <B>Caveat:</B> this collection may be un-modifiable...
- */
- Collection<String> getSupportedTypeNames();
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
deleted file mode 100644
index fbc3ce7..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java
+++ /dev/null
@@ -1,159 +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.common.config.keys;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class IdentityUtils {
- private IdentityUtils() {
- throw new UnsupportedOperationException("No instance");
- }
-
- private static final class LazyDefaultUserHomeFolderHolder {
- private static final Path PATH =
- Paths.get(ValidateUtils.checkNotNullAndNotEmpty(System.getProperty("user.home"), "No user home"))
- .toAbsolutePath()
- .normalize();
-
- private LazyDefaultUserHomeFolderHolder() {
- throw new UnsupportedOperationException("No instance allowed");
- }
- }
-
- /**
- * @return The {@link Path} to the currently running user home
- */
- @SuppressWarnings("synthetic-access")
- public static Path getUserHomeFolder() {
- return LazyDefaultUserHomeFolderHolder.PATH;
- }
-
- /**
- * @param prefix The file name prefix - ignored if {@code null}/empty
- * @param type The identity type - ignored if {@code null}/empty
- * @param suffix The file name suffix - ignored if {@code null}/empty
- * @return The identity file name or {@code null} if no name
- */
- public static String getIdentityFileName(String prefix, String type, String suffix) {
- if (GenericUtils.isEmpty(type)) {
- return null;
- } else {
- return GenericUtils.trimToEmpty(prefix)
- + type.toLowerCase() + GenericUtils.trimToEmpty(suffix);
- }
- }
-
- /**
- * @param ids A {@link Map} of the loaded identities where key=the identity type,
- * value=the matching {@link KeyPair} - ignored if {@code null}/empty
- * @param supportedOnly If {@code true} then ignore identities that are not
- * supported internally
- * @return A {@link KeyPair} for the identities - {@code null} if no identities
- * available (e.g., after filtering unsupported ones)
- * @see BuiltinIdentities
- */
- public static KeyPairProvider createKeyPairProvider(Map<String, KeyPair> ids, boolean supportedOnly) {
- if (GenericUtils.isEmpty(ids)) {
- return null;
- }
-
- Map<String, KeyPair> pairsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- ids.forEach((type, kp) -> {
- BuiltinIdentities id = BuiltinIdentities.fromName(type);
- if (id == null) {
- id = BuiltinIdentities.fromKeyPair(kp);
- }
-
- if (supportedOnly && ((id == null) || (!id.isSupported()))) {
- return;
- }
-
- String keyType = KeyUtils.getKeyType(kp);
- if (GenericUtils.isEmpty(keyType)) {
- return;
- }
-
- KeyPair prev = pairsMap.put(keyType, kp);
- if (prev != null) {
- return; // less of an offense if 2 pairs mapped to same key type
- }
- });
-
- if (GenericUtils.isEmpty(pairsMap)) {
- return null;
- } else {
- return new MappedKeyPairProvider(pairsMap);
- }
- }
-
- /**
- * @param paths A {@link Map} of the identities where key=identity type (case
- * <U>insensitive</U>), value=the {@link Path} of file with the identity key
- * @param provider A {@link FilePasswordProvider} - may be {@code null}
- * if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
- * to {@link FilePasswordProvider#getPassword(String)} is the path of the
- * file whose key is to be loaded
- * @param options The {@link OpenOption}s to use when reading the key data
- * @return A {@link Map} of the identities where key=identity type (case
- * <U>insensitive</U>), value=the {@link KeyPair} of the identity
- * @throws IOException If failed to access the file system
- * @throws GeneralSecurityException If failed to load the keys
- * @see SecurityUtils#loadKeyPairIdentity(String, InputStream, FilePasswordProvider)
- */
- public static Map<String, KeyPair> loadIdentities(Map<String, ? extends Path> paths, FilePasswordProvider provider, OpenOption... options)
- throws IOException, GeneralSecurityException {
- if (GenericUtils.isEmpty(paths)) {
- return Collections.emptyMap();
- }
-
- Map<String, KeyPair> ids = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- // Cannot use forEach because the potential for IOExceptions being thrown
- for (Map.Entry<String, ? extends Path> pe : paths.entrySet()) {
- String type = pe.getKey();
- Path path = pe.getValue();
- try (InputStream inputStream = Files.newInputStream(path, options)) {
- KeyPair kp = SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
- KeyPair prev = ids.put(type, kp);
- ValidateUtils.checkTrue(prev == null, "Multiple keys for type=%s", type);
- }
- }
-
- return ids;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
deleted file mode 100644
index 4bfbea0..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/config/keys/KeyEntryResolver.java
+++ /dev/null
@@ -1,190 +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.common.config.keys;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.math.BigInteger;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import org.apache.sshd.common.util.io.IoUtils;
-
-/**
- * @param <PUB> Type of {@link PublicKey}
- * @param <PRV> Type of {@link PrivateKey}
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface KeyEntryResolver<PUB extends PublicKey, PRV extends PrivateKey> extends IdentityResourceLoader<PUB, PRV> {
- /**
- * @param keySize Key size in bits
- * @return A {@link KeyPair} with the specified key size
- * @throws GeneralSecurityException if unable to generate the pair
- */
- default KeyPair generateKeyPair(int keySize) throws GeneralSecurityException {
- KeyPairGenerator gen = getKeyPairGenerator();
- gen.initialize(keySize);
- return gen.generateKeyPair();
- }
-
- /**
- * @param kp The {@link KeyPair} to be cloned - ignored if {@code null}
- * @return A cloned pair (or {@code null} if no original pair)
- * @throws GeneralSecurityException If failed to clone - e.g., provided key
- * pair does not contain keys of the expected type
- * @see #getPublicKeyType()
- * @see #getPrivateKeyType()
- */
- default KeyPair cloneKeyPair(KeyPair kp) throws GeneralSecurityException {
- if (kp == null) {
- return null;
- }
-
- PUB pubCloned = null;
- PublicKey pubOriginal = kp.getPublic();
- Class<PUB> pubExpected = getPublicKeyType();
- if (pubOriginal != null) {
- Class<?> orgType = pubOriginal.getClass();
- if (!pubExpected.isAssignableFrom(orgType)) {
- throw new InvalidKeyException("Mismatched public key types: expected=" + pubExpected.getSimpleName() + ", actual=" + orgType.getSimpleName());
- }
-
- pubCloned = clonePublicKey(pubExpected.cast(pubOriginal));
- }
-
- PRV prvCloned = null;
- PrivateKey prvOriginal = kp.getPrivate();
- Class<PRV> prvExpected = getPrivateKeyType();
- if (prvOriginal != null) {
- Class<?> orgType = prvOriginal.getClass();
- if (!prvExpected.isAssignableFrom(orgType)) {
- throw new InvalidKeyException("Mismatched private key types: expected=" + prvExpected.getSimpleName() + ", actual=" + orgType.getSimpleName());
- }
-
- prvCloned = clonePrivateKey(prvExpected.cast(prvOriginal));
- }
-
- return new KeyPair(pubCloned, prvCloned);
- }
-
- /**
- * @param key The {@link PublicKey} to clone - ignored if {@code null}
- * @return The cloned key (or {@code null} if no original key)
- * @throws GeneralSecurityException If failed to clone the key
- */
- PUB clonePublicKey(PUB key) throws GeneralSecurityException;
-
- /**
- * @param key The {@link PrivateKey} to clone - ignored if {@code null}
- * @return The cloned key (or {@code null} if no original key)
- * @throws GeneralSecurityException If failed to clone the key
- */
- PRV clonePrivateKey(PRV key) throws GeneralSecurityException;
-
- /**
- * @return A {@link KeyPairGenerator} suitable for this decoder
- * @throws GeneralSecurityException If failed to create the generator
- */
- KeyPairGenerator getKeyPairGenerator() throws GeneralSecurityException;
-
- /**
- * @return A {@link KeyFactory} suitable for the specific decoder type
- * @throws GeneralSecurityException If failed to create one
- */
- KeyFactory getKeyFactoryInstance() throws GeneralSecurityException;
-
- static int encodeString(OutputStream s, String v) throws IOException {
- return encodeString(s, v, StandardCharsets.UTF_8);
- }
-
- static int encodeString(OutputStream s, String v, String charset) throws IOException {
- return encodeString(s, v, Charset.forName(charset));
- }
-
- static int encodeString(OutputStream s, String v, Charset cs) throws IOException {
- return writeRLEBytes(s, v.getBytes(cs));
- }
-
- static int encodeBigInt(OutputStream s, BigInteger v) throws IOException {
- return writeRLEBytes(s, v.toByteArray());
- }
-
- static int writeRLEBytes(OutputStream s, byte... bytes) throws IOException {
- return writeRLEBytes(s, bytes, 0, bytes.length);
- }
-
- static int writeRLEBytes(OutputStream s, byte[] bytes, int off, int len) throws IOException {
- byte[] lenBytes = encodeInt(s, len);
- s.write(bytes, off, len);
- return lenBytes.length + len;
- }
-
- static byte[] encodeInt(OutputStream s, int v) throws IOException {
- byte[] bytes = {
- (byte) ((v >> 24) & 0xFF),
- (byte) ((v >> 16) & 0xFF),
- (byte) ((v >> 8) & 0xFF),
- (byte) (v & 0xFF)
- };
- s.write(bytes);
- return bytes;
- }
-
- static String decodeString(InputStream s) throws IOException {
- return decodeString(s, StandardCharsets.UTF_8);
- }
-
- static String decodeString(InputStream s, String charset) throws IOException {
- return decodeString(s, Charset.forName(charset));
- }
-
- static String decodeString(InputStream s, Charset cs) throws IOException {
- byte[] bytes = readRLEBytes(s);
- return new String(bytes, cs);
- }
-
- static BigInteger decodeBigInt(InputStream s) throws IOException {
- return new BigInteger(readRLEBytes(s));
- }
-
- static byte[] readRLEBytes(InputStream s) throws IOException {
- int len = decodeInt(s);
- byte[] bytes = new byte[len];
- IoUtils.readFully(s, bytes);
- return bytes;
- }
-
- static int decodeInt(InputStream s) throws IOException {
- byte[] bytes = {0, 0, 0, 0};
- IoUtils.readFully(s, bytes);
- return ((bytes[0] & 0xFF) << 24)
- | ((bytes[1] & 0xFF) << 16)
- | ((bytes[2] & 0xFF) << 8)
- | (bytes[3] & 0xFF);
- }
-}