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:
exceptionfactory
2021-12-22 03:37:36 -06:00
committed by GitHub
parent 624747c527
commit ced27fc898
7 changed files with 62 additions and 122 deletions

View File

@@ -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'
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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--) {