Compare commits

..

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
26986be4ba
!25 [sync] PR-21: Fix CVE-2023-48795
From: @openeuler-sync-bot 
Reviewed-by: @wk333 
Signed-off-by: @wk333
2024-01-22 03:13:55 +00:00
wk333
0b83536590 Fix CVE-2023-48795
(cherry picked from commit b530cf02136303fd9ff20333467d6cd5f386a622)
2024-01-22 10:28:56 +08:00
openeuler-ci-bot
97c8ac8cb4
!17 [sync] PR-13: Fix CVE-2023-35887
From: @openeuler-sync-bot 
Reviewed-by: @wk333 
Signed-off-by: @wk333
2024-01-12 00:50:35 +00:00
starlet-dx
e7c7e18533 Fix CVE-2023-35887
(cherry picked from commit 91fac8710abf01ff4259485c5b5b061a9b5d05e9)
2024-01-11 19:18:26 +08:00
openeuler-ci-bot
93906a0d43
!12 [sync] PR-7: fix CVE-2022-45047
From: @openeuler-sync-bot 
Reviewed-by: @caodongxia 
Signed-off-by: @caodongxia
2022-11-22 10:01:08 +00:00
emancipator
11555fa551 fix CVE-2022-45047
(cherry picked from commit 7cf5e7e4c84936deedd907a0dca7f331ba5b1fa4)
2022-11-22 16:30:15 +08:00
openeuler-ci-bot
4ceee46a15 !2 fix CVE-2021-30129
From: @starlet-dx
Reviewed-by: @houyingchao,@myeuler
Signed-off-by: @myeuler
2021-08-11 01:36:23 +00:00
starlet_dx
8373c8893a fix CVE-2021-30129 2021-08-10 16:01:42 +08:00
openeuler-ci-bot
64db206fbf !1 package init
Merge pull request !1 from jeff200902/master
2020-08-31 15:28:43 +08:00
jeff200902
a62138aa30 Package init 2020-08-10 16:11:50 +08:00
7 changed files with 3752 additions and 0 deletions

View File

@ -0,0 +1,105 @@
From accd3e006a05615cf6eed9369d91fbedcc4eab16 Mon Sep 17 00:00:00 2001
From: Mat Booth <mat.booth@redhat.com>
Date: Thu, 7 Mar 2019 11:27:55 +0000
Subject: [PATCH] Avoid optional dependency on native tomcat APR library
---
pom.xml | 5 -----
sshd-core/pom.xml | 6 ------
.../sshd/agent/local/ProxyAgentFactory.java | 16 +---------------
sshd-osgi/pom.xml | 6 ------
4 files changed, 1 insertion(+), 32 deletions(-)
diff --git a/pom.xml b/pom.xml
index 867ca88..7c29678 100644
--- a/pom.xml
+++ b/pom.xml
@@ -428,11 +428,6 @@
<artifactId>mina-core</artifactId>
<version>2.0.23</version>
</dependency>
- <dependency>
- <groupId>tomcat</groupId>
- <artifactId>tomcat-apr</artifactId>
- <version>5.5.23</version>
- </dependency>
<dependency>
<groupId>net.i2p.crypto</groupId>
diff --git a/sshd-core/pom.xml b/sshd-core/pom.xml
index 6171c5c..73a43a7 100644
--- a/sshd-core/pom.xml
+++ b/sshd-core/pom.xml
@@ -43,12 +43,6 @@
</dependency>
<dependency>
- <groupId>tomcat</groupId>
- <artifactId>tomcat-apr</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<optional>true</optional>
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
index ab19539..5757e68 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
@@ -27,8 +27,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
-import org.apache.sshd.agent.unix.AprLibrary;
-import org.apache.sshd.agent.unix.UnixAgentFactory;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.channel.ChannelFactory;
@@ -51,9 +49,7 @@ public class ProxyAgentFactory implements SshAgentFactory {
@Override
public List<ChannelFactory> getChannelForwardingFactories(FactoryManager manager) {
- return isPreferredUnixAgent(manager)
- ? UnixAgentFactory.DEFAULT_FORWARDING_CHANNELS
- : LocalAgentFactory.DEFAULT_FORWARDING_CHANNELS;
+ return LocalAgentFactory.DEFAULT_FORWARDING_CHANNELS;
}
@Override
@@ -104,16 +100,6 @@ public class ProxyAgentFactory implements SshAgentFactory {
}
public static boolean isPreferredUnixAgent(PropertyResolver resolver) {
- if (CoreModuleProperties.PREFER_UNIX_AGENT.getRequired(resolver)) {
- try {
- if (AprLibrary.getInstance() != null) {
- return true;
- }
- } catch (Exception ignore) {
- // ignored
- }
- }
-
return false;
}
}
diff --git a/sshd-osgi/pom.xml b/sshd-osgi/pom.xml
index 5395ceb..f456263 100644
--- a/sshd-osgi/pom.xml
+++ b/sshd-osgi/pom.xml
@@ -68,12 +68,6 @@
<optional>true</optional>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>tomcat</groupId>
- <artifactId>tomcat-apr</artifactId>
- <optional>true</optional>
- <scope>provided</scope>
- </dependency>
</dependencies>
<build>
--
2.20.1

2338
CVE-2023-35887.patch Normal file

File diff suppressed because it is too large Load Diff

976
CVE-2023-48795.patch Normal file
View File

@ -0,0 +1,976 @@
From 6b0fd46f64bcb75eeeee31d65f10242660aad7c1 Mon Sep 17 00:00:00 2001
From: Thomas Wolf <twolf@apache.org>
Date: Fri, 29 Dec 2023 17:39:14 +0100
Subject: [PATCH 1/3] GH-445: OpenSSH "strict KEX" protocol extension
Origin: https://github.com/apache/mina-sshd/pull/449
Implements the OpenSSH "strict KEX" protocol extension.[1] If both
parties in a an SSH connection announce support for strict KEX in the
initial KEX_INIT message, strict KEX is active; otherwise it isn't.
With strict KEX active, there must be only KEX-related messages during
the initial key exchange (no IGNORE or DEBUG messages are allowed), and
the KEX_INIT message must be the first one to have been received after
the initial version exchange. If these conditions are violated, the
connection is terminated.
Strict KEX also resets message sequence numbers to zero after each
NEW_KEYS message sent or received.
[1] https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
---
CHANGES.md | 11 ++
docs/standards.md | 35 ++--
docs/technical/kex.md | 15 ++
.../common/kex/extension/KexExtensions.java | 20 ++-
.../session/helpers/AbstractSession.java | 161 ++++++++++++++++--
.../session/helpers/AbstractSessionTest.java | 1 +
6 files changed, 213 insertions(+), 30 deletions(-)
diff --git a/docs/technical/kex.md b/docs/technical/kex.md
index e5d353a92..a3f5facc1 100644
--- a/docs/technical/kex.md
+++ b/docs/technical/kex.md
@@ -129,3 +129,18 @@ thread is not overrun by producers and actually can finish.
Again, "client" and "server" could also be inverted. For instance, a client uploading
files via SFTP might have an application thread pumping data through a channel, which
might be blocked during KEX.
+
+### Strict Key Exchange
+
+"Strict KEX" is an SSH protocol extension introduced in 2023 to harden the protocol against
+a particular form of attack. For details, see ["Terrapin attack"](https://www.terrapin-attack.com/)
+and [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). The "strict KEX"
+counter-measures are active if both peers indicate support for it at the start of the initial
+key exchange. By default, Apache MINA sshd always supports "strict kex" and advertises it, and
+thus it will always be active if the other party also supports it.
+
+If for whatever reason you want to disable using "strict KEX", this can be achieved by setting
+a custom session factory on the `SshClient` or `SshServer`. This custom session factory would create
+custom sessions subclassed from `ClientSessionImpl`or `ServerSessionImpl` that do not do anything
+in method `doStrictKexProposal()` (just return the proposal unchanged).
+
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
index 9fac45c13..f275227e1 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java
@@ -59,9 +59,23 @@ public final class KexExtensions {
public static final String CLIENT_KEX_EXTENSION = "ext-info-c";
public static final String SERVER_KEX_EXTENSION = "ext-info-s";
- @SuppressWarnings("checkstyle:Indentation")
- public static final Predicate<String> IS_KEX_EXTENSION_SIGNAL
- = n -> CLIENT_KEX_EXTENSION.equalsIgnoreCase(n) || SERVER_KEX_EXTENSION.equalsIgnoreCase(n);
+ public static final Predicate<String> IS_KEX_EXTENSION_SIGNAL = //
+ n -> CLIENT_KEX_EXTENSION.equalsIgnoreCase(n) || SERVER_KEX_EXTENSION.equalsIgnoreCase(n);
+
+ /**
+ * Reminder:
+ *
+ * These pseudo-algorithms are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored if they are present in
+ * subsequent SSH2_MSG_KEXINIT packets.
+ *
+ * <B>Note:</B> these values are <U>appended</U> to the initial proposals and removed if received before proceeding
+ * with the standard KEX proposals negotiation.
+ *
+ * @see <A HREF="https://github.com/openssh/openssh-portable/blob/master/PROTOCOL">OpenSSH PROTOCOL - 1.9 transport:
+ * strict key exchange extension</A>
+ */
+ public static final String STRICT_KEX_CLIENT_EXTENSION = "kex-strict-c-v00@openssh.com";
+ public static final String STRICT_KEX_SERVER_EXTENSION = "kex-strict-s-v00@openssh.com";
/**
* A case <U>insensitive</U> map of all the default known {@link KexExtensionParser} where key=the extension name
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
index 4bdb39c4c..b05a3ab92 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
@@ -27,13 +27,17 @@
import java.time.Duration;
import java.time.Instant;
import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.EnumMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -45,6 +49,7 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.LongConsumer;
import java.util.logging.Level;
+import java.util.stream.Collectors;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.Factory;
@@ -109,6 +114,7 @@
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
+@SuppressWarnings("checkstyle:MethodCount")
public abstract class AbstractSession extends SessionHelper {
/**
* Name of the property where this session is stored in the attributes of the underlying MINA session. See
@@ -192,6 +198,22 @@ public abstract class AbstractSession extends SessionHelper {
protected final Object decodeLock = new Object();
protected final Object requestLock = new Object();
+ /**
+ * "Strict KEX" is a mitigation for the "Terrapin attack". The KEX protocol is modified as follows:
+ * <ol>
+ * <li>During the initial (unencrypted) KEX, no extra messages not strictly necessary for KEX are allowed. The
+ * KEX_INIT message must be the first one after the version identification, and no IGNORE or DEBUG messages are
+ * allowed until the KEX is completed. If a party receives such a message, it terminates the connection.</li>
+ * <li>Message sequence numbers are reset to zero after a key exchange (initial or later). When the NEW_KEYS message
+ * has been sent, the outgoing message number is reset; after a NEW_KEYS message has been received, the incoming
+ * message number is reset.</li>
+ * </ol>
+ * Strict KEX is negotiated in the original KEX proposal; it is active if and only if both parties indicate that
+ * they support strict KEX.
+ */
+ protected boolean strictKex;
+ protected long initialKexInitSequenceNumber = -1;
+
/**
* The {@link KeyExchangeMessageHandler} instance also serves as lock protecting {@link #kexState} changes from DONE
* to INIT or RUN, and from KEYS to DONE.
@@ -550,18 +572,24 @@ protected void doHandleMessage(Buffer buffer) throws Exception {
handleDisconnect(buffer);
break;
case SshConstants.SSH_MSG_IGNORE:
+ failStrictKex(cmd);
handleIgnore(buffer);
break;
case SshConstants.SSH_MSG_UNIMPLEMENTED:
+ failStrictKex(cmd);
handleUnimplemented(buffer);
break;
case SshConstants.SSH_MSG_DEBUG:
+ // Fail after handling -- by default a message will be logged, which might be helpful.
handleDebug(buffer);
+ failStrictKex(cmd);
break;
case SshConstants.SSH_MSG_SERVICE_REQUEST:
+ failStrictKex(cmd);
handleServiceRequest(buffer);
break;
case SshConstants.SSH_MSG_SERVICE_ACCEPT:
+ failStrictKex(cmd);
handleServiceAccept(buffer);
break;
case SshConstants.SSH_MSG_KEXINIT:
@@ -571,9 +599,11 @@ protected void doHandleMessage(Buffer buffer) throws Exception {
handleNewKeys(cmd, buffer);
break;
case KexExtensions.SSH_MSG_EXT_INFO:
+ failStrictKex(cmd);
handleKexExtension(cmd, buffer);
break;
case KexExtensions.SSH_MSG_NEWCOMPRESS:
+ failStrictKex(cmd);
handleNewCompression(cmd, buffer);
break;
default:
@@ -589,26 +619,35 @@ protected void doHandleMessage(Buffer buffer) throws Exception {
}
handleKexMessage(cmd, buffer);
- } else if (currentService.process(cmd, buffer)) {
- resetIdleTimeout();
} else {
- /*
- * According to https://tools.ietf.org/html/rfc4253#section-11.4
- *
- * An implementation MUST respond to all unrecognized messages with an SSH_MSG_UNIMPLEMENTED message
- * in the order in which the messages were received.
- */
- if (log.isDebugEnabled()) {
- log.debug("process({}) Unsupported command: {}",
- this, SshConstants.getCommandMessageName(cmd));
+ failStrictKex(cmd);
+ if (currentService.process(cmd, buffer)) {
+ resetIdleTimeout();
+ } else {
+ /*
+ * According to https://tools.ietf.org/html/rfc4253#section-11.4
+ *
+ * An implementation MUST respond to all unrecognized messages with an SSH_MSG_UNIMPLEMENTED
+ * message in the order in which the messages were received.
+ */
+ if (log.isDebugEnabled()) {
+ log.debug("process({}) Unsupported command: {}", this, SshConstants.getCommandMessageName(cmd));
+ }
+ notImplemented(cmd, buffer);
}
- notImplemented(cmd, buffer);
}
break;
}
checkRekey();
}
+ protected void failStrictKex(int cmd) throws SshException {
+ if (!initialKexDone && strictKex) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ SshConstants.getCommandMessageName(cmd) + " not allowed during initial key exchange in strict KEX");
+ }
+ }
+
protected boolean handleFirstKexPacketFollows(int cmd, Buffer buffer, boolean followFlag) {
if (!followFlag) {
return true; // if 1st KEX packet does not follow then process the command
@@ -1118,7 +1157,7 @@ protected IoWriteFuture doWritePacket(Buffer buffer) throws IOException {
}
protected int resolveIgnoreBufferDataLength() {
- if ((ignorePacketDataLength <= 0)
+ if (!initialKexDone || (ignorePacketDataLength <= 0)
|| (ignorePacketsFrequency <= 0L)
|| (ignorePacketsVariance < 0)) {
return 0;
@@ -1931,6 +1970,13 @@ protected void prepareNewKeys() throws Exception {
* @throws Exception on errors
*/
protected void setOutputEncoding() throws Exception {
+ if (strictKex) {
+ if (log.isDebugEnabled()) {
+ log.debug("setOutputEncoding({}): strict KEX resets output message sequence number from {} to 0", this, seqo);
+ }
+ seqo = 0;
+ }
+
outCipher = outSettings.getCipher(seqo);
outMac = outSettings.getMac();
outCompression = outSettings.getCompression();
@@ -1962,6 +2008,13 @@ protected void setOutputEncoding() throws Exception {
* @throws Exception on errors
*/
protected void setInputEncoding() throws Exception {
+ if (strictKex) {
+ if (log.isDebugEnabled()) {
+ log.debug("setInputEncoding({}): strict KEX resets input message sequence number from {} to 0", this, seqi);
+ }
+ seqi = 0;
+ }
+
inCipher = inSettings.getCipher(seqi);
inMac = inSettings.getMac();
inCompression = inSettings.getCompression();
@@ -2044,6 +2097,25 @@ protected IoWriteFuture notImplemented(int cmd, Buffer buffer) throws Exception
return sendNotImplemented(seqi - 1L);
}
+ /**
+ * Given a KEX proposal and a {@link KexProposalOption}, removes all occurrences of a value from a comma-separated
+ * value list.
+ *
+ * @param options {@link Map} holding the Kex proposal
+ * @param option {@link KexProposalOption} to modify
+ * @param toRemove value to remove
+ * @return {@code true} if the option contained the value (and it was removed); {@code false} otherwise
+ */
+ protected boolean removeValue(Map<KexProposalOption, String> options, KexProposalOption option, String toRemove) {
+ String val = options.get(option);
+ Set<String> algorithms = new LinkedHashSet<>(Arrays.asList(val.split(",")));
+ boolean result = algorithms.remove(toRemove);
+ if (result) {
+ options.put(option, algorithms.stream().collect(Collectors.joining(",")));
+ }
+ return result;
+ }
+
/**
* Compute the negotiated proposals by merging the client and server proposal. The negotiated proposal will also be
* stored in the {@link #negotiationResult} property.
@@ -2056,11 +2128,43 @@ protected Map<KexProposalOption, String> negotiate() throws Exception {
Map<KexProposalOption, String> s2cOptions = getServerKexProposals();
signalNegotiationStart(c2sOptions, s2cOptions);
+ // Make modifiable. Strict KEX flags are to be heeded only in initial KEX, and to be ignored afterwards.
+ c2sOptions = new EnumMap<>(c2sOptions);
+ s2cOptions = new EnumMap<>(s2cOptions);
+ boolean strictKexClient = removeValue(c2sOptions, KexProposalOption.ALGORITHMS,
+ KexExtensions.STRICT_KEX_CLIENT_EXTENSION);
+ boolean strictKexServer = removeValue(s2cOptions, KexProposalOption.ALGORITHMS,
+ KexExtensions.STRICT_KEX_SERVER_EXTENSION);
+ if (removeValue(c2sOptions, KexProposalOption.ALGORITHMS, KexExtensions.STRICT_KEX_SERVER_EXTENSION)
+ && !initialKexDone) {
+ log.warn("negotiate({}) client proposal contains server flag {}; will be ignored", this,
+ KexExtensions.STRICT_KEX_SERVER_EXTENSION);
+ }
+ if (removeValue(s2cOptions, KexProposalOption.ALGORITHMS, KexExtensions.STRICT_KEX_CLIENT_EXTENSION)
+ && !initialKexDone) {
+ log.warn("negotiate({}) server proposal contains client flag {}; will be ignored", this,
+ KexExtensions.STRICT_KEX_CLIENT_EXTENSION);
+ }
+ // Make unmodifiable again
+ c2sOptions = Collections.unmodifiableMap(c2sOptions);
+ s2cOptions = Collections.unmodifiableMap(s2cOptions);
Map<KexProposalOption, String> guess = new EnumMap<>(KexProposalOption.class);
Map<KexProposalOption, String> negotiatedGuess = Collections.unmodifiableMap(guess);
try {
boolean debugEnabled = log.isDebugEnabled();
boolean traceEnabled = log.isTraceEnabled();
+ if (!initialKexDone) {
+ strictKex = strictKexClient && strictKexServer;
+ if (debugEnabled) {
+ log.debug("negotiate({}) strict KEX={} client={} server={}", this, strictKex, strictKexClient,
+ strictKexServer);
+ }
+ if (strictKex && initialKexInitSequenceNumber != 1) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Strict KEX negotiated but sequence number of first KEX_INIT received is not 1: "
+ + initialKexInitSequenceNumber);
+ }
+ }
SessionDisconnectHandler discHandler = getSessionDisconnectHandler();
KexExtensionHandler extHandler = getKexExtensionHandler();
for (KexProposalOption paramType : KexProposalOption.VALUES) {
@@ -2520,8 +2624,34 @@ protected String resolveSessionKexProposal(String hostKeyTypes) throws IOExcepti
}
}
+ protected Map<KexProposalOption, String> doStrictKexProposal(Map<KexProposalOption, String> proposal) {
+ String value = proposal.get(KexProposalOption.ALGORITHMS);
+ String askForStrictKex = isServerSession()
+ ? KexExtensions.STRICT_KEX_SERVER_EXTENSION
+ : KexExtensions.STRICT_KEX_CLIENT_EXTENSION;
+ if (!initialKexDone) {
+ // On the initial KEX, include the strict KEX flag
+ if (GenericUtils.isEmpty(value)) {
+ value = askForStrictKex;
+ } else {
+ value += "," + askForStrictKex;
+ }
+ } else if (!GenericUtils.isEmpty(value)) {
+ // On subsequent KEXes, do not include ext-info-c/ext-info-s or the strict KEX flag in the proposal.
+ List<String> algorithms = new ArrayList<>(Arrays.asList(value.split(",")));
+ String extType = isServerSession() ? KexExtensions.SERVER_KEX_EXTENSION : KexExtensions.CLIENT_KEX_EXTENSION;
+ boolean changed = algorithms.remove(extType);
+ changed |= algorithms.remove(askForStrictKex);
+ if (changed) {
+ value = algorithms.stream().collect(Collectors.joining(","));
+ }
+ }
+ proposal.put(KexProposalOption.ALGORITHMS, value);
+ return proposal;
+ }
+
protected byte[] sendKexInit() throws Exception {
- Map<KexProposalOption, String> proposal = getKexProposal();
+ Map<KexProposalOption, String> proposal = doStrictKexProposal(getKexProposal());
byte[] seed;
synchronized (kexState) {
@@ -2588,6 +2718,9 @@ protected void setServerKexData(byte[] data) {
protected byte[] receiveKexInit(Buffer buffer) throws Exception {
Map<KexProposalOption, String> proposal = new EnumMap<>(KexProposalOption.class);
+ if (!initialKexDone) {
+ initialKexInitSequenceNumber = seqi;
+ }
byte[] seed;
synchronized (kexState) {
seed = receiveKexInit(buffer, proposal);
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java b/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
index 6fe6e8104..8d74d51b7 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/session/helpers/AbstractSessionTest.java
@@ -437,6 +437,7 @@ public static class MySession extends AbstractSession {
public MySession() {
super(true, org.apache.sshd.util.test.CoreTestSupportUtils.setupTestServer(AbstractSessionTest.class),
new MyIoSession());
+ initialKexDone = true;
}
@Override
From 315739e4e9d1dc7a4ff32ea64936982ed0b73e76 Mon Sep 17 00:00:00 2001
From: Thomas Wolf <twolf@apache.org>
Date: Mon, 1 Jan 2024 15:00:40 +0100
Subject: [PATCH 2/3] GH-445: Unit tests for strict KEX
Add tests for the restricted message handling if strict KEX is active:
* Initial KEX fails if KEX_INIT is not the first message
* Initial KEX fails if there are spurious messages like DEBUG during KEX
* Re-KEX succeeds even if there are spurious messages
---
.../common/kex/extension/StrictKexTest.java | 264 ++++++++++++++++++
1 file changed, 264 insertions(+)
create mode 100644 sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexTest.java
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexTest.java b/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexTest.java
new file mode 100644
index 000000000..6d6c2ce8c
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexTest.java
@@ -0,0 +1,264 @@
+/*
+ * 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.kex.extension;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.kex.KexProposalOption;
+import org.apache.sshd.common.session.Session;
+import org.apache.sshd.common.session.SessionListener;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * Tests for message handling during "strict KEX" is active: initial KEX must fail and disconnect if the KEX_INIT
+ * message is not first, or if there are spurious extra messages like IGNORE or DEBUG during KEX. Later KEXes must
+ * succeed even if there are spurious messages.
+ * <p>
+ * The other part of "strict KEX" is resetting the message sequence numbers after KEX. This is not tested here but in
+ * the {@link StrictKexInteroperabilityTest}, which runs an Apache MINA sshd client against OpenSSH servers that have or
+ * do not have the "strict KEX" extension. If the sequence number handling was wrong, those tests would fail.
+ * </p>
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="https://github.com/apache/mina-sshd/issues/445">Terrapin Mitigation: &quot;strict-kex&quot;</A>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class StrictKexTest extends BaseTestSupport {
+ private SshServer sshd;
+ private SshClient client;
+
+ public StrictKexTest() {
+ super();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ sshd = setupTestServer();
+ client = setupTestClient();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (sshd != null) {
+ sshd.stop(true);
+ }
+ if (client != null) {
+ client.stop();
+ }
+ }
+
+ @Test
+ public void connectionClosedIfFirstPacketFromClientNotKexInit() throws Exception {
+ testConnectionClosedIfFirstPacketFromPeerNotKexInit(true);
+ }
+
+ @Test
+ public void connectionClosedIfFirstPacketFromServerNotKexInit() throws Exception {
+ testConnectionClosedIfFirstPacketFromPeerNotKexInit(false);
+ }
+
+ private void testConnectionClosedIfFirstPacketFromPeerNotKexInit(boolean clientInitiates) throws Exception {
+ AtomicReference<IoWriteFuture> debugMsg = new AtomicReference<>();
+ SessionListener messageInitiator = new SessionListener() {
+ @Override // At this stage KEX-INIT not sent yet
+ public void sessionNegotiationOptionsCreated(Session session, Map<KexProposalOption, String> proposal) {
+ try {
+ debugMsg.set(session.sendDebugMessage(true, getCurrentTestName(), null));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ if (clientInitiates) {
+ client.addSessionListener(messageInitiator);
+ } else {
+ sshd.addSessionListener(messageInitiator);
+ }
+
+ try (ClientSession session = obtainInitialTestClientSession()) {
+ fail("Unexpected session success");
+ } catch (SshException e) {
+ IoWriteFuture future = debugMsg.get();
+ assertNotNull("No SSH_MSG_DEBUG", future);
+ assertTrue("SSH_MSG_DEBUG should have been sent", future.isWritten());
+ // Due to a race condition in the Nio2 transport when closing a connection due to an exception it's possible
+ // that we do _not_ get the expected disconnection code. The race condition may lead to the IoSession being
+ // closed in the peer before it has sent the DISCONNECT message. Happens in particular on Windows.
+ if (e.getDisconnectCode() == SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED) {
+ assertTrue("Unexpected disconnect reason: " + e.getMessage(), e.getMessage()
+ .startsWith("Strict KEX negotiated but sequence number of first KEX_INIT received is not 1"));
+ }
+ }
+ }
+
+ @Test
+ public void connectionClosedIfSpuriousPacketFromClientInKex() throws Exception {
+ testConnectionClosedIfSupriousPacketInKex(true);
+ }
+
+ @Test
+ public void connectionClosedIfSpuriousPacketFromServerInKex() throws Exception {
+ testConnectionClosedIfSupriousPacketInKex(false);
+ }
+
+ private void testConnectionClosedIfSupriousPacketInKex(boolean clientInitiates) throws Exception {
+ AtomicReference<IoWriteFuture> debugMsg = new AtomicReference<>();
+ SessionListener messageInitiator = new SessionListener() {
+ @Override // At this stage the peer's KEX_INIT has been received
+ public void sessionNegotiationEnd(
+ Session session, Map<KexProposalOption, String> clientProposal,
+ Map<KexProposalOption, String> serverProposal, Map<KexProposalOption, String> negotiatedOptions,
+ Throwable reason) {
+ try {
+ debugMsg.set(session.sendDebugMessage(true, getCurrentTestName(), null));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ if (clientInitiates) {
+ client.addSessionListener(messageInitiator);
+ } else {
+ sshd.addSessionListener(messageInitiator);
+ }
+
+ try (ClientSession session = obtainInitialTestClientSession()) {
+ fail("Unexpected session success");
+ } catch (SshException e) {
+ IoWriteFuture future = debugMsg.get();
+ assertNotNull("No SSH_MSG_DEBUG", future);
+ assertTrue("SSH_MSG_DEBUG should have been sent", future.isWritten());
+ if (e.getDisconnectCode() == SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED) {
+ assertEquals("Unexpected disconnect reason",
+ "SSH_MSG_DEBUG not allowed during initial key exchange in strict KEX", e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void reKeyAllowsDebugInKexFromClient() throws Exception {
+ testReKeyAllowsDebugInKex(true);
+ }
+
+ @Test
+ public void reKeyAllowsDebugInKexFromServer() throws Exception {
+ testReKeyAllowsDebugInKex(false);
+ }
+
+ private void testReKeyAllowsDebugInKex(boolean clientInitiates) throws Exception {
+ AtomicBoolean sendDebug = new AtomicBoolean();
+ AtomicReference<IoWriteFuture> debugMsg = new AtomicReference<>();
+ SessionListener messageInitiator = new SessionListener() {
+ @Override // At this stage the peer's KEX_INIT has been received
+ public void sessionNegotiationEnd(
+ Session session, Map<KexProposalOption, String> clientProposal,
+ Map<KexProposalOption, String> serverProposal, Map<KexProposalOption, String> negotiatedOptions,
+ Throwable reason) {
+ if (sendDebug.get()) {
+ try {
+ debugMsg.set(session.sendDebugMessage(true, getCurrentTestName(), null));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ };
+
+ if (clientInitiates) {
+ client.addSessionListener(messageInitiator);
+ } else {
+ sshd.addSessionListener(messageInitiator);
+ }
+
+ try (ClientSession session = obtainInitialTestClientSession()) {
+ assertTrue("Session should be stablished", session.isOpen());
+ sendDebug.set(true);
+ assertTrue("KEX not done", session.reExchangeKeys().verify(CONNECT_TIMEOUT).isDone());
+ IoWriteFuture future = debugMsg.get();
+ assertNotNull("No SSH_MSG_DEBUG", future);
+ assertTrue("SSH_MSG_DEBUG should have been sent", future.isWritten());
+ assertTrue(session.isOpen());
+ }
+ }
+
+ @Test
+ public void strictKexWorksWithServerFlagInClientProposal() throws Exception {
+ testStrictKexWorksWithWrongFlag(true);
+ }
+
+ @Test
+ public void strictKexWorksWithClientFlagInServerProposal() throws Exception {
+ testStrictKexWorksWithWrongFlag(false);
+ }
+
+ private void testStrictKexWorksWithWrongFlag(boolean clientInitiates) throws Exception {
+ SessionListener messageInitiator = new SessionListener() {
+ @Override
+ public void sessionNegotiationOptionsCreated(Session session, Map<KexProposalOption, String> proposal) {
+ // Modify the proposal by including the *wrong* flag. (The framework will also add the correct flag.)
+ String value = proposal.get(KexProposalOption.ALGORITHMS);
+ String toAdd = clientInitiates
+ ? KexExtensions.STRICT_KEX_SERVER_EXTENSION
+ : KexExtensions.STRICT_KEX_CLIENT_EXTENSION;
+ if (GenericUtils.isEmpty(value)) {
+ value = toAdd;
+ } else {
+ value += ',' + toAdd;
+ }
+ proposal.put(KexProposalOption.ALGORITHMS, value);
+ }
+ };
+
+ if (clientInitiates) {
+ client.addSessionListener(messageInitiator);
+ } else {
+ sshd.addSessionListener(messageInitiator);
+ }
+
+ try (ClientSession session = obtainInitialTestClientSession()) {
+ assertTrue("Session should be stablished", session.isOpen());
+ }
+ }
+
+ private ClientSession obtainInitialTestClientSession() throws IOException {
+ sshd.start();
+ int port = sshd.getPort();
+
+ client.start();
+ return createAuthenticatedClientSession(client, port);
+ }
+}
From 7b2c781640a7a78a9455b86593a1f63c9e8cab92 Mon Sep 17 00:00:00 2001
From: Thomas Wolf <twolf@apache.org>
Date: Tue, 2 Jan 2024 22:35:42 +0100
Subject: [PATCH 3/3] GH-445: strict KEX interoperability tests
Run an Apache MINA sshd client against OpenSSH servers that do have or
do not have strict KEX.
---
.../StrictKexInteroperabilityTest.java | 192 ++++++++++++++++++
.../sshd/common/kex/extensions/client/bob_key | 27 +++
.../common/kex/extensions/client/bob_key.pub | 1 +
.../kex/extensions/client/entrypoint.sh | 6 +
sshd-mina/pom.xml | 1 +
sshd-netty/pom.xml | 1 +
6 files changed, 228 insertions(+)
create mode 100644 sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
create mode 100644 sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key
create mode 100644 sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key.pub
create mode 100644 sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/entrypoint.sh
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
new file mode 100644
index 000000000..43e6d8a8e
--- /dev/null
+++ b/sshd-core/src/test/java/org/apache/sshd/common/kex/extension/StrictKexInteroperabilityTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.kex.extension;
+
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ChannelShell;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.SessionFactory;
+import org.apache.sshd.common.channel.StreamingChannel;
+import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.util.test.BaseTestSupport;
+import org.apache.sshd.util.test.CommonTestSupportUtils;
+import org.apache.sshd.util.test.ContainerTestCase;
+import org.junit.After;
+import org.junit.Before;
+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;
+import org.testcontainers.images.builder.dockerfile.DockerfileBuilder;
+import org.testcontainers.utility.MountableFile;
+
+/**
+ * Tests to ensure that an Apache MINA sshd client can talk to OpenSSH servers with or without "strict KEX". This
+ * implicitly tests the message sequence number handling; if sequence numbers get out of sync or are reset wrongly,
+ * subsequent messages cannot be decrypted correctly and there will be exceptions.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="https://github.com/apache/mina-sshd/issues/445">Terrapin Mitigation: &quot;strict-kex&quot;</A>
+ */
+@Category(ContainerTestCase.class)
+public class StrictKexInteroperabilityTest extends BaseTestSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(StrictKexInteroperabilityTest.class);
+
+ private static final String TEST_RESOURCES = "org/apache/sshd/common/kex/extensions/client";
+
+ private SshClient client;
+
+ public StrictKexInteroperabilityTest() {
+ super();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ client = setupTestClient();
+ SessionFactory factory = new TestSessionFactory(client);
+ client.setSessionFactory(factory);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (client != null) {
+ client.stop();
+ }
+ }
+
+ 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
+ } else {
+ return builder
+ .from("alpine:20231219") //
+ .run("apk --update add openssh-server") // Installs OpenSSH 9.6
+ .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
+ }
+ }
+
+ @Test
+ public void testStrictKexOff() throws Exception {
+ testStrictKex(false);
+ }
+
+ @Test
+ public void testStrictKexOn() throws Exception {
+ testStrictKex(true);
+ }
+
+ private void testStrictKex(boolean withStrictKex) throws Exception {
+ // This tests that the message sequence numbers are handled correctly. Strict KEX resets them to zero on any
+ // KEX, without strict KEX, they're not reset. If sequence numbers get out of sync, received messages are
+ // decrypted wrongly and there will be exceptions.
+ @SuppressWarnings("resource")
+ GenericContainer<?> sshdContainer = new GenericContainer<>(new ImageFromDockerfile()
+ .withDockerfileFromBuilder(builder -> strictKexImage(builder, withStrictKex) //
+ .run("mkdir -p /home/bob/.ssh") // Create the SSH config directory
+ .entryPoint("/entrypoint.sh") //
+ .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));
+ sshdContainer.start();
+ try {
+ FileKeyPairProvider keyPairProvider = CommonTestSupportUtils.createTestKeyPairProvider(TEST_RESOURCES + "/bob_key");
+ client.setKeyIdentityProvider(keyPairProvider);
+ client.start();
+ try (ClientSession session = client.connect("bob", sshdContainer.getHost(), sshdContainer.getMappedPort(22))
+ .verify(CONNECT_TIMEOUT).getSession()) {
+ session.auth().verify(AUTH_TIMEOUT);
+ assertTrue("Should authenticate", session.isAuthenticated());
+ assertTrue("Unexpected session type " + session.getClass().getName(), session instanceof TestSession);
+ assertEquals("Unexpected strict KEX usage", withStrictKex, ((TestSession) session).usesStrictKex());
+ 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));
+ LOG.info("writing some data...");
+ pos.write("\n\n".getBytes(StandardCharsets.UTF_8));
+ assertTrue("Channel should be open", channel.isOpen());
+ assertTrue(session.reExchangeKeys().verify(CONNECT_TIMEOUT).isDone());
+ assertTrue("Channel should be open", channel.isOpen());
+ LOG.info("writing some data...");
+ pos.write("\n\n".getBytes(StandardCharsets.UTF_8));
+ assertTrue("Channel should be open", channel.isOpen());
+ channel.close(true);
+ }
+ }
+ } finally {
+ sshdContainer.stop();
+ }
+ }
+
+ // Subclass ClientSessionImpl to get access to the strictKex flag.
+
+ private static class TestSessionFactory extends SessionFactory {
+
+ TestSessionFactory(ClientFactoryManager client) {
+ super(client);
+ }
+
+ @Override
+ protected ClientSessionImpl doCreateSession(IoSession ioSession) throws Exception {
+ return new TestSession(getClient(), ioSession);
+ }
+ }
+
+ private static class TestSession extends ClientSessionImpl {
+
+ TestSession(ClientFactoryManager client, IoSession ioSession) throws Exception {
+ super(client, ioSession);
+ }
+
+ boolean usesStrictKex() {
+ return strictKex;
+ }
+ }
+}
diff --git a/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key
new file mode 100644
index 000000000..b5b70aeaa
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAxY3Hr1SqpJIQ9SbFfGMGweVy8jg2TEH3GC1K0LudQHJwogRi
++debdCqUtuSITbpPhjkeZSk9rq198d6RhT6TQmY9J8wLL2/+VXZk/rMVEEjeXQS3
+ImRnL2vVmkAunv6LwfDGHIovkhwj3/lqGWphDAKnHyXusPDwQ3N4LFGgxwXvRGqc
+lzmP8H+KDWaaPapk1AZCBIoD4JbL8faBtLNU01r+pB3sIKvfsPJ5DxPErThfrPuD
+qIbA3axEqFlgX4aVl3yMnSWjfhLhO7xD3YwrtUhannHt8pZQo5FkwCGWDpkG3xs+
+qK3ZACrhMFMTvPuDS83jDtEzNd5KYb4KnkOPMQIDAQABAoIBAQCE5GktgrD/39pU
+b25tzFehW25FjpbIGZ/UvbMUUwDnd5RZCMZj9yv1qyc7GOSwFOKmEgpmVqXNuZt9
+dxFBJuT8x7Xf7Zygnp/icbBivakvuTUMMb3X/t6CwfGAwCgcgHMXVZaPYE275f4k
+Dq3Wxv7di3NMusGkeY/GcAipF4gmGKKe7Ck1ifRypF2cDJsgTtsoFUHNNKfnT3gf
+OcJsVLRl0osbsxdqU+Tep46+jHrNt8J9n2VeRNRIqGHj0CkNdpLQOs+MjvIO3Hgq
+9NUxwIExwaPnBpTLlWwfemCz3JQnlAineMbYBGa1tpAA3Iw56NWcNbiOPyUyffbI
+wBC4r1uZAoGBAPESsergFD+ontChEI+h38oM/D9DKCObZR2kz6WArZ54i1dJWOgh
+HCsuxgPjxmaddPKghfNhUORdZBynuS5G7n6BfItNilDiFm2KBk12d38OVovUFo1Q
+r5akclKf0kFxHt5TzHIrNAv7B4OF0Uk3kuDHM7ITX3qDpTSBLlzPAUUHAoGBANHJ
+QIPmuF2q+PXnnSgdEyiETfl/IqUTXQyxda8kRIPJKKHZKPHZePhgJKUq9VP32PrP
+AxIBNrS3Netsp+EAApj09hmWUcgJRIU1/wjpVGqUmguYgh8nVFOPDudOJD5ltQ/A
+enzQ19IkGroaQB8CBGZsPaBAvqRZ5PLbm+BZEPQHAoGAblaMMGCXY/udlQfjOJpy
+f1wqKBpoyMNbKJJCqBGZZaruu+jKVJSy++DQqP8b0+PFnzdxl8+24o8MP0FVNKUq
+i6RgiLHY2ORiN4ixEctjLjg1zJIqMEv50g06di7IYUORSVk5fhfgHourCLu66rQQ
++eiy9JKBZOXUO4/U1I26mwkCgYAhfuCuLsiBLCtUGAcfwISuk3FfxMzjTpQs0qjX
+rhLCd/vk26eN9gs6nR88v/8ryQb8BNGYrljtwdL6I/8qDbZcdcBVlYq5RcGLA3QV
+GCxCWDfAYjlkgAMW1GCsze07iUG/ohvskevjwaAC1u4mBUxujhnI3I2T8EZ+AFKD
+H7V1QQKBgQDNt+zjSdLtA9AczxDwWmi5SbS+k+nGbi6AQO9i73wky/wxx7FonfWS
+2skkOUIst3HBc0Oz+CJTfNFQK6GVqtzTdlZFhMYS0ua1Djd6q6S648+K0cieY4r5
+5irivHYVN8t7lBcvbA7E7yD6dHXSHsn6yOLTrV382qRfJTbxG7ZVWA==
+-----END RSA PRIVATE KEY-----
diff --git a/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key.pub b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key.pub
new file mode 100644
index 000000000..efecd1b08
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/bob_key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFjcevVKqkkhD1JsV8YwbB5XLyODZMQfcYLUrQu51AcnCiBGL515t0KpS25IhNuk+GOR5lKT2urX3x3pGFPpNCZj0nzAsvb/5VdmT+sxUQSN5dBLciZGcva9WaQC6e/ovB8MYcii+SHCPf+WoZamEMAqcfJe6w8PBDc3gsUaDHBe9EapyXOY/wf4oNZpo9qmTUBkIEigPglsvx9oG0s1TTWv6kHewgq9+w8nkPE8StOF+s+4OohsDdrESoWWBfhpWXfIydJaN+EuE7vEPdjCu1SFqece3yllCjkWTAIZYOmQbfGz6ordkAKuEwUxO8+4NLzeMO0TM13kphvgqeQ48x user01
diff --git a/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/entrypoint.sh b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/entrypoint.sh
new file mode 100644
index 000000000..26489c5f0
--- /dev/null
+++ b/sshd-core/src/test/resources/org/apache/sshd/common/kex/extensions/client/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+chown -R bob /home/bob
+chmod 0600 /home/bob/.ssh/*
+
+/usr/sbin/sshd -D -ddd
diff --git a/sshd-mina/pom.xml b/sshd-mina/pom.xml
index 967b12930..6d1c4ed6a 100644
--- a/sshd-mina/pom.xml
+++ b/sshd-mina/pom.xml
@@ -124,6 +124,7 @@
<exclude>**/SessionReKeyHostKeyExchangeTest.java</exclude>
<exclude>**/HostBoundPubKeyAuthTest.java</exclude>
<exclude>**/PortForwardingWithOpenSshTest.java</exclude>
+ <exclude>**/StrictKexInteroperabilityTest.java</exclude>
<!-- reading files from classpath doesn't work correctly w/ reusable test jar -->
<exclude>**/OpenSSHCertificateTest.java</exclude>
</excludes>
diff --git a/sshd-netty/pom.xml b/sshd-netty/pom.xml
index 5d774029f..ac34b5094 100644
--- a/sshd-netty/pom.xml
+++ b/sshd-netty/pom.xml
@@ -143,6 +143,7 @@
<exclude>**/SessionReKeyHostKeyExchangeTest.java</exclude>
<exclude>**/HostBoundPubKeyAuthTest.java</exclude>
<exclude>**/PortForwardingWithOpenSshTest.java</exclude>
+ <exclude>**/StrictKexInteroperabilityTest.java</exclude>
<!-- reading files from classpath doesn't work correctly w/ reusable test jar -->
<exclude>**/OpenSSHCertificateTest.java</exclude>
</excludes>

Binary file not shown.

241
apache-sshd-javadoc.patch Normal file
View File

@ -0,0 +1,241 @@
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/client/auth/password/PasswordIdentityProvider.java 2022-11-16 09:50:02.519293210 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/client/auth/password/PasswordIdentityProvider.java 2022-11-16 10:29:30.819501234 +0100
@@ -36,7 +36,7 @@
public interface PasswordIdentityProvider {
/**
- * An &quot;empty&quot implementation of {@link PasswordIdentityProvider} that returns an empty group of passwords
+ * An &quot;empty&quot; implementation of {@link PasswordIdentityProvider} that returns an empty group of passwords
*/
PasswordIdentityProvider EMPTY_PASSWORDS_PROVIDER = new PasswordIdentityProvider() {
@Override
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java 2022-11-16 09:50:02.523293237 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java 2022-11-16 10:21:06.704044979 +0100
@@ -754,7 +754,7 @@
* @param expected The expected fingerprint if {@code null} or empty then returns a failure with the default
* fingerprint.
* @param key the {@link PublicKey} - if {@code null} then returns null.
- * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
+ * @return SimpleImmutableEntry&lt;Boolean, String&gt; - key is success indicator, value is actual fingerprint,
* {@code null} if no key.
* @see #getDefaultFingerPrintFactory()
* @see #checkFingerPrint(String, Factory, PublicKey)
@@ -768,7 +768,7 @@
* fingerprint.
* @param f The {@link Factory} to be used to generate the default {@link Digest} for the key
* @param key the {@link PublicKey} - if {@code null} then returns null.
- * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
+ * @return SimpleImmutableEntry&lt;Boolean, String&gt; - key is success indicator, value is actual fingerprint,
* {@code null} if no key.
*/
public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(
@@ -781,7 +781,7 @@
* fingerprint.
* @param d The {@link Digest} to be used to generate the default fingerprint for the key
* @param key the {@link PublicKey} - if {@code null} then returns null.
- * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
+ * @return SimpleImmutableEntry&lt;Boolean, String&gt; - key is success indicator, value is actual fingerprint,
* {@code null} if no key.
*/
public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(String expected, Digest d, PublicKey key) {
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java 2022-11-16 09:50:02.523293237 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParser.java 2022-11-16 10:27:11.094543153 +0100
@@ -63,9 +63,7 @@
import org.apache.sshd.common.util.security.SecurityUtils;
/**
- * Basic support for <A HREF=
- * "http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?rev=1.1&content-type=text/x-cvsweb-markup">OpenSSH
- * key file(s)</A>
+ * Basic support for <A HREF="http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?rev=1.1&amp;content-type=text/x-cvsweb-markup">OpenSSH key file(s)</A>
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java 2022-11-16 09:50:02.531293291 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/BufferPublicKeyParser.java 2022-11-16 10:07:03.290271908 +0100
@@ -64,13 +64,13 @@
SkED25519BufferPublicKeyParser.INSTANCE));
/**
- * @param keyType The key type - e.g., &quot;ssh-rsa&quot, &quot;ssh-dss&quot;
+ * @param keyType The key type - e.g., &quot;ssh-rsa&quot;, &quot;ssh-dss&quot;
* @return {@code true} if this key type is supported by the parser
*/
boolean isKeyTypeSupported(String keyType);
/**
- * @param keyType The key type - e.g., &quot;ssh-rsa&quot, &quot;ssh-dss&quot;
+ * @param keyType The key type - e.g., &quot;ssh-rsa&quot;, &quot;ssh-dss&quot;
* @param buffer The {@link Buffer} containing the encoded raw public key
* @return The decoded {@link PublicKey}
* @throws GeneralSecurityException If failed to generate the key
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java 2022-11-16 09:50:02.527293266 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java 2022-11-16 10:17:14.006452121 +0100
@@ -112,10 +112,11 @@
* @param with String to replace with
* @param max maximum number of values to replace, or <code>-1</code> if no maximum
* @return the text with any replacements processed
- * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
- * @author Magesh Umasankar
- * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
- * @author <a href="mailto:levylambert@tiscali-dsl.de">Antoine Levy-Lambert</a>
+ *
+ * author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
+ * author Magesh Umasankar
+ * author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
+ * author <a href="mailto:levylambert@tiscali-dsl.de">Antoine Levy-Lambert</a>
*/
@SuppressWarnings("PMD.AssignmentInOperand")
public static String replace(String text, String repl, String with, int max) {
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/io/der/DERWriter.java 2022-11-16 09:50:02.531293291 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/io/der/DERWriter.java 2022-11-16 10:09:10.435142161 +0100
@@ -76,7 +76,7 @@
}
/**
- * The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
+ * The integer is always considered to be positive, so if the first byte is &lt; 0, we pad with a zero to make it
* positive
*
* @param bytes {@link BigInteger} bytes
@@ -87,7 +87,7 @@
}
/**
- * The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
+ * The integer is always considered to be positive, so if the first byte is &lt; 0, we pad with a zero to make it
* positive
*
* @param bytes {@link BigInteger} bytes
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java 2022-11-16 09:50:02.527293266 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java 2022-11-16 10:28:23.527039819 +0100
@@ -165,7 +165,7 @@
}
/**
- * Remove {@code Windows} domain and/or group prefix as well as &quot;(User);&quot suffix
+ * Remove {@code Windows} domain and/or group prefix as well as &quot;(User);&quot; suffix
*
* @param user The original username - ignored if {@code null}/empty
* @return The canonical user - unchanged if {@code Unix} O/S
--- apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java 2022-11-16 09:50:02.535293319 +0100
+++ apache-sshd-2.9.2/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java 2022-11-16 10:31:13.564205742 +0100
@@ -119,7 +119,7 @@
/**
* The min. key size value used for testing whether Diffie-Hellman Group Exchange is supported or not. According to
* <A HREF="https://tools.ietf.org/html/rfc4419">RFC 4419</A> section 3: &quot;Servers and clients SHOULD support
- * groups with a modulus length of k bits, where 1024 <= k <= 8192&quot;. </code>
+ * groups with a modulus length of k bits, where 1024 &lt;= k &lt;= 8192&quot;. </code>
*
* <B>Note: this has been amended by <A HREF="https://tools.ietf.org/html/rfc8270">RFC 8270</A>
*/
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/client/session/ClientProxyConnector.java 2022-11-16 09:50:02.571293565 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/client/session/ClientProxyConnector.java 2022-11-16 10:28:51.175229400 +0100
@@ -23,8 +23,8 @@
/**
* Provides a way to implement proxied connections where some metadata about the client is sent <U>before</U> the actual
- * SSH protocol is executed - e.g., the <A HREF=@http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt">PROXY
- * protocol</A>. The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the
+ * SSH protocol is executed - e.g., the <A HREF="http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt">PROXY protocol</A>.
+ * The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the
* meta-data.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java 2022-11-16 09:50:02.575293593 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/BaseBuilder.java 2022-11-16 10:04:31.529233186 +0100
@@ -67,7 +67,7 @@
/**
* The default {@link BuiltinCiphers} setup in order of preference as specified by
- * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">ssh_config(5)</A>
+ * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&amp;sektion=5">ssh_config(5)</A>
*/
public static final List<BuiltinCiphers> DEFAULT_CIPHERS_PREFERENCE = Collections.unmodifiableList(
Arrays.asList(
@@ -83,7 +83,7 @@
/**
* The default {@link BuiltinDHFactories} setup in order of preference as specified by
- * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5"> ssh_config(5)</A>
+ * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&amp;sektion=5"> ssh_config(5)</A>
*/
public static final List<BuiltinDHFactories> DEFAULT_KEX_PREFERENCE = Collections.unmodifiableList(
Arrays.asList(
@@ -104,7 +104,7 @@
/**
* The default {@link BuiltinMacs} setup in order of preference as specified by
- * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5"> ssh_config(5)</A>
+ * <A HREF="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&amp;sektion=5"> ssh_config(5)</A>
*/
public static final List<BuiltinMacs> DEFAULT_MAC_PREFERENCE = Collections.unmodifiableList(
Arrays.asList(
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/channel/LocalWindow.java 2022-11-16 09:50:02.575293593 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/channel/LocalWindow.java 2022-11-16 10:22:11.968492069 +0100
@@ -51,8 +51,6 @@
/**
* Initializes the {@link LocalWindow} with the packet and window sizes from the {@code resolver}.
*
- * @param size the initial window size
- * @param packetSize the peer's advertised maximum packet size
* @param resolver {@PropertyResolver} to access properties
*/
public void init(PropertyResolver resolver) {
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/KeyExchangeMessageHandler.java 2022-11-16 09:50:02.579293619 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/KeyExchangeMessageHandler.java 2022-11-16 10:49:31.567743605 +0100
@@ -46,7 +46,7 @@
/**
* Manages SSH message sending during a key exchange. RFC 4253 specifies that during a key exchange, no high-level
* messages are to be sent, but a receiver must be able to deal with messages "in flight" until the peer's
- * {@link SshConstants#SSH_MSG_KEX_INIT} message is received.
+ * {@link SshConstants#SSH_MSG_KEXINIT} message is received.
* <p>
* Apache MINA sshd queues up high-level messages that threads try to send while a key exchange is ongoing, and sends
* them once the key exchange is done. Sending queued messages may make the peer re-trigger a new key exchange, in which
@@ -154,7 +154,7 @@
}
/**
- * Initializes the state for a new key exchange. {@link #allPacketsFlushed()} will be {@code false}, and a new
+ * Initializes the state for a new key exchange. <code>kexFlushed</code> will be {@code false}, and a new
* future to be fulfilled when all queued packets will be flushed once the key exchange is done is set. The
* currently set future from an earlier key exchange is returned. The returned future may or may not be fulfilled;
* if it isn't, there are still left-over pending packets to write from the previous key exchange, which will be
@@ -406,7 +406,7 @@
* exchange, flushing is stopped and is to be resumed by another call to this method when the new key exchange is
* done.
*
- * @param flushDone the future obtained from {@link #getFlushedFuture()}; will be fulfilled once all pending packets
+ * @param flushDone the future obtained from {@link #terminateKeyExchange()}; will be fulfilled once all pending packets
* have been written
*/
protected void flushQueue(DefaultKeyExchangeFuture flushDone) {
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java 2022-11-16 09:50:02.579293619 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java 2022-11-16 10:02:05.032231651 +0100
@@ -224,11 +224,11 @@
* {@link Buffer} to the given {@link ReplyHandler}, which may execute in a different thread.
*
* <dl>
- * <dt>want-reply == true && replyHandler != null</dt>
+ * <dt>want-reply == true &amp;&amp; replyHandler != null</dt>
* <dd>The returned future is fulfilled with {@code null} when the request was sent, or with an exception if the
* request could not be sent. The {@code replyHandler} is invoked once the reply is received, with the SSH reply
* code and the data received.</dd>
- * <dt>want-reply == true && replyHandler == null</dt>
+ * <dt>want-reply == true &amp;&amp; replyHandler == null</dt>
* <dd>The returned future is fulfilled with an exception if the request could not be sent, or a failure reply was
* received. If a success reply was received, the future is fulfilled with the received data buffer.</dd>
* <dt>want-reply == false</dt>
--- apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/server/session/ServerProxyAcceptor.java 2022-11-16 09:50:02.583293646 +0100
+++ apache-sshd-2.9.2/sshd-core/src/main/java/org/apache/sshd/server/session/ServerProxyAcceptor.java 2022-11-16 10:33:44.345239622 +0100
@@ -23,8 +23,7 @@
/**
* Provides a way to implement proxied connections where some metadata about the client is sent <U>before</U> the actual
- * SSH protocol is executed - e.g., the <A HREF=@http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt">PROXY
- * protocol</A>.
+ * SSH protocol is executed - e.g., the <A HREF="http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt">PROXY protocol</A>.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/

88
apache-sshd.spec Normal file
View File

@ -0,0 +1,88 @@
Epoch: 1
Name: apache-sshd
Version: 2.9.2
Release: 3
Summary: Apache SSHD
License: ASL 2.0 and ISC
URL: http://mina.apache.org/sshd-project
Source0: https://archive.apache.org/dist/mina/sshd/%{version}/apache-sshd-%{version}-src.tar.gz
Patch0: 0001-Avoid-optional-dependency-on-native-tomcat-APR-libra.patch
Patch1: apache-sshd-javadoc.patch
# https://github.com/apache/mina-sshd/commit/c20739b43aab0f7bf2ccad982a6cb37b9d5a8a0b
Patch2: CVE-2023-35887.patch
Patch3: CVE-2023-48795.patch
BuildRequires: maven-local mvn(junit:junit) mvn(net.i2p.crypto:eddsa) mvn(org.apache.ant:ant)
BuildRequires: mvn(org.apache:apache:pom:) mvn(org.apache.felix:maven-bundle-plugin)
BuildRequires: mvn(org.apache.maven:maven-archiver)
BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin)
BuildRequires: mvn(org.apache.maven.plugins:maven-clean-plugin)
BuildRequires: mvn(org.apache.maven.plugins:maven-dependency-plugin)
BuildRequires: mvn(org.apache.maven.plugins:maven-remote-resources-plugin)
BuildRequires: mvn(org.apache.maven.surefire:surefire-junit47)
BuildRequires: mvn(org.bouncycastle:bcpg-jdk15on) mvn(org.bouncycastle:bcpkix-jdk15on)
BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin)
BuildRequires: mvn(org.codehaus.plexus:plexus-archiver) mvn(org.slf4j:slf4j-api)
BuildRequires: mvn(org.slf4j:jcl-over-slf4j)
BuildArch: noarch
%description
Apache SSHD is a 100% pure java library to support the SSH protocols on both
the client and server side.
%package javadoc
Summary: API documentation for %{name}
%description javadoc
This package provides %{name}.
%prep
%autosetup -p1
rm -rf sshd-core/src/main/java/org/apache/sshd/agent/unix
%pom_remove_dep :spring-framework-bom
%pom_remove_dep :testcontainers-bom sshd-sftp sshd-core
%pom_disable_module assembly
%pom_disable_module sshd-mina
%pom_disable_module sshd-netty
%pom_disable_module sshd-ldap
%pom_disable_module sshd-git
%pom_disable_module sshd-contrib
%pom_disable_module sshd-spring-sftp
%pom_disable_module sshd-cli
%pom_disable_module sshd-openpgp
%pom_remove_plugin :apache-rat-plugin
%pom_remove_plugin :gmavenplus-plugin
%pom_remove_plugin :maven-checkstyle-plugin
%pom_remove_plugin :maven-enforcer-plugin
%pom_remove_plugin :maven-pmd-plugin
%pom_remove_plugin :animal-sniffer-maven-plugin
%pom_remove_plugin :impsort-maven-plugin
%pom_remove_plugin :formatter-maven-plugin . sshd-core
%pom_xpath_inject "pom:configuration/pom:instructions" "<_nouses>true</_nouses>" .
%build
%mvn_build -f -- -Dworkspace.root.dir=$(pwd)
%install
%mvn_install
%files -f .mfiles
%doc CHANGES.md
%license LICENSE.txt NOTICE.txt assembly/src/main/legal/licenses/jbcrypt.txt
%files javadoc -f .mfiles-javadoc
%license LICENSE.txt NOTICE.txt assembly/src/main/legal/licenses/jbcrypt.txt
%changelog
* Mon Jan 22 2024 wangkai <13474090681@163.com> - 1:2.9.2-3
- Fix CVE-2023-48795
* Thu Jan 11 2024 yaoxin <yao_xin001@hoperun.com> - 1:2.9.2-2
- Fix CVE-2023-35887
* Mon Nov 21 2022 liangqifeng <liangqifeng@ncti-gba.cn> - 1:2.9.2-1
- Fix CVE-2022-45047
* Tue Aug 10 2021 yaoxin <yaoxin30@huawei.com> - 2.2.0-2
- Fix CVE-2021-30129
* Thu Aug 6 2020 Jeffery.Gao <gaojianxing@huawei.com> - 2.2.0-1
- Package init

4
apache-sshd.yaml Normal file
View File

@ -0,0 +1,4 @@
version_control: NA
src_repo: NA
tag_prefix: NA
seperator: NA