This is an automated email from the ASF dual-hosted git repository.
twolf pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
The following commit(s) were added to refs/heads/master by this push:
new ebc660232 Fix tests using EOL CentOS 7.9 image
ebc660232 is described below
commit ebc660232b3cfc27b584e7b54448e0435de72212
Author: Thomas Wolf <[email protected]>
AuthorDate: Thu Jul 11 22:59:22 2024 +0200
Fix tests using EOL CentOS 7.9 image
It appears that the yum repository has gone. So move away from CentOS
images for tests against old OpenSSH versions.
Remove SessionsReKeyJostExchangeTest. It tested SSHD-1264, which could
never reproduced with other containers, not even with an Alpine using
an older OpenSSH. Finding an alternative for the CentOS image on which
SSHD-1264 would be reproducible would require testing first with an old
Apache MINA sshd in which SSHD-1264 wasn't fixed yet. I don't have the
time for this.
Remove ArcFourOpenSShTest. This test was useful to analyze a problem
and verify a fix, but the test took a lot of time and was completely
overblown. Replaced by a simple JUnit test method that verifies that all
ciphers have block sizes >= 8.
For the StrictKexInteroperabilityTest, use alpine:3.9.2 instead of
CentOS. That old Alpine installs OpenSSH 7.9, which also never got the
"strict kex" fixes.
---
.../session/SessionReKeyHostKeyExchangeTest.java | 181 ---------------------
.../sshd/common/cipher/ArcFourOpenSshTest.java | 139 ----------------
.../sshd/common/cipher/BuiltinCiphersTest.java | 7 +
.../extension/StrictKexInteroperabilityTest.java | 10 +-
4 files changed, 12 insertions(+), 325 deletions(-)
diff --git
a/sshd-core/src/test/java/org/apache/sshd/client/session/SessionReKeyHostKeyExchangeTest.java
b/sshd-core/src/test/java/org/apache/sshd/client/session/SessionReKeyHostKeyExchangeTest.java
deleted file mode 100644
index 2521be62f..000000000
---
a/sshd-core/src/test/java/org/apache/sshd/client/session/SessionReKeyHostKeyExchangeTest.java
+++ /dev/null
@@ -1,181 +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.client.session;
-
-import java.io.IOException;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.net.SocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.security.PublicKey;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.channel.ChannelShell;
-import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
-import org.apache.sshd.common.channel.StreamingChannel;
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.session.SessionHeartbeatController;
-import org.apache.sshd.util.test.BaseTestSupport;
-import org.apache.sshd.util.test.ContainerTestCase;
-import org.hamcrest.Description;
-import org.hamcrest.MatcherAssert;
-import org.hamcrest.TypeSafeDiagnosingMatcher;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.output.Slf4jLogConsumer;
-import org.testcontainers.containers.wait.strategy.Wait;
-import org.testcontainers.images.builder.ImageFromDockerfile;
-
-@Category(ContainerTestCase.class)
-public class SessionReKeyHostKeyExchangeTest extends BaseTestSupport {
-
- private static final Logger LOG =
LoggerFactory.getLogger(SessionReKeyHostKeyExchangeTest.class);
-
- @Rule
- public GenericContainer<?> sshdContainer = new GenericContainer<>(
- new ImageFromDockerfile()
- .withDockerfileFromBuilder(builder -> builder
- // With alpine, which installs newer OpenSSH
versions, SSHD-1264 does not occur.
- .from("centos:7.9.2009") // So use CentOS, even if
it's much slower
- .run("yum install -y openssh-server") // Installs
OpenSSH 7.4
- .run("/usr/sbin/sshd-keygen") // Generate multiple
host keys
- .run("adduser bob") // Add a user
- .run("echo \"123qweASD\" | passwd bob --stdin") //
Give the user a password
- .run("echo RekeyLimit default 1 >>
/etc/ssh/sshd_config") // Re-key every second
- .entryPoint("/usr/sbin/sshd", "-D", "-ddd") //
- .build()))
- .waitingFor(Wait.forLogMessage(".*Server
listening on :: port 22.*\\n", 1))
- .withExposedPorts(22) //
- .withLogConsumer(new
Slf4jLogConsumer(LOG));
-
- public SessionReKeyHostKeyExchangeTest() {
- super();
- }
-
- @Test // https://issues.apache.org/jira/browse/SSHD-1264
- public void testRekeyUsesSameHostKeyAlgorithm() throws Exception {
-
LOG.info("*************************************************************************************");
- SshClient client = SshClient.setUpDefaultClient();
- AcceptFirstAlgorithmHostKeyVerifier hostKeyVerifier = new
AcceptFirstAlgorithmHostKeyVerifier();
- client.setServerKeyVerifier(hostKeyVerifier);
-
- try {
- client.start();
- try (ClientSession session = client.connect("bob",
sshdContainer.getHost(), sshdContainer.getMappedPort(22))
- .verify(CONNECT_TIMEOUT).getSession()) {
- session.addPasswordIdentity("123qweASD");
- assertTrue("Could not authenticate",
session.auth().await(AUTH_TIMEOUT));
-
session.setSessionHeartbeat(SessionHeartbeatController.HeartbeatType.IGNORE,
TimeUnit.MILLISECONDS, 1);
-
- try (ChannelShell channel = session.createShellChannel()) {
- channel.setOut(System.out);
- channel.setErr(System.err);
- channel.setStreaming(StreamingChannel.Streaming.Sync);
- PipedOutputStream pos = new PipedOutputStream();
- PipedInputStream pis = new PipedInputStream(pos);
- channel.setIn(pis);
- assertTrue("Could not open session",
channel.open().await(DEFAULT_TIMEOUT));
- for (int i = 0; i < 20; i++) {
- Thread.sleep(1000);
- LOG.info("writing some data...");
- pos.write("\n\n".getBytes(StandardCharsets.UTF_8));
- }
- channel.close(true);
- } catch (IOException e) {
- // When KEX fails, we most likely get an exception on the
PipedInputStream.
- // Let's produce a halfway reasonable test failure.
- assertEquals("Expected no host key changes in KEX", 0,
hostKeyVerifier.errors);
- throw new AssertionError("Exception in test", e);
- }
- Thread.sleep(5_000);
- assertTrue("Session should still be open", session.isOpen());
- }
- // We should have about 25 key exchanges, but anything greater
than 10 is fine.
- MatcherAssert.assertThat("Not enough re-key attempts",
hostKeyVerifier.verifications,
- AtLeastMatcher.greaterThan(10));
- } finally {
- client.stop();
- }
-
- }
-
- private static class AcceptFirstAlgorithmHostKeyVerifier implements
ServerKeyVerifier {
-
- volatile int errors;
-
- volatile int verifications;
-
- private PublicKey hostKey;
-
- AcceptFirstAlgorithmHostKeyVerifier() {
- super();
- }
-
- @Override
- public boolean verifyServerKey(ClientSession clientSession,
SocketAddress remoteAddress, PublicKey serverKey) {
- if (hostKey == null) {
- // first connect to this host we allow it and store the host
key
- hostKey = serverKey;
- LOG.info("**** Accepting initial connection with host key
algorithm {}", serverKey.getAlgorithm());
- verifications++;
- return true;
- }
-
- boolean sameKey = KeyUtils.compareKeys(hostKey, serverKey);
- if (sameKey) {
- LOG.info("Accepting subsequent hostkey, same as in initial
connection");
- } else {
- LOG.error("**** Rejecting subsequent host key of type {},
inital host key was {}", serverKey.getAlgorithm(),
- hostKey.getAlgorithm());
- errors++;
- }
- verifications++;
- return sameKey;
- }
- }
-
- private static final class AtLeastMatcher extends
TypeSafeDiagnosingMatcher<Integer> {
-
- private final int atLeast;
-
- private AtLeastMatcher(int atLeast) {
- this.atLeast = atLeast;
- }
-
- @Override
- protected boolean matchesSafely(Integer item, Description
mismatchDescription) {
- mismatchDescription.appendValue(item);
- return atLeast <= item.intValue();
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("a number greater than
").appendValue(atLeast);
- }
-
- public static AtLeastMatcher greaterThan(int atLeast) {
- return new AtLeastMatcher(atLeast);
- }
- }
-}
diff --git
a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ArcFourOpenSshTest.java
b/sshd-core/src/test/java/org/apache/sshd/common/cipher/ArcFourOpenSshTest.java
deleted file mode 100644
index 0825b170d..000000000
---
a/sshd-core/src/test/java/org/apache/sshd/common/cipher/ArcFourOpenSshTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.common.cipher;
-
-import java.security.Security;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.future.AuthFuture;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
-import org.apache.sshd.common.mac.BuiltinMacs;
-import org.apache.sshd.util.test.BaseTestSupport;
-import org.apache.sshd.util.test.CommonTestSupportUtils;
-import org.apache.sshd.util.test.ContainerTestCase;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.output.Slf4jLogConsumer;
-import org.testcontainers.containers.wait.strategy.Wait;
-import org.testcontainers.images.builder.ImageFromDockerfile;
-import org.testcontainers.utility.MountableFile;
-
-/**
- * Test RC4 ciphers against OpenSSH 7.4.
- *
- * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a>
- */
-@RunWith(Parameterized.class)
-@Category(ContainerTestCase.class)
-public class ArcFourOpenSshTest extends BaseTestSupport {
-
- private static final Logger LOG =
LoggerFactory.getLogger(ArcFourOpenSshTest.class);
-
- // Re-use an already defined key
- private static final String TEST_RESOURCES =
"org/apache/sshd/common/kex/extensions/client";
-
- @Rule
- public GenericContainer<?> sshdContainer = new GenericContainer<>(new
ImageFromDockerfile()
- .withDockerfileFromBuilder(builder -> builder //
- // Use old CentOS to get an OpenSSH that supports arcfour
- .from("centos:7.9.2009") //
- .run("yum install -y openssh-server") // Installs OpenSSH
7.4
- // Enable deprecated ciphers
- .run("echo 'Ciphers +arcfour128,arcfour256' >>
/etc/ssh/sshd_config")
- .run("echo 'MACs
+hmac-md5,hmac-md5-96,hmac-sha1,hmac-sha1-96' >> /etc/ssh/sshd_config")
- .run("/usr/sbin/sshd-keygen") // Generate multiple host
keys
- .run("adduser bob") // Add a user
- .run("echo \\\"123qweASD\\\" | passwd bob --stdin") //
Give it a password to unlock the user
- .run("mkdir -p /home/bob/.ssh") // Create the SSH config
directory
- .entryPoint("/entrypoint.sh") // Sets bob as owner of
anything under /home/bob and launches sshd
- .build())) //
-
.withCopyFileToContainer(MountableFile.forClasspathResource(TEST_RESOURCES +
"/bob_key.pub"),
- "/home/bob/.ssh/authorized_keys")
- // entrypoint must be executable. Spotbugs doesn't
like 0777, so use hex
- .withCopyFileToContainer(
-
MountableFile.forClasspathResource(TEST_RESOURCES + "/entrypoint.sh", 0x1ff),
- "/entrypoint.sh")
- .waitingFor(Wait.forLogMessage(".*Server listening
on :: port 22.*\\n", 1)).withExposedPorts(22) //
- .withLogConsumer(new Slf4jLogConsumer(LOG));
-
- private final BuiltinCiphers builtIn;
-
- private final BuiltinMacs mac;
-
- public ArcFourOpenSshTest(String providerName, BuiltinCiphers factory,
String name, BuiltinMacs mac, String macName) {
- this.builtIn = factory;
- this.mac = mac;
- if ("BC".equals(providerName)) {
- registerBouncyCastleProviderIfNecessary();
- }
- }
-
- private static void registerBouncyCastleProviderIfNecessary() {
- if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
- Security.addProvider(new BouncyCastleProvider());
- }
- }
-
- private static void addCipher(BuiltinCiphers cipherFactory, List<Object[]>
items) {
- for (BuiltinMacs mac : BuiltinMacs.VALUES) {
- items.add(new Object[] { "SunJCE", cipherFactory,
cipherFactory.getName(), mac, mac.getName() });
- items.add(new Object[] { "BC", cipherFactory,
cipherFactory.getName(), mac, mac.getName() });
- }
- }
-
- @SuppressWarnings("deprecation")
- @Parameters(name = "{2} - {4} - {0}")
- public static List<Object[]> getParameters() {
- List<Object[]> items = new ArrayList<>();
- addCipher(BuiltinCiphers.arcfour128, items);
- addCipher(BuiltinCiphers.arcfour256, items);
- return items;
- }
-
- @Test
- public void testConnection() throws Exception {
- FileKeyPairProvider keyPairProvider =
CommonTestSupportUtils.createTestKeyPairProvider(TEST_RESOURCES + "/bob_key");
- SshClient client = setupTestClient();
- client.setKeyIdentityProvider(keyPairProvider);
- client.setCipherFactories(Collections.singletonList(builtIn));
- client.setMacFactories(Collections.singletonList(mac));
- client.start();
-
- Integer actualPort = sshdContainer.getMappedPort(22);
- String actualHost = sshdContainer.getHost();
- try (ClientSession session = client.connect("bob", actualHost,
actualPort).verify(CONNECT_TIMEOUT).getSession()) {
- AuthFuture authed = session.auth().verify(AUTH_TIMEOUT);
- assertTrue(authed.isDone() && authed.isSuccess());
- } finally {
- client.stop();
- }
- }
-}
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 57c1d0be5..b23213f4e 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
@@ -50,6 +50,13 @@ public class BuiltinCiphersTest extends BaseTestSupport {
super();
}
+ @Test
+ public void testBlockSize() {
+ for (BuiltinCiphers cipher : BuiltinCiphers.VALUES) {
+ assertTrue("Cipher " + cipher + " block size too small",
cipher.getCipherBlockSize() >= 8);
+ }
+ }
+
@Test
public void testFromEnumName() {
for (BuiltinCiphers expected : BuiltinCiphers.VALUES) {
diff --git
a/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
b/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
index 43e6d8a8e..5a77fde3a 100644
---
a/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
+++
b/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
@@ -86,11 +86,11 @@ public class StrictKexInteroperabilityTest extends
BaseTestSupport {
private DockerfileBuilder strictKexImage(DockerfileBuilder builder,
boolean withStrictKex) {
if (!withStrictKex) {
return builder
- // CentOS 7 is EOL and thus unlikely to get the security
update for strict KEX.
- .from("centos:7.9.2009") //
- .run("yum install -y openssh-server") // Installs OpenSSH
7.4
- .run("/usr/sbin/sshd-keygen") // Generate multiple host
keys
- .run("adduser bob"); // Add a user
+ .from("alpine:3.9.2") //
+ .run("apk --update add openssh-server") // Installs
OpenSSH 7.9_p1-r6
+ .run("ssh-keygen -A") // Generate multiple host keys
+ .run("adduser -D bob") // Add a user
+ .run("echo 'bob:passwordBob' | chpasswd"); // Give it a
password to unlock the user
} else {
return builder
.from("alpine:20231219") //