This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-vfs.git
The following commit(s) were added to refs/heads/master by this push: new 885ca9f [VFS-609] SFTP provider doesn't support a private key as byte array #60. 885ca9f is described below commit 885ca9fd1a6da890e9fd9b5d9b8884ae94cbb45d Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Sat Apr 27 10:31:56 2019 -0400 [VFS-609] SFTP provider doesn't support a private key as byte array #60. --- .../vfs2/provider/sftp/BytesIdentityInfo.java | 79 +++++++++++++ .../commons/vfs2/provider/sftp/IdentityInfo.java | 40 ++++--- .../vfs2/provider/sftp/IdentityProvider.java | 32 +++++ .../vfs2/provider/sftp/SftpClientFactory.java | 18 ++- .../provider/sftp/SftpFileSystemConfigBuilder.java | 131 +++++++++++++-------- .../provider/sftp/test/SftpProviderTestCase.java | 35 ++++-- src/changes/changes.xml | 3 + 7 files changed, 254 insertions(+), 84 deletions(-) diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java new file mode 100644 index 0000000..aaa833f --- /dev/null +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java @@ -0,0 +1,79 @@ +/* + * 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.commons.vfs2.provider.sftp; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; + +/** + * Structure for an identity based on byte arrays. + * + * @since 2.4 + */ +public class BytesIdentityInfo implements IdentityProvider { + + private final byte[] passPhrase; + + private final byte[] privateKey; + + private final byte[] publicKey; + + /** + * Constructs an identity info with private and passphrase for the private key. + * + * @param privateKey Private key bytes + * @param passPhrase The passphrase to decrypt the private key (can be {@code null} if no passphrase is used) + */ + public BytesIdentityInfo(byte[] privateKey, byte[] passPhrase) { + super(); + this.privateKey = privateKey; + this.publicKey = null; + this.passPhrase = passPhrase; + } + + /** + * Constructs an identity info with private and public key and passphrase for the private key. + * + * @param privateKey Private key bytes + * @param publicKey The public key part used for connections with exchange of certificates (can be {@code null}) + * @param passPhrase The passphrase to decrypt the private key (can be {@code null} if no passphrase is used) + */ + public BytesIdentityInfo(byte[] privateKey, byte[] publicKey, byte[] passPhrase) { + super(); + this.privateKey = privateKey; + this.publicKey = publicKey; + this.passPhrase = passPhrase; + } + + @Override + public void addIdentity(JSch jsch) throws JSchException { + jsch.addIdentity("PrivateKey", privateKey, publicKey, passPhrase); + } + + public byte[] getPassPhrase() { + return passPhrase; + } + + public byte[] getPrivateKeyBytes() { + return privateKey; + } + + public byte[] getPublicKeyBytes() { + return publicKey; + } +} diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java index e1f1ccf..7fb4331 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java @@ -18,15 +18,18 @@ package org.apache.commons.vfs2.provider.sftp; import java.io.File; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; + /** - * Structure for an identity. + * Structure for an identity based on Files. * * @since 2.1 */ -public class IdentityInfo { +public class IdentityInfo implements IdentityProvider { + private final byte[] passPhrase; private final File privateKey; private final File publicKey; - private final byte[] passPhrase; /** * Constructs an identity info with private key. @@ -61,7 +64,7 @@ public class IdentityInfo { * We use java.io.File because JSch cannot deal with VFS FileObjects. * * @param privateKey The file with the private key - * @param publicKey The public key part used for connections with exchange of certificates (can be {@code null}) + * @param publicKey The public key part used for connections with exchange of certificates (can be {@code null}) * @param passPhrase The passphrase to decrypt the private key (can be {@code null} if no passphrase is used) * @since 2.1 */ @@ -71,6 +74,25 @@ public class IdentityInfo { this.passPhrase = passPhrase; } + @Override + public void addIdentity(final JSch jsch) throws JSchException { + jsch.addIdentity(getAbsolutePath(privateKey), getAbsolutePath(publicKey), passPhrase); + } + + private String getAbsolutePath(final File file) { + return file != null ? file.getAbsolutePath() : null; + } + + /** + * Get the passphrase of the private key. + * + * @return the passphrase + * @since 2.1 + */ + public byte[] getPassPhrase() { + return passPhrase; + } + /** * Get the file with the private key. * @@ -90,14 +112,4 @@ public class IdentityInfo { public File getPublicKey() { return publicKey; } - - /** - * Get the passphrase of the private key. - * - * @return the passphrase - * @since 2.1 - */ - public byte[] getPassPhrase() { - return passPhrase; - } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java new file mode 100644 index 0000000..a5690a2 --- /dev/null +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java @@ -0,0 +1,32 @@ +/* + * 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.commons.vfs2.provider.sftp; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; + +/** + * Provides identity to a {@link JSch}. + * + * @since 2.4 + */ +public interface IdentityProvider { + + void addIdentity(final JSch jsch) throws JSchException; + +} diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java index 6be9cc2..3a6ef19 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java @@ -73,7 +73,7 @@ public final class SftpClientFactory { // new style - user passed final SftpFileSystemConfigBuilder builder = SftpFileSystemConfigBuilder.getInstance(); final File knownHostsFile = builder.getKnownHosts(fileSystemOptions); - final IdentityInfo[] identities = builder.getIdentityInfo(fileSystemOptions); + final IdentityProvider[] identities = builder.getIdentityProvider(fileSystemOptions); final IdentityRepositoryFactory repositoryFactory = builder.getIdentityRepositoryFactory(fileSystemOptions); final ConfigRepository configRepository = builder.getConfigRepository(fileSystemOptions); final boolean loadOpenSSHConfig = builder.isLoadOpenSSHConfig(fileSystemOptions); @@ -166,17 +166,17 @@ public final class SftpClientFactory { return session; } - private static void addIdentities(final JSch jsch, final File sshDir, final IdentityInfo[] identities) + private static void addIdentities(final JSch jsch, final File sshDir, final IdentityProvider[] identities) throws FileSystemException { if (identities != null) { - for (final IdentityInfo info : identities) { - addIndentity(jsch, info); + for (final IdentityProvider info : identities) { + addIdentity(jsch, info); } } else { // Load the private key (rsa-key only) final File privateKeyFile = new File(sshDir, "id_rsa"); if (privateKeyFile.isFile() && privateKeyFile.canRead()) { - addIndentity(jsch, new IdentityInfo(privateKeyFile)); + addIdentity(jsch, new IdentityInfo(privateKeyFile)); } } } @@ -195,13 +195,11 @@ public final class SftpClientFactory { } } - private static void addIndentity(final JSch jsch, final IdentityInfo info) throws FileSystemException { + private static void addIdentity(final JSch jsch, final IdentityProvider identity) throws FileSystemException { try { - final String privateKeyFile = info.getPrivateKey() != null ? info.getPrivateKey().getAbsolutePath() : null; - final String publicKeyFile = info.getPublicKey() != null ? info.getPublicKey().getAbsolutePath() : null; - jsch.addIdentity(privateKeyFile, publicKeyFile, info.getPassPhrase()); + identity.addIdentity(jsch); } catch (final JSchException e) { - throw new FileSystemException("vfs.provider.sftp/load-private-key.error", info, e); + throw new FileSystemException("vfs.provider.sftp/load-private-key.error", identity, e); } } diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java index 93ba4fe..eeefb74 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java @@ -18,6 +18,8 @@ package org.apache.commons.vfs2.provider.sftp; import java.io.File; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.vfs2.FileSystem; import org.apache.commons.vfs2.FileSystemConfigBuilder; @@ -105,13 +107,13 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { private static final String PROXY_OPTIONS = _PREFIX + ".PROXY_OPTIONS"; private static final String PROXY_PASSWORD = _PREFIX + ".PROXY_PASSWORD"; private static final String PROXY_PORT = _PREFIX + ".PROXY_PORT"; - + /** HTTP Proxy. */ public static final ProxyType PROXY_HTTP = new ProxyType("http"); - + /** SOCKS Proxy. */ public static final ProxyType PROXY_SOCKS5 = new ProxyType("socks"); - + /** * Connects to the SFTP server through a remote host reached by SSH. * <p> @@ -202,14 +204,36 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { } /** - * Gets the identity info. + * Gets the identity infos. * * @param opts The FileSystem options. - * @return the array of identity info instances. + * @return the array of identity info. * @see #setIdentityInfo */ public IdentityInfo[] getIdentityInfo(final FileSystemOptions opts) { - return (IdentityInfo[]) this.getParam(opts, IDENTITIES); + final IdentityProvider[] infos = getIdentityProvider(opts); + if (infos != null) { + final List<IdentityInfo> list = new ArrayList<>(infos.length); + for (IdentityProvider identityProvider : infos) { + if (identityProvider instanceof IdentityInfo) { + list.add((IdentityInfo) identityProvider); + } + } + return list.toArray(new IdentityInfo[list.size()]); + } + return null; + } + + /** + * Gets the identity providers. + * + * @param opts The FileSystem options. + * @return the array of identity providers. + * @see #setIdentityProvider + * @since 2.4 + */ + public IdentityProvider[] getIdentityProvider(final FileSystemOptions opts) { + return (IdentityProvider[]) this.getParam(opts, IDENTITIES); } /** @@ -233,9 +257,8 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { } /** - * Returns {@link Boolean#TRUE} if VFS should load the OpenSSH config. Defaults to - * <code>Boolean.FALSE</code> if the method {@link #setLoadOpenSSHConfig(FileSystemOptions, boolean)} has not been - * invoked. + * Returns {@link Boolean#TRUE} if VFS should load the OpenSSH config. Defaults to <code>Boolean.FALSE</code> if the + * method {@link #setLoadOpenSSHConfig(FileSystemOptions, boolean)} has not been invoked. * * @param opts The FileSystemOptions. * @return <code>Boolean.TRUE</code> if VFS should load the OpenSSH config. @@ -369,12 +392,12 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { public String getStrictHostKeyChecking(final FileSystemOptions opts) { return this.getString(opts, STRICT_HOST_KEY_CHECKING, HOST_KEY_CHECK_NO); } - + /** - * @param opts The FileSystem options. - * @return the option value for spesific key exchange algorithm - * @see #setKeyExchangeAlgorithm(FileSystemOptions, String) - **/ + * @param opts The FileSystem options. + * @return the option value for spesific key exchange algorithm + * @see #setKeyExchangeAlgorithm(FileSystemOptions, String) + **/ public String getKeyExchangeAlgorithm(final FileSystemOptions opts) { return this.getString(opts, KEY_EXCHANGE_ALGORITHM); } @@ -419,7 +442,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <p> * See the Jsch documentation (in particular the README file) for details. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param compression The names of the compression algorithms, comma-separated. * @throws FileSystemException if an error occurs. */ @@ -430,7 +453,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the timeout value to create a Jsch connection. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param timeout The connect timeout in milliseconds. * @since 2.3 */ @@ -441,7 +464,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the file name encoding. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param fileNameEncoding The name of the encoding to use for file names. */ public void setFileNameEncoding(final FileSystemOptions opts, final String fileNameEncoding) { @@ -453,16 +476,16 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <p> * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param identityFiles An array of identity Files. * @throws FileSystemException if an error occurs. * @deprecated As of 2.1 use {@link #setIdentityInfo(FileSystemOptions, IdentityInfo...)} */ @Deprecated public void setIdentities(final FileSystemOptions opts, final File... identityFiles) throws FileSystemException { - IdentityInfo[] info = null; + IdentityProvider[] info = null; if (identityFiles != null) { - info = new IdentityInfo[identityFiles.length]; + info = new IdentityProvider[identityFiles.length]; for (int i = 0; i < identityFiles.length; i++) { info[i] = new IdentityInfo(identityFiles[i]); } @@ -473,22 +496,37 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the identity info (your private key files). * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param identites An array of identity info. * @throws FileSystemException if an error occurs. * @since 2.1 + * @deprecated Use {@link #setIdentityProvider(FileSystemOptions,IdentityProvider...)} */ + @Deprecated public void setIdentityInfo(final FileSystemOptions opts, final IdentityInfo... identites) throws FileSystemException { this.setParam(opts, IDENTITIES, identites); } /** + * Sets the identity info (your private key files). + * + * @param opts The FileSystem options. + * @param identites An array of identity info. + * @throws FileSystemException if an error occurs. + * @since 2.4 + */ + public void setIdentityProvider(final FileSystemOptions opts, final IdentityProvider... identites) + throws FileSystemException { + this.setParam(opts, IDENTITIES, identites); + } + + /** * Set the identity repository. * <p> * This is useful when you want to use e.g. an SSH agent as provided. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param factory An identity repository. * @throws FileSystemException if an error occurs. * @see <a href="http://www.jcraft.com/jsch-agent-proxy/">JSch agent proxy</a> @@ -503,7 +541,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <p> * This is useful when you want to use OpenSSHConfig. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param configRepository An config repository. * @throws FileSystemException if an error occurs. * @see <a href="http://www.jcraft.com/jsch/examples/OpenSSHConfig.java.html">OpenSSHConfig</a> @@ -518,7 +556,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <p> * We use {@link java.io.File} because JSch cannot deal with VFS FileObjects. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param knownHosts The known hosts file. * @throws FileSystemException if an error occurs. */ @@ -529,7 +567,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Configures authentication order. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param preferredAuthentications The authentication order. * @since 2.0 */ @@ -540,7 +578,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the proxy username to use for the SFTP connection. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyCommand the port * @see #getProxyOptions * @since 2.1 @@ -554,7 +592,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * * You MUST also set the proxy port to use the proxy. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyHost the host * @see #setProxyPort */ @@ -565,7 +603,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the proxy username to use for the SFTP connection. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyOptions the options * @see #getProxyOptions * @since 2.1 @@ -577,7 +615,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the proxy password to use for the SFTP connection. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyPassword the username used to connect to the proxy * @see #getProxyPassword * @since 2.1 @@ -591,7 +629,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <p> * You MUST also set the proxy host to use the proxy. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyPort the port * @see #setProxyHost */ @@ -609,7 +647,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * <li>{@linkplain #PROXY_STREAM} connects through a remote host stream command</li> * </ul> * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyType the type of the proxy to use. */ public void setProxyType(final FileSystemOptions opts, final ProxyType proxyType) { @@ -619,7 +657,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the proxy username to use for the SFTP connection. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param proxyUser the username used to connect to the proxy * @see #getProxyUser * @since 2.1 @@ -631,7 +669,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the timeout value on Jsch session. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param timeout The session timeout in milliseconds. * @since 2.3 */ @@ -639,18 +677,17 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { this.setParam(opts, SESSION_TIMEOUT_MILLIS, timeout); } - /** - ** Configure Key exchange algoritm explicitly - ** e.g diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 - * @param opts The FileSystem options. - * @param keyExchangeAlgoritm The key exchange algoritm picked. - **/ - public void setKeyExchangeAlgorithm(final FileSystemOptions opts, final String keyExchangeAlgoritm) { - setParam(opts, KEY_EXCHANGE_ALGORITHM, keyExchangeAlgoritm); + ** Configure Key exchange algoritm explicitly e.g + * diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 + * + * @param opts The FileSystem options. + * @param keyExchangeAlgoritm The key exchange algoritm picked. + **/ + public void setKeyExchangeAlgorithm(final FileSystemOptions opts, final String keyExchangeAlgoritm) { + setParam(opts, KEY_EXCHANGE_ALGORITHM, keyExchangeAlgoritm); } - - + /** * Configures the host key checking to use. * <p> @@ -660,7 +697,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { * See the jsch documentation for details. * </p> * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param hostKeyChecking The host key checking to use. * @throws FileSystemException if an error occurs. */ @@ -677,7 +714,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the timeout value on Jsch session. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param timeout The timeout in milliseconds. * @deprecated Use {@link #setSessionTimeoutMillis(FileSystemOptions, Integer)} */ @@ -689,7 +726,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the whether to use the user directory as root (do not change to file system root). * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param userDirIsRoot true if the user directory is the root directory. */ public void setUserDirIsRoot(final FileSystemOptions opts, final boolean userDirIsRoot) { @@ -709,7 +746,7 @@ public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder { /** * Sets the whether to load OpenSSH config. * - * @param opts The FileSystem options. + * @param opts The FileSystem options. * @param loadOpenSSHConfig true if the OpenSSH config should be loaded. */ public void setLoadOpenSSHConfig(final FileSystemOptions opts, final boolean loadOpenSSHConfig) { diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java index 69cf1d6..a44da9d 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java @@ -32,10 +32,6 @@ import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; -import junit.extensions.TestSetup; -import junit.framework.Test; -import junit.framework.TestSuite; - import org.apache.commons.AbstractVfsTestCase; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemManager; @@ -80,6 +76,10 @@ import org.apache.sshd.server.sftp.SftpSubsystem; import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.TestIdentityRepositoryFactory; +import junit.extensions.TestSetup; +import junit.framework.Test; +import junit.framework.TestSuite; + /** * Tests cases for the SFTP provider. * <p> @@ -87,6 +87,7 @@ import com.jcraft.jsch.TestIdentityRepositoryFactory; * </p> */ public class SftpProviderTestCase extends AbstractProviderTestConfig { + /** * The underlying filesystem */ @@ -378,12 +379,16 @@ public class SftpProviderTestCase extends AbstractProviderTestConfig { final URI parsedURI = new URI(uri); final String userInfo = parsedURI.getUserInfo(); - final String[] userFields = userInfo.split(":", 2); + final String[] userFields = userInfo == null ? null : userInfo.split(":", 2); builder.setProxyType(fileSystemOptions, SftpFileSystemConfigBuilder.PROXY_STREAM); - builder.setProxyUser(fileSystemOptions, userFields[0]); - if (userFields.length > 1) { - builder.setProxyPassword(fileSystemOptions, userFields[1]); + if (userFields != null) { + if (userFields.length > 0) { + builder.setProxyUser(fileSystemOptions, userFields[0]); + } + if (userFields.length > 1) { + builder.setProxyPassword(fileSystemOptions, userFields[1]); + } } builder.setProxyHost(fileSystemOptions, parsedURI.getHost()); builder.setProxyPort(fileSystemOptions, parsedURI.getPort()); @@ -392,7 +397,11 @@ public class SftpProviderTestCase extends AbstractProviderTestConfig { builder.setProxyPassword(fileSystemOptions, parsedURI.getAuthority()); // Set up the new URI - uri = String.format("sftp://%s@localhost:%d", userInfo, parsedURI.getPort()); + if (userInfo == null) { + uri = String.format("sftp://localhost:%d", parsedURI.getPort()); + } else { + uri = String.format("sftp://%s@localhost:%d", userInfo, parsedURI.getPort()); + } } final FileObject fileObject = manager.resolveFile(uri, fileSystemOptions); @@ -497,11 +506,11 @@ public class SftpProviderTestCase extends AbstractProviderTestConfig { /** * Creates a pipe thread that connects an input to an output * - * @param name The name of the thread (for debugging purposes) - * @param in The input stream - * @param out The output stream + * @param name The name of the thread (for debugging purposes) + * @param in The input stream + * @param out The output stream * @param callback An object whose method {@linkplain ExitCallback#onExit(int)} will be called when the pipe is - * broken. The integer argument is 0 if everything went well. + * broken. The integer argument is 0 if everything went well. */ private static void connect(final String name, final InputStream in, final OutputStream out, final ExitCallback callback) { diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 709a09f..25fa371 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -86,6 +86,9 @@ The <action> type attribute can be add,update,fix,remove. <action issue="VFS-706" dev="ggregory" type="add" due-to="Boris Petrov"> Add ability to specify buffer sizes #59. </action> + <action issue="VFS-609" dev="ggregory" type="add" due-to="stevezhuang, Rostislav, Gary Gregory"> + SFTP provider doesn't support a private key as byte array #60. + </action> </release> <release version="2.3" date="2019-02-01" description="New features and bug fix release."> <action issue="VFS-645" dev="ggregory" type="fix">