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 2015/09/02 07:40:00 UTC
[1/4] mina-sshd git commit: [SSHD-559] Add support for reading
specific host configuration from config file
Repository: mina-sshd
Updated Branches:
refs/heads/master 3615e4ffb -> 950e896dc
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
index 77c1894..d2a8e87 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/BuiltinCiphersTest.java
@@ -39,6 +39,7 @@ import org.apache.sshd.common.cipher.BuiltinCiphers.ParseResult;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
+import org.apache.sshd.util.Utils;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
@@ -156,14 +157,14 @@ public class BuiltinCiphersTest extends BaseTestSupport {
@Test
public void testSshClientSupportedCiphersConfiguration() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
testSupportedCiphersConfiguration(client);
}
}
@Test
public void testSshSercerSupportedCiphersConfiguration() throws Exception {
- try (SshServer server = SshServer.setUpDefaultServer()) {
+ try (SshServer server = Utils.setupTestServer()) {
testSupportedCiphersConfiguration(server);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java b/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
index 14279d8..41a91df 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/cipher/CipherTest.java
@@ -27,15 +27,12 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import com.jcraft.jsch.JSch;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.random.Random;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -47,6 +44,8 @@ import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import com.jcraft.jsch.JSch;
+
/**
* Test Cipher algorithms.
*
@@ -105,11 +104,8 @@ public class CipherTest extends BaseTestSupport {
public void testBuiltinCipherSession() throws Exception {
Assume.assumeTrue("No internal support for " + builtInCipher.getName(), builtInCipher.isSupported() && checkCipher(jschCipher.getName()));
- try (SshServer sshd = SshServer.setUpDefaultServer()) {
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ try (SshServer sshd = Utils.setupTestServer()) {
sshd.setCipherFactories(Arrays.<NamedFactory<org.apache.sshd.common.cipher.Cipher>>asList(builtInCipher));
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
try {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java b/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
index 035e8c2..ee4f2cb 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/compression/CompressionTest.java
@@ -23,12 +23,9 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import com.jcraft.jsch.JSch;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -37,6 +34,8 @@ import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import com.jcraft.jsch.JSch;
+
/**
* Test compression algorithms.
*
@@ -66,11 +65,8 @@ public class CompressionTest extends BaseTestSupport {
}
protected void setUp(NamedFactory<org.apache.sshd.common.compression.Compression> compression) throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setCompressionFactories(Arrays.<NamedFactory<org.apache.sshd.common.compression.Compression>>asList(compression));
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
JSch.setConfig("compression.s2c", "zlib@openssh.com,zlib,none");
JSch.setConfig("compression.c2s", "zlib@openssh.com,zlib,none");
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java b/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
index 002196c..8dd1e07 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/io/nio2/Nio2ServiceTest.java
@@ -25,9 +25,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.ServerTest.TestEchoShellFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.Utils;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -44,7 +42,7 @@ public class Nio2ServiceTest extends BaseTestSupport {
@Test // see SSHD-554
public void testSetSocketOptions() throws Exception {
- try(SshServer sshd = SshServer.setUpDefaultServer()) {
+ try(SshServer sshd = Utils.setupTestServer()) {
FactoryManagerUtils.updateProperty(sshd, FactoryManager.SOCKET_KEEPALIVE, true);
FactoryManagerUtils.updateProperty(sshd, FactoryManager.SOCKET_LINGER, 5);
FactoryManagerUtils.updateProperty(sshd, FactoryManager.SOCKET_RCVBUF, 1024);
@@ -52,9 +50,6 @@ public class Nio2ServiceTest extends BaseTestSupport {
FactoryManagerUtils.updateProperty(sshd, FactoryManager.SOCKET_SNDBUF, 1024);
FactoryManagerUtils.updateProperty(sshd, FactoryManager.TCP_NODELAY, true);
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new TestEchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
int port = sshd.getPort();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java b/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
index 48402e9..11b544c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/mac/MacTest.java
@@ -23,15 +23,12 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import com.jcraft.jsch.JSch;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.cipher.Cipher;
import org.apache.sshd.common.random.Random;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -41,6 +38,8 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import com.jcraft.jsch.JSch;
+
/**
* Test Cipher algorithms.
*
@@ -117,11 +116,9 @@ public class MacTest extends BaseTestSupport {
protected void setUp(NamedFactory<Mac> mac) throws Exception {
- sshd = SshServer.setUpDefaultServer();
+ sshd = Utils.setupTestServer();
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setMacFactories(Arrays.<NamedFactory<Mac>>asList(mac));
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
port = sshd.getPort();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/session/AbstractSessionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/session/AbstractSessionTest.java b/sshd-core/src/test/java/org/apache/sshd/common/session/AbstractSessionTest.java
index 8899b8d..14906db 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/session/AbstractSessionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/session/AbstractSessionTest.java
@@ -27,8 +27,8 @@ import org.apache.sshd.common.kex.KexProposalOption;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
-import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
+import org.apache.sshd.util.Utils;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -114,7 +114,7 @@ public class AbstractSessionTest extends BaseTestSupport {
public static class MySession extends AbstractSession {
public MySession() {
- super(true, SshServer.setUpDefaultServer(), null);
+ super(true, Utils.setupTestServer(), null);
}
@Override
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java b/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
index b958ceb..cca6f1f 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/signature/AbstractSignatureFactoryTestSupport.java
@@ -35,7 +35,7 @@ import org.apache.sshd.common.keyprovider.KeyPairProvider;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -66,8 +66,7 @@ public abstract class AbstractSignatureFactoryTestSupport extends BaseTestSuppor
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
}
@After
@@ -118,7 +117,7 @@ public abstract class AbstractSignatureFactoryTestSupport extends BaseTestSuppor
sshd.start();
port = sshd.getPort();
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
client.setSignatureFactories(signatures);
client.start();
try (ClientSession s = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
index 4c2c4ba..95a3577 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
@@ -63,7 +63,7 @@ import org.apache.sshd.deprecated.ClientUserAuthServiceOld;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShell;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
@@ -92,14 +92,12 @@ public class ServerTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setShellFactory(new TestEchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
port = sshd.getPort();
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
}
@After
@@ -193,7 +191,7 @@ public class ServerTest extends BaseTestSupport {
@Test
public void testIdleTimeout() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
- TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
+ TestEchoShell.latch = new CountDownLatch(1);
final long IDLE_TIMEOUT = 2500;
FactoryManagerUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, IDLE_TIMEOUT);
@@ -236,8 +234,8 @@ public class ServerTest extends BaseTestSupport {
client.stop();
}
- assertTrue("Session latch not signalled in time", latch.await(1, TimeUnit.SECONDS));
- assertTrue("Shell latch not signalled in time", TestEchoShellFactory.TestEchoShell.latch.await(1, TimeUnit.SECONDS));
+ assertTrue("Session latch not signalled in time", latch.await(1L, TimeUnit.SECONDS));
+ assertTrue("Shell latch not signalled in time", TestEchoShell.latch.await(1L, TimeUnit.SECONDS));
}
/**
@@ -585,22 +583,22 @@ public class ServerTest extends BaseTestSupport {
public Command create() {
return new TestEchoShell();
}
+ }
- public static class TestEchoShell extends EchoShell {
+ public static class TestEchoShell extends EchoShell {
- public static CountDownLatch latch = new CountDownLatch(1);
+ public static CountDownLatch latch;
- public TestEchoShell() {
- super();
- }
+ public TestEchoShell() {
+ super();
+ }
- @Override
- public void destroy() {
- if (latch != null) {
- latch.countDown();
- }
- super.destroy();
+ @Override
+ public void destroy() {
+ if (latch != null) {
+ latch.countDown();
}
+ super.destroy();
}
}
@@ -663,10 +661,11 @@ public class ServerTest extends BaseTestSupport {
@Override
public void run() {
try {
- Thread.sleep(5000);
+ Thread.sleep(TimeUnit.SECONDS.toMillis(5L));
while (true) {
+ byte[] data = "0123456789\n".getBytes(StandardCharsets.UTF_8);
for (int i = 0; i < 100; i++) {
- out.write("0123456789\n".getBytes(StandardCharsets.UTF_8));
+ out.write(data);
}
out.flush();
}
@@ -683,14 +682,11 @@ public class ServerTest extends BaseTestSupport {
}
public static void main(String[] args) throws Exception {
- SshServer sshd = SshServer.setUpDefaultServer();
+ SshServer sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, TimeUnit.SECONDS.toMillis(10L));
sshd.setPort(8001);
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
- sshd.setShellFactory(new EchoShellFactory());
sshd.setCommandFactory(new ScpCommandFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
Thread.sleep(100000);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
index 4d63003..2cd8734 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/SshServerTest.java
@@ -22,8 +22,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.FixMethodOrder;
import org.junit.Test;
@@ -49,7 +47,7 @@ public class SshServerTest extends BaseTestSupport {
public void testExecutorShutdownFalse() throws Exception {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
- try (SshServer sshd = createTestServer()) {
+ try (SshServer sshd = Utils.setupTestServer()) {
sshd.setScheduledExecutorService(executorService);
sshd.start();
@@ -64,7 +62,7 @@ public class SshServerTest extends BaseTestSupport {
public void testExecutorShutdownTrue() throws Exception {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
- try (SshServer sshd = createTestServer()) {
+ try (SshServer sshd = Utils.setupTestServer()) {
sshd.setScheduledExecutorService(executorService, true);
sshd.start();
@@ -76,7 +74,7 @@ public class SshServerTest extends BaseTestSupport {
@Test
public void testDynamicPort() throws Exception {
- try (SshServer sshd = createTestServer()) {
+ try (SshServer sshd = Utils.setupTestServer()) {
sshd.setHost("localhost");
sshd.start();
@@ -85,14 +83,4 @@ public class SshServerTest extends BaseTestSupport {
sshd.stop();
}
}
-
-
- private SshServer createTestServer() {
- SshServer sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
-
- return sshd;
- }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticatorTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticatorTest.java b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticatorTest.java
index 52f6ad6..708e677 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticatorTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/AuthorizedKeysAuthenticatorTest.java
@@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.sshd.common.config.keys.PublicKeyEntry;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.util.BaseTestSupport;
@@ -89,16 +90,15 @@ public class AuthorizedKeysAuthenticatorTest extends BaseTestSupport {
assertHierarchyTargetFolderExists(file.getParent());
- final String EOL = System.getProperty("line.separator");
while(keyLines.size() > 0) {
try (Writer w = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
w.append(PublicKeyEntry.COMMENT_CHAR)
.append(' ').append(getCurrentTestName())
.append(' ').append(String.valueOf(keyLines.size())).append(" remaining keys")
- .append(EOL)
+ .append(IoUtils.EOL)
;
for (String l : keyLines) {
- w.append(l).append(EOL);
+ w.append(l).append(IoUtils.EOL);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java b/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java
index 60c47e8..29fadfa 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java
+++ b/sshd-core/src/test/java/org/apache/sshd/server/subsystem/sftp/SshFsMounter.java
@@ -50,7 +50,6 @@ import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.SessionAware;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.password.AcceptAllPasswordAuthenticator;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
@@ -293,7 +292,7 @@ public class SshFsMounter {
System.err.println("Starting SSHD on port " + port);
- SshServer sshd = SshServer.setUpDefaultServer();
+ SshServer sshd = Utils.setupTestServer();
Map<String, Object> props = sshd.getProperties();
// FactoryManagerUtils.updateProperty(props, ServerFactoryManager.WELCOME_BANNER, "Welcome to SSH-FS Mounter\n");
props.putAll(options);
@@ -308,7 +307,6 @@ public class SshFsMounter {
sshd.setShellFactory(InteractiveProcessShellFactory.INSTANCE);
sshd.setPasswordAuthenticator(AcceptAllPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd.setCommandFactory(new ScpCommandFactory.Builder().withDelegate(MounterCommandFactory.INSTANCE).build());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/util/EchoShell.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/EchoShell.java b/sshd-core/src/test/java/org/apache/sshd/util/EchoShell.java
new file mode 100644
index 0000000..95fdbe6
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/util/EchoShell.java
@@ -0,0 +1,121 @@
+/*
+ * 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.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class EchoShell implements Command, Runnable {
+
+ private InputStream in;
+ private OutputStream out;
+ private OutputStream err;
+ private ExitCallback callback;
+ private Environment environment;
+ private Thread thread;
+
+ public EchoShell() {
+ super();
+ }
+
+ public InputStream getIn() {
+ return in;
+ }
+
+ public OutputStream getOut() {
+ return out;
+ }
+
+ public OutputStream getErr() {
+ return err;
+ }
+
+ public Environment getEnvironment() {
+ return environment;
+ }
+
+ @Override
+ public void setInputStream(InputStream in) {
+ this.in = in;
+ }
+
+ @Override
+ public void setOutputStream(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ public void setErrorStream(OutputStream err) {
+ this.err = err;
+ }
+
+ @Override
+ public void setExitCallback(ExitCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void start(Environment env) throws IOException {
+ environment = env;
+ thread = new Thread(this, "EchoShell");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ @Override
+ public void destroy() {
+ thread.interrupt();
+ }
+
+ @Override
+ public void run() {
+ BufferedReader r = new BufferedReader(new InputStreamReader(in));
+ try {
+ for (; ; ) {
+ String s = r.readLine();
+ if (s == null) {
+ return;
+ }
+ out.write((s + "\n").getBytes(StandardCharsets.UTF_8));
+ out.flush();
+ if ("exit".equals(s)) {
+ return;
+ }
+ }
+ } catch (InterruptedIOException e) {
+ // Ignore
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ callback.onExit(0);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java b/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java
index 1fdacd2..1121fdf 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java
@@ -18,18 +18,8 @@
*/
package org.apache.sshd.util;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-
import org.apache.sshd.common.Factory;
import org.apache.sshd.server.Command;
-import org.apache.sshd.server.Environment;
-import org.apache.sshd.server.ExitCallback;
/**
* TODO Add javadoc
@@ -37,96 +27,14 @@ import org.apache.sshd.server.ExitCallback;
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class EchoShellFactory implements Factory<Command> {
+ public static final EchoShellFactory INSTANCE = new EchoShellFactory();
+
+ public EchoShellFactory() {
+ super();
+ }
@Override
public Command create() {
return new EchoShell();
}
-
- public static class EchoShell implements Command, Runnable {
-
- private InputStream in;
- private OutputStream out;
- private OutputStream err;
- private ExitCallback callback;
- private Environment environment;
- private Thread thread;
-
- public EchoShell() {
- super();
- }
-
- public InputStream getIn() {
- return in;
- }
-
- public OutputStream getOut() {
- return out;
- }
-
- public OutputStream getErr() {
- return err;
- }
-
- public Environment getEnvironment() {
- return environment;
- }
-
- @Override
- public void setInputStream(InputStream in) {
- this.in = in;
- }
-
- @Override
- public void setOutputStream(OutputStream out) {
- this.out = out;
- }
-
- @Override
- public void setErrorStream(OutputStream err) {
- this.err = err;
- }
-
- @Override
- public void setExitCallback(ExitCallback callback) {
- this.callback = callback;
- }
-
- @Override
- public void start(Environment env) throws IOException {
- environment = env;
- thread = new Thread(this, "EchoShell");
- thread.setDaemon(true);
- thread.start();
- }
-
- @Override
- public void destroy() {
- thread.interrupt();
- }
-
- @Override
- public void run() {
- BufferedReader r = new BufferedReader(new InputStreamReader(in));
- try {
- for (; ; ) {
- String s = r.readLine();
- if (s == null) {
- return;
- }
- out.write((s + "\n").getBytes(StandardCharsets.UTF_8));
- out.flush();
- if ("exit".equals(s)) {
- return;
- }
- }
- } catch (InterruptedIOException e) {
- // Ignore
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- callback.onExit(0);
- }
- }
- }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommand.java b/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommand.java
new file mode 100644
index 0000000..75605d9
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommand.java
@@ -0,0 +1,82 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.ExitCallback;
+
+/**
+ * Implementation of an unknown command that can be returned by <code>CommandFactory</code>
+ * when the command is not known, as it is supposed to always
+ * return a valid <code>Command</code> object.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class UnknownCommand implements Command {
+
+ private String command;
+ private InputStream in;
+ private OutputStream out;
+ private OutputStream err;
+ private ExitCallback callback;
+
+ public UnknownCommand(String command) {
+ this.command = command;
+ }
+
+ @Override
+ public void setInputStream(InputStream in) {
+ this.in = in;
+ }
+
+ @Override
+ public void setOutputStream(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ public void setErrorStream(OutputStream err) {
+ this.err = err;
+ }
+
+ @Override
+ public void setExitCallback(ExitCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void start(Environment env) throws IOException {
+ err.write(("Unknown command: " + command + "\n").getBytes(StandardCharsets.UTF_8));
+ err.flush();
+ if (callback != null) {
+ callback.onExit(1, "Unknown command: " + command);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ // ignored
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommandFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommandFactory.java b/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommandFactory.java
new file mode 100644
index 0000000..69a8e8e
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/util/UnknownCommandFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util;
+
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.CommandFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class UnknownCommandFactory implements CommandFactory {
+ public static final UnknownCommandFactory INSTANCE = new UnknownCommandFactory();
+
+ public UnknownCommandFactory() {
+ super();
+ }
+
+ @Override
+ public Command createCommand(String command) {
+ return new UnknownCommand(command);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/util/Utils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/Utils.java b/sshd-core/src/test/java/org/apache/sshd/util/Utils.java
index a347e22..c9db26c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/Utils.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/Utils.java
@@ -42,6 +42,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
+import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
@@ -49,6 +52,8 @@ import org.apache.sshd.common.random.Random;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
public class Utils {
@@ -62,7 +67,6 @@ public class Utils {
return provider;
}
-
File targetFolder = ValidateUtils.checkNotNull(detectTargetFolder(Utils.class), "Failed to detect target folder");
File file = new File(targetFolder, "hostkey." + DEFAULT_TEST_HOST_KEY_PROVIDER_ALGORITHM.toLowerCase());
SimpleGeneratorHostKeyProvider keyProvider = new SimpleGeneratorHostKeyProvider();
@@ -544,4 +548,21 @@ public class Utils {
Path relPath = root.relativize(file);
return relPath.toString().replace(File.separatorChar, '/');
}
+
+ public static final SshClient setupTestClient() {
+ SshClient client = SshClient.setUpDefaultClient();
+ client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
+ client.setHostConfigEntryResolver(HostConfigEntryResolver.EMPTY);
+ return client;
+ }
+
+ public static final SshServer setupTestServer() {
+ SshServer sshd = SshServer.setUpDefaultServer();
+ sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+ sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
+ sshd.setShellFactory(EchoShellFactory.INSTANCE);
+ sshd.setCommandFactory(UnknownCommandFactory.INSTANCE);
+ return sshd;
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadGlobalHostsConfigEntries.config.txt
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadGlobalHostsConfigEntries.config.txt b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadGlobalHostsConfigEntries.config.txt
new file mode 100644
index 0000000..a0be861
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadGlobalHostsConfigEntries.config.txt
@@ -0,0 +1,23 @@
+# Global section first
+
+ User global
+ Port 7365
+ IdentityFile ~/.ssh/github.key
+ HostName 37.77.34.7
+
+# User override
+Host *.apache.org
+ User mina-sshd
+
+# Port override
+Host *.github.com
+ Port 443
+
+# Host name override
+Host 10.*.*.*
+ HostName 7.3.6.5
+
+# Identity override
+Host 192.168.*.*
+ IdentityFile ~/.ssh/internal.key
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadMultipleHostPatterns.config.txt
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadMultipleHostPatterns.config.txt b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadMultipleHostPatterns.config.txt
new file mode 100644
index 0000000..0f5edcb
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadMultipleHostPatterns.config.txt
@@ -0,0 +1,5 @@
+# Same configuration duplicated in multiple configuration entries
+Host *.github.com *.apache.org 10.*.*.*
+ User mina-sshd
+ Port 443
+ HostName 7.3.6.5
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadSimpleHostsConfigEntries.config.txt
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadSimpleHostsConfigEntries.config.txt b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadSimpleHostsConfigEntries.config.txt
new file mode 100644
index 0000000..1058777
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/client/config/hosts/testReadSimpleHostsConfigEntries.config.txt
@@ -0,0 +1,8 @@
+# Simple configuration file
+Host *.github.com
+ User mina-sshd
+ Port 443
+ IdentityFile ~/.ssh/github.key
+
+Host *.apache.org
+ User mina-sshd
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java
----------------------------------------------------------------------
diff --git a/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java b/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java
index 191ca5d..1f32721 100644
--- a/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java
+++ b/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java
@@ -20,7 +20,7 @@ package org.apache.sshd.git.pack;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
-import org.apache.sshd.server.command.UnknownCommand;
+import org.apache.sshd.util.UnknownCommand;
/**
* TODO Add javadoc
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java
----------------------------------------------------------------------
diff --git a/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java b/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java
index c6f767a..ff5ff50 100644
--- a/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java
+++ b/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java
@@ -20,7 +20,7 @@ package org.apache.sshd.git.pgm;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
-import org.apache.sshd.server.command.UnknownCommand;
+import org.apache.sshd.util.UnknownCommand;
/**
* TODO Add javadoc
[3/4] mina-sshd git commit: [SSHD-559] Add support for reading
specific host configuration from config file
Posted by lg...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java
new file mode 100644
index 0000000..8ee1d09
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java
@@ -0,0 +1,1403 @@
+/*
+ * 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.client.config.hosts;
+
+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.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StreamCorruptedException;
+import java.io.Writer;
+import java.net.InetAddress;
+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.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.sshd.common.config.SshConfigFileReader;
+import org.apache.sshd.common.config.keys.PublicKeyEntry;
+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.NoCloseOutputStream;
+import org.apache.sshd.common.util.io.NoCloseReader;
+
+/**
+ * Represents an entry in the client's configuration file as defined by
+ * the <A HREF="http://www.gsp.com/cgi-bin/man.cgi?topic=ssh_config">configuration
+ * file format</A>
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class HostConfigEntry implements Cloneable {
+
+ /**
+ * Used in a host pattern to denote zero or more consecutive characters
+ */
+ public static final char WILDCARD_PATTERN = '*';
+ public static final String ALL_HOSTS_PATTERN = String.valueOf(HostConfigEntry.WILDCARD_PATTERN);
+
+ /**
+ * Standard OpenSSH config file name
+ */
+ public static final String STD_CONFIG_FILENAME = "config";
+
+ /**
+ * Used in a host pattern to denote any <U>one</U> character
+ */
+ public static final char SINGLE_CHAR_PATTERN = '?';
+
+ /**
+ * The available pattern characters
+ */
+ public static final String PATTERN_CHARS = new String(new char[]{WILDCARD_PATTERN, SINGLE_CHAR_PATTERN});
+
+ public static final String HOST_CONFIG_PROP = "Host";
+ public static final String HOST_NAME_CONFIG_PROP = "HostName";
+ public static final String PORT_CONFIG_PROP = SshConfigFileReader.PORT_CONFIG_PROP;
+ public static final String USER_CONFIG_PROP = "User";
+ public static final String IDENTITY_FILE_CONFIG_PROP = "IdentityFile";
+
+ /**
+ * A case <U>insensitive</U> {@link Set} of the properties that receive special handling
+ */
+ public static final Set<String> EXPLICIT_PROPERTIES =
+ Collections.unmodifiableSet(
+ GenericUtils.asSortedSet(String.CASE_INSENSITIVE_ORDER,
+ HOST_CONFIG_PROP, HOST_NAME_CONFIG_PROP, PORT_CONFIG_PROP,
+ USER_CONFIG_PROP, IDENTITY_FILE_CONFIG_PROP
+ ));
+
+ public static final String MULTI_VALUE_SEPARATORS = " ,";
+
+ public static final char HOME_TILDE_CHAR = '~';
+ public static final char PATH_MACRO_CHAR = '%';
+ public static final char LOCAL_HOME_MACRO = 'd';
+ public static final char LOCAL_USER_MACRO = 'u';
+ public static final char LOCAL_HOST_MACRO = 'l';
+ public static final char REMOTE_HOST_MACRO = 'h';
+ public static final char REMOTE_USER_MACRO = 'r';
+ // Extra - not part of the standard
+ public static final char REMOTE_PORT_MACRO = 'p';
+
+ private static final class LazyDefaultConfigFileHolder {
+ private static final File KEYS_FILE = new File(PublicKeyEntry.getDefaultKeysFolder(), STD_CONFIG_FILENAME);
+ }
+
+ private String hostValue;
+ private Pattern hostPattern;
+ private String hostName;
+ private int port;
+ private String username;
+ private Collection<String> identities = Collections.emptyList();
+ private Map<String, String> properties = Collections.emptyMap();
+
+ public HostConfigEntry() {
+ super();
+ }
+
+ public HostConfigEntry(String pattern, String host, int port, String username) {
+ setHost(pattern);
+ setHostName(host);
+ setPort(port);
+ setUsername(username);
+ }
+
+ /**
+ * @return The host <U>pattern</U> represented by this entry
+ * @see <A HREF="http://www.gsp.com/cgi-bin/man.cgi?topic=ssh_config#3">Host Patterns</A>
+ */
+ public String getHost() {
+ return hostValue;
+ }
+
+ public Pattern getHostPattern() {
+ return hostPattern;
+ }
+
+ /**
+ * @param host The host name/address/pattern represented by the entry
+ */
+ public void setHost(String host) {
+ hostValue = host;
+ hostPattern = toPattern(host);
+ }
+
+ /**
+ * Checks if a given host name / address matches the entry's host pattern
+ *
+ * @param host The host name / address - ignored if {@code null}/empty
+ * @return {@code true} if the name / address matches the pattern
+ * @see #getHostPattern()
+ * @see #isHostMatch(String, Pattern)
+ */
+ public boolean isHostMatch(String host) {
+ return isHostMatch(host, getHostPattern());
+ }
+
+ /**
+ * @return The effective host name to connect to if the pattern matches
+ */
+ public String getHostName() {
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ public String resolveHostName(String originalHost) {
+ return resolveHostName(originalHost, getHostName());
+ }
+
+ /**
+ * @return A port override - if positive
+ */
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * Resolves the effective port to use
+ *
+ * @param originalPort The original requested port
+ * @return If the host entry port is positive, then it is used, otherwise
+ * the original requested port
+ * @see #resolvePort(int, int)
+ */
+ public int resolvePort(int originalPort) {
+ return resolvePort(originalPort, getPort());
+ }
+
+ /**
+ * @return A username override - if not {@code null}/empty
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ /**
+ * Resolves the effective username
+ *
+ * @param originalUser The original requested username
+ * @return If the configured host entry username is not {@code null}/empty
+ * then it is used, otherwise the original one.
+ * @see #resolveUsername(String)
+ */
+ public String resolveUsername(String originalUser) {
+ return resolveUsername(originalUser, getUsername());
+ }
+
+ /**
+ * @return The current identities file paths - may be {@code null}/empty
+ */
+ public Collection<String> getIdentities() {
+ return identities;
+ }
+
+ /**
+ * @param path A {@link File{ that contains an identity key - never {@code null}
+ */
+ public void addIdentity(File file) {
+ addIdentity(ValidateUtils.checkNotNull(file, "No file").toPath());
+ }
+
+ /**
+ * @param path A {@link Path} to a file that contains an identity key
+ * - never {@code null}
+ */
+ public void addIdentity(Path path) {
+ addIdentity(ValidateUtils.checkNotNull(path, "No path").toAbsolutePath().normalize().toString());
+ }
+
+ /**
+ * Adds a path to an identity file
+ *
+ * @param id The identity path to add - never {@code null{
+ */
+ public void addIdentity(String id) {
+ String path = ValidateUtils.checkNotNullAndNotEmpty(id, "No identity provided");
+ if (GenericUtils.isEmpty(identities)) {
+ identities = new LinkedList<>();
+ }
+ identities.add(path);
+ }
+
+ public void setIdentities(Collection<String> identities) {
+ this.identities = (identities == null) ? Collections.<String>emptyList() : identities;
+ }
+
+ /**
+ * @return A {@link Map} of extra properties that have been read - may be
+ * {@code null}/empty, or even contain some values that have been parsed
+ * and set as members of the entry (e.g., host, port, etc.). <B>Note:</B>
+ * multi-valued keys use a comma-separated list of values
+ */
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ /**
+ * @param name Property name - never {@code null}/empty
+ * @param value Property value - {@code null} if no such property
+ * @see #getProperty(String, String)
+ */
+ public String getProperty(String name) {
+ return getProperty(name, null);
+ }
+
+ /**
+ * @param name Property name - never {@code null}/empty
+ * @param defaultValue Default value to return if no such property
+ * @return The property value or the default one if no such property
+ */
+ public String getProperty(String name, String defaultValue) {
+ String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ Map<String, String> props = getProperties();
+ if (GenericUtils.isEmpty(props)) {
+ return null;
+ }
+
+ String value = props.get(key);
+ if (GenericUtils.isEmpty(value)) {
+ return defaultValue;
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Updates the values that are <U>not</U> already configured with those
+ * from the global entry
+ *
+ * @param globalEntry The global entry - ignored if {@code null} or
+ * same reference as this entry
+ * @return {@code true} if anything updated
+ */
+ public boolean processGlobalValues(HostConfigEntry globalEntry) {
+ if ((globalEntry == null) || (this == globalEntry)) {
+ return false;
+ }
+
+ boolean modified = false;
+ /*
+ * NOTE !!! DO NOT TRY TO CHANGE THE ORDER OF THE OR-ing AS IT
+ * WOULD CAUSE INVALID CODE EXECUTION
+ */
+ modified = updateGlobalPort(globalEntry.getPort()) || modified;
+ modified = updateGlobalHostName(globalEntry.getHostName()) || modified;
+ modified = updateGlobalUserName(globalEntry.getUsername()) || modified;
+ modified = updateGlobalIdentities(globalEntry.getIdentities()) || modified;
+
+ Map<String, String> updated = updateGlobalProperties(globalEntry.getProperties());
+ modified = (GenericUtils.size(updated) > 0) || modified;
+
+ return modified;
+ }
+
+ /**
+ * Sets all the properties for which no current value exists in the entry
+ *
+ * @param props The global properties - ignored if {@code null}/empty
+ * @return A {@link Map} of the <U>updated</U> properties
+ */
+ public Map<String, String> updateGlobalProperties(Map<String, String> props) {
+ if (GenericUtils.isEmpty(props)) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, String> updated = null;
+ for (Map.Entry<String, String> pe : props.entrySet()) {
+ String key = pe.getKey();
+ String curValue = getProperty(key);
+ if (GenericUtils.length(curValue) > 0) {
+ continue;
+ }
+
+ String newValue = pe.getValue();
+ setProperty(key, newValue);
+
+ if (updated == null) {
+ updated = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ }
+
+ updated.put(key, newValue);
+ }
+
+ if (updated == null) {
+ return Collections.emptyMap();
+ } else {
+ return updated;
+ }
+ }
+
+ /**
+ * @param ids Global identities - ignored if {@code null}/empty or already
+ * have configured identities
+ * @return {@code true} if updated identities
+ */
+ public boolean updateGlobalIdentities(Collection<String> ids) {
+ if (GenericUtils.isEmpty(ids) || (GenericUtils.size(getIdentities()) > 0)) {
+ return false;
+ }
+
+ for (String id : ids) {
+ addIdentity(id);
+ }
+
+ return true;
+ }
+
+ /**
+ * @param name The global user name - ignored if {@code null}/empty or
+ * already have a configured user
+ * @return {@code true} if updated the username
+ */
+ public boolean updateGlobalUserName(String user) {
+ if (GenericUtils.isEmpty(user) || (GenericUtils.length(getUsername()) > 0)) {
+ return false;
+ }
+
+ setUsername(user);
+ return true;
+ }
+
+ /**
+ * @param name The global host name - ignored if {@code null}/empty or
+ * already have a configured target host
+ * @return {@code true} if updated the target host
+ */
+ public boolean updateGlobalHostName(String name) {
+ if (GenericUtils.isEmpty(name) || (GenericUtils.length(getHostName()) > 0)) {
+ return false;
+ }
+
+ setHostName(name);
+ return true;
+ }
+
+ /**
+ * @param portValue The global port value - ignored if not positive
+ * or already have a configured port
+ * @return {@code true} if updated the port value
+ */
+ public boolean updateGlobalPort(int portValue) {
+ if ((portValue <= 0) || (getPort() > 0)) {
+ return false;
+ }
+
+ setPort(portValue);
+ return true;
+ }
+
+ /**
+ * @param name Property name - never {@code null}/empty
+ * @param valsList The available values for the property
+ * @param ignoreAlreadyInitialized If {@code false} and one of the "known"
+ * properties is encountered then throws an exception
+ * @throws IllegalArgumentException If an existing value is overwritten and
+ * <tt>ignoreAlreadyInitialized</tt> is {@code false} (except for {@link #IDENTITY_FILE_CONFIG_PROP}
+ * which is <U>cumulative</U>
+ * @see #HOST_NAME_CONFIG_PROP
+ * @see #PORT_CONFIG_PROP
+ * @see #USER_CONFIG_PROP
+ * @see #IDENTITY_FILE_CONFIG_PROP
+ */
+ public void processProperty(String name, Collection<String> valsList, boolean ignoreAlreadyInitialized) {
+ String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ String joinedValue = GenericUtils.join(valsList, ',');
+ appendPropertyValue(key, joinedValue);
+
+ if (HOST_NAME_CONFIG_PROP.equalsIgnoreCase(key)) {
+ ValidateUtils.checkTrue(GenericUtils.size(valsList) == 1, "Multiple target hosts N/A: %s", joinedValue);
+
+ String curValue = getHostName();
+ ValidateUtils.checkTrue(GenericUtils.isEmpty(curValue) || ignoreAlreadyInitialized, "Already initialized %s: %s", key, curValue);
+ setHostName(joinedValue);
+ } else if (PORT_CONFIG_PROP.equalsIgnoreCase(key)) {
+ ValidateUtils.checkTrue(GenericUtils.size(valsList) == 1, "Multiple target ports N/A: %s", joinedValue);
+
+ int curValue = getPort();
+ ValidateUtils.checkTrue((curValue <= 0) || ignoreAlreadyInitialized, "Already initialized %s: %d", key, curValue);
+
+ int newValue = Integer.parseInt(joinedValue);
+ ValidateUtils.checkTrue(newValue > 0, "Bad new port value: %d", newValue);
+ setPort(newValue);
+ } else if (USER_CONFIG_PROP.equalsIgnoreCase(key)) {
+ ValidateUtils.checkTrue(GenericUtils.size(valsList) == 1, "Multiple target users N/A: %s", joinedValue);
+
+ String curValue = getUsername();
+ ValidateUtils.checkTrue(GenericUtils.isEmpty(curValue) || ignoreAlreadyInitialized, "Already initialized %s: %s", key, curValue);
+ setUsername(joinedValue);
+ } else if (IDENTITY_FILE_CONFIG_PROP.equalsIgnoreCase(key)) {
+ ValidateUtils.checkTrue(GenericUtils.size(valsList) > 0, "No identity files specified");
+ for (String id : valsList) {
+ addIdentity(id);
+ }
+ }
+ }
+
+ /**
+ * Appends a value using a <U>comma</U> to an existing one. If no previous
+ * value then same as calling {@link #setProperty(String, String)}.
+ *
+ * @param name Property name - never {@code null}/empty
+ * @param value The value to be appended - ignored if {@code null}/empty
+ * @return The value <U>before</U> appending - {@code null} if no previous value
+ */
+ public String appendPropertyValue(String name, String value) {
+ String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ String curVal = getProperty(key);
+ if (GenericUtils.isEmpty(value)) {
+ return curVal;
+ }
+
+ if (GenericUtils.isEmpty(curVal)) {
+ return setProperty(key, value);
+ }
+
+ StringBuilder sb = new StringBuilder(curVal.length() + value.length() + 1);
+ sb.append(curVal).append(',').append(value);
+ return setProperty(key, sb.toString());
+ }
+
+ /**
+ * Sets / Replaces the property value
+ *
+ * @param name Property name - never {@code null}/empty
+ * @param value Property value - if {@code null}/empty then
+ * {@link #removeProperty(String)} is called
+ * @return The previous property value - {@code null} if no such name
+ */
+ public String setProperty(String name, String value) {
+ if (GenericUtils.isEmpty(value)) {
+ return removeProperty(name);
+ }
+
+ String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ if (GenericUtils.isEmpty(properties)) {
+ properties = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ }
+
+ return properties.put(key, value);
+ }
+
+ /**
+ * @param name Property name - never {@code null}/empty
+ * @return The removed property value - {@code null} if no such property name
+ */
+ public String removeProperty(String name) {
+ String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ Map<String, String> props = getProperties();
+ if (GenericUtils.isEmpty(props)) {
+ return null;
+ } else {
+ return props.remove(key);
+ }
+ }
+
+ /**
+ * @param properties The properties to set - if {@code null} then an empty
+ * map is effectively set. <B>Note:</B> it is highly recommended to use a
+ * <U>case insensitive</U> key mapper.
+ */
+ public void setProperties(Map<String, String> properties) {
+ this.properties = (properties == null) ? Collections.<String, String>emptyMap() : properties;
+ }
+
+ public <A extends Appendable> A append(A sb) throws IOException {
+ sb.append(HOST_CONFIG_PROP).append(' ').append(ValidateUtils.checkNotNullAndNotEmpty(getHost(), "No host pattern")).append(IoUtils.EOL);
+ appendNonEmptyProperty(sb, HOST_NAME_CONFIG_PROP, getHostName());
+ appendNonEmptyPort(sb, PORT_CONFIG_PROP, getPort());
+ appendNonEmptyProperty(sb, USER_CONFIG_PROP, getUsername());
+ appendNonEmptyValues(sb, IDENTITY_FILE_CONFIG_PROP, getIdentities());
+ appendNonEmptyProperties(sb, getProperties());
+ return sb;
+ }
+
+ @Override
+ public HostConfigEntry clone() {
+ try {
+ HostConfigEntry other = getClass().cast(super.clone());
+
+ // avoid shared instances
+ other.setIdentities(null);
+ Collection<String> ids = this.getIdentities();
+ if (GenericUtils.size(ids) > 0) {
+ for (String kp : ids) {
+ other.addIdentity(kp);
+ }
+ }
+
+ // avoid shared instances
+ other.setProperties(null);
+ Map<String, String> props = this.getProperties();
+ if (GenericUtils.size(props) > 0) {
+ for (Map.Entry<String, String> pe : props.entrySet()) {
+ other.setProperty(pe.getKey(), pe.getValue());
+ }
+ }
+
+ return other;
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("Failed (" + e.getClass().getSimpleName() + ") to clone " + toString() + ": " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getHost() + ": " + getUsername() + "@" + getHostName() + ":" + getPort();
+ }
+
+ /**
+ * @param <A> The {@link Appendable} type
+ * @param sb The target appender
+ * @param name The property name - never {@code null}/empty
+ * @param port The port value - ignored if non-positive
+ * @return The target appender after having appended (or not) the value
+ * @throws IOException If failed to append the requested data
+ * @see #appendNonEmptyProperty(Appendable, String, Object)
+ */
+ public static <A extends Appendable> A appendNonEmptyPort(A sb, String name, int port) throws IOException {
+ return appendNonEmptyProperty(sb, name, (port > 0) ? Integer.toString(port) : null);
+ }
+
+ /**
+ * Appends the extra properties - while skipping the {@link #EXPLICIT_PROPERTIES} ones
+ *
+ * @param <A> The {@link Appendable} type
+ * @param sb The target appender
+ * @param props The {@link Map} of properties - ignored if {@code null}/empty
+ * @return The target appender after having appended (or not) the value
+ * @throws IOException If failed to append the requested data
+ * @see #appendNonEmptyProperty(Appendable, String, Object)
+ */
+ public static <A extends Appendable> A appendNonEmptyProperties(A sb, Map<String, ?> props) throws IOException {
+ if (GenericUtils.isEmpty(props)) {
+ return sb;
+ }
+
+ for (Map.Entry<String, ?> pe : props.entrySet()) {
+ String name = pe.getKey();
+ if (EXPLICIT_PROPERTIES.contains(name)) {
+ continue;
+ }
+
+ appendNonEmptyProperty(sb, name, pe.getValue());
+ }
+
+ return sb;
+ }
+
+ /**
+ * @param <A> The {@link Appendable} type
+ * @param sb The target appender
+ * @param name The property name - never {@code null}/empty
+ * @param value The property value - ignored if {@code null}. <B>Note:</B>
+ * if the string representation of the value contains any commas, they are
+ * assumed to indicate a multi-valued property which is broken down to
+ * <U>individual</U> lines - one per value.
+ * @return The target appender after having appended (or not) the value
+ * @throws IOException If failed to append the requested data
+ * @see #appendNonEmptyValues(Appendable, String, Object...)
+ */
+ public static <A extends Appendable> A appendNonEmptyProperty(A sb, String name, Object value) throws IOException {
+ String s = Objects.toString(value, null);
+ String[] vals = GenericUtils.split(s, ',');
+ return appendNonEmptyValues(sb, name, (Object[]) vals);
+ }
+
+ /**
+ * @param <A> The {@link Appendable} type
+ * @param sb The target appender
+ * @param name The property name - never {@code null}/empty
+ * @param values The values to be added - one per line - ignored if {@code null}/empty
+ * @return The target appender after having appended (or not) the value
+ * @throws IOException If failed to append the requested data
+ * @see #appendNonEmptyValues(Appendable, String, Collection)
+ */
+ public static <A extends Appendable> A appendNonEmptyValues(A sb, String name, Object ... values) throws IOException {
+ return appendNonEmptyValues(sb, name, GenericUtils.isEmpty(values) ? Collections.<Object>emptyList() : Arrays.asList(values));
+ }
+
+ /**
+ * @param <A> The {@link Appendable} type
+ * @param sb The target appender
+ * @param name The property name - never {@code null}/empty
+ * @param values The values to be added - one per line - ignored if {@code null}/empty
+ * @return The target appender after having appended (or not) the value
+ * @throws IOException If failed to append the requested data
+ */
+ public static <A extends Appendable> A appendNonEmptyValues(A sb, String name, Collection<?> values) throws IOException {
+ String k = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name");
+ if (GenericUtils.isEmpty(values)) {
+ return sb;
+ }
+
+ for (Object v : values) {
+ sb.append(" ").append(k).append(' ').append(Objects.toString(v)).append(IoUtils.EOL);
+ }
+
+ return sb;
+ }
+
+ /**
+ * @param entries The entries - ignored if {@code null}/empty
+ * @return A {@link HostConfigEntryResolver} wrapper using the entries
+ */
+ public static HostConfigEntryResolver toHostConfigEntryResolver(final Collection<? extends HostConfigEntry> entries) {
+ if (GenericUtils.isEmpty(entries)) {
+ return HostConfigEntryResolver.EMPTY;
+ } else {
+ return new HostConfigEntryResolver() {
+ @Override
+ public HostConfigEntry resolveEffectiveHost(String host, int port, String username) throws IOException {
+ List<HostConfigEntry> matches = findMatchingEntries(host, entries);
+ int numMatches = GenericUtils.size(matches);
+ if (numMatches <= 0) {
+ return null;
+ }
+
+ HostConfigEntry match = (numMatches == 1) ? matches.get(0) : findBestMatch(matches);
+ if (match == null) {
+ ValidateUtils.throwIllegalArgumentException("No best match found for %s@%s:%d out of %d matches", username, host, port, numMatches);
+ }
+
+ return normalizeEntry(match, host, port, username);
+ }
+ };
+ }
+ }
+
+ /**
+ * @param entry The original entry - ignored if {@code null}
+ * @param host The original host name / address
+ * @param port The original port
+ * @param username The original user name
+ * @return A <U>cloned</U> entry whose values are resolved - including
+ * expanding macros in the identities files
+ * @throws IOException If failed to normalize the entry
+ * @see #resolveHostName(String)
+ * @see #resolvePort(int)
+ * @see #resolveUsername(String)
+ * @see #resolveIdentityFilePath(String, String, int, String)
+ */
+ public static HostConfigEntry normalizeEntry(HostConfigEntry entry, String host, int port, String username) throws IOException {
+ if (entry == null) {
+ return entry;
+ }
+
+ HostConfigEntry normal = entry.clone();
+ normal.setHostName(entry.resolveHostName(host));
+ normal.setPort(entry.resolvePort(port));
+ normal.setUsername(entry.resolveUsername(username));
+
+ Collection<String> ids = entry.getIdentities();
+ if (GenericUtils.isEmpty(ids)) {
+ return normal;
+ }
+
+ normal.setIdentities(Collections.<String>emptyList()); // start fresh
+ for (String id : ids) {
+ String path = resolveIdentityFilePath(id, host, port, username);
+ normal.addIdentity(path);
+ }
+
+ return normal;
+ }
+
+ /**
+ * Finds the best match out of the given ones.
+ *
+ * @param matches The available matches - ignored if {@code null}/empty
+ * @return The best match or {@code null} if no matches or no best match found
+ * @see #findBestMatch(Iterator)
+ */
+ public static HostConfigEntry findBestMatch(Collection<? extends HostConfigEntry> matches) {
+ if (GenericUtils.isEmpty(matches)) {
+ return null;
+ } else {
+ return findBestMatch(matches.iterator());
+ }
+ }
+
+ /**
+ * Finds the best match out of the given ones.
+ *
+ * @param matches The available matches - ignored if {@code null}/empty
+ * @return The best match or {@code null} if no matches or no best match found
+ * @see #findBestMatch(Iterator)
+ */
+ public static HostConfigEntry findBestMatch(Iterable<? extends HostConfigEntry> matches) {
+ if (matches == null) {
+ return null;
+ } else {
+ return findBestMatch(matches.iterator());
+ }
+ }
+
+ /**
+ * Finds the best match out of the given ones. The best match is defined as one whose
+ * pattern is as <U>specific</U> as possible (if more than one match is available).
+ * I.e., a non-global match is preferred over global one, and a match with no wildcards
+ * is preferred over one with such a pattern.
+ *
+ * @param matches The available matches - ignored if {@code null}/empty
+ * @return The best match or {@code null} if no matches or no best match found
+ * @see #isSpecificHostPattern(String)
+ */
+ public static HostConfigEntry findBestMatch(Iterator<? extends HostConfigEntry> matches) {
+ if ((matches == null) || (!matches.hasNext())) {
+ return null;
+ }
+
+ HostConfigEntry candidate = matches.next();
+ int wildcardMatches = 0;
+ while (matches.hasNext()) {
+ HostConfigEntry entry = matches.next();
+ String entryPattern = entry.getHost();
+ String candidatePattern = candidate.getHost();
+ // prefer non-global entry over global entry
+ if (ALL_HOSTS_PATTERN.equalsIgnoreCase(candidatePattern)) {
+ // unlikely, but handle it
+ if (ALL_HOSTS_PATTERN.equalsIgnoreCase(entryPattern)) {
+ wildcardMatches++;
+ } else {
+ candidate = entry;
+ wildcardMatches = 0;
+ }
+ continue;
+ }
+
+ if (isSpecificHostPattern(entryPattern)) {
+ // if both are specific then no best match
+ if (isSpecificHostPattern(candidatePattern)) {
+ return null;
+ }
+
+ candidate = entry;
+ wildcardMatches = 0;
+ continue;
+ }
+
+ wildcardMatches++;
+ }
+
+ String candidatePattern = candidate.getHost();
+ // best match either has specific host or no wildcard matches
+ if ((wildcardMatches <= 0) || (isSpecificHostPattern(candidatePattern))) {
+ return candidate;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param pattern The pattern to check - ignored if {@code null}/empty
+ * @return {@code true} if the pattern is not empty and contains no wildcard characters
+ * @see #WILDCARD_PATTERN
+ * @see #SINGLE_CHAR_PATTERN
+ */
+ public static boolean isSpecificHostPattern(String pattern) {
+ if (GenericUtils.isEmpty(pattern)) {
+ return false;
+ }
+
+ for (int index = 0; index < PATTERN_CHARS.length(); index++) {
+ char ch = PATTERN_CHARS.charAt(index);
+ if (pattern.indexOf(ch) >= 0) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Locates all the matching entries for a give host name / address
+ *
+ * @param host The host name / address - ignored if {@code null}/empty
+ * @param entries The {@link HostConfigEntry}-ies to scan - ignored if {@code null}/empty
+ * @return A {@link List} of all the matching entries
+ * @see #isHostMatch(String)
+ */
+ public static List<HostConfigEntry> findMatchingEntries(String host, HostConfigEntry ... entries) {
+ // TODO in Java-8 use Stream(s) + predicate
+ if (GenericUtils.isEmpty(host) || GenericUtils.isEmpty(entries)) {
+ return Collections.emptyList();
+ } else {
+ return findMatchingEntries(host, Arrays.asList(entries));
+ }
+ }
+
+ /**
+ * Locates all the matching entries for a give host name / address
+ *
+ * @param host The host name / address - ignored if {@code null}/empty
+ * @param entries The {@link HostConfigEntry}-ies to scan - ignored if {@code null}/empty
+ * @return A {@link List} of all the matching entries
+ * @see #isHostMatch(String)
+ */
+ public static List<HostConfigEntry> findMatchingEntries(String host, Collection<? extends HostConfigEntry> entries) {
+ // TODO in Java-8 use Stream(s) + predicate
+ if (GenericUtils.isEmpty(host) || GenericUtils.isEmpty(entries)) {
+ return Collections.emptyList();
+ }
+
+ List<HostConfigEntry> matches = null;
+ for (HostConfigEntry entry : entries) {
+ if (!entry.isHostMatch(host)) {
+ continue; // debug breakpoint
+ }
+
+ if (matches == null) {
+ matches = new ArrayList<>(entries.size()); // in case ALL of them match
+ }
+
+ matches.add(entry);
+ }
+
+ if (matches == null) {
+ return Collections.emptyList();
+ } else {
+ return matches;
+ }
+ }
+
+ /**
+ * Resolves the effective target host
+ *
+ * @param originalName The original requested host
+ * @param entryName The configured host
+ * @return If the configured host entry is not {@code null}/empty
+ * then it is used, otherwise the original one.
+ */
+ public static String resolveHostName(String originalName, String entryName) {
+ if (GenericUtils.isEmpty(entryName)) {
+ return originalName;
+ } else {
+ return entryName;
+ }
+ }
+
+ /**
+ * Resolves the effective username
+ *
+ * @param originalUser The original requested username
+ * @param entryUser The configured host entry username
+ * @return If the configured host entry username is not {@code null}/empty
+ * then it is used, otherwise the original one.
+ */
+ public static String resolveUsername(String originalUser, String entryUser) {
+ if (GenericUtils.isEmpty(entryUser)) {
+ return originalUser;
+ } else {
+ return entryUser;
+ }
+ }
+
+ /**
+ * Resolves the effective port to use
+ *
+ * @param originalPort The original requested port
+ * @param entryPort The configured host entry port
+ * @return If the host entry port is positive, then it is used, otherwise
+ * the original requested port
+ */
+ public static int resolvePort(int originalPort, int entryPort) {
+ if (entryPort <= 0) {
+ return originalPort;
+ } else {
+ return entryPort;
+ }
+ }
+
+ /**
+ * Checks if a given host name / address matches a host pattern
+ *
+ * @param host The host name / address - ignored if {@code null}/empty
+ * @param pattern The host pattern string - ignored if {@code null}/empty
+ * @return {@code true} if the name / address matches the pattern
+ * @see #toPattern(String)
+ * @see #isHostMatch(String, Pattern)
+ */
+ public static boolean isHostMatch(String host, CharSequence pattern) {
+ return isHostMatch(host, toPattern(pattern));
+ }
+
+ /**
+ * Checks if a given host name / address matches a host pattern
+ *
+ * @param host The host name / address - ignored if {@code null}/empty
+ * @param pattern The host {@link Pattern} - ignored if {@code null}
+ * @return {@code true} if the name / address matches the pattern
+ */
+ public static boolean isHostMatch(String host, Pattern pattern) {
+ if (GenericUtils.isEmpty(host) || (pattern == null)) {
+ return false;
+ }
+
+ Matcher m = pattern.matcher(host);
+ return m.matches();
+ }
+
+ /**
+ * Converts a host pattern string to a regular expression matcher.
+ * <B>Note:</B> pattern matching is <U>case insensitive</U>
+ *
+ * @param pattern The original pattern string - ignored if {@code null}/empty
+ * @return The regular expression matcher {@link Pattern} - {@code null}
+ * if empty original string
+ * @see #WILDCARD_PATTERN
+ * @see #SINGLE_CHAR_PATTERN
+ */
+ public static Pattern toPattern(CharSequence pattern) {
+ if (GenericUtils.isEmpty(pattern)) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder(pattern.length());
+ for (int curPos = 0; curPos < pattern.length(); curPos++) {
+ char ch = pattern.charAt(curPos);
+ ValidateUtils.checkTrue(isValidPatternChar(ch), "Invalid host pattern char in %s", pattern);
+
+ switch(ch) {
+ case '.': // need to escape it
+ sb.append('\\').append(ch);
+ break;
+ case SINGLE_CHAR_PATTERN:
+ sb.append('.');
+ break;
+ case WILDCARD_PATTERN:
+ sb.append(".*");
+ break;
+ default:
+ sb.append(ch);
+ }
+ }
+
+ return Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
+ }
+
+ /**
+ * Checks if the given character is valid for a host pattern. Valid
+ * characters are:
+ * <UL>
+ * <LI>A-Z</LI>
+ * <LI>a-z</LI>
+ * <LI>0-9</LI>
+ * <LI>Underscore (_)</LI>
+ * <LI>Hyphen (-)</LI>
+ * <LI>Dot (.)</LI>
+ * <LI>The {@link #WILDCARD_PATTERN}</LI>
+ * <LI>The {@link #SINGLE_CHAR_PATTERN}</LI>
+ * </UL>
+ *
+ * @param ch The character to validate
+ * @return {@code true} if valid pattern character
+ */
+ public static boolean isValidPatternChar(char ch) {
+ if ((ch <= ' ') || (ch >= 0x7E)) {
+ return false;
+ }
+ if ((ch >= 'a') && (ch <= 'z')) {
+ return true;
+ }
+ if ((ch >= 'A') && (ch <= 'Z')) {
+ return true;
+ }
+ if ((ch >= '0') && (ch <= '9')) {
+ return true;
+ }
+ if ("-_.".indexOf(ch) >= 0) {
+ return true;
+ }
+ if ((ch == SINGLE_CHAR_PATTERN) || (ch == WILDCARD_PATTERN)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(File file) throws IOException {
+ return readHostConfigEntries(file.toPath(), IoUtils.EMPTY_OPEN_OPTIONS);
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(Path path, OpenOption... options) throws IOException {
+ try (InputStream input = Files.newInputStream(path, options)) {
+ return readHostConfigEntries(input, true);
+ }
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(URL url) throws IOException {
+ try (InputStream input = url.openStream()) {
+ return readHostConfigEntries(input, true);
+ }
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(String filePath) throws IOException {
+ try (InputStream inStream = new FileInputStream(filePath)) {
+ return readHostConfigEntries(inStream, true);
+ }
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(InputStream inStream, boolean okToClose) throws IOException {
+ try (Reader reader = new InputStreamReader(NoCloseInputStream.resolveInputStream(inStream, okToClose), StandardCharsets.UTF_8)) {
+ return readHostConfigEntries(reader, true);
+ }
+ }
+
+ public static List<HostConfigEntry> readHostConfigEntries(Reader rdr, boolean okToClose) throws IOException {
+ try (BufferedReader buf = new BufferedReader(NoCloseReader.resolveReader(rdr, okToClose))) {
+ return readHostConfigEntries(buf);
+ }
+ }
+
+ /**
+ * Reads configuration entries
+ *
+ * @param rdr The {@link BufferedReader} to use
+ * @return The {@link List} of read {@link HostConfigEntry}-ies
+ * @throws IOException If failed to parse the read configuration
+ */
+ public static List<HostConfigEntry> readHostConfigEntries(BufferedReader rdr) throws IOException {
+ HostConfigEntry curEntry = null;
+ HostConfigEntry globalEntry = null;
+ List<HostConfigEntry> entries = null;
+ List<String> multiHosts = Collections.emptyList();
+
+ int lineNumber = 1;
+ for (String line = rdr.readLine(); line != null; line = rdr.readLine(), lineNumber++) {
+ line = GenericUtils.trimToEmpty(line);
+ if (GenericUtils.isEmpty(line)) {
+ continue;
+ }
+
+ int pos = line.indexOf(SshConfigFileReader.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 configuration value delimiter at line " + lineNumber + ": " + line);
+ }
+
+ String key = line.substring(0, pos);
+ String value = line.substring(pos + 1);
+ List<String> valsList = parseConfigValue(value);
+
+ if (HOST_CONFIG_PROP.equalsIgnoreCase(key)) {
+ if (GenericUtils.isEmpty(valsList)) {
+ throw new StreamCorruptedException("Missing host pattern(s) at line " + lineNumber + ": " + line);
+ }
+
+ // If the all-hosts pattern is used, make sure no global section already active
+ for (String name : valsList) {
+ if (ALL_HOSTS_PATTERN.equalsIgnoreCase(name) && (globalEntry != null)) {
+ throw new StreamCorruptedException("Overriding the global section with a specific one at line " + lineNumber + ": " + line);
+ }
+ }
+
+ if (curEntry != null) {
+ curEntry.processGlobalValues(globalEntry);
+ }
+
+ entries = updateEntriesList(entries, curEntry, multiHosts);
+
+ curEntry = new HostConfigEntry();
+ curEntry.setHost(valsList.get(0));
+ // allow for multiple hosts patterns
+ if (valsList.size() > 1) {
+ multiHosts = valsList.subList(1, valsList.size());
+ } else {
+ multiHosts = Collections.emptyList();
+ }
+ } else if (curEntry == null) {
+ // if 1st encountered property is NOT for a specific host, then configuration applies to ALL
+ curEntry = new HostConfigEntry();
+ curEntry.setHost(ALL_HOSTS_PATTERN);
+ multiHosts = Collections.emptyList();
+ globalEntry = curEntry;
+ }
+
+ try {
+ curEntry.processProperty(key, valsList, false);
+ } catch (RuntimeException e) {
+ throw new StreamCorruptedException("Failed (" + e.getClass().getSimpleName() + ")"
+ + " to process line #" + lineNumber + " (" + line + ")"
+ + ": " + e.getMessage());
+ }
+ }
+
+ if (curEntry != null) {
+ curEntry.processGlobalValues(globalEntry);
+ }
+
+ entries = updateEntriesList(entries, curEntry, multiHosts);
+ if (entries == null) {
+ return Collections.emptyList();
+ } else {
+ return entries;
+ }
+ }
+
+ public static void writeHostConfigEntries(File file, Collection<? extends HostConfigEntry> entries) throws IOException {
+ writeHostConfigEntries(ValidateUtils.checkNotNull(file, "No file").toPath(), entries, IoUtils.EMPTY_OPEN_OPTIONS);
+ }
+
+ public static void writeHostConfigEntries(Path path, Collection<? extends HostConfigEntry> entries, OpenOption ... options) throws IOException {
+ try (OutputStream outputStream = Files.newOutputStream(path, options)) {
+ writeHostConfigEntries(outputStream, true, entries);
+ }
+ }
+
+ public static void writeHostConfigEntries(OutputStream outputStream, boolean okToClose, Collection<? extends HostConfigEntry> entries) throws IOException {
+ if (GenericUtils.isEmpty(entries)) {
+ return;
+ }
+
+ try (Writer w = new OutputStreamWriter(NoCloseOutputStream.resolveOutputStream(outputStream, okToClose), StandardCharsets.UTF_8)) {
+ appendHostConfigEntries(w, entries);
+ }
+ }
+
+ public static <A extends Appendable> A appendHostConfigEntries(A sb, Collection<? extends HostConfigEntry> entries) throws IOException {
+ if (GenericUtils.isEmpty(entries)) {
+ return sb;
+ }
+
+ for (HostConfigEntry entry : entries) {
+ entry.append(sb);
+ }
+
+ return sb;
+ }
+
+ /**
+ * @param entries The original list - if {@code null} one will be allocated if necessary
+ * @param curEntry The current entry - ignored if {@code null}
+ * @param hosts The extra host patterns to be attached to the entry - ignored
+ * if {@code null}/empty
+ * @return The updated list of entries - same as input if nothing added
+ * @see #duplicateConfiguration(HostConfigEntry, Collection)
+ */
+ public static List<HostConfigEntry> updateEntriesList(List<HostConfigEntry> entries, HostConfigEntry curEntry, Collection<String> hosts) {
+ if (curEntry == null) {
+ return entries;
+ }
+
+ // TODO consider allowing multiple patterns for same entry instead of duplicating the entries
+ Collection<HostConfigEntry> dups = duplicateConfiguration(curEntry, hosts);
+ int extraHosts = Math.max(0, GenericUtils.size(dups));
+ if (entries == null) {
+ entries = new ArrayList<>(Math.max(1 + extraHosts, Byte.SIZE));
+ }
+
+ entries.add(curEntry);
+
+ if (extraHosts > 0) {
+ entries.addAll(dups);
+ }
+
+ return entries;
+ }
+
+ /**
+ * @param entry The original entry to duplicate - ignored if {@code null}
+ * @param hosts The hosts patterns to attach to each duplicated entry -
+ * ignored if {@code null}/empty
+ * @return A {@link List} of duplicated entries where each new entry host
+ * pattern is updated from the given one
+ */
+ public static List<HostConfigEntry> duplicateConfiguration(HostConfigEntry entry, Collection<String> hosts) {
+ if ((entry == null) || GenericUtils.isEmpty(hosts)) {
+ return Collections.emptyList();
+ }
+
+ List<HostConfigEntry> dups = new ArrayList<>(hosts.size());
+ for (String pattern : hosts) {
+ HostConfigEntry cloned = entry.clone();
+ cloned.setHost(pattern);
+ dups.add(cloned);
+ }
+
+ return dups;
+ }
+
+ /**
+ * Checks if this is a multi-value - allow space and comma
+ *
+ * @param value The value - ignored if {@code null}/empty (after trimming)
+ * @return A {@link List} of the encountered values
+ */
+ public static List<String> parseConfigValue(String value) {
+ String s = GenericUtils.trimToEmpty(value);
+ if (GenericUtils.isEmpty(s)) {
+ return Collections.emptyList();
+ }
+
+ for (int index = 0; index < MULTI_VALUE_SEPARATORS.length(); index++) {
+ char sep = MULTI_VALUE_SEPARATORS.charAt(index);
+ int pos = s.indexOf(sep);
+ if (pos >= 0) {
+ String[] vals = GenericUtils.split(s, sep);
+ if (GenericUtils.isEmpty(vals)) {
+ return Collections.emptyList();
+ } else {
+ return Arrays.asList(vals);
+ }
+ }
+ }
+
+ // this point is reached if no separators found
+ return Collections.singletonList(s);
+ }
+
+ // The file name may use the tilde syntax to refer to a user’s home directory or one of the following escape characters:
+ // '%d' (local user's home directory), '%u' (local user name), '%l' (local host name), '%h' (remote host name) or '%r' (remote user name).
+ public static String resolveIdentityFilePath(String id, String host, int port, String username) throws IOException {
+ if (GenericUtils.isEmpty(id)) {
+ return id;
+ }
+
+ String path = id.replace('/', File.separatorChar); // make sure all separators are local
+ String[] elements = GenericUtils.split(path, File.separatorChar);
+ StringBuilder sb = new StringBuilder(path.length() + Long.SIZE);
+ for (int index = 0; index < elements.length; index++) {
+ String elem = elements[index];
+ if (index > 0) {
+ sb.append(File.separatorChar);
+ }
+
+ for (int curPos = 0; curPos < elem.length(); curPos++) {
+ char ch = elem.charAt(curPos);
+ if (ch == HOME_TILDE_CHAR) {
+ ValidateUtils.checkTrue((curPos == 0) && (index == 0), "Home tilde must be first: %s", id);
+ appendUserHome(sb);
+ } else if (ch == PATH_MACRO_CHAR) {
+ curPos++;
+ ValidateUtils.checkTrue(curPos < elem.length(), "Missing macro modifier in %s", id);
+ ch = elem.charAt(curPos);
+ switch(ch) {
+ case PATH_MACRO_CHAR:
+ sb.append(ch);
+ break;
+ case LOCAL_HOME_MACRO:
+ ValidateUtils.checkTrue((curPos == 1) && (index == 0), "Home macro must be first: %s", id);
+ appendUserHome(sb);
+ break;
+ case LOCAL_USER_MACRO:
+ sb.append(ValidateUtils.checkNotNullAndNotEmpty(System.getProperty("user.name"), "No local user name value"));
+ break;
+ case LOCAL_HOST_MACRO:
+ {
+ InetAddress address = ValidateUtils.checkNotNull(InetAddress.getLocalHost(), "No local address");
+ sb.append(ValidateUtils.checkNotNullAndNotEmpty(address.getHostName(), "No local name"));
+ break;
+ }
+ case REMOTE_HOST_MACRO:
+ sb.append(ValidateUtils.checkNotNullAndNotEmpty(host, "No remote host provided"));
+ break;
+ case REMOTE_USER_MACRO:
+ sb.append(ValidateUtils.checkNotNullAndNotEmpty(username, "No remote user provided"));
+ break;
+ case REMOTE_PORT_MACRO:
+ ValidateUtils.checkTrue(port > 0, "Bad remote port value: %d", port);
+ sb.append(port);
+ break;
+ default:
+ ValidateUtils.throwIllegalArgumentException("Bad modifier '%s' in %s", String.valueOf(ch), id);
+ }
+ } else {
+ sb.append(ch);
+ }
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public static StringBuilder appendUserHome(StringBuilder sb) {
+ return appendUserHome(sb, ValidateUtils.checkNotNullAndNotEmpty(System.getProperty("user.home"), "No user home property"));
+ }
+
+ public static StringBuilder appendUserHome(StringBuilder sb, String userHome) {
+ if (GenericUtils.isEmpty(userHome)) {
+ return sb;
+ }
+
+ sb.append(userHome);
+ // strip any ending separator since we add our own
+ int len = sb.length();
+ if (sb.charAt(len - 1) == File.separatorChar) {
+ sb.setLength(len - 1);
+ }
+
+ return sb;
+ }
+
+ /**
+ * @return The default {@link File} location of the OpenSSH authorized keys file
+ */
+ @SuppressWarnings("synthetic-access")
+ public static File getDefaultHostConfigFile() {
+ return LazyDefaultConfigFileHolder.KEYS_FILE;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolver.java
new file mode 100644
index 0000000..596c59d
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolver.java
@@ -0,0 +1,59 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.IOException;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface HostConfigEntryResolver {
+
+ /**
+ * An "empty" implementation that does not resolve any entry
+ */
+ HostConfigEntryResolver EMPTY = new HostConfigEntryResolver() {
+ @Override
+ public HostConfigEntry resolveEffectiveHost(String host, int port, String username) throws IOException {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "EMPTY";
+ }
+ };
+
+ /**
+ * Invoked when creating a new client session in order to allow for overriding
+ * of the original parameters
+ *
+ * @param host The requested host - never {@code null}/empty
+ * @param port The requested port
+ * @param username The requested username
+ * @return A {@link HostConfigEntry} for the actual target - {@code null} if use
+ * original parameters. <B>Note:</B> if any identity files are attached to the
+ * configuration then they must point to <U>existing</U> locations. This means
+ * that any macros such as <code>~, %d, %h</code>, etc. must be resolved <U>prior</U>
+ * to returning the value
+ * @throws IOException If failed to resolve the configuration
+ */
+ HostConfigEntry resolveEffectiveHost(String host, int port, String username) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
new file mode 100644
index 0000000..cb11e10
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
@@ -0,0 +1,99 @@
+/*
+ * 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.client.config.keys;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ClientIdentityLoader {
+ /**
+ * <P>A default implementation that assumes a file location that <U>must</U> exist.</P>
+ *
+ * <P>
+ * <B>Note:</B> It calls {@link SecurityUtils#loadKeyPairIdentity(String, InputStream, FilePasswordProvider)}
+ * which fails if the {@code Bouncycastle} provider is not registered, therefore the
+ * default {@link #isValidLocation(String)} implementation also checks if
+ * {@link SecurityUtils#isBouncyCastleRegistered()}
+ * </P>
+ */
+ ClientIdentityLoader DEFAULT = new ClientIdentityLoader() {
+ @Override
+ public boolean isValidLocation(String location) throws IOException {
+ if (!SecurityUtils.isBouncyCastleRegistered()) {
+ return false;
+ }
+ Path path = toPath(location);
+ return Files.exists(path, IoUtils.EMPTY_LINK_OPTIONS);
+ }
+
+ @Override
+ public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ Path path = toPath(location);
+ try (InputStream inputStream = Files.newInputStream(path, IoUtils.EMPTY_OPEN_OPTIONS)) {
+ return SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DEFAULT";
+ }
+
+ private Path toPath(String location) {
+ Path path = new File(ValidateUtils.checkNotNullAndNotEmpty(location, "No location")).toPath();
+ return path.toAbsolutePath().normalize();
+ }
+ };
+
+ /**
+ * @param location The identity key-pair location - the actual meaning (file, URL, etc.)
+ * depends on the implementation.
+ * @return {@code true} if it represents a valid location - the actual meaning of
+ * the validity depends on the implementation
+ * @throws IOException If failed to validate the location
+ */
+ boolean isValidLocation(String location) throws IOException;
+
+ /**
+ * @param location The identity key-pair location - the actual meaning (file, URL, etc.)
+ * depends on the implementation.
+ * @param provider The {@link FilePasswordProvider} to consult if the location contains
+ * an encrypted identity
+ * @return The loaded {@link KeyPair} - {@code null} if location is empty
+ * and it is OK that it does not exist
+ * @throws IOException If failed to access / process the remote location
+ * @throws GeneralSecurityException If failed to convert the contents into
+ * a valid identity
+ */
+ KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/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
index 95a1496..1af1fd8 100644
--- 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
@@ -26,6 +26,21 @@ import java.io.IOException;
*/
public interface FilePasswordProvider {
/**
+ * An "empty" provider that returns {@code null} - i.e., unprotected key file
+ */
+ FilePasswordProvider EMPTY = new FilePasswordProvider() {
+ @Override
+ public String getPassword(String resourceKey) throws IOException {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "EMPTY";
+ }
+ };
+
+ /**
* @param resourceKey The resource key representing the <U>private</U>
* file
* @return The password - if {@code null}/empty then no password is required
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index 87631d7..c82dabf 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -286,6 +286,18 @@ public final class GenericUtils {
* @return A {@link SortedSet} containing the values (if any) sorted
* using the provided comparator
*/
+ @SafeVarargs
+ public static <V> SortedSet<V> asSortedSet(Comparator<? super V> comp, V ... values) {
+ return asSortedSet(comp, isEmpty(values) ? Collections.<V>emptyList() : Arrays.asList(values));
+ }
+
+ /**
+ * @param <V> The element type
+ * @param comp The (non-{@code null}) {@link Comparator} to use
+ * @param values The values to be added (ignored if {@code null}/empty)
+ * @return A {@link SortedSet} containing the values (if any) sorted
+ * using the provided comparator
+ */
public static <V> SortedSet<V> asSortedSet(Comparator<? super V> comp, Collection<? extends V> values) {
// TODO for JDK-8 return Collections.emptySortedSet()
SortedSet<V> set = new TreeSet<V>(ValidateUtils.checkNotNull(comp, "No comparator"));
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
index df9a0a3..d049cad 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java
@@ -54,8 +54,16 @@ public final class IoUtils {
public static final List<String> WINDOWS_EXECUTABLE_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(".bat", ".exe", ".cmd"));
+ /**
+ * Size of preferred work buffer when reading / writing data to / from streams
+ */
public static final int DEFAULT_COPY_SIZE = 8192;
+ /**
+ * The local O/S line separator
+ */
+ public static final String EOL = System.getProperty("line.separator");
+
private static final LinkOption[] NO_FOLLOW_OPTIONS = new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
/**
@@ -378,4 +386,30 @@ public final class IoUtils {
return true;
}
+ public static String appendPathComponent(String prefix, String component) {
+ if (GenericUtils.isEmpty(prefix)) {
+ return component;
+ }
+
+ if (GenericUtils.isEmpty(component)) {
+ return prefix;
+ }
+
+ StringBuilder sb = new StringBuilder(prefix.length() + component.length() + File.separator.length()).append(prefix);
+
+ if (sb.charAt(prefix.length() - 1) == File.separatorChar) {
+ if (component.charAt(0) == File.separatorChar) {
+ sb.append(component.substring(1));
+ } else {
+ sb.append(component);
+ }
+ } else {
+ if (component.charAt(0) != File.separatorChar) {
+ sb.append(File.separatorChar);
+ }
+ sb.append(component);
+ }
+
+ return sb.toString();
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/common/util/io/ModifiableFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/ModifiableFileWatcher.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/ModifiableFileWatcher.java
index 1b2c0dd..52d00a6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/io/ModifiableFileWatcher.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/ModifiableFileWatcher.java
@@ -158,7 +158,7 @@ public class ModifiableFileWatcher extends AbstractLoggingBean {
long size = size();
FileTime modifiedTime = lastModified();
- if (size >= 0L && modifiedTime != null) {
+ if ((size >= 0L) && (modifiedTime != null)) {
lastExisted.set(true);
lastSize.set(size);
lastModified.set(modifiedTime.toMillis());
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/server/command/UnknownCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/UnknownCommand.java b/sshd-core/src/main/java/org/apache/sshd/server/command/UnknownCommand.java
deleted file mode 100644
index 75f4b1f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/command/UnknownCommand.java
+++ /dev/null
@@ -1,82 +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.server.command;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.Environment;
-import org.apache.sshd.server.ExitCallback;
-
-/**
- * Implementation of an unknown command that can be returned by <code>CommandFactory</code>
- * when the command is not known, as it is supposed to always
- * return a valid <code>Command</code> object.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class UnknownCommand implements Command {
-
- private String command;
- private InputStream in;
- private OutputStream out;
- private OutputStream err;
- private ExitCallback callback;
-
- public UnknownCommand(String command) {
- this.command = command;
- }
-
- @Override
- public void setInputStream(InputStream in) {
- this.in = in;
- }
-
- @Override
- public void setOutputStream(OutputStream out) {
- this.out = out;
- }
-
- @Override
- public void setErrorStream(OutputStream err) {
- this.err = err;
- }
-
- @Override
- public void setExitCallback(ExitCallback callback) {
- this.callback = callback;
- }
-
- @Override
- public void start(Environment env) throws IOException {
- err.write(("Unknown command: " + command + "\n").getBytes(StandardCharsets.UTF_8));
- err.flush();
- if (callback != null) {
- callback.onExit(1, "Unknown command: " + command);
- }
- }
-
- @Override
- public void destroy() {
- // ignored
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeyEntry.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeyEntry.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeyEntry.java
index 052b05c..e6347ee 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeyEntry.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/AuthorizedKeyEntry.java
@@ -68,6 +68,10 @@ public class AuthorizedKeyEntry extends PublicKeyEntry {
private static final long serialVersionUID = -9007505285002809156L;
+ private static final class LazyDefaultAuthorizedKeysFileHolder {
+ private static final File KEYS_FILE = new File(PublicKeyEntry.getDefaultKeysFolder(), STD_AUTHORIZED_KEYS_FILENAME);
+ }
+
private String comment;
// for options that have no value, "true" is used
private Map<String, String> loginOptions = Collections.emptyMap();
@@ -163,10 +167,6 @@ public class AuthorizedKeyEntry extends PublicKeyEntry {
return keys;
}
- private static final class LazyDefaultAuthorizedKeysFileHolder {
- private static final File KEYS_FILE = new File(PublicKeyEntry.getDefaultKeysFolder(), STD_AUTHORIZED_KEYS_FILENAME);
- }
-
/**
* @return The default {@link File} location of the OpenSSH authorized keys file
*/
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/server/config/keys/DefaultAuthorizedKeysAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/DefaultAuthorizedKeysAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/DefaultAuthorizedKeysAuthenticator.java
index d4e485b..6e6ac22 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/DefaultAuthorizedKeysAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/DefaultAuthorizedKeysAuthenticator.java
@@ -103,7 +103,7 @@ public class DefaultAuthorizedKeysAuthenticator extends AuthorizedKeysAuthentica
protected Collection<AuthorizedKeyEntry> reloadAuthorizedKeys(Path path, String username, ServerSession session) throws IOException {
if (isStrict()) {
if (log.isDebugEnabled()) {
- log.info("reloadAuthorizedKeys(" + username + ")[" + session + "] check permissions of " + path);
+ log.debug("reloadAuthorizedKeys(" + username + ")[" + session + "] check permissions of " + path);
}
KeyUtils.validateStrictKeyFilePermissions(path);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 7e15fd9..d47fc74 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -2095,7 +2095,7 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
protected void appendExtensions(Buffer buffer, String supportedVersions) {
appendVersionsExtension(buffer, supportedVersions);
- appendNewlineExtension(buffer, System.getProperty("line.separator"));
+ appendNewlineExtension(buffer, IoUtils.EOL);
appendVendorIdExtension(buffer, VersionProperties.getVersionProperties());
appendOpenSSHExtensions(buffer);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java b/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java
index 25a2de8..a292909 100644
--- a/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java
@@ -37,11 +37,9 @@ import org.apache.sshd.deprecated.UserAuthPassword;
import org.apache.sshd.deprecated.UserAuthPublicKey;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSessionImpl;
import org.apache.sshd.server.session.SessionFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -63,10 +61,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.WELCOME_BANNER, WELCOME);
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.AUTH_METHODS, "publickey,password publickey,keyboard-interactive");
sshd.setSessionFactory(new SessionFactory(sshd) {
@@ -88,7 +83,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Test
public void testWrongPassword() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession s = client.connect("user", "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
s.addPasswordIdentity("bad password");
@@ -100,7 +95,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Test
public void testChangeUser() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setServiceFactories(Arrays.asList(
new ClientUserAuthServiceOld.Factory(),
ClientConnectionServiceFactory.INSTANCE
@@ -125,7 +120,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Test
public void testAuthPasswordOnly() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setServiceFactories(Arrays.asList(
new ClientUserAuthServiceOld.Factory(),
ClientConnectionServiceFactory.INSTANCE
@@ -146,7 +141,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Test
public void testAuthKeyPassword() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setServiceFactories(Arrays.asList(
new ClientUserAuthServiceOld.Factory(),
ClientConnectionServiceFactory.INSTANCE
@@ -168,7 +163,7 @@ public class AuthenticationTest extends BaseTestSupport {
@Test
public void testAuthKeyInteractive() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setServiceFactories(Arrays.asList(
new ClientUserAuthServiceOld.Factory(),
ClientConnectionServiceFactory.INSTANCE
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
index 18203fb..1cab46b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
@@ -30,9 +30,8 @@ import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShell;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
@@ -58,12 +57,9 @@ public class KeepAliveTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, FactoryManager.IDLE_TIMEOUT, TIMEOUT);
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new TestEchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd.start();
port = sshd.getPort();
}
@@ -77,7 +73,7 @@ public class KeepAliveTest extends BaseTestSupport {
@Test
public void testIdleClient() throws Exception {
- SshClient client = SshClient.setUpDefaultClient();
+ SshClient client = Utils.setupTestClient();
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -97,7 +93,7 @@ public class KeepAliveTest extends BaseTestSupport {
@Test
public void testClientWithHeartBeat() throws Exception {
- SshClient client = SshClient.setUpDefaultClient();
+ SshClient client = Utils.setupTestClient();
FactoryManagerUtils.updateProperty(client, ClientFactoryManager.HEARTBEAT_INTERVAL, HEARTBEAT);
client.start();
@@ -118,9 +114,9 @@ public class KeepAliveTest extends BaseTestSupport {
@Test
public void testShellClosedOnClientTimeout() throws Exception {
- TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
+ TestEchoShell.latch = new CountDownLatch(1);
- SshClient client = SshClient.setUpDefaultClient();
+ SshClient client = Utils.setupTestClient();
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -135,13 +131,14 @@ public class KeepAliveTest extends BaseTestSupport {
channel.setErr(err);
channel.open().verify(9L, TimeUnit.SECONDS);
- assertTrue("Latch time out", TestEchoShellFactory.TestEchoShell.latch.await(10L, TimeUnit.SECONDS));
+ assertTrue("Latch time out", TestEchoShell.latch.await(10L, TimeUnit.SECONDS));
int state = channel.waitFor(ClientChannel.CLOSED, WAIT);
assertEquals("Wrong channel state", ClientChannel.CLOSED | ClientChannel.EOF | ClientChannel.OPENED, state);
channel.close(false);
}
} finally {
+ TestEchoShell.latch = null;
client.stop();
}
}
@@ -151,18 +148,18 @@ public class KeepAliveTest extends BaseTestSupport {
public Command create() {
return new TestEchoShell();
}
+ }
- public static class TestEchoShell extends EchoShell {
+ public static class TestEchoShell extends EchoShell {
- public static CountDownLatch latch;
+ public static CountDownLatch latch;
- @Override
- public void destroy() {
- if (latch != null) {
- latch.countDown();
- }
- super.destroy();
+ @Override
+ public void destroy() {
+ if (latch != null) {
+ latch.countDown();
}
+ super.destroy();
}
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
index 571357f..5f541e9 100644
--- a/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
@@ -49,8 +49,6 @@ import org.apache.sshd.common.subsystem.sftp.SftpConstants;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.TeeOutputStream;
@@ -83,7 +81,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
}
protected void setUp(long bytesLimit, long timeLimit) throws Exception {
- sshd = SshServer.setUpDefaultServer();
+ sshd = Utils.setupTestServer();
if (bytesLimit > 0L) {
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.REKEY_BYTES_LIMIT, bytesLimit);
}
@@ -91,9 +89,6 @@ public class KeyReExchangeTest extends BaseTestSupport {
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.REKEY_TIME_LIMIT, timeLimit);
}
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.start();
port = sshd.getPort();
}
@@ -103,7 +98,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
setUp(0, 0);
sshd.getCipherFactories().add(BuiltinCiphers.none);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.getCipherFactories().add(BuiltinCiphers.none);
client.start();
@@ -127,7 +122,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
setUp(0, 0);
sshd.getCipherFactories().add(BuiltinCiphers.none);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.getCipherFactories().add(BuiltinCiphers.none);
// replace the original KEX factories with wrapped ones that we can fail intentionally
List<NamedFactory<KeyExchange>> kexFactories = new ArrayList<>();
@@ -235,7 +230,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
public void testReExchangeFromSshdClient() throws Exception {
setUp(0, 0);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -292,7 +287,7 @@ public class KeyReExchangeTest extends BaseTestSupport {
public void testReExchangeFromServer() throws Exception {
setUp(8192, 0);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
index 96b0ce1..187c204 100644
--- a/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
@@ -40,8 +40,6 @@ import org.apache.sshd.common.cipher.Cipher;
import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -57,10 +55,7 @@ public class LoadTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
sshd.start();
port = sshd.getPort();
}
@@ -120,7 +115,7 @@ public class LoadTest extends BaseTestSupport {
}
protected void runClient(String msg) throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
Map<String, Object> props = client.getProperties();
FactoryManagerUtils.updateProperty(props, FactoryManager.MAX_PACKET_SIZE, 1024 * 16);
FactoryManagerUtils.updateProperty(props, FactoryManager.WINDOW_SIZE, 1024 * 8);
[4/4] mina-sshd git commit: [SSHD-559] Add support for reading
specific host configuration from config file
Posted by lg...@apache.org.
[SSHD-559] Add support for reading specific host configuration from config file
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/950e896d
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/950e896d
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/950e896d
Branch: refs/heads/master
Commit: 950e896dc766b2d48a8946a197d7e0b4bf233549
Parents: 3615e4f
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Wed Sep 2 08:39:46 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Wed Sep 2 08:39:46 2015 +0300
----------------------------------------------------------------------
.../org/apache/sshd/client/ClientBuilder.java | 40 +
.../sshd/client/ClientFactoryManager.java | 32 +
.../java/org/apache/sshd/client/SshClient.java | 194 ++-
.../java/org/apache/sshd/client/SshKeyScan.java | 4 +-
.../hosts/ConfigFileHostEntryResolver.java | 104 ++
.../DefaultConfigFileHostEntryResolver.java | 82 +
.../client/config/hosts/HostConfigEntry.java | 1403 ++++++++++++++++++
.../config/hosts/HostConfigEntryResolver.java | 59 +
.../config/keys/ClientIdentityLoader.java | 99 ++
.../config/keys/FilePasswordProvider.java | 15 +
.../apache/sshd/common/util/GenericUtils.java | 12 +
.../org/apache/sshd/common/util/io/IoUtils.java | 34 +
.../common/util/io/ModifiableFileWatcher.java | 2 +-
.../sshd/server/command/UnknownCommand.java | 82 -
.../server/config/keys/AuthorizedKeyEntry.java | 8 +-
.../DefaultAuthorizedKeysAuthenticator.java | 2 +-
.../server/subsystem/sftp/SftpSubsystem.java | 2 +-
.../org/apache/sshd/AuthenticationTest.java | 17 +-
.../java/org/apache/sshd/KeepAliveTest.java | 35 +-
.../java/org/apache/sshd/KeyReExchangeTest.java | 15 +-
.../src/test/java/org/apache/sshd/LoadTest.java | 9 +-
.../org/apache/sshd/PortForwardingLoadTest.java | 7 +-
.../org/apache/sshd/PortForwardingTest.java | 9 +-
.../test/java/org/apache/sshd/ProxyTest.java | 9 +-
.../apache/sshd/SinglePublicKeyAuthTest.java | 16 +-
.../java/org/apache/sshd/WelcomeBannerTest.java | 9 +-
.../java/org/apache/sshd/WindowAdjustTest.java | 7 +-
.../java/org/apache/sshd/agent/AgentTest.java | 37 +-
.../java/org/apache/sshd/client/ClientTest.java | 41 +-
.../hosts/ConfigFileHostEntryResolverTest.java | 113 ++
.../hosts/HostConfigEntryResolverTest.java | 188 +++
.../config/hosts/HostConfigEntryTest.java | 301 ++++
.../org/apache/sshd/client/kex/KexTest.java | 9 +-
.../org/apache/sshd/client/scp/ScpTest.java | 52 +-
.../sftp/AbstractSftpClientTestSupport.java | 7 +-
.../subsystem/sftp/SftpFileSystemTest.java | 11 +-
.../sshd/client/subsystem/sftp/SftpTest.java | 22 +-
.../impl/AbstractCheckFileExtensionTest.java | 4 +-
.../impl/AbstractMD5HashExtensionTest.java | 4 +-
.../impl/CopyDataExtensionImplTest.java | 4 +-
.../impl/CopyFileExtensionImplTest.java | 2 +-
.../impl/SpaceAvailableExtensionImplTest.java | 2 +-
.../openssh/impl/OpenSSHExtensionsTest.java | 4 +-
.../apache/sshd/common/channel/WindowTest.java | 34 +-
.../sshd/common/cipher/BuiltinCiphersTest.java | 5 +-
.../apache/sshd/common/cipher/CipherTest.java | 10 +-
.../common/compression/CompressionTest.java | 10 +-
.../sshd/common/io/nio2/Nio2ServiceTest.java | 7 +-
.../org/apache/sshd/common/mac/MacTest.java | 9 +-
.../common/session/AbstractSessionTest.java | 4 +-
.../AbstractSignatureFactoryTestSupport.java | 7 +-
.../java/org/apache/sshd/server/ServerTest.java | 46 +-
.../org/apache/sshd/server/SshServerTest.java | 18 +-
.../keys/AuthorizedKeysAuthenticatorTest.java | 6 +-
.../server/subsystem/sftp/SshFsMounter.java | 4 +-
.../java/org/apache/sshd/util/EchoShell.java | 121 ++
.../org/apache/sshd/util/EchoShellFactory.java | 102 +-
.../org/apache/sshd/util/UnknownCommand.java | 82 +
.../apache/sshd/util/UnknownCommandFactory.java | 39 +
.../test/java/org/apache/sshd/util/Utils.java | 23 +-
.../testReadGlobalHostsConfigEntries.config.txt | 23 +
.../testReadMultipleHostPatterns.config.txt | 5 +
.../testReadSimpleHostsConfigEntries.config.txt | 8 +
.../sshd/git/pack/GitPackCommandFactory.java | 2 +-
.../sshd/git/pgm/GitPgmCommandFactory.java | 2 +-
65 files changed, 3165 insertions(+), 510 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
index 0f9de38..c7f1bb5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientBuilder.java
@@ -23,12 +23,16 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import org.apache.sshd.client.config.hosts.DefaultConfigFileHostEntryResolver;
+import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
+import org.apache.sshd.client.config.keys.ClientIdentityLoader;
import org.apache.sshd.client.kex.DHGClient;
import org.apache.sshd.client.kex.DHGEXClient;
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
import org.apache.sshd.common.BaseBuilder;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.channel.Channel;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
import org.apache.sshd.common.kex.DHFactory;
import org.apache.sshd.common.kex.KeyExchange;
import org.apache.sshd.common.util.Transformer;
@@ -56,8 +60,14 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
Collections.unmodifiableList(Arrays.<NamedFactory<Channel>>asList(ForwardedTcpipFactory.INSTANCE));
public static final ServerKeyVerifier DEFAULT_SERVER_KEY_VERIFIER = AcceptAllServerKeyVerifier.INSTANCE;
+ public static final HostConfigEntryResolver DEFAULT_HOST_CONFIG_ENTRY_RESOLVER = DefaultConfigFileHostEntryResolver.INSTANCE;
+ public static final ClientIdentityLoader DEFAULT_CLIENT_IDENTITY_LOADER = ClientIdentityLoader.DEFAULT;
+ public static final FilePasswordProvider DEFAULT_FILE_PASSWORD_PROVIDER = FilePasswordProvider.EMPTY;
protected ServerKeyVerifier serverKeyVerifier;
+ protected HostConfigEntryResolver hostConfigEntryResolver;
+ protected ClientIdentityLoader clientIdentityLoader;
+ protected FilePasswordProvider filePasswordProvider;
public ClientBuilder() {
super();
@@ -68,6 +78,21 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
return me();
}
+ public ClientBuilder hostConfigEntryResolver(HostConfigEntryResolver resolver) {
+ this.hostConfigEntryResolver = resolver;
+ return me();
+ }
+
+ public ClientBuilder clientIdentityLoader(ClientIdentityLoader loader) {
+ this.clientIdentityLoader = loader;
+ return me();
+ }
+
+ public ClientBuilder filePasswordProvider(FilePasswordProvider provider) {
+ this.filePasswordProvider = provider;
+ return me();
+ }
+
@Override
protected ClientBuilder fillWithDefaultValues() {
super.fillWithDefaultValues();
@@ -84,6 +109,18 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
serverKeyVerifier = DEFAULT_SERVER_KEY_VERIFIER;
}
+ if (hostConfigEntryResolver == null) {
+ hostConfigEntryResolver = DEFAULT_HOST_CONFIG_ENTRY_RESOLVER;
+ }
+
+ if (clientIdentityLoader == null) {
+ clientIdentityLoader = DEFAULT_CLIENT_IDENTITY_LOADER;
+ }
+
+ if (filePasswordProvider == null) {
+ filePasswordProvider = DEFAULT_FILE_PASSWORD_PROVIDER;
+ }
+
if (factory == null) {
factory = SshClient.DEFAULT_SSH_CLIENT_FACTORY;
}
@@ -95,6 +132,9 @@ public class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
public SshClient build(boolean isFillWithDefaultValues) {
SshClient client = super.build(isFillWithDefaultValues);
client.setServerKeyVerifier(serverKeyVerifier);
+ client.setHostConfigEntryResolver(hostConfigEntryResolver);
+ client.setClientIdentityLoader(clientIdentityLoader);
+ client.setFilePasswordProvider(filePasswordProvider);
return client;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
index 03b7308..ef4bda3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/ClientFactoryManager.java
@@ -22,8 +22,11 @@ import java.util.List;
import org.apache.sshd.client.auth.UserAuth;
import org.apache.sshd.client.auth.UserInteraction;
+import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
+import org.apache.sshd.client.config.keys.ClientIdentityLoader;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
/**
* The <code>ClientFactoryManager</code> enable the retrieval of additional
@@ -70,6 +73,18 @@ public interface ClientFactoryManager extends FactoryManager {
int DEFAULT_PASSWORD_PROMPTS = 3;
/**
+ * Whether to ignore invalid identities files when pre-initializing
+ * the client session
+ * @see ClientIdentityLoader#isValidLocation(String)
+ */
+ String IGNORE_INVALID_IDENTITIES = "ignore-invalid-identities";
+
+ /**
+ * Default value of {@link #IGNORE_INVALID_IDENTITIES} if none configured
+ */
+ boolean DEFAULT_IGNORE_INVALID_IDENTITIES = true;
+
+ /**
* Retrieve the server key verifier to be used to check the key when connecting
* to an ssh server.
*
@@ -89,4 +104,21 @@ public interface ClientFactoryManager extends FactoryManager {
*/
List<NamedFactory<UserAuth>> getUserAuthFactories();
+ /**
+ * @return The {@link HostConfigEntryResolver} to use in order to resolve the
+ * effective session parameters
+ */
+ HostConfigEntryResolver getHostConfigEntryResolver();
+
+ /**
+ * @return The {@link ClientIdentityLoader} to use in order to load client
+ * key pair identities
+ */
+ ClientIdentityLoader getClientIdentityLoader();
+
+ /**
+ * @return The {@link FilePasswordProvider} to use if need to load encrypted
+ * identities keys
+ */
+ FilePasswordProvider getFilePasswordProvider();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
index 6e21329..aa0db19 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java
@@ -20,15 +20,21 @@ package org.apache.sshd.client;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
+import java.io.StreamCorruptedException;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.nio.file.LinkOption;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
@@ -49,7 +55,10 @@ import org.apache.sshd.client.auth.UserAuthPublicKeyFactory;
import org.apache.sshd.client.auth.UserInteraction;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.config.hosts.HostConfigEntry;
+import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.client.config.keys.ClientIdentity;
+import org.apache.sshd.client.config.keys.ClientIdentityLoader;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.future.DefaultConnectFuture;
import org.apache.sshd.client.session.ClientConnectionServiceFactory;
@@ -59,12 +68,14 @@ import org.apache.sshd.client.session.SessionFactory;
import org.apache.sshd.common.AbstractFactoryManager;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.SshdSocketAddress;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.config.SshConfigFileReader;
import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoConnectFuture;
import org.apache.sshd.common.io.IoConnector;
@@ -73,6 +84,7 @@ import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SecurityUtils;
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.NoCloseOutputStream;
@@ -153,6 +165,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
protected List<NamedFactory<UserAuth>> userAuthFactories;
private ServerKeyVerifier serverKeyVerifier;
+ private HostConfigEntryResolver hostConfigEntryResolver;
+ private ClientIdentityLoader clientIdentityLoader;
+ private FilePasswordProvider filePasswordProvider;
public SshClient() {
super();
@@ -176,6 +191,33 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
}
@Override
+ public HostConfigEntryResolver getHostConfigEntryResolver() {
+ return hostConfigEntryResolver;
+ }
+
+ public void setHostConfigEntryResolver(HostConfigEntryResolver resolver) {
+ this.hostConfigEntryResolver = resolver;
+ }
+
+ @Override
+ public FilePasswordProvider getFilePasswordProvider() {
+ return filePasswordProvider;
+ }
+
+ public void setFilePasswordProvider(FilePasswordProvider provider) {
+ this.filePasswordProvider = provider;
+ }
+
+ @Override
+ public ClientIdentityLoader getClientIdentityLoader() {
+ return clientIdentityLoader;
+ }
+
+ public void setClientIdentityLoader(ClientIdentityLoader loader) {
+ this.clientIdentityLoader = loader;
+ }
+
+ @Override
public UserInteraction getUserInteraction() {
return userInteraction;
}
@@ -199,6 +241,9 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
ValidateUtils.checkNotNull(getTcpipForwarderFactory(), "TcpipForwarderFactory not set");
ValidateUtils.checkNotNull(getServerKeyVerifier(), "ServerKeyVerifier not set");
+ ValidateUtils.checkNotNull(getHostConfigEntryResolver(), "HostConfigEntryResolver not set");
+ ValidateUtils.checkNotNull(getClientIdentityLoader(), "ClientIdentityLoader not set");
+ ValidateUtils.checkNotNull(getFilePasswordProvider(), "FilePasswordProvider not set");
// Register the additional agent forwarding channel if needed
SshAgentFactory agentFactory = getAgentFactory();
@@ -275,18 +320,144 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
.build();
}
+ /**
+ * Resolves the <U>effective</U> {@link HostConfigEntry} and connects to it
+ *
+ * @param username The intended username
+ * @param host The target host name/address - never {@code null}/empty
+ * @param port The target port
+ * @return A {@link ConnectFuture}
+ * @throws IOException If failed to resolve the effective target or
+ * connect to it
+ * @see #getHostConfigEntryResolver()
+ * @see #connect(HostConfigEntry)
+ */
public ConnectFuture connect(String username, String host, int port) throws IOException {
- ValidateUtils.checkTrue(port >= 0, "Invalid port: %d", port);
- SocketAddress address = new InetSocketAddress(ValidateUtils.checkNotNullAndNotEmpty(host, "No host"), port);
- return connect(username, address);
+ HostConfigEntryResolver resolver = getHostConfigEntryResolver();
+ HostConfigEntry entry = resolver.resolveEffectiveHost(host, port, username);
+ if (entry == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("connect({}@{}:{}) no overrides", username, host, port);
+ }
+
+ // generate a synthetic entry
+ entry = new HostConfigEntry(host, host, port, username);
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("connect({}@{}:{}) effective: {}", username, host, port, entry);
+ }
+ }
+
+ return connect(entry);
+ }
+
+ /**
+ * Resolves the <U>effective</U> {@link HostConfigEntry} and connects to it
+ *
+ * @param username The intended username
+ * @param address The intended {@link SocketAddress] - never {@code null}. If
+ * this is an {@link InetSocketAddress} then the <U>effective</U> {@link HostConfigEntry}
+ * is resolved and used.
+ * @return A {@link ConnectFuture}
+ * @throws IOException If failed to resolve the effective target or
+ * connect to it
+ * @see #getHostConfigEntryResolver()
+ * @see #connect(HostConfigEntry)
+ * @see #doConnect(String, SocketAddress)
+ */
+ public ConnectFuture connect(String username, SocketAddress address) throws IOException {
+ ValidateUtils.checkNotNull(address, "No target address");
+ if (address instanceof InetSocketAddress) {
+ InetSocketAddress inetAddress = (InetSocketAddress) address;
+ String host = ValidateUtils.checkNotNullAndNotEmpty(inetAddress.getHostString(), "No host");
+ int port = inetAddress.getPort();
+ ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);
+
+ HostConfigEntryResolver resolver = getHostConfigEntryResolver();
+ HostConfigEntry entry = resolver.resolveEffectiveHost(host, port, username);
+ if (entry == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("connect({}@{}:{}) no overrides", username, host, port);
+ }
+
+ return doConnect(username, address, Collections.<KeyPair>emptyList());
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("connect({}@{}:{}) effective: {}", username, host, port, entry);
+ }
+
+ return connect(entry);
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("connect({}@{}) not an InetSocketAddress: {}", username, address, address.getClass().getName());
+ }
+ return doConnect(username, address, Collections.<KeyPair>emptyList());
+ }
+ }
+
+ /**
+ * @param hostConfig The effective {@link HostConfigEntry} to connect to - never {@code null}
+ * @return A {@link ConnectFuture}
+ * @throws IOException If failed to create the connector
+ * @see #doCloseGracefully()
+ */
+ public ConnectFuture connect(HostConfigEntry hostConfig) throws IOException {
+ ValidateUtils.checkNotNull(hostConfig, "No host configuration");
+ String host = ValidateUtils.checkNotNullAndNotEmpty(hostConfig.getHostName(), "No target host");
+ int port = hostConfig.getPort();
+ ValidateUtils.checkTrue(port > 0, "Invalid port: %d", port);
+
+ Collection<KeyPair> keys = loadClientIdentities(hostConfig.getIdentities(), IoUtils.EMPTY_LINK_OPTIONS);
+ return doConnect(hostConfig.getUsername(), new InetSocketAddress(host, port), keys);
+ }
+
+ protected List<KeyPair> loadClientIdentities(Collection<String> locations, LinkOption ... options) throws IOException {
+ if (GenericUtils.isEmpty(locations)) {
+ return Collections.emptyList();
+ }
+
+ List<KeyPair> ids = new ArrayList<>(locations.size());
+ boolean ignoreNonExisting = FactoryManagerUtils.getBooleanProperty(this, IGNORE_INVALID_IDENTITIES, DEFAULT_IGNORE_INVALID_IDENTITIES);
+ ClientIdentityLoader loader = ValidateUtils.checkNotNull(getClientIdentityLoader(), "No ClientIdentityLoader");
+ FilePasswordProvider provider = ValidateUtils.checkNotNull(getFilePasswordProvider(), "No FilePasswordProvider");
+ for (String l : locations) {
+ if (!loader.isValidLocation(l)) {
+ if (ignoreNonExisting) {
+ log.debug("loadClientIdentities - skip non-existing identity location: {}", l);
+ continue;
+ }
+
+ throw new FileNotFoundException("Invalid identity location: " + l);
+ }
+
+ try {
+ KeyPair kp = loader.loadClientIdentity(l, provider);
+ if (kp == null) {
+ throw new IOException("No identity loaded from " + l);
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("loadClientIdentities({}) type={}, fingerprint={}",
+ l, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ }
+
+ ids.add(kp);
+ } catch (GeneralSecurityException e) {
+ throw new StreamCorruptedException("Failed (" + e.getClass().getSimpleName() + ") to load identity from " + l + ": " + e.getMessage());
+ }
+ }
+
+ return ids;
}
- public ConnectFuture connect(final String username, SocketAddress address) {
+ protected ConnectFuture doConnect(final String username, final SocketAddress address, final Collection<? extends KeyPair> identities) throws IOException {
if (connector == null) {
throw new IllegalStateException("SshClient not started. Please call start() method before connecting to a server");
}
final ConnectFuture connectFuture = new DefaultConnectFuture(null);
connector.connect(address).addListener(new SshFutureListener<IoConnectFuture>() {
+ @SuppressWarnings("synthetic-access")
@Override
public void operationComplete(IoConnectFuture future) {
if (future.isCanceled()) {
@@ -296,13 +467,26 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
} else {
ClientSession session = (ClientSession) AbstractSession.getSession(future.getSession());
session.setUsername(username);
+
+ int numIds = GenericUtils.size(identities);
+ if (numIds > 0) {
+ if (log.isDebugEnabled()) {
+ log.debug("doConnect({}@{}) adding {} identities", username, address, numIds);
+ }
+ for (KeyPair kp : identities) {
+ if (log.isTraceEnabled()) {
+ log.trace("doConnect({}@{}) add identity type={}, fingerprint={}",
+ username, address, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
+ }
+ session.addPublicKeyIdentity(kp);
+ }
+ }
connectFuture.setSession(session);
}
}
});
return connectFuture;
}
-
protected IoConnector createConnector() {
return getIoServiceFactory().createConnector(getSessionFactory());
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java b/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
index 8e1b49a..d602958 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/SshKeyScan.java
@@ -73,6 +73,7 @@ import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SecurityUtils;
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.logging.AbstractSimplifiedLog;
import org.apache.sshd.common.util.logging.LoggingUtils;
@@ -608,9 +609,8 @@ public class SshKeyScan extends AbstractSimplifiedLog
// convert the hosts from the arguments into a "file" - one host per line
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(hosts.size() * 32)) {
try (Writer w = new OutputStreamWriter(baos, StandardCharsets.UTF_8)) {
- String eol = System.getProperty("line.separator");
for (String h : hosts) {
- w.append(h).append(eol);
+ w.append(h).append(IoUtils.EOL);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolver.java
new file mode 100644
index 0000000..2a694c6
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolver.java
@@ -0,0 +1,104 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+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.ModifiableFileWatcher;
+
+/**
+ * Watches for changes in a configuration file and automatically reloads any changes
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ConfigFileHostEntryResolver extends ModifiableFileWatcher implements HostConfigEntryResolver {
+ private final AtomicReference<HostConfigEntryResolver> delegateHolder = // assumes initially empty
+ new AtomicReference<HostConfigEntryResolver>(HostConfigEntryResolver.EMPTY);
+
+ public ConfigFileHostEntryResolver(File file) {
+ this(ValidateUtils.checkNotNull(file, "No file to watch").toPath());
+ }
+
+ public ConfigFileHostEntryResolver(Path file) {
+ this(file, IoUtils.EMPTY_LINK_OPTIONS);
+ }
+
+ public ConfigFileHostEntryResolver(Path file, LinkOption... options) {
+ super(file, options);
+ }
+
+ @Override
+ public HostConfigEntry resolveEffectiveHost(String host, int port, String username) throws IOException {
+ try {
+ HostConfigEntryResolver delegate = ValidateUtils.checkNotNull(resolveEffectiveResolver(host, port, username), "No delegate");
+ HostConfigEntry entry = delegate.resolveEffectiveHost(host, port, username);
+ if (log.isDebugEnabled()) {
+ log.debug("resolveEffectiveHost({}@{}:{}) => {}", username, host, port, entry);
+ }
+
+ return entry;
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.debug("resolveEffectiveHost({}@{}:{}) failed ({}) to resolve: {}",
+ username, host, port, e.getClass().getSimpleName(), e.getMessage());
+ }
+
+ if (e instanceof IOException) {
+ throw (IOException) e;
+ } else {
+ throw new IOException(e);
+ }
+ }
+ }
+
+ protected HostConfigEntryResolver resolveEffectiveResolver(String host, int port, String username) throws IOException {
+ if (checkReloadRequired()) {
+ delegateHolder.set(HostConfigEntryResolver.EMPTY); // start fresh
+
+ Path path = getPath();
+ if (exists()) {
+ Collection<HostConfigEntry> entries = reloadHostConfigEntries(path, host, port, username);
+ if (GenericUtils.size(entries) > 0) {
+ delegateHolder.set(HostConfigEntry.toHostConfigEntryResolver(entries));
+ }
+ } else {
+ log.info("resolveEffectiveResolver({}@{}:{}) no configuration file at {}", username, host, port, path);
+ }
+ }
+
+ return delegateHolder.get();
+ }
+
+ protected List<HostConfigEntry> reloadHostConfigEntries(Path path, String host, int port, String username) throws IOException {
+ List<HostConfigEntry> entries = HostConfigEntry.readHostConfigEntries(path);
+ log.info("resolveEffectiveResolver({}@{}:{}) loaded {} entries from {}", username, host, port, GenericUtils.size(entries), path);
+ updateReloadAttributes();
+ return entries;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/DefaultConfigFileHostEntryResolver.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/DefaultConfigFileHostEntryResolver.java b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/DefaultConfigFileHostEntryResolver.java
new file mode 100644
index 0000000..86c4fea
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/DefaultConfigFileHostEntryResolver.java
@@ -0,0 +1,82 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.List;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+
+/**
+ * Monitors the {@code ~/.ssh/config} file of the user currently running
+ * the server, re-loading it if necessary. It also (optionally) enforces the same
+ * permissions regime as {@code OpenSSH} does for the file permissions.
+
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class DefaultConfigFileHostEntryResolver extends ConfigFileHostEntryResolver {
+
+ /**
+ * The default instance that enforces the same permissions regime as {@code OpenSSH}
+ */
+ public static final DefaultConfigFileHostEntryResolver INSTANCE = new DefaultConfigFileHostEntryResolver(true);
+
+ private final boolean strict;
+
+ /**
+ * @param strict If {@code true} then makes sure that the containing folder
+ * has 0700 access and the file 0600. <B>Note:</B> for <I>Windows</I> it
+ * does not check these permissions
+ */
+ public DefaultConfigFileHostEntryResolver(boolean strict) {
+ this(HostConfigEntry.getDefaultHostConfigFile(), strict);
+ }
+
+ public DefaultConfigFileHostEntryResolver(File file, boolean strict) {
+ this(ValidateUtils.checkNotNull(file, "No file provided").toPath(), strict, IoUtils.getLinkOptions(false));
+ }
+
+ public DefaultConfigFileHostEntryResolver(Path path, boolean strict, LinkOption ... options) {
+ super(path, options);
+ this.strict = strict;
+ }
+
+ public final boolean isStrict() {
+ return strict;
+ }
+
+ @Override
+ protected List<HostConfigEntry> reloadHostConfigEntries(Path path, String host, int port, String username) throws IOException {
+ if (isStrict()) {
+ if (log.isDebugEnabled()) {
+ log.debug("reloadHostConfigEntries({}@{}:{}) check permissions of {}", username, host, port, path);
+ }
+
+ KeyUtils.validateStrictKeyFilePermissions(path);
+ }
+
+ return super.reloadHostConfigEntries(path, host, port, username);
+ }
+}
[2/4] mina-sshd git commit: [SSHD-559] Add support for reading
specific host configuration from config file
Posted by lg...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java b/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
index 589bf13..0d845fe 100644
--- a/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
@@ -51,8 +51,6 @@ import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -83,10 +81,7 @@ public class PortForwardingLoadTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
sshd.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd.start();
sshPort = sshd.getPort();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java b/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
index 5dfc8e2..e2b0029 100644
--- a/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
@@ -60,8 +60,6 @@ import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
import org.apache.sshd.server.global.TcpipForwardHandler;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -92,12 +90,9 @@ public class PortForwardingTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, FactoryManager.WINDOW_SIZE, 2048);
FactoryManagerUtils.updateProperty(sshd, FactoryManager.MAX_PACKET_SIZE, 256);
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd.start();
@@ -598,7 +593,7 @@ public class PortForwardingTest extends BaseTestSupport {
}
protected ClientSession createNativeSession() throws Exception {
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
FactoryManagerUtils.updateProperty(client, FactoryManager.WINDOW_SIZE, 2048);
FactoryManagerUtils.updateProperty(client, FactoryManager.MAX_PACKET_SIZE, 256);
client.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/ProxyTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/ProxyTest.java b/sshd-core/src/test/java/org/apache/sshd/ProxyTest.java
index 8636bd2..1e84b29 100644
--- a/sshd-core/src/test/java/org/apache/sshd/ProxyTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/ProxyTest.java
@@ -40,8 +40,6 @@ import org.apache.sshd.common.SshdSocketAddress;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -62,12 +60,9 @@ public class ProxyTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, FactoryManager.WINDOW_SIZE, 2048);
FactoryManagerUtils.updateProperty(sshd, FactoryManager.MAX_PACKET_SIZE, "256");
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd.start();
sshPort = sshd.getPort();
@@ -145,7 +140,7 @@ public class ProxyTest extends BaseTestSupport {
}
protected ClientSession createNativeSession() throws Exception {
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
FactoryManagerUtils.updateProperty(client, FactoryManager.WINDOW_SIZE, 2048);
FactoryManagerUtils.updateProperty(client, FactoryManager.MAX_PACKET_SIZE, 256);
client.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java b/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
index 99445fe..eacdc6c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
@@ -30,14 +30,11 @@ import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.server.Command;
-import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.CachingPublicKeyAuthenticator;
import org.apache.sshd.server.auth.UserAuthPublicKeyFactory;
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
-import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.util.BaseTestSupport;
@@ -70,14 +67,7 @@ public class SinglePublicKeyAuthTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setCommandFactory(new CommandFactory() {
- @Override
- public Command createCommand(String command) {
- return new UnknownCommand(command);
- }
- });
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.AUTH_METHODS, UserAuthPublicKeyFactory.NAME);
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
@SuppressWarnings("synthetic-access")
@@ -111,7 +101,7 @@ public class SinglePublicKeyAuthTest extends BaseTestSupport {
});
delegate = auth;
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -147,7 +137,7 @@ public class SinglePublicKeyAuthTest extends BaseTestSupport {
}
};
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java b/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
index a71cd1a..e3c1d13 100644
--- a/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
@@ -27,9 +27,7 @@ import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.FactoryManagerUtils;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -47,10 +45,7 @@ public class WelcomeBannerTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
FactoryManagerUtils.updateProperty(sshd, ServerFactoryManager.WELCOME_BANNER, WELCOME);
sshd.start();
port = sshd.getPort();
@@ -67,7 +62,7 @@ public class WelcomeBannerTest extends BaseTestSupport {
public void testBanner() throws Exception {
final AtomicReference<String> welcome = new AtomicReference<String>();
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setUserInteraction(new UserInteraction() {
@Override
public void welcome(String banner) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java b/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
index 4e02001..1b66d6f 100644
--- a/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/WindowAdjustTest.java
@@ -46,7 +46,7 @@ import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
@@ -71,7 +71,7 @@ public class WindowAdjustTest {
@Before
public void setUp() throws Exception {
- sshServer = SshServer.setUpDefaultServer();
+ sshServer = Utils.setupTestServer();
final byte[] msg = Files.readAllBytes(
Paths.get(getClass().getResource("/big-msg.txt").toURI()));
@@ -82,7 +82,6 @@ public class WindowAdjustTest {
}
});
- sshServer.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshServer.start();
port = sshServer.getPort();
@@ -99,7 +98,7 @@ public class WindowAdjustTest {
@Test(timeout = 2L * 60L * 1000L)
public void testTrafficHeavyLoad() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (final ClientSession session = client.connect("admin", "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
index 397f162..2917837 100644
--- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
@@ -40,10 +40,9 @@ import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShell;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.Assume;
@@ -107,27 +106,21 @@ public class AgentTest extends BaseTestSupport {
KeyPair pair = createTestKeyPairProvider("dsaprivkey.pem").loadKey(KeyPairProvider.SSH_DSS);
localAgentFactory.getAgent().addIdentity(pair, username);
- try (SshServer sshd1 = SshServer.setUpDefaultServer()) {
- sshd1.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ try (SshServer sshd1 = Utils.setupTestServer()) {
sshd1.setShellFactory(shellFactory);
- sshd1.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd1.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd1.setAgentFactory(agentFactory);
sshd1.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd1.start();
final int port1 = sshd1.getPort();
- try (SshServer sshd2 = SshServer.setUpDefaultServer()) {
- sshd2.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ try (SshServer sshd2 = Utils.setupTestServer()) {
sshd2.setShellFactory(new TestEchoShellFactory());
- sshd2.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd2.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd1.setTcpipForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
sshd2.setAgentFactory(new ProxyAgentFactory());
sshd2.start();
final int port2 = sshd2.getPort();
- try (SshClient client1 = SshClient.setUpDefaultClient()) {
+ try (SshClient client1 = Utils.setupTestClient()) {
client1.setAgentFactory(localAgentFactory);
client1.start();
@@ -151,7 +144,7 @@ public class AgentTest extends BaseTestSupport {
}
}
- try (SshClient client2 = SshClient.setUpDefaultClient()) {
+ try (SshClient client2 = Utils.setupTestClient()) {
client2.setAgentFactory(agentFactory);
client2.getProperties().putAll(shellFactory.shell.getEnvironment().getEnv());
client2.start();
@@ -190,24 +183,22 @@ public class AgentTest extends BaseTestSupport {
}
public static class TestEchoShellFactory extends EchoShellFactory {
-
- TestEchoShell shell = new TestEchoShell();
+ public final TestEchoShell shell = new TestEchoShell();
@Override
public Command create() {
return shell;
}
+ }
- public class TestEchoShell extends EchoShell {
-
- boolean started;
+ public static class TestEchoShell extends EchoShell {
+ public boolean started;
- @Override
- public synchronized void start(Environment env) throws IOException {
- super.start(env);
- started = true;
- notifyAll();
- }
+ @Override
+ public synchronized void start(Environment env) throws IOException {
+ super.start(env);
+ started = true;
+ notifyAll();
}
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
index 7713b2d..604b39c 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/ClientTest.java
@@ -94,13 +94,10 @@ import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.io.NoCloseOutputStream;
import org.apache.sshd.server.Command;
-import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.channel.ChannelSessionFactory;
-import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.forward.DirectTcpipFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerConnectionServiceFactory;
@@ -110,7 +107,7 @@ import org.apache.sshd.server.session.ServerUserAuthServiceFactory;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.apache.sshd.util.AsyncEchoShellFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShell;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.TeeOutputStream;
import org.apache.sshd.util.Utils;
@@ -167,17 +164,8 @@ public class ClientTest extends BaseTestSupport {
authLatch = new CountDownLatch(0);
channelLatch = new CountDownLatch(0);
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setShellFactory(new TestEchoShellFactory());
- sshd.setCommandFactory(new CommandFactory() {
- @Override
- public Command createCommand(String command) {
- return new UnknownCommand(command);
- }
- });
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd.setServiceFactories(Arrays.asList(
new ServerUserAuthServiceFactory() {
@Override
@@ -221,7 +209,7 @@ public class ClientTest extends BaseTestSupport {
sshd.start();
port = sshd.getPort();
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
clientSessionHolder.set(null); // just making sure
client.addSessionListener(clientSessionListener);
}
@@ -1164,7 +1152,7 @@ public class ClientTest extends BaseTestSupport {
@Test
public void testClientDisconnect() throws Exception {
- TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
+ TestEchoShell.latch = new CountDownLatch(1);
try {
client.start();
@@ -1191,14 +1179,14 @@ public class ClientTest extends BaseTestSupport {
assertTrue("Packet writing not completed in time", f.await(11L, TimeUnit.SECONDS));
suspend(cs.getIoSession());
- TestEchoShellFactory.TestEchoShell.latch.await();
+ TestEchoShell.latch.await();
} finally {
client.stop();
}
assertNull("Session closure not signalled", clientSessionHolder.get());
} finally {
- TestEchoShellFactory.TestEchoShell.latch = null;
+ TestEchoShell.latch = null;
}
}
@@ -1352,18 +1340,17 @@ public class ClientTest extends BaseTestSupport {
public Command create() {
return new TestEchoShell();
}
+ }
- public static class TestEchoShell extends EchoShell {
-
- public static CountDownLatch latch = new CountDownLatch(1);
+ public static class TestEchoShell extends EchoShell {
+ public static CountDownLatch latch;
- @Override
- public void destroy() {
- if (latch != null) {
- latch.countDown();
- }
- super.destroy();
+ @Override
+ public void destroy() {
+ if (latch != null) {
+ latch.countDown();
}
+ super.destroy();
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolverTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolverTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolverTest.java
new file mode 100644
index 0000000..2405cbd
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/ConfigFileHostEntryResolverTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ConfigFileHostEntryResolverTest extends BaseTestSupport {
+ public ConfigFileHostEntryResolverTest() {
+ super();
+ }
+
+ @Test
+ public void testConfigFileReload() throws IOException {
+ File dir = new File(new File(detectTargetFolder(), TEMP_SUBFOLDER_NAME), getClass().getSimpleName());
+ final AtomicInteger reloadCount = new AtomicInteger();
+ ConfigFileHostEntryResolver resolver = new ConfigFileHostEntryResolver(new File(assertHierarchyTargetFolderExists(dir), getCurrentTestName() + ".config.txt")) {
+ @Override
+ protected List<HostConfigEntry> reloadHostConfigEntries(Path path, String host, int port, String username)
+ throws IOException {
+ reloadCount.incrementAndGet();
+ return super.reloadHostConfigEntries(path, host, port, username);
+ }
+ };
+ Path path = resolver.getPath();
+
+ HostConfigEntry expected = new HostConfigEntry(getCurrentTestName(), getCurrentTestName(), 7365, getCurrentTestName());
+ testConfigFileReload("Non-existing", path, reloadCount, null, resolver, expected, null);
+ testConfigFileReload("Empty", path, reloadCount, Collections.<HostConfigEntry>emptyList(), resolver, expected, null);
+ testConfigFileReload("Global", path, reloadCount,
+ Collections.singletonList(new HostConfigEntry(HostConfigEntry.ALL_HOSTS_PATTERN, expected.getHost(), expected.getPort(), expected.getUsername())),
+ resolver, expected, expected);
+ testConfigFileReload("Wildcard", path, reloadCount,
+ Arrays.asList(
+ new HostConfigEntry(HostConfigEntry.ALL_HOSTS_PATTERN, getClass().getSimpleName(), 1234, getClass().getSimpleName()),
+ new HostConfigEntry(expected.getHost() + String.valueOf(HostConfigEntry.WILDCARD_PATTERN), expected.getHost(), expected.getPort(), expected.getUsername())),
+ resolver, expected, expected);
+ testConfigFileReload("Specific", path, reloadCount,
+ Arrays.asList(
+ new HostConfigEntry(HostConfigEntry.ALL_HOSTS_PATTERN, getClass().getSimpleName(), 1234, getClass().getSimpleName()),
+ new HostConfigEntry(getClass().getSimpleName() + String.valueOf(HostConfigEntry.WILDCARD_PATTERN), getClass().getSimpleName(), 1234, getClass().getSimpleName()),
+ expected),
+ resolver, expected, expected);
+ }
+
+ private static void testConfigFileReload(
+ String phase, Path path, AtomicInteger reloadCount, Collection<? extends HostConfigEntry> entries, HostConfigEntryResolver resolver, HostConfigEntry query, HostConfigEntry expected)
+ throws IOException {
+ if (entries == null) {
+ if (Files.exists(path)) {
+ Files.delete(path);
+ }
+ } else {
+ HostConfigEntry.writeHostConfigEntries(path, entries, IoUtils.EMPTY_OPEN_OPTIONS);
+ }
+
+ reloadCount.set(0);
+
+ for (int index = 1; index < Byte.SIZE; index++) {
+ HostConfigEntry actual = resolver.resolveEffectiveHost(query.getHostName(), query.getPort(), query.getUsername());
+
+ if (entries == null) {
+ assertEquals(phase + "[" + index + "]: mismatched reload count", 0, reloadCount.get());
+ } else {
+ assertEquals(phase + "[" + index + "]: mismatched reload count", 1, reloadCount.get());
+ }
+
+ if (expected == null) {
+ assertNull(phase + "[" + index + "]: Unexpected success for " + query, actual);
+ } else {
+ assertNotNull(phase + "[" + index + "]: No result for " + query, actual);
+ assertNotSame(phase + "[" + index + "]: No cloned result for " + query, expected, actual);
+ assertEquals(phase + "[" + index + "]: Mismatched host for " + query, expected.getHostName(), actual.getHostName());
+ assertEquals(phase + "[" + index + "]: Mismatched port for " + query, expected.getPort(), actual.getPort());
+ assertEquals(phase + "[" + index + "]: Mismatched user for " + query, expected.getUsername(), actual.getUsername());
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
new file mode 100644
index 0000000..a47d999
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryResolverTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.util.Iterator;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.config.keys.ClientIdentityLoader;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.FactoryManagerUtils;
+import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.server.auth.password.RejectAllPasswordAuthenticator;
+import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator;
+import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.util.BaseTestSupport;
+import org.apache.sshd.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class HostConfigEntryResolverTest extends BaseTestSupport {
+ private SshServer sshd;
+ private SshClient client;
+ private int port;
+
+ public HostConfigEntryResolverTest() {
+ super();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ sshd = Utils.setupTestServer();
+ sshd.start();
+ port = sshd.getPort();
+
+ client = Utils.setupTestClient();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (sshd != null) {
+ sshd.stop(true);
+ }
+ if (client != null) {
+ client.stop();
+ }
+ }
+
+ @Test
+ public void testEffectiveHostConfigResolution() throws Exception {
+ final HostConfigEntry entry = new HostConfigEntry(getCurrentTestName(), "localhost", port, getCurrentTestName());
+ client.setHostConfigEntryResolver(new HostConfigEntryResolver() {
+ @Override
+ public HostConfigEntry resolveEffectiveHost(String host, int portValue, String username) throws IOException {
+ return entry;
+ }
+ });
+ client.start();
+
+ try(ClientSession session = client.connect(getClass().getSimpleName(), getClass().getPackage().getName(), getMovedPortNumber(port)).verify(7L, TimeUnit.SECONDS).getSession()) {
+ session.addPasswordIdentity(getCurrentTestName());
+ session.auth().verify(5L, TimeUnit.SECONDS);
+ assertEffectiveRemoteAddress(session, entry);
+ } finally {
+ client.stop();
+ }
+ }
+
+ @Test
+ public void testPreloadedIdentities() throws Exception {
+ KeyPairProvider provider = ValidateUtils.checkNotNull(sshd.getKeyPairProvider(), "No key pair provider");
+ Iterable<? extends KeyPair> pairs = ValidateUtils.checkNotNull(provider.loadKeys(), "No loaded keys");
+ Iterator<? extends KeyPair> iter = ValidateUtils.checkNotNull(pairs.iterator(), "No keys iterator");
+ assertTrue("Empty loaded kyes iterator", iter.hasNext());
+
+ final KeyPair identity = iter.next();
+ final String USER = getCurrentTestName();
+ // make sure authentication is achieved only via the identity public key
+ sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
+ @Override
+ public boolean authenticate(String username, PublicKey key, ServerSession session) {
+ if (USER.equals(username)) {
+ return KeyUtils.compareKeys(identity.getPublic(), key);
+ }
+
+ return false;
+ }
+ });
+ sshd.setPasswordAuthenticator(RejectAllPasswordAuthenticator.INSTANCE);
+
+ final String IDENTITY = getCurrentTestName();
+ client.setClientIdentityLoader(new ClientIdentityLoader() {
+ @Override
+ public boolean isValidLocation(String location) throws IOException {
+ return IDENTITY.equals(location);
+ }
+
+ @Override
+ public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
+ if (isValidLocation(location)) {
+ return identity;
+ }
+
+ throw new FileNotFoundException("Unknown location: " + location);
+ }
+ });
+ FactoryManagerUtils.updateProperty(client, ClientFactoryManager.IGNORE_INVALID_IDENTITIES, false);
+
+ final String HOST = getClass().getSimpleName();
+ final HostConfigEntry entry = new HostConfigEntry(HOST, "localhost", port, USER);
+ entry.addIdentity(IDENTITY);
+ client.setHostConfigEntryResolver(new HostConfigEntryResolver() {
+ @Override
+ public HostConfigEntry resolveEffectiveHost(String host, int portValue, String username) throws IOException {
+ return entry;
+ }
+ });
+
+ client.start();
+ try(ClientSession session = client.connect(USER, HOST, getMovedPortNumber(port)).verify(7L, TimeUnit.SECONDS).getSession()) {
+ session.auth().verify(5L, TimeUnit.SECONDS);
+ assertEffectiveRemoteAddress(session, entry);
+ } finally {
+ client.stop();
+ }
+
+ }
+
+ private static int getMovedPortNumber(int port) {
+ return (port > Short.MAX_VALUE) ? (port - Short.MAX_VALUE) : (1 + Short.MAX_VALUE - port);
+ }
+
+ private static <S extends Session> S assertEffectiveRemoteAddress(S session, HostConfigEntry entry) {
+ IoSession ioSession = session.getIoSession();
+ SocketAddress remoteAddress = ioSession.getRemoteAddress();
+ InetSocketAddress inetAddress;
+ if (remoteAddress instanceof InetSocketAddress) {
+ inetAddress = (InetSocketAddress) remoteAddress;
+ } else if (remoteAddress instanceof SshdSocketAddress) {
+ inetAddress = ((SshdSocketAddress) remoteAddress).toInetSocketAddress();
+ } else {
+ throw new ClassCastException("Unknown remote address type: " + remoteAddress);
+ }
+
+ assertEquals("Mismatched effective port", entry.getPort(), inetAddress.getPort());
+ assertEquals("Mismatched effective user", entry.getUsername(), session.getUsername());
+ return session;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java
new file mode 100644
index 0000000..00e61dd
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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.client.config.hosts;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.BaseTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class HostConfigEntryTest extends BaseTestSupport {
+ public HostConfigEntryTest() {
+ super();
+ }
+
+ @Test
+ public void testHostWildcardPatternMatching() {
+ String pkgName = getClass().getPackage().getName();
+ String[] elements = GenericUtils.split(pkgName, '.');
+ StringBuilder sb = new StringBuilder(pkgName.length() + Long.SIZE + 1).append(HostConfigEntry.WILDCARD_PATTERN);
+ for (int index = elements.length - 1; index >= 0; index--) {
+ sb.append('.').append(elements[index]);
+ }
+
+ String value = sb.toString();
+ Pattern pattern = HostConfigEntry.toPattern(value);
+ String domain = value.substring(1); // chomp the wildcard prefix
+ for (String host : new String[] {
+ getClass().getSimpleName(),
+ getCurrentTestName(),
+ getClass().getSimpleName() + "-" + getCurrentTestName(),
+ getClass().getSimpleName() + "." + getCurrentTestName(),
+ }) {
+ sb.setLength(0); // start from scratch
+ sb.append(host).append(domain);
+
+ testCaseInsensitivePatternMatching(sb.toString(), pattern, true);
+ }
+ }
+
+ @Test
+ public void testIPAddressWildcardPatternMatching() {
+ StringBuilder sb = new StringBuilder().append("10.0.0.");
+ int sbLen = sb.length();
+
+ Pattern pattern = HostConfigEntry.toPattern(sb.append(HostConfigEntry.WILDCARD_PATTERN));
+ for (int v = 0; v <= 255; v++) {
+ sb.setLength(sbLen); // start from scratch
+ sb.append(v);
+
+ String address = sb.toString();
+ assertTrue("No match for " + address, HostConfigEntry.isHostMatch(address, pattern));
+ }
+ }
+
+ @Test
+ public void testHostSingleCharPatternMatching() {
+ String value = getCurrentTestName();
+ StringBuilder sb = new StringBuilder(value);
+ for (boolean restoreOriginal : new boolean[] { true, false }) {
+ for (int index = 0; index < value.length(); index++) {
+ sb.setCharAt(index, HostConfigEntry.SINGLE_CHAR_PATTERN);
+ testCaseInsensitivePatternMatching(value, HostConfigEntry.toPattern(sb.toString()), true);
+ if (restoreOriginal) {
+ sb.setCharAt(index, value.charAt(index));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testIPAddressSingleCharPatternMatching() {
+ StringBuilder sb = new StringBuilder().append("10.0.0.");
+ int sbLen = sb.length();
+
+ for (int v = 0; v <= 255; v++) {
+ sb.setLength(sbLen); // start from scratch
+ sb.append(v);
+
+ String address = sb.toString();
+ // replace the added digits with single char pattern
+ for (int index = sbLen; index < sb.length(); index++) {
+ sb.setCharAt(index, HostConfigEntry.SINGLE_CHAR_PATTERN);
+ }
+ String pattern = sb.toString();
+
+ assertTrue("No match for " + address + " on pattern=" + pattern, HostConfigEntry.isHostMatch(address, pattern));
+ }
+ }
+
+ @Test
+ public void testIsValidPatternChar() {
+ for (char ch = '\0'; ch <= ' '; ch++) {
+ assertFalse("Unexpected valid character (0x" + Integer.toHexString(ch & 0xFF) + ")", HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch = 'a'; ch <= 'z'; ch++) {
+ assertTrue("Valid character not recognized: " + String.valueOf(ch), HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch = 'A'; ch <= 'Z'; ch++) {
+ assertTrue("Valid character not recognized: " + String.valueOf(ch), HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch = '0'; ch <= '9'; ch++) {
+ assertTrue("Valid character not recognized: " + String.valueOf(ch), HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch : new char[] { '-', '_', '.', HostConfigEntry.SINGLE_CHAR_PATTERN, HostConfigEntry.WILDCARD_PATTERN }) {
+ assertTrue("Valid character not recognized: " + String.valueOf(ch), HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch : new char[] {
+ '(', ')', '{', '}', '[', ']', '!', '@',
+ '#', '$', '^', '&', '%', '~', '<', '>',
+ ',', '/', '\\', '\'', '"', ':', ';' }) {
+ assertFalse("Unexpected valid character: " + String.valueOf(ch), HostConfigEntry.isValidPatternChar(ch));
+ }
+
+ for (char ch = 0x7E; ch <= 0xFF; ch++) {
+ assertFalse("Unexpected valid character (0x" + Integer.toHexString(ch & 0xFF) + ")", HostConfigEntry.isValidPatternChar(ch));
+ }
+ }
+
+ @Test
+ public void testResolvePort() {
+ final int ORIGINAL_PORT = Short.MAX_VALUE;
+ final int ENTRY_PORT = 7365;
+ assertEquals("Mismatched entry port preference", ENTRY_PORT, HostConfigEntry.resolvePort(ORIGINAL_PORT, ENTRY_PORT));
+
+ for (int entryPort : new int[] { -1, 0 }) {
+ assertEquals("Non-preferred original port for entry port=" + entryPort, ORIGINAL_PORT, HostConfigEntry.resolvePort(ORIGINAL_PORT, entryPort));
+ }
+ }
+
+ @Test
+ public void testResolveUsername() {
+ final String ORIGINAL_USER = getCurrentTestName();
+ final String ENTRY_USER = getClass().getSimpleName();
+ assertSame("Mismatched entry user preference", ENTRY_USER, HostConfigEntry.resolveUsername(ORIGINAL_USER, ENTRY_USER));
+
+ for (String entryUser : new String[] { null, "" }) {
+ assertSame("Non-preferred original user for entry user='" + entryUser + "'", ORIGINAL_USER, HostConfigEntry.resolveUsername(ORIGINAL_USER, entryUser));
+ }
+ }
+
+ @Test
+ public void testReadSimpleHostsConfigEntries() throws IOException {
+ validateHostConfigEntries(readHostConfigEntries());
+ }
+
+ @Test
+ public void testReadGlobalHostsConfigEntries() throws IOException {
+ List<HostConfigEntry> entries = validateHostConfigEntries(readHostConfigEntries());
+ assertTrue("Not enough entries read", GenericUtils.size(entries) > 1);
+
+ // global entry MUST be 1st one
+ HostConfigEntry globalEntry = entries.get(0);
+ assertEquals("Mismatched global entry pattern", HostConfigEntry.ALL_HOSTS_PATTERN, globalEntry.getHost());
+
+ for (int index = 1; index < entries.size(); index++) {
+ HostConfigEntry entry = entries.get(index);
+ assertFalse("No target host for " + entry, GenericUtils.isEmpty(entry.getHostName()));
+ assertTrue("No target port for " + entry, entry.getPort() > 0);
+ assertFalse("No username for " + entry, GenericUtils.isEmpty(entry.getUsername()));
+ assertFalse("No identities for " + entry, GenericUtils.isEmpty(entry.getIdentities()));
+ assertFalse("No properties for " + entry, GenericUtils.isEmpty(entry.getProperties()));
+ }
+ }
+
+ @Test
+ public void testReadMultipleHostPatterns() throws IOException {
+ List<HostConfigEntry> entries = validateHostConfigEntries(readHostConfigEntries());
+ assertEquals("Mismatched number of duplicates", 3, GenericUtils.size(entries));
+
+ HostConfigEntry prototype = entries.get(0);
+ String protoIds = GenericUtils.join(prototype.getIdentities(), ',');
+ Collection<Map.Entry<String,String>> protoProps = prototype.getProperties().entrySet();
+ for (int index = 1; index < entries.size(); index++) {
+ HostConfigEntry entry = entries.get(index);
+ assertEquals("Mismatched host name for " + entry, prototype.getHostName(), entry.getHostName());
+ assertEquals("Mismatched port for " + entry, prototype.getPort(), entry.getPort());
+ assertSame("Mismatched user for " + entry, prototype.getUsername(), entry.getUsername());
+ assertEquals("Mismatched identities for " + entry, protoIds, GenericUtils.join(entry.getIdentities(), ','));
+
+ Map<String,String> entryProps = entry.getProperties();
+ assertEquals("Mismatched properties count for " + entry, GenericUtils.size(protoProps), GenericUtils.size(entryProps));
+
+ for (Map.Entry<String,String> ppe : protoProps) {
+ String key = ppe.getKey();
+ String expected = ppe.getValue();
+ String actual = entryProps.get(key);
+ assertEquals("Mismatched value for " + key + " property of " + entry, expected, actual);
+ }
+ }
+ }
+
+ @Test
+ public void testResolveIdentityFilePath() throws Exception {
+ final String HOST = getClass().getSimpleName();
+ final int PORT = 7365;
+ final String USER = getCurrentTestName();
+
+ Exception err = null;
+ for (String pattern : new String[] {
+ "~/.ssh/%h.key",
+ "%d/.ssh/%h.key",
+ "/home/%u/.ssh/id_rsa_%p",
+ "/home/%u/.ssh/id_%r_rsa",
+ "/home/%u/.ssh/%h/%l.key"
+ }) {
+ try {
+ String result = HostConfigEntry.resolveIdentityFilePath(pattern, HOST, PORT, USER);
+ System.out.append('\t').append(pattern).append(" => ").println(result);
+ } catch(Exception e) {
+ System.err.append("Failed (").append(e.getClass().getSimpleName())
+ .append(") to process pattern=").append(pattern)
+ .append(": ").println(e.getMessage());
+ err = e;
+ }
+ }
+
+ if (err != null) {
+ throw err;
+ }
+ }
+
+ @Test
+ public void testFindBestMatch() {
+ final String HOST = getCurrentTestName();
+ HostConfigEntry expected = new HostConfigEntry(HOST, HOST, 7365, HOST);
+ List<HostConfigEntry> matches = new ArrayList<>();
+ matches.add(new HostConfigEntry(HostConfigEntry.ALL_HOSTS_PATTERN, getClass().getSimpleName(), Short.MAX_VALUE, getClass().getSimpleName()));
+ matches.add(new HostConfigEntry(HOST + String.valueOf(HostConfigEntry.WILDCARD_PATTERN), getClass().getSimpleName(), Byte.MAX_VALUE, getClass().getSimpleName()));
+ matches.add(expected);
+
+ for (int index = 0; index < matches.size(); index++) {
+ HostConfigEntry actual = HostConfigEntry.findBestMatch(matches);
+ assertSame("Mismatched best match for " + matches, expected, actual);
+ Collections.shuffle(matches);
+ }
+ }
+
+ private static <C extends Collection<HostConfigEntry>> C validateHostConfigEntries(C entries) {
+ assertFalse("No entries", GenericUtils.isEmpty(entries));
+
+ for (HostConfigEntry entry : entries) {
+ assertFalse("No pattern for " + entry, GenericUtils.isEmpty(entry.getHost()));
+ assertFalse("No extra properties for " + entry, GenericUtils.isEmpty(entry.getProperties()));
+ }
+
+ return entries;
+ }
+
+ private List<HostConfigEntry> readHostConfigEntries() throws IOException {
+ return readHostConfigEntries(getCurrentTestName() + ".config.txt");
+ }
+
+ private List<HostConfigEntry> readHostConfigEntries(String resourceName) throws IOException {
+ URL url = getClass().getResource(resourceName);
+ assertNotNull("Missing resource " + resourceName, url);
+ return HostConfigEntry.readHostConfigEntries(url);
+ }
+ private static void testCaseInsensitivePatternMatching(String value, Pattern pattern, boolean expected) {
+ for (int index = 0; index < value.length(); index++) {
+ boolean actual = HostConfigEntry.isHostMatch(value, pattern);
+ assertEquals("Mismatched match result for " + value + " on pattern=" + pattern.pattern(), expected, actual);
+ value = shuffleCase(value);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
index 5ff1111..3c96be4 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/kex/KexTest.java
@@ -37,8 +37,6 @@ import org.apache.sshd.common.kex.BuiltinDHFactories;
import org.apache.sshd.common.kex.KeyExchange;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.TeeOutputStream;
import org.apache.sshd.util.Utils;
import org.junit.After;
@@ -75,10 +73,7 @@ public class KexTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
+ sshd = Utils.setupTestServer();
sshd.start();
port = sshd.getPort();
}
@@ -102,7 +97,7 @@ public class KexTest extends BaseTestSupport {
try (ByteArrayOutputStream sent = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.setKeyExchangeFactories(Collections.singletonList(kex));
client.start();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
index 9e7ab79..5cf9543 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
@@ -55,11 +55,10 @@ import org.apache.sshd.common.scp.ScpTransferEventListener;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
+import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
@@ -99,11 +98,8 @@ public class ScpTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setCommandFactory(new ScpCommandFactory());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.setFileSystemFactory(fileSystemFactory);
sshd.start();
port = sshd.getPort();
@@ -145,7 +141,7 @@ public class ScpTest extends BaseTestSupport {
Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
Path localFile = localDir.resolve("file.txt");
- byte[] data = writeFile(localFile, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(localFile, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
Path remoteFile = remoteDir.resolve(localFile.getFileName().toString());
@@ -153,7 +149,7 @@ public class ScpTest extends BaseTestSupport {
String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
String[] remoteComps = GenericUtils.split(remotePath, '/');
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
Factory<? extends Random> factory = client.getRandomFactory();
@@ -208,14 +204,14 @@ public class ScpTest extends BaseTestSupport {
Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
Path localFile = localDir.resolve("file-1.txt");
- byte[] data = writeFile(localFile, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(localFile, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path remoteDir = assertHierarchyTargetFolderExists(scpRoot.resolve("remote"));
Path remoteFile = remoteDir.resolve(localFile.getFileName().toString());
String localPath = localFile.toString();
String remotePath = Utils.resolveRelativeRemotePath(parentPath, remoteFile);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -243,7 +239,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpUploadOverwrite() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -251,7 +247,7 @@ public class ScpTest extends BaseTestSupport {
session.auth().verify(5L, TimeUnit.SECONDS);
ScpClient scp = createScpClient(session);
- String data = getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator");
+ String data = getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL;
Path targetPath = detectTargetFolder().toPath();
Path parentPath = targetPath.getParent();
@@ -295,7 +291,7 @@ public class ScpTest extends BaseTestSupport {
Files.delete(zeroRemote);
}
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -331,7 +327,7 @@ public class ScpTest extends BaseTestSupport {
}
assertEquals("Non-zero size for remote file=" + zeroRemote, 0L, Files.size(zeroRemote));
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -350,7 +346,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativeOnSingleFile() throws Exception {
- String data = getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator");
+ String data = getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL;
Path targetPath = detectTargetFolder().toPath();
Path parentPath = targetPath.getParent();
@@ -362,7 +358,7 @@ public class ScpTest extends BaseTestSupport {
Path remoteDir = scpRoot.resolve("remote");
Path remoteOutFile = remoteDir.resolve(localOutFile.getFileName());
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -402,7 +398,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativeOnMultipleFiles() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -417,7 +413,7 @@ public class ScpTest extends BaseTestSupport {
Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
Path local1 = localDir.resolve("file-1.txt");
- byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path local2 = localDir.resolve("file-2.txt");
Files.write(local2, data);
@@ -483,7 +479,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativeOnRecursiveDirs() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -499,7 +495,7 @@ public class ScpTest extends BaseTestSupport {
Path localDir = scpRoot.resolve("local");
Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
Path localSub1 = localSubDir.resolve("file-1.txt");
- byte[] data = writeFile(localSub1, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(localSub1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path localSub2 = localSubDir.resolve("file-2.txt");
Files.write(localSub2, data);
@@ -523,7 +519,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativeOnDirWithPattern() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -538,7 +534,7 @@ public class ScpTest extends BaseTestSupport {
Path localDir = assertHierarchyTargetFolderExists(scpRoot.resolve("local"));
Path local1 = localDir.resolve("file-1.txt");
- byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path local2 = localDir.resolve("file-2.txt");
Files.write(local2, data);
@@ -561,7 +557,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativeOnMixedDirAndFiles() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -577,7 +573,7 @@ public class ScpTest extends BaseTestSupport {
Path localDir = scpRoot.resolve("local");
Path localSubDir = assertHierarchyTargetFolderExists(localDir.resolve("dir"));
Path local1 = localDir.resolve("file-1.txt");
- byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
Path localSub2 = localSubDir.resolve("file-2.txt");
Files.write(localSub2, data);
@@ -608,7 +604,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testScpNativePreserveAttributes() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -627,7 +623,7 @@ public class ScpTest extends BaseTestSupport {
final long lastModMillis = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
final long lastModSecs = TimeUnit.MILLISECONDS.toSeconds(lastModMillis);
Path local1 = localDir.resolve("file-1.txt");
- byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + System.getProperty("line.separator"));
+ byte[] data = writeFile(local1, getClass().getName() + "#" + getCurrentTestName() + IoUtils.EOL);
File lclFile1 = local1.toFile();
boolean lcl1ModSet = lclFile1.setLastModified(lastModMillis);
@@ -672,7 +668,7 @@ public class ScpTest extends BaseTestSupport {
@Test
public void testStreamsUploadAndDownload() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -821,7 +817,7 @@ public class ScpTest extends BaseTestSupport {
byte[] remoteData = Files.readAllBytes(remoteFile);
assertArrayEquals("Mismatched remote put data", expected, remoteData);
- Arrays.fill(remoteData, (byte) 0); // make sure we start with a clean slate
+ Arrays.fill(remoteData, (byte) 0); // make sure we start with a clean slate
try (InputStream input = scp_client.get(remotePath + "/" + fileName)) {
int readLen = input.read(remoteData);
assertEquals("Mismatched remote get data size", expected.length, readLen);
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
index 75ff85d..8033be7 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClientTestSupport.java
@@ -35,8 +35,6 @@ import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
/**
@@ -61,12 +59,9 @@ public abstract class AbstractSftpClientTestSupport extends BaseTestSupport {
}
protected void setupServer() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
sshd.setCommandFactory(new ScpCommandFactory());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.setFileSystemFactory(fileSystemFactory);
sshd.start();
port = sshd.getPort();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
index 6c70d54..9603a87 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemTest.java
@@ -66,8 +66,6 @@ import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
-import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
@@ -96,12 +94,9 @@ public class SftpFileSystemTest extends BaseTestSupport {
@Before
public void setUp() throws Exception {
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
sshd.setCommandFactory(new ScpCommandFactory());
- sshd.setShellFactory(new EchoShellFactory());
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
sshd.setFileSystemFactory(fileSystemFactory);
sshd.start();
port = sshd.getPort();
@@ -216,7 +211,7 @@ public class SftpFileSystemTest extends BaseTestSupport {
@Test
public void testMultipleFileStoresOnSameProvider() throws IOException {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
SftpFileSystemProvider provider = new SftpFileSystemProvider(client);
@@ -286,7 +281,7 @@ public class SftpFileSystemTest extends BaseTestSupport {
return selected.get();
}
};
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index 3226877..1c039c2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -131,7 +131,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
rnd.fill(expectedRandom);
byte[] expectedText = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -183,7 +183,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
rnd.fill(expected);
Files.write(testFile, expected);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -227,7 +227,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
}
});
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -247,7 +247,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
@Test
public void testNormalizeRemoteRootValues() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -286,7 +286,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
String[] comps = GenericUtils.split(file, '/');
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
Factory<? extends Random> factory = client.getRandomFactory();
@@ -347,7 +347,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
File javaFile = testFile.toFile();
assertHierarchyTargetFolderExists(javaFile.getParentFile());
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -439,7 +439,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
@Test
public void testClient() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -464,7 +464,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
*/
@Test
public void testWriteChunking() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -655,7 +655,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
Path parentPath = targetPath.getParent();
Path clientFolder = assertHierarchyTargetFolderExists(lclSftp.resolve("client"));
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -701,7 +701,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
@Test
public void testServerExtensionsDeclarations() throws Exception {
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -800,7 +800,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
}
};
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractCheckFileExtensionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractCheckFileExtensionTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractCheckFileExtensionTest.java
index c591c1c..89415d2 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractCheckFileExtensionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractCheckFileExtensionTest.java
@@ -138,7 +138,7 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
byte[] seed = (getClass().getName() + "#" + getCurrentTestName()
+ "-" + expectedAlgorithm
+ "-" + inputDataSize + "/" + hashBlockSize
- + System.getProperty("line.separator"))
+ + IoUtils.EOL)
.getBytes(StandardCharsets.UTF_8);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(inputDataSize + seed.length)) {
@@ -175,7 +175,7 @@ public class AbstractCheckFileExtensionTest extends AbstractSftpClientTestSuppor
String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
String srcFolder = Utils.resolveRelativeRemotePath(parentPath, srcFile.getParent());
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractMD5HashExtensionTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractMD5HashExtensionTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractMD5HashExtensionTest.java
index e2013a8..6b39051 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractMD5HashExtensionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/AbstractMD5HashExtensionTest.java
@@ -96,7 +96,7 @@ public class AbstractMD5HashExtensionTest extends AbstractSftpClientTestSupport
}
private void testMD5HashExtension(int dataSize) throws Exception {
- byte[] seed = (getClass().getName() + "#" + getCurrentTestName() + "-" + dataSize + System.getProperty("line.separator")).getBytes(StandardCharsets.UTF_8);
+ byte[] seed = (getClass().getName() + "#" + getCurrentTestName() + "-" + dataSize + IoUtils.EOL).getBytes(StandardCharsets.UTF_8);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(dataSize + seed.length)) {
while (baos.size() < dataSize) {
baos.write(seed);
@@ -131,7 +131,7 @@ public class AbstractMD5HashExtensionTest extends AbstractSftpClientTestSupport
String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
String srcFolder = Utils.resolveRelativeRemotePath(parentPath, srcFile.getParent());
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImplTest.java
index 7c0f989..dda241e 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyDataExtensionImplTest.java
@@ -123,7 +123,7 @@ public class CopyDataExtensionImplTest extends AbstractSftpClientTestSupport {
byte[] seed = (getClass().getName() + "#" + getCurrentTestName()
+ "-" + dataSize
+ "-" + readOffset + "/" + readLength + "/" + writeOffset
- + System.getProperty("line.separator"))
+ + IoUtils.EOL)
.getBytes(StandardCharsets.UTF_8);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(dataSize + seed.length)) {
while (baos.size() < dataSize) {
@@ -150,7 +150,7 @@ public class CopyDataExtensionImplTest extends AbstractSftpClientTestSupport {
}
String dstPath = Utils.resolveRelativeRemotePath(parentPath, dstFile);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
if (writeOffset > 0L) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyFileExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyFileExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyFileExtensionImplTest.java
index 1f9ebb1..59c1ef5 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyFileExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/CopyFileExtensionImplTest.java
@@ -78,7 +78,7 @@ public class CopyFileExtensionImplTest extends AbstractSftpClientTestSupport {
LinkOption[] options = IoUtils.getLinkOptions(false);
assertFalse("Destination file unexpectedly exists", Files.exists(dstFile, options));
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/SpaceAvailableExtensionImplTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/SpaceAvailableExtensionImplTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/SpaceAvailableExtensionImplTest.java
index 1c9e0d9..d200267 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/SpaceAvailableExtensionImplTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/impl/SpaceAvailableExtensionImplTest.java
@@ -88,7 +88,7 @@ public class SpaceAvailableExtensionImplTest extends AbstractSftpClientTestSuppo
}
}));
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
index 20ab5fa..087ae37 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/extensions/openssh/impl/OpenSSHExtensionsTest.java
@@ -89,7 +89,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
Path parentPath = targetPath.getParent();
String srcPath = Utils.resolveRelativeRemotePath(parentPath, srcFile);
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
@@ -178,7 +178,7 @@ public class OpenSSHExtensionsTest extends AbstractSftpClientTestSupport {
}
}));
- try (SshClient client = SshClient.setUpDefaultClient()) {
+ try (SshClient client = Utils.setupTestClient()) {
client.start();
try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/950e896d/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
index f8b23fb..73b64df 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/channel/WindowTest.java
@@ -47,12 +47,9 @@ import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.server.Command;
-import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.auth.pubkey.AcceptAllPublickeyAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.channel.ChannelSessionFactory;
-import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.forward.DirectTcpipFactory;
import org.apache.sshd.server.session.ServerConnectionService;
import org.apache.sshd.server.session.ServerConnectionServiceFactory;
@@ -60,7 +57,7 @@ import org.apache.sshd.server.session.ServerUserAuthService;
import org.apache.sshd.server.session.ServerUserAuthServiceFactory;
import org.apache.sshd.util.AsyncEchoShellFactory;
import org.apache.sshd.util.BaseTestSupport;
-import org.apache.sshd.util.BogusPasswordAuthenticator;
+import org.apache.sshd.util.EchoShell;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
@@ -92,17 +89,8 @@ public class WindowTest extends BaseTestSupport {
authLatch = new CountDownLatch(0);
channelLatch = new CountDownLatch(0);
- sshd = SshServer.setUpDefaultServer();
- sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
+ sshd = Utils.setupTestServer();
sshd.setShellFactory(new TestEchoShellFactory());
- sshd.setCommandFactory(new CommandFactory() {
- @Override
- public Command createCommand(String command) {
- return new UnknownCommand(command);
- }
- });
- sshd.setPasswordAuthenticator(BogusPasswordAuthenticator.INSTANCE);
- sshd.setPublickeyAuthenticator(AcceptAllPublickeyAuthenticator.INSTANCE);
sshd.setServiceFactories(Arrays.asList(
new ServerUserAuthServiceFactory() {
@Override
@@ -146,7 +134,7 @@ public class WindowTest extends BaseTestSupport {
sshd.start();
port = sshd.getPort();
- client = SshClient.setUpDefaultClient();
+ client = Utils.setupTestClient();
}
@After
@@ -348,18 +336,18 @@ public class WindowTest extends BaseTestSupport {
public Command create() {
return new TestEchoShell();
}
+ }
- public static class TestEchoShell extends EchoShell {
+ public static class TestEchoShell extends EchoShell {
- public static CountDownLatch latch = new CountDownLatch(1);
+ public static final CountDownLatch latch = new CountDownLatch(1);
- @Override
- public void destroy() {
- if (latch != null) {
- latch.countDown();
- }
- super.destroy();
+ @Override
+ public void destroy() {
+ if (latch != null) {
+ latch.countDown();
}
+ super.destroy();
}
}
}