mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 07:10:53 +03:00
Upgraded Bouncy Castle to 1.70 and upgraded test dependencies (#755)
- Adjusted test classes to work with Apache SSHD 2.8.0 - Upgraded Bouncy Castle from 1.69 to 1.70 - Upgraded Apache SSHD from 2.1.0 to 2.8.0 - Upgraded JUnit from 4.12 to 4.13.2 - Upgraded Mockito from 2.28.2 to 4.2.0 - Upgraded Logback from 1.2.6 to 1.2.9 - Upgraded Apache HTTP Client from 4.5.9 to 4.5.14
This commit is contained in:
12
build.gradle
12
build.gradle
@@ -35,8 +35,8 @@ project.version = scmVersion.version
|
||||
|
||||
configurations.implementation.transitive = false
|
||||
|
||||
def bouncycastleVersion = "1.69"
|
||||
def sshdVersion = "2.1.0"
|
||||
def bouncycastleVersion = "1.70"
|
||||
def sshdVersion = "2.8.0"
|
||||
|
||||
dependencies {
|
||||
implementation "org.slf4j:slf4j-api:1.7.32"
|
||||
@@ -47,15 +47,15 @@ dependencies {
|
||||
|
||||
implementation "net.i2p.crypto:eddsa:0.3.0"
|
||||
|
||||
testImplementation "junit:junit:4.12"
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.4'
|
||||
testImplementation "org.mockito:mockito-core:2.28.2"
|
||||
testImplementation "org.mockito:mockito-core:4.2.0"
|
||||
testImplementation "org.apache.sshd:sshd-core:$sshdVersion"
|
||||
testImplementation "org.apache.sshd:sshd-sftp:$sshdVersion"
|
||||
testImplementation "org.apache.sshd:sshd-scp:$sshdVersion"
|
||||
testImplementation "ch.qos.logback:logback-classic:1.2.6"
|
||||
testImplementation "ch.qos.logback:logback-classic:1.2.9"
|
||||
testImplementation 'org.glassfish.grizzly:grizzly-http-server:2.4.4'
|
||||
testImplementation 'org.apache.httpcomponents:httpclient:4.5.9'
|
||||
testImplementation 'org.apache.httpcomponents:httpclient:4.5.13'
|
||||
testImplementation 'org.testcontainers:testcontainers:1.16.2'
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,10 @@ public class RemotePortForwarder
|
||||
// Listen on all IPv4
|
||||
return true;
|
||||
}
|
||||
if ("0.0.0.0".equals(address) && "0:0:0:0:0:0:0:0".equals(channelForward.address)) {
|
||||
// Handle IPv4 requests on IPv6 channel forward
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class RemotePortForwarderTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(RemotePortForwarderTest.class);
|
||||
|
||||
private static final PortRange RANGE = new PortRange(9000, 9999);
|
||||
private static final InetSocketAddress HTTP_SERVER_SOCKET_ADDR = new InetSocketAddress("127.0.0.1", 8080);
|
||||
private static final String LOCALHOST = "127.0.0.1";
|
||||
private static final InetSocketAddress HTTP_SERVER_SOCKET_ADDR = new InetSocketAddress(LOCALHOST, 8080);
|
||||
|
||||
@Rule
|
||||
public SshFixture fixture = new SshFixture();
|
||||
@@ -62,61 +62,63 @@ public class RemotePortForwarderTest {
|
||||
@Test
|
||||
public void shouldHaveWorkingHttpServer() throws IOException {
|
||||
// Just to check that we have a working http server...
|
||||
assertThat(httpGet("127.0.0.1", 8080), equalTo(200));
|
||||
assertEquals(200, httpGet( 8080));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDynamicallyForwardPortForLocalhost() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "127.0.0.1", new SinglePort(0));
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDynamicallyForwardPortForAllIPv4() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "0.0.0.0", new SinglePort(0));
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDynamicallyForwardPortForAllProtocols() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "", new SinglePort(0));
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldForwardPortForLocalhost() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "127.0.0.1", RANGE);
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldForwardPortForAllIPv4() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "0.0.0.0", RANGE);
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldForwardPortForAllProtocols() throws IOException {
|
||||
SSHClient sshClient = getFixtureClient();
|
||||
RemotePortForwarder.Forward bind = forwardPort(sshClient, "", RANGE);
|
||||
assertThat(httpGet("127.0.0.1", bind.getPort()), equalTo(200));
|
||||
assertHttpGetSuccess(bind);
|
||||
}
|
||||
|
||||
private void assertHttpGetSuccess(final RemotePortForwarder.Forward bind) throws IOException {
|
||||
assertEquals(200, httpGet(bind.getPort()));
|
||||
}
|
||||
|
||||
private RemotePortForwarder.Forward forwardPort(SSHClient sshClient, String address, PortRange portRange) throws IOException {
|
||||
while (true) {
|
||||
try {
|
||||
RemotePortForwarder.Forward forward = sshClient.getRemotePortForwarder().bind(
|
||||
return sshClient.getRemotePortForwarder().bind(
|
||||
// where the server should listen
|
||||
new RemotePortForwarder.Forward(address, portRange.nextPort()),
|
||||
// what we do with incoming connections that are forwarded to us
|
||||
new SocketForwardingConnectListener(HTTP_SERVER_SOCKET_ADDR));
|
||||
|
||||
return forward;
|
||||
} catch (ConnectionException ce) {
|
||||
if (!portRange.hasNext()) {
|
||||
throw ce;
|
||||
@@ -125,9 +127,9 @@ public class RemotePortForwarderTest {
|
||||
}
|
||||
}
|
||||
|
||||
private int httpGet(String server, int port) throws IOException {
|
||||
private int httpGet(int port) throws IOException {
|
||||
HttpClient client = HttpClientBuilder.create().build();
|
||||
String urlString = "http://" + server + ":" + port;
|
||||
String urlString = "http://" + LOCALHOST + ":" + port;
|
||||
log.info("Trying: GET " + urlString);
|
||||
HttpResponse execute = client.execute(new HttpGet(urlString));
|
||||
return execute.getStatusLine().getStatusCode();
|
||||
@@ -140,7 +142,7 @@ public class RemotePortForwarderTest {
|
||||
}
|
||||
|
||||
private static class PortRange {
|
||||
private int upper;
|
||||
private final int upper;
|
||||
private int current;
|
||||
|
||||
public PortRange(int lower, int upper) {
|
||||
|
||||
@@ -19,21 +19,17 @@ import net.schmizz.sshj.Config;
|
||||
import net.schmizz.sshj.DefaultConfig;
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
import net.schmizz.sshj.util.gss.BogusGSSAuthenticator;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.keyprovider.ClassLoadableResourceKeyPairProvider;
|
||||
import org.apache.sshd.scp.server.ScpCommandFactory;
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
|
||||
import org.apache.sshd.server.command.Command;
|
||||
import org.apache.sshd.server.command.CommandFactory;
|
||||
import org.apache.sshd.server.scp.ScpCommandFactory;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
import org.apache.sshd.server.shell.ProcessShellFactory;
|
||||
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
|
||||
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@@ -43,9 +39,9 @@ public class SshFixture extends ExternalResource {
|
||||
public static final String hostkey = "hostkey.pem";
|
||||
public static final String fingerprint = "ce:a7:c1:cf:17:3f:96:49:6a:53:1a:05:0b:ba:90:db";
|
||||
|
||||
private SshServer server = defaultSshServer();
|
||||
private final SshServer server = defaultSshServer();
|
||||
private SSHClient client = null;
|
||||
private AtomicBoolean started = new AtomicBoolean(false);
|
||||
private final AtomicBoolean started = new AtomicBoolean(false);
|
||||
private boolean autoStart = true;
|
||||
|
||||
public SshFixture(boolean autoStart) {
|
||||
@@ -108,38 +104,23 @@ public class SshFixture extends ExternalResource {
|
||||
sshServer.setPort(randomPort());
|
||||
ClassLoadableResourceKeyPairProvider fileKeyPairProvider = new ClassLoadableResourceKeyPairProvider(hostkey);
|
||||
sshServer.setKeyPairProvider(fileKeyPairProvider);
|
||||
sshServer.setPasswordAuthenticator(new PasswordAuthenticator() {
|
||||
@Override
|
||||
public boolean authenticate(String username, String password, ServerSession session) {
|
||||
return username.equals(password);
|
||||
}
|
||||
});
|
||||
sshServer.setPasswordAuthenticator((username, password, session) -> username.equals(password));
|
||||
sshServer.setGSSAuthenticator(new BogusGSSAuthenticator());
|
||||
sshServer.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystemFactory()));
|
||||
sshServer.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
|
||||
ScpCommandFactory commandFactory = new ScpCommandFactory();
|
||||
commandFactory.setDelegateCommandFactory(new CommandFactory() {
|
||||
@Override
|
||||
public Command createCommand(String command) {
|
||||
return new ProcessShellFactory(command.split(" ")).create();
|
||||
}
|
||||
});
|
||||
commandFactory.setDelegateCommandFactory((session, command) -> new ProcessShellFactory(command, command.split(" ")).createShell(session));
|
||||
sshServer.setCommandFactory(commandFactory);
|
||||
sshServer.setShellFactory(new ProcessShellFactory("ls"));
|
||||
sshServer.setShellFactory(new ProcessShellFactory("ls", "ls"));
|
||||
return sshServer;
|
||||
}
|
||||
|
||||
private int randomPort() {
|
||||
try {
|
||||
ServerSocket s = null;
|
||||
try {
|
||||
s = new ServerSocket(0);
|
||||
try (final ServerSocket s = new ServerSocket(0)) {
|
||||
return s.getLocalPort();
|
||||
} finally {
|
||||
if (s != null)
|
||||
s.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,8 @@ import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.transport.kex.DHGexSHA1;
|
||||
import net.schmizz.sshj.transport.kex.DHGexSHA256;
|
||||
import net.schmizz.sshj.transport.kex.ECDHNistP;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.kex.BuiltinDHFactories;
|
||||
import org.apache.sshd.common.kex.KeyExchange;
|
||||
import org.apache.sshd.common.kex.KeyExchangeFactory;
|
||||
import org.apache.sshd.server.SshServer;
|
||||
import org.apache.sshd.server.kex.DHGEXServer;
|
||||
import org.apache.sshd.server.kex.DHGServer;
|
||||
@@ -38,6 +37,7 @@ import java.util.Collections;
|
||||
@RunWith(Parameterized.class)
|
||||
public class KeyExchangeTest extends BaseAlgorithmTest {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Parameterized.Parameters(name = "algorithm={0}")
|
||||
public static Collection<Object[]> getParameters() {
|
||||
return Arrays.asList(new Object[][]{
|
||||
@@ -56,10 +56,10 @@ public class KeyExchangeTest extends BaseAlgorithmTest {
|
||||
});
|
||||
}
|
||||
|
||||
private Factory.Named<net.schmizz.sshj.transport.kex.KeyExchange> clientFactory;
|
||||
private NamedFactory<KeyExchange> serverFactory;
|
||||
private final Factory.Named<net.schmizz.sshj.transport.kex.KeyExchange> clientFactory;
|
||||
private final KeyExchangeFactory serverFactory;
|
||||
|
||||
public KeyExchangeTest(NamedFactory<KeyExchange> serverFactory, Factory.Named<net.schmizz.sshj.transport.kex.KeyExchange> clientFactory) {
|
||||
public KeyExchangeTest(KeyExchangeFactory serverFactory, Factory.Named<net.schmizz.sshj.transport.kex.KeyExchange> clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.serverFactory = serverFactory;
|
||||
}
|
||||
|
||||
@@ -20,12 +20,8 @@ import net.schmizz.sshj.SSHClient;
|
||||
import net.schmizz.sshj.userauth.method.AuthKeyboardInteractive;
|
||||
import net.schmizz.sshj.userauth.method.ChallengeResponseProvider;
|
||||
import net.schmizz.sshj.userauth.password.Resource;
|
||||
import org.apache.sshd.client.auth.keyboard.UserAuthKeyboardInteractiveFactory;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.server.auth.UserAuth;
|
||||
import org.apache.sshd.server.auth.keyboard.UserAuthKeyboardInteractive;
|
||||
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
import org.apache.sshd.server.auth.keyboard.UserAuthKeyboardInteractiveFactory;
|
||||
import org.apache.sshd.server.auth.password.AcceptAllPasswordAuthenticator;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -43,28 +39,8 @@ public class AuthKeyboardInteractiveTest {
|
||||
|
||||
@Before
|
||||
public void setKeyboardInteractiveAuthenticator() throws IOException {
|
||||
fixture.getServer().setUserAuthFactories(Collections.<NamedFactory<UserAuth>>singletonList(new NamedFactory<UserAuth>() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return UserAuthKeyboardInteractiveFactory.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAuth get() {
|
||||
return new UserAuthKeyboardInteractive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAuth create() {
|
||||
return get();
|
||||
}
|
||||
}));
|
||||
fixture.getServer().setPasswordAuthenticator(new PasswordAuthenticator() {
|
||||
@Override
|
||||
public boolean authenticate(String username, String password, ServerSession session) {
|
||||
return password.equals(username);
|
||||
}
|
||||
});
|
||||
fixture.getServer().setUserAuthFactories(Collections.singletonList(new UserAuthKeyboardInteractiveFactory()));
|
||||
fixture.getServer().setPasswordAuthenticator(AcceptAllPasswordAuthenticator.INSTANCE);
|
||||
fixture.getServer().start();
|
||||
}
|
||||
|
||||
@@ -75,7 +51,7 @@ public class AuthKeyboardInteractiveTest {
|
||||
sshClient.auth(userAndPassword, new AuthKeyboardInteractive(new ChallengeResponseProvider() {
|
||||
@Override
|
||||
public List<String> getSubmethods() {
|
||||
return new ArrayList<String>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,56 +21,29 @@ import net.schmizz.sshj.userauth.UserAuthException;
|
||||
import net.schmizz.sshj.userauth.password.PasswordFinder;
|
||||
import net.schmizz.sshj.userauth.password.PasswordUpdateProvider;
|
||||
import net.schmizz.sshj.userauth.password.Resource;
|
||||
import org.apache.sshd.common.NamedFactory;
|
||||
import org.apache.sshd.common.util.buffer.Buffer;
|
||||
import org.apache.sshd.server.auth.UserAuth;
|
||||
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
|
||||
import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
|
||||
import org.apache.sshd.server.auth.password.UserAuthPassword;
|
||||
import org.apache.sshd.server.auth.password.UserAuthPasswordFactory;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Stack;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class AuthPasswordTest {
|
||||
|
||||
@Rule
|
||||
public SshFixture fixture = new SshFixture(false);
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setPasswordAuthenticator() throws IOException {
|
||||
fixture.getServer().setUserAuthFactories(Collections.<NamedFactory<UserAuth>>singletonList(new NamedFactory<UserAuth>() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return UserAuthPasswordFactory.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAuth get() {
|
||||
return new UserAuthPassword() {
|
||||
@Override
|
||||
protected Boolean handleClientPasswordChangeRequest(Buffer buffer, ServerSession session, String username, String oldPassword, String newPassword) throws Exception {
|
||||
return session.getPasswordAuthenticator().authenticate(username, newPassword, session);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserAuth create() {
|
||||
return get();
|
||||
}
|
||||
}));
|
||||
fixture.getServer().setUserAuthFactories(Collections.singletonList(new UserAuthPasswordFactory()));
|
||||
fixture.getServer().setPasswordAuthenticator(new PasswordAuthenticator() {
|
||||
@Override
|
||||
public boolean authenticate(String username, String password, ServerSession session) {
|
||||
@@ -80,6 +53,12 @@ public class AuthPasswordTest {
|
||||
return password.equals(username);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClientPasswordChangeRequest(
|
||||
ServerSession session, String username, String oldPassword, String newPassword) {
|
||||
return username.equals(newPassword);
|
||||
}
|
||||
});
|
||||
fixture.getServer().start();
|
||||
}
|
||||
@@ -87,8 +66,7 @@ public class AuthPasswordTest {
|
||||
@Test
|
||||
public void shouldNotHandlePasswordChangeIfNoPasswordUpdateProviderSet() throws IOException {
|
||||
SSHClient sshClient = fixture.setupConnectedDefaultClient();
|
||||
expectedException.expect(UserAuthException.class);
|
||||
sshClient.authPassword("jeroen", "changeme");
|
||||
assertThrows(UserAuthException.class, () -> sshClient.authPassword("jeroen", "changeme"));
|
||||
assertThat("Should not have authenticated", !sshClient.isAuthenticated());
|
||||
}
|
||||
|
||||
@@ -112,8 +90,7 @@ public class AuthPasswordTest {
|
||||
@Test
|
||||
public void shouldHandlePasswordChangeWithWrongPassword() throws IOException {
|
||||
SSHClient sshClient = fixture.setupConnectedDefaultClient();
|
||||
expectedException.expect(UserAuthException.class);
|
||||
sshClient.authPassword("jeroen", new PasswordFinder() {
|
||||
assertThrows(UserAuthException.class, () -> sshClient.authPassword("jeroen", new PasswordFinder() {
|
||||
@Override
|
||||
public char[] reqPassword(Resource<?> resource) {
|
||||
return "changeme".toCharArray();
|
||||
@@ -123,7 +100,7 @@ public class AuthPasswordTest {
|
||||
public boolean shouldRetry(Resource<?> resource) {
|
||||
return false;
|
||||
}
|
||||
}, new StaticPasswordUpdateProvider("bad"));
|
||||
}, new StaticPasswordUpdateProvider("bad")));
|
||||
assertThat("Should not have authenticated", !sshClient.isAuthenticated());
|
||||
}
|
||||
|
||||
@@ -153,7 +130,7 @@ public class AuthPasswordTest {
|
||||
}
|
||||
|
||||
private static class StaticPasswordUpdateProvider implements PasswordUpdateProvider {
|
||||
private Stack<String> newPasswords = new Stack<String>();
|
||||
private final Stack<String> newPasswords = new Stack<>();
|
||||
|
||||
public StaticPasswordUpdateProvider(String... newPasswords) {
|
||||
for (int i = newPasswords.length - 1; i >= 0; i--) {
|
||||
|
||||
Reference in New Issue
Block a user