diff --git a/0001-Avoid-optional-dependency-on-native-tomcat-APR-libra.patch b/0001-Avoid-optional-dependency-on-native-tomcat-APR-libra.patch index 6006344..f1a3b44 100644 --- a/0001-Avoid-optional-dependency-on-native-tomcat-APR-libra.patch +++ b/0001-Avoid-optional-dependency-on-native-tomcat-APR-libra.patch @@ -14,9 +14,9 @@ diff --git a/pom.xml b/pom.xml index 867ca88..7c29678 100644 --- a/pom.xml +++ b/pom.xml -@@ -397,11 +397,6 @@ +@@ -428,11 +428,6 @@ mina-core - 2.0.19 + 2.0.23 - - tomcat @@ -30,19 +30,19 @@ 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 -@@ -44,12 +44,6 @@ - ${project.version} +@@ -43,12 +43,6 @@ -- + - tomcat - tomcat-apr - true - - - +- org.bouncycastle bcpg-jdk15on + true 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 @@ -54,24 +54,24 @@ index ab19539..5757e68 100644 -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.NamedFactory; import org.apache.sshd.common.PropertyResolver; -@@ -53,9 +51,7 @@ public class ProxyAgentFactory implements SshAgentFactory { + import org.apache.sshd.common.channel.ChannelFactory; +@@ -51,9 +49,7 @@ public class ProxyAgentFactory implements SshAgentFactory { @Override - public List> getChannelForwardingFactories(FactoryManager manager) { + public List getChannelForwardingFactories(FactoryManager manager) { - return isPreferredUnixAgent(manager) -- ? UnixAgentFactory.DEFAULT_FORWARDING_CHANNELS -- : LocalAgentFactory.DEFAULT_FORWARDING_CHANNELS; +- ? UnixAgentFactory.DEFAULT_FORWARDING_CHANNELS +- : LocalAgentFactory.DEFAULT_FORWARDING_CHANNELS; + return LocalAgentFactory.DEFAULT_FORWARDING_CHANNELS; } @Override -@@ -106,16 +102,6 @@ public class ProxyAgentFactory implements SshAgentFactory { +@@ -104,16 +100,6 @@ public class ProxyAgentFactory implements SshAgentFactory { } public static boolean isPreferredUnixAgent(PropertyResolver resolver) { -- if (PropertyResolverUtils.getBooleanProperty(resolver, PREFER_UNIX_AGENT, OsUtils.isUNIX())) { +- if (CoreModuleProperties.PREFER_UNIX_AGENT.getRequired(resolver)) { - try { - if (AprLibrary.getInstance() != null) { - return true; @@ -103,5 +103,3 @@ index 5395ceb..f456263 100644 -- 2.20.1 - - diff --git a/CVE-2021-30129-1.patch b/CVE-2021-30129-1.patch deleted file mode 100644 index a6148be..0000000 --- a/CVE-2021-30129-1.patch +++ /dev/null @@ -1,1116 +0,0 @@ -From 68c780f2e746eedb714ff6e17c6815fbffddeff6 Mon Sep 17 00:00:00 2001 -From: Guillaume Nodet -Date: Fri, 17 Jul 2020 11:33:21 +0200 -Subject: [PATCH 1/1] [SSHD-1035] Move property definitions tocommon locations - ---- - .../java/org/apache/sshd/common/Property.java | 408 +++++++++++ - .../sshd/core/CoreModuleProperties.java | 681 ++++++++++++++++++ - 2 files changed, 1089 insertions(+) - create mode 100644 sshd-common/src/main/java/org/apache/sshd/common/Property.java - create mode 100644 sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java - -diff --git a/sshd-common/src/main/java/org/apache/sshd/common/Property.java b/sshd-common/src/main/java/org/apache/sshd/common/Property.java -new file mode 100644 -index 0000000..f5ad335 ---- /dev/null -+++ b/sshd-common/src/main/java/org/apache/sshd/common/Property.java -@@ -0,0 +1,408 @@ -+/* -+ * 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; -+ -+import java.nio.charset.Charset; -+import java.time.Duration; -+import java.util.Arrays; -+import java.util.Objects; -+import java.util.Optional; -+import java.util.function.Consumer; -+ -+/** -+ * Property definition. -+ * -+ * @author Apache MINA SSHD Project -+ */ -+public interface Property { -+ -+ static Property string(String name) { -+ return new StringProperty(name); -+ } -+ -+ static Property string(String name, String def) { -+ return new StringProperty(name, def); -+ } -+ -+ static Property bool(String name) { -+ return new BooleanProperty(name); -+ } -+ -+ static Property bool(String name, boolean def) { -+ return new BooleanProperty(name, def); -+ } -+ -+ static Property integer(String name) { -+ return new IntProperty(name); -+ } -+ -+ static Property integer(String name, int def) { -+ return new IntProperty(name, def); -+ } -+ -+ // CHECKSTYLE:OFF -+ static Property long_(String name) { -+ return new LongProperty(name); -+ } -+ -+ static Property long_(String name, long def) { -+ return new LongProperty(name, def); -+ } -+ -+ static > Property enum_(String name, Class type) { -+ return new EnumProperty<>(name, type); -+ } -+ -+ static > Property enum_(String name, Class type, T def) { -+ return new EnumProperty<>(name, type, def); -+ } -+ // CHECKSTYLE:ON -+ -+ static Property duration(String name) { -+ return new DurationProperty(name); -+ } -+ -+ static Property duration(String name, Duration def) { -+ return new DurationProperty(name, def); -+ } -+ -+ static Property durationSec(String name) { -+ return new DurationInSecondsProperty(name); -+ } -+ -+ static Property durationSec(String name, Duration def) { -+ return new DurationInSecondsProperty(name, def); -+ } -+ -+ static Property charset(String name) { -+ return new CharsetProperty(name); -+ } -+ -+ static Property charset(String name, Charset def) { -+ return new CharsetProperty(name, def); -+ } -+ -+ static Property object(String name) { -+ return new ObjectProperty(name); -+ } -+ -+ static Property object(String name, Object def) { -+ return new ObjectProperty(name, def); -+ } -+ -+ static Property validating(Property prop, Consumer validator) { -+ return new Validating<>(prop, validator); -+ } -+ -+ abstract class BaseProperty implements Property { -+ -+ private final String name; -+ private final T defaultValue; -+ -+ public BaseProperty(String name) { -+ this(name, null); -+ } -+ -+ public BaseProperty(String name, T defaultValue) { -+ this.name = Objects.requireNonNull(name, "No name provided"); -+ this.defaultValue = defaultValue; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Optional getDefault() { -+ return Optional.ofNullable(defaultValue); -+ } -+ -+ @Override -+ public T getRequiredDefault() { -+ return getDefault().get(); -+ } -+ -+ @Override -+ public Optional get(PropertyResolver resolver) { -+ Object propValue = PropertyResolverUtils.resolvePropertyValue(resolver, name); -+ return propValue != null ? Optional.of(fromStorage(propValue)) : getDefault(); -+ } -+ -+ @Override -+ public T getRequired(PropertyResolver resolver) { -+ return get(resolver).get(); -+ } -+ -+ @Override -+ public T getOrNull(PropertyResolver resolver) { -+ return get(resolver).orElse(null); -+ } -+ -+ @Override -+ public void set(PropertyResolver resolver, T value) { -+ PropertyResolverUtils.updateProperty(resolver, name, toStorage(value)); -+ } -+ -+ @Override -+ public void remove(PropertyResolver resolver) { -+ PropertyResolverUtils.updateProperty(resolver, name, null); -+ } -+ -+ protected Object toStorage(T value) { -+ return value; -+ } -+ -+ protected abstract T fromStorage(Object value); -+ -+ @Override -+ public String toString() { -+ return "Property[" + name + "]"; -+ } -+ } -+ -+ class DurationProperty extends BaseProperty { -+ -+ public DurationProperty(String name) { -+ super(name); -+ } -+ -+ public DurationProperty(String name, Duration def) { -+ super(name, def); -+ } -+ -+ @Override -+ protected Object toStorage(Duration value) { -+ return value != null ? value.toMillis() : null; -+ } -+ -+ @Override -+ protected Duration fromStorage(Object value) { -+ Long val = PropertyResolverUtils.toLong(value); -+ return val != null ? Duration.ofMillis(val) : null; -+ } -+ } -+ -+ class DurationInSecondsProperty extends DurationProperty { -+ public DurationInSecondsProperty(String name) { -+ super(name); -+ } -+ -+ public DurationInSecondsProperty(String name, Duration def) { -+ super(name, def); -+ } -+ -+ @Override -+ protected Object toStorage(Duration value) { -+ return value != null ? value.toMillis() / 1_000 : null; -+ } -+ -+ @Override -+ protected Duration fromStorage(Object value) { -+ Long val = PropertyResolverUtils.toLong(value); -+ return val != null ? Duration.ofSeconds(val) : null; -+ } -+ } -+ -+ class StringProperty extends BaseProperty { -+ -+ public StringProperty(String name) { -+ super(name); -+ } -+ -+ public StringProperty(String name, String def) { -+ super(name, def); -+ } -+ -+ @Override -+ protected String fromStorage(Object value) { -+ return value != null ? value.toString() : null; -+ } -+ } -+ -+ class BooleanProperty extends BaseProperty { -+ -+ public BooleanProperty(String name) { -+ super(name); -+ } -+ -+ public BooleanProperty(String name, Boolean defaultValue) { -+ super(name, defaultValue); -+ } -+ -+ @Override -+ protected Boolean fromStorage(Object value) { -+ return PropertyResolverUtils.toBoolean(value); -+ } -+ -+ } -+ -+ class LongProperty extends BaseProperty { -+ -+ public LongProperty(String name) { -+ super(name); -+ } -+ -+ public LongProperty(String name, Long defaultValue) { -+ super(name, defaultValue); -+ } -+ -+ @Override -+ protected Long fromStorage(Object value) { -+ return PropertyResolverUtils.toLong(value); -+ } -+ } -+ -+ class IntProperty extends BaseProperty { -+ -+ public IntProperty(String name) { -+ super(name); -+ } -+ -+ public IntProperty(String name, Integer defaultValue) { -+ super(name, defaultValue); -+ } -+ -+ @Override -+ protected Integer fromStorage(Object value) { -+ return PropertyResolverUtils.toInteger(value); -+ } -+ } -+ -+ class CharsetProperty extends BaseProperty { -+ -+ public CharsetProperty(String name) { -+ super(name); -+ } -+ -+ public CharsetProperty(String name, Charset defaultValue) { -+ super(name, defaultValue); -+ } -+ -+ @Override -+ protected Charset fromStorage(Object value) { -+ return PropertyResolverUtils.toCharset(value); -+ } -+ } -+ -+ class ObjectProperty extends BaseProperty { -+ -+ public ObjectProperty(String name) { -+ super(name); -+ } -+ -+ public ObjectProperty(String name, Object defaultValue) { -+ super(name, defaultValue); -+ } -+ -+ @Override -+ protected Object fromStorage(Object value) { -+ return value; -+ } -+ } -+ -+ class EnumProperty> extends BaseProperty { -+ -+ private final Class type; -+ -+ public EnumProperty(String name, Class type) { -+ super(name); -+ this.type = Objects.requireNonNull(type, "type is required"); -+ } -+ -+ public EnumProperty(String name, Class type, T def) { -+ super(name, def); -+ this.type = Objects.requireNonNull(type, "type is required"); -+ } -+ -+ @Override -+ protected T fromStorage(Object value) { -+ return PropertyResolverUtils.toEnum(type, value, false, Arrays.asList(type.getEnumConstants())); -+ } -+ } -+ -+ class Validating implements Property { -+ private final Property delegate; -+ private final Consumer validator; -+ -+ public Validating(Property delegate, Consumer validator) { -+ this.delegate = delegate; -+ this.validator = validator; -+ } -+ -+ @Override -+ public String getName() { -+ return delegate.getName(); -+ } -+ -+ @Override -+ public Optional getDefault() { -+ return delegate.getDefault(); -+ } -+ -+ @Override -+ public T getRequiredDefault() { -+ return delegate.getRequiredDefault(); -+ } -+ -+ @Override -+ public Optional get(PropertyResolver resolver) { -+ Optional t = delegate.get(resolver); -+ t.ifPresent(validator); -+ return t; -+ } -+ -+ @Override -+ public T getRequired(PropertyResolver resolver) { -+ return get(resolver).get(); -+ } -+ -+ @Override -+ public T getOrNull(PropertyResolver resolver) { -+ return get(resolver).orElse(null); -+ } -+ -+ @Override -+ public void set(PropertyResolver resolver, T value) { -+ validator.accept(value); -+ delegate.set(resolver, value); -+ } -+ -+ @Override -+ public void remove(PropertyResolver resolver) { -+ delegate.remove(resolver); -+ } -+ } -+ -+ String getName(); -+ -+ Optional getDefault(); -+ -+ T getRequiredDefault(); -+ -+ Optional get(PropertyResolver resolver); -+ -+ T getRequired(PropertyResolver resolver); -+ -+ T getOrNull(PropertyResolver resolver); -+ -+ void set(PropertyResolver resolver, T value); -+ -+ void remove(PropertyResolver resolver); -+} -diff --git a/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java b/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java -new file mode 100644 -index 0000000..9e9b2d2 ---- /dev/null -+++ b/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java -@@ -0,0 +1,681 @@ -+/* -+ * 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.core; -+ -+import java.io.IOException; -+import java.nio.charset.Charset; -+import java.time.Duration; -+ -+import org.apache.sshd.client.config.keys.ClientIdentityLoader; -+import org.apache.sshd.common.Property; -+import org.apache.sshd.common.channel.Channel; -+import org.apache.sshd.common.session.Session; -+import org.apache.sshd.common.util.OsUtils; -+import org.apache.sshd.common.util.ValidateUtils; -+import org.apache.sshd.common.util.io.IoUtils; -+import org.apache.sshd.common.util.net.SshdSocketAddress; -+import org.apache.sshd.server.auth.WelcomeBannerPhase; -+import org.apache.sshd.server.channel.ChannelDataReceiver; -+ -+/** -+ * Configurable properties for sshd-core. -+ * -+ * @author Apache MINA SSHD Project -+ */ -+public final class CoreModuleProperties { -+ -+ /** -+ * Value that can be set in order to control the type of authentication channel being requested when forwarding a -+ * PTY session. -+ */ -+ public static final Property PROXY_AUTH_CHANNEL_TYPE -+ = Property.string("ssh-agent-factory-proxy-auth-channel-type", "auth-agent-req@openssh.com"); -+ -+ /** -+ * See {@link org.apache.sshd.agent.local.ProxyAgentFactory#getChannelForwardingFactories} -+ */ -+ public static final Property PREFER_UNIX_AGENT -+ = Property.bool("ssh-prefer-unix-agent", OsUtils.isUNIX()); -+ -+ /** -+ * Value that can be set on the {@link org.apache.sshd.common.FactoryManager} or the session to configure the -+ * channel open timeout value (millis). -+ */ -+ public static final Property CHANNEL_OPEN_TIMEOUT -+ = Property.duration("ssh-agent-server-channel-open-timeout", Duration.ofSeconds(30)); -+ -+ /** -+ * Value used to configure the type of proxy forwarding channel to be used. See also -+ * https://tools.ietf.org/html/draft-ietf-secsh-agent-02 -+ */ -+ public static final Property PROXY_CHANNEL_TYPE -+ = Property.string("ssh-agent-server-channel-proxy-type", "auth-agent@openssh.com"); -+ -+ /** -+ * Property that can be set on the {@link Session} in order to control the authentication timeout (millis). -+ */ -+ public static final Property AUTH_SOCKET_TIMEOUT -+ = Property.duration("ssh-agent-server-proxy-auth-socket-timeout", Duration.ofHours(1)); -+ -+ public static final int DEFAULT_FORWARDER_BUF_SIZE = 1024; -+ public static final int MIN_FORWARDER_BUF_SIZE = 127; -+ public static final int MAX_FORWARDER_BUF_SIZE = 32767; -+ -+ /** -+ * Property that can be set on the factory manager in order to control the buffer size used to forward data from the -+ * established channel -+ * -+ * @see #MIN_FORWARDER_BUF_SIZE -+ * @see #MAX_FORWARDER_BUF_SIZE -+ * @see #DEFAULT_FORWARDER_BUF_SIZE -+ */ -+ public static final Property FORWARDER_BUFFER_SIZE -+ = Property.integer("channel-agent-fwd-buf-size", DEFAULT_FORWARDER_BUF_SIZE); -+ /** -+ * Ordered comma separated list of authentications methods. Authentications methods accepted by the server will be -+ * tried in the given order. If not configured or {@code null}/empty, then the session's -+ * {@link org.apache.sshd.client.ClientAuthenticationManager#getUserAuthFactories()} is used as-is -+ */ -+ public static final Property PREFERRED_AUTHS -+ = Property.string("preferred-auths"); -+ -+ /** -+ * Specifies the number of interactive prompts before giving up. The argument to this keyword must be an integer. -+ */ -+ public static final Property PASSWORD_PROMPTS -+ = Property.integer("password-prompts", 3); -+ -+ /** -+ * Key used to retrieve the value of the client identification string. If set, then it is appended to the -+ * (standard) "SSH-2.0-" prefix. Otherwise a default is sent that consists of "SSH-2.0-" plus -+ * the current SSHD artifact name and version in uppercase - e.g., "SSH-2.0-APACHE-SSHD-1.0.0" -+ */ -+ public static final Property CLIENT_IDENTIFICATION -+ = Property.string("client-identification"); -+ -+ /** -+ * Whether to send the identification string immediately upon session connection being established or wait for the -+ * server's identification before sending our own. -+ * -+ * @see RFC 4253 - section 4.2 - Protocol Version -+ * Exchange -+ */ -+ public static final Property SEND_IMMEDIATE_IDENTIFICATION -+ = Property.bool("send-immediate-identification", true); -+ /** -+ * Whether to send {@code SSH_MSG_KEXINIT} immediately after sending the client identification string or wait until -+ * the severer's one has been received. -+ * -+ * @see #SEND_IMMEDIATE_IDENTIFICATION -+ */ -+ public static final Property SEND_IMMEDIATE_KEXINIT -+ = Property.bool("send-immediate-kex-init", true); -+ -+ /** -+ * Key used to set the heartbeat interval in milliseconds (0 to disable = default) -+ */ -+ public static final Property HEARTBEAT_INTERVAL -+ = Property.duration("heartbeat-interval", Duration.ZERO); -+ -+ /** -+ * Key used to check the heartbeat request that should be sent to the server -+ */ -+ public static final Property HEARTBEAT_REQUEST -+ = Property.string("heartbeat-request", "keepalive@sshd.apache.org"); -+ -+ /** -+ * Key used to indicate that the heartbeat request is also expecting a reply - time in milliseconds to wait -+ * for the reply. If non-positive then no reply is expected (nor requested). -+ */ -+ public static final Property HEARTBEAT_REPLY_WAIT -+ = Property.durationSec("heartbeat-reply-wait", Duration.ZERO); -+ -+ /** -+ * Whether to ignore invalid identities files when pre-initializing the client session -+ * -+ * @see ClientIdentityLoader#isValidLocation(org.apache.sshd.common.NamedResource) -+ */ -+ public static final Property IGNORE_INVALID_IDENTITIES -+ = Property.bool("ignore-invalid-identities", true); -+ -+ /** -+ * Defines if we should abort in case we encounter an invalid (e.g. expired) openssh certificate. -+ */ -+ public static final Property ABORT_ON_INVALID_CERTIFICATE -+ = Property.bool("abort-on-invalid-certificate", false); -+ -+ /** -+ * As per RFC-4256: -+ * -+ * The language tag is deprecated and SHOULD be the empty string. It may be removed in a future revision of this -+ * specification. Instead, the server SHOULD select the language to be used based on the tags communicated during -+ * key exchange -+ */ -+ public static final Property INTERACTIVE_LANGUAGE_TAG -+ = Property.string("kb-client-interactive-language-tag", ""); -+ -+ /** -+ * As per RFC-4256: -+ * -+ * The submethods field is included so the user can give a hint of which actual methods he wants to use. It is a -+ * comma-separated list of authentication submethods (software or hardware) that the user prefers. If the client has -+ * knowledge of the submethods preferred by the user, presumably through a configuration setting, it MAY use the -+ * submethods field to pass this information to the server. Otherwise, it MUST send the empty string. -+ * -+ * The actual names of the submethods is something the user and the server need to agree upon. -+ * -+ * Server interpretation of the submethods field is implementation- dependent. -+ */ -+ public static final Property INTERACTIVE_SUBMETHODS -+ = Property.string("kb-client-interactive-sub-methods", ""); -+ -+ /** -+ * Configure whether reply for the "exec" request is required -+ */ -+ public static final Property REQUEST_EXEC_REPLY -+ = Property.bool("channel-exec-want-reply", false); -+ -+ /** -+ * On some platforms, a call to {@ode System.in.read(new byte[65536], 0, 32768)} always throws an -+ * {@link IOException}. So we need to protect against that and chunk the call into smaller calls. This problem was -+ * found on Windows, JDK 1.6.0_03-b05. -+ */ -+ public static final Property INPUT_STREAM_PUMP_CHUNK_SIZE -+ = Property.integer("stdin-pump-chunk-size", 1024); -+ -+ /** -+ * Configure whether reply for the "shell" request is required -+ */ -+ public static final Property REQUEST_SHELL_REPLY -+ = Property.bool("channel-shell-want-reply", false); -+ -+ /** -+ * Configure whether reply for the "subsystem&quoot; request is required -+ * -+ *

-+ * Default value for {@link #REQUEST_SUBSYSTEM_REPLY} - according to -+ * RFC4254 section 6.5: -+ *

-+ *

-+ * It is RECOMMENDED that the reply to these messages be requested and checked. -+ *

-+ */ -+ public static final Property REQUEST_SUBSYSTEM_REPLY -+ = Property.bool("channel-subsystem-want-reply", true); -+ -+ public static final Property PROP_DHGEX_CLIENT_MIN_KEY -+ = Property.integer("dhgex-client-min"); -+ -+ public static final Property PROP_DHGEX_CLIENT_MAX_KEY -+ = Property.integer("dhgex-client-max"); -+ -+ public static final Property PROP_DHGEX_CLIENT_PRF_KEY -+ = Property.integer("dhgex-client-prf"); -+ /** -+ * Key used to retrieve the value of the channel window size in the configuration properties map. -+ */ -+ public static final Property WINDOW_SIZE -+ = Property.long_("window-size", 0x200000L); -+ -+ /** -+ * Key used to retrieve timeout (msec.) to wait for data to become available when reading from a channel. If not set -+ * or non-positive then infinite value is assumed -+ */ -+ public static final Property WINDOW_TIMEOUT -+ = Property.duration("window-timeout", Duration.ZERO); -+ -+ /** -+ * Key used to retrieve the value of the maximum packet size in the configuration properties map. -+ */ -+ public static final Property MAX_PACKET_SIZE -+ = Property.long_("packet-size", 0x8000L); -+ -+ /** -+ * A safety value that is designed to avoid an attack that uses large channel packet sizes -+ */ -+ public static final Property LIMIT_PACKET_SIZE -+ = Property.long_("max-packet-size", Integer.MAX_VALUE / 4L); -+ -+ /** -+ * Number of NIO worker threads to use. -+ */ -+ public static final Property NIO_WORKERS -+ = Property.validating(Property.integer("nio-workers", Runtime.getRuntime().availableProcessors() + 1), -+ w -> ValidateUtils.checkTrue(w > 0, "Number of NIO workers must be positive: %d", w)); -+ /** -+ * Key used to retrieve the value of the timeout after which it will close the connection if the other side has not -+ * been authenticated - in milliseconds. -+ */ -+ public static final Property AUTH_TIMEOUT -+ = Property.duration("auth-timeout", Duration.ofMinutes(2)); -+ -+ /** -+ * Key used to retrieve the value of idle timeout after which it will close the connection - in milliseconds. -+ */ -+ public static final Property IDLE_TIMEOUT -+ = Property.duration("idle-timeout", Duration.ofMinutes(10)); -+ -+ /** -+ * Key used to retrieve the value of the socket read timeout for NIO2 session implementation - in milliseconds. -+ */ -+ public static final Property NIO2_READ_TIMEOUT -+ = Property.duration("nio2-read-timeout", IDLE_TIMEOUT.getRequiredDefault().plus(Duration.ofSeconds(15L))); -+ -+ /** -+ * Minimum NIO2 write wait timeout for a single outgoing packet - in milliseconds -+ */ -+ public static final Property NIO2_MIN_WRITE_TIMEOUT -+ = Property.duration("nio2-min-write-timeout", Duration.ofSeconds(30L)); -+ -+ /** -+ * Key used to retrieve the value of the disconnect timeout which is used when a disconnection is attempted. If the -+ * disconnect message has not been sent before the timeout, the underlying socket will be forcibly closed - in -+ * milliseconds. -+ */ -+ public static final Property DISCONNECT_TIMEOUT -+ = Property.duration("disconnect-timeout", Duration.ofSeconds(10)); -+ -+ /** -+ * Key used to configure the timeout used when writing a close request on a channel. If the message can not be -+ * written before the specified timeout elapses, the channel will be immediately closed. In milliseconds. -+ */ -+ public static final Property CHANNEL_CLOSE_TIMEOUT -+ = Property.duration("channel-close-timeout", Duration.ofSeconds(5)); -+ -+ /** -+ * Timeout (milliseconds) to wait for client / server stop request if immediate stop requested. -+ */ -+ public static final Property STOP_WAIT_TIME -+ = Property.duration("stop-wait-time", Duration.ofMinutes(1)); -+ -+ /** -+ * Socket backlog. See {@link java.nio.channels.AsynchronousServerSocketChannel#bind(java.net.SocketAddress, int)} -+ */ -+ public static final Property SOCKET_BACKLOG -+ = Property.integer("socket-backlog", 0); -+ -+ /** -+ * Socket keep-alive. See {@link java.net.StandardSocketOptions#SO_KEEPALIVE} -+ */ -+ public static final Property SOCKET_KEEPALIVE -+ = Property.bool("socket-keepalive", false); -+ -+ /** -+ * Socket send buffer size. See {@link java.net.StandardSocketOptions#SO_SNDBUF} -+ */ -+ public static final Property SOCKET_SNDBUF -+ = Property.integer("socket-sndbuf"); -+ -+ /** -+ * Socket receive buffer size. See {@link java.net.StandardSocketOptions#SO_RCVBUF} -+ */ -+ public static final Property SOCKET_RCVBUF -+ = Property.integer("socket-rcvbuf"); -+ -+ /** -+ * Socket reuse address. See {@link java.net.StandardSocketOptions#SO_REUSEADDR} -+ */ -+ public static final Property SOCKET_REUSEADDR -+ = Property.bool("socket-reuseaddr", true); -+ /** -+ * Socket linger. See {@link java.net.StandardSocketOptions#SO_LINGER} -+ */ -+ public static final Property SOCKET_LINGER -+ = Property.integer("socket-linger", -1); -+ -+ /** -+ * Socket tcp no-delay. See {@link java.net.StandardSocketOptions#TCP_NODELAY} -+ */ -+ public static final Property TCP_NODELAY -+ = Property.bool("tcp-nodelay", false); -+ -+ /** -+ * Read buffer size for NIO2 sessions See {@link org.apache.sshd.common.io.nio2.Nio2Session} -+ */ -+ public static final Property NIO2_READ_BUFFER_SIZE -+ = Property.integer("nio2-read-buf-size", 32 * 1024); -+ -+ /** -+ * Maximum allowed size of the initial identification text sent during the handshake -+ */ -+ public static final Property MAX_IDENTIFICATION_SIZE -+ = Property.integer("max-identification-size", 16 * 1024); -+ -+ /** -+ * Key re-exchange will be automatically performed after the session has sent or received the given amount of bytes. -+ * If non-positive, then disabled. -+ */ -+ public static final Property REKEY_BYTES_LIMIT -+ = Property.long_("rekey-bytes-limit", 1024L * 1024L * 1024L); // 1GB -+ -+ /** -+ * Key re-exchange will be automatically performed after the specified amount of time has elapsed since the last key -+ * exchange - in milliseconds. If non-positive then disabled. -+ * -+ * @see RFC4253 section 9 -+ */ -+ public static final Property REKEY_TIME_LIMIT -+ = Property.duration("rekey-time-limit", Duration.ofHours(1)); -+ -+ /** -+ * Key re-exchange will be automatically performed after the specified number of packets has been exchanged - -+ * positive 64-bit value. If non-positive then disabled. -+ * -+ * @see RFC4344 section 3.1 -+ */ -+ public static final Property REKEY_PACKETS_LIMIT -+ = Property.long_("rekey-packets-limit", 1L << 31); -+ -+ /** -+ * Key re-exchange will be automatically performed after the specified number of cipher blocks has been processed - -+ * positive 64-bit value. If non-positive then disabled. The default is calculated according to -+ * RFC4344 section 3.2 -+ */ -+ public static final Property REKEY_BLOCKS_LIMIT -+ = Property.long_("rekey-blocks-limit", 0L); -+ -+ /** -+ * Average number of packets to be skipped before an {@code SSH_MSG_IGNORE} message is inserted in the stream. If -+ * non-positive, then feature is disabled -+ * -+ * @see #IGNORE_MESSAGE_VARIANCE -+ * @see RFC4251 section 9.3.1 -+ */ -+ public static final Property IGNORE_MESSAGE_FREQUENCY -+ = Property.long_("ignore-message-frequency", 1024L); -+ -+ /** -+ * The variance to be used around the configured {@link #IGNORE_MESSAGE_FREQUENCY} value in order to avoid insertion -+ * at a set frequency. If zero, then exact frequency is used. If negative, then the absolute value is -+ * used. If greater or equal to the frequency, then assumed to be zero - i.e., no variance -+ * -+ * @see RFC4251 section 9.3.1 -+ */ -+ public static final Property IGNORE_MESSAGE_VARIANCE -+ = Property.integer("ignore-message-variance", 32); -+ -+ /** -+ * Minimum size of {@code SSH_MSG_IGNORE} payload to send if feature enabled. If non-positive then no message is -+ * sent. Otherwise, the actual size is between this size and twice its value -+ * -+ * @see RFC4251 section 9.3.1 -+ */ -+ public static final Property IGNORE_MESSAGE_SIZE -+ = Property.integer("ignore-message-size", 16); -+ -+ /** -+ * The request type of agent forwarding. The value may be {@value #AGENT_FORWARDING_TYPE_IETF} or -+ * {@value #AGENT_FORWARDING_TYPE_OPENSSH}. -+ */ -+ public static final String AGENT_FORWARDING_TYPE = "agent-fw-auth-type"; -+ -+ /** -+ * The agent forwarding type defined by IETF (https://tools.ietf.org/html/draft-ietf-secsh-agent-02). -+ */ -+ public static final String AGENT_FORWARDING_TYPE_IETF = "auth-agent-req"; -+ -+ /** -+ * The agent forwarding type defined by OpenSSH. -+ */ -+ public static final String AGENT_FORWARDING_TYPE_OPENSSH = "auth-agent-req@openssh.com"; -+ -+ /** -+ * Configure max. wait time (millis) to wait for space to become available -+ */ -+ public static final Property WAIT_FOR_SPACE_TIMEOUT -+ = Property.duration("channel-output-wait-for-space-timeout", Duration.ofSeconds(30L)); -+ -+ /** -+ * Used to configure the timeout (milliseconds) for receiving a response for the forwarding request -+ */ -+ public static final Property FORWARD_REQUEST_TIMEOUT -+ = Property.duration("tcpip-forward-request-timeout", Duration.ofSeconds(15L)); -+ -+ /** -+ * Property that can be used to configure max. allowed concurrent active channels -+ * -+ * @see org.apache.sshd.common.session.ConnectionService#registerChannel(Channel) -+ */ -+ public static final Property MAX_CONCURRENT_CHANNELS -+ = Property.integer("max-sshd-channels", Integer.MAX_VALUE); -+ -+ /** -+ * RFC4254 does not clearly specify how to handle {@code SSH_MSG_CHANNEL_DATA} and -+ * {@code SSH_MSG_CHANNEL_EXTENDED_DATA} received through an unknown channel. Therefore, we provide a configurable -+ * approach to it with the default set to ignore it. -+ */ -+ public static final Property SEND_REPLY_FOR_CHANNEL_DATA -+ = Property.bool("send-unknown-channel-data-reply", false); -+ -+ /** -+ * Key used to retrieve the value in the configuration properties map of the maximum number of failed authentication -+ * requests before the server closes the connection. -+ */ -+ public static final Property MAX_AUTH_REQUESTS -+ = Property.integer("max-auth-requests", 20); -+ -+ /** -+ * Key used to retrieve the value of welcome banner that will be displayed when a user connects to the server. If -+ * {@code null}/empty then no banner will be sent. The value can be one of the following: -+ *
    -+ *

    -+ *

  • A {@link java.io.File} or {@link java.nio.file.Path}, in which case its contents will be transmitted. -+ * Note: if the file is empty or does not exits, no banner will be transmitted.
  • -+ *

    -+ * -+ *

    -+ *

  • A {@link java.net.URI} or a string starting with "file:/", in which case it will be converted to a -+ * {@link java.nio.file.Path} and handled accordingly.
  • -+ *

    -+ * -+ *

    -+ *

  • A string containing a special value indicator - e.g., {@link #AUTO_WELCOME_BANNER_VALUE}, in which case the -+ * relevant banner content will be generated.
  • -+ *

    -+ * -+ *

    -+ *

  • Any other object whose {@code toString()} value yields a non empty string will be used as the banner -+ * contents.
  • -+ *

    -+ *
-+ * -+ * @see RFC-4252 section 5.4 -+ */ -+ public static final Property WELCOME_BANNER -+ = Property.object("welcome-banner"); -+ -+ /** -+ * Special value that can be set for the {@link #WELCOME_BANNER} property indicating that the server should generate -+ * a banner consisting of the random art of the server's keys (if any are provided). If no server keys are -+ * available, then no banner will be sent -+ */ -+ public static final String AUTO_WELCOME_BANNER_VALUE = "#auto-welcome-banner"; -+ -+ /** -+ * Key used to denote the language code for the welcome banner (if such a banner is configured). -+ */ -+ public static final Property WELCOME_BANNER_LANGUAGE -+ = Property.string("welcome-banner-language", "en"); -+ -+ /** -+ * The {@link WelcomeBannerPhase} value - either as an enum or a string -+ */ -+ public static final Property WELCOME_BANNER_PHASE -+ = Property.enum_("welcome-banner-phase", WelcomeBannerPhase.class, WelcomeBannerPhase.IMMEDIATE); -+ -+ /** -+ * The charset to use if the configured welcome banner points to a file - if not specified (either as a string or a -+ * {@link java.nio.charset.Charset} then the local default is used. -+ */ -+ public static final Property WELCOME_BANNER_CHARSET -+ = Property.charset("welcome-banner-charset", Charset.defaultCharset()); -+ -+ /** -+ * This key is used when configuring multi-step authentications. The value needs to be a blank separated list of -+ * comma separated list of authentication method names. For example, an argument of -+ * publickey,password publickey,keyboard-interactive would require the user to complete public key -+ * authentication, followed by either password or keyboard interactive authentication. Only methods that are next in -+ * one or more lists are offered at each stage, so for this example, it would not be possible to attempt password or -+ * keyboard-interactive authentication before public key. -+ */ -+ public static final Property AUTH_METHODS -+ = Property.string("auth-methods"); -+ -+ /** -+ * Key used to retrieve the value of the maximum concurrent open session count per username. If not set, then -+ * unlimited -+ */ -+ public static final Property MAX_CONCURRENT_SESSIONS -+ = Property.integer("max-concurrent-sessions"); -+ -+ /** -+ * Key used to retrieve any extra lines to be sent during initial protocol handshake before the -+ * identification. The configured string value should use {@value #SERVER_EXTRA_IDENT_LINES_SEPARATOR} character to -+ * denote line breaks -+ */ -+ public static final Property SERVER_EXTRA_IDENTIFICATION_LINES -+ = Property.string("server-extra-identification-lines"); -+ -+ /** -+ * Separator used in the {@link #SERVER_EXTRA_IDENTIFICATION_LINES} configuration string to indicate new line break -+ */ -+ public static final char SERVER_EXTRA_IDENT_LINES_SEPARATOR = '|'; -+ -+ /** -+ * Key used to retrieve the value of the server identification string. If set, then it is appended to the -+ * (standard) "SSH-2.0-" prefix. Otherwise a default is sent that consists of "SSH-2.0-" plus -+ * the current SSHD artifact name and version in uppercase - e.g., "SSH-2.0-APACHE-SSHD-1.0.0" -+ */ -+ public static final Property SERVER_IDENTIFICATION -+ = Property.string("server-identification"); -+ -+ /** -+ * Key used to configure the timeout used when receiving a close request on a channel to wait until the command -+ * cleanly exits after setting an EOF on the input stream. -+ */ -+ public static final Property COMMAND_EXIT_TIMEOUT -+ = Property.duration("command-exit-timeout", Duration.ofMillis(5L)); -+ -+ /** -+ * A URL pointing to the moduli file. If not specified, the default internal file will be used. -+ */ -+ public static final Property MODULI_URL -+ = Property.string("moduli-url"); -+ -+ /** -+ * See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}. -+ */ -+ public static final Property KB_SERVER_INTERACTIVE_NAME -+ = Property.string("kb-server-interactive-name", "Password authentication"); -+ -+ /** -+ * See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}. -+ */ -+ public static final Property KB_SERVER_INTERACTIVE_INSTRUCTION -+ = Property.string("kb-server-interactive-instruction", ""); -+ -+ /** -+ * See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}. -+ */ -+ public static final Property KB_SERVER_INTERACTIVE_LANG -+ = Property.string("kb-server-interactive-language", "en-US"); -+ -+ /** -+ * See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}. -+ */ -+ public static final Property KB_SERVER_INTERACTIVE_PROMPT -+ = Property.string("kb-server-interactive-prompt", "Password: "); -+ -+ /** -+ * See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}. -+ */ -+ public static final Property KB_SERVER_INTERACTIVE_ECHO_PROMPT -+ = Property.bool("kb-server-interactive-echo-prompt", false); -+ -+ /** -+ * Maximum amount of extended (a.k.a. STDERR) data allowed to be accumulated until a {@link ChannelDataReceiver} for -+ * the data is registered -+ */ -+ public static final Property MAX_EXTDATA_BUFSIZE -+ = Property.integer("channel-session-max-extdata-bufsize", 0); -+ -+ /** -+ * See {@link org.apache.sshd.server.kex.DHGEXServer}. -+ */ -+ public static final Property PROP_DHGEX_SERVER_MIN_KEY -+ = Property.integer("dhgex-server-min"); -+ -+ /** -+ * See {@link org.apache.sshd.server.kex.DHGEXServer}. -+ */ -+ public static final Property PROP_DHGEX_SERVER_MAX_KEY -+ = Property.integer("dhgex-server-max"); -+ /** -+ * Value used by the {@link org.apache.sshd.server.shell.InvertedShellWrapper} to control the "busy-wait" -+ * sleep time (millis) on the pumping loop if nothing was pumped - must be positive. -+ */ -+ public static final Property PUMP_SLEEP_TIME -+ = Property.duration("inverted-shell-wrapper-pump-sleep", Duration.ofMillis(1)); -+ -+ /** -+ * Value used by the {@link org.apache.sshd.server.shell.InvertedShellWrapper} to control copy buffer size. -+ */ -+ public static final Property BUFFER_SIZE -+ = Property.integer("inverted-shell-wrapper-buffer-size", IoUtils.DEFAULT_COPY_SIZE); -+ -+ /** -+ * Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the channel open -+ * timeout. -+ */ -+ public static final Property X11_OPEN_TIMEOUT -+ = Property.duration("x11-fwd-open-timeout", Duration.ofSeconds(30L)); -+ -+ /** -+ * Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control from which X11 -+ * display number to start looking for a free value. -+ */ -+ public static final Property X11_DISPLAY_OFFSET -+ = Property.integer("x11-fwd-display-offset", 10); -+ -+ /** -+ * Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control up to which (but not -+ * including) X11 display number to look or a free value. -+ */ -+ public static final Property X11_MAX_DISPLAYS -+ = Property.integer("x11-fwd-max-display", 1000); -+ -+ /** -+ * Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the base port number -+ * for the X11 display number socket binding. -+ */ -+ public static final Property X11_BASE_PORT -+ = Property.integer("x11-fwd-base-port", 6000); -+ -+ /** -+ * Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the host used to bind -+ * to for the X11 display when looking for a free port. -+ */ -+ public static final Property X11_BIND_HOST -+ = Property.string("x11-fwd-bind-host", SshdSocketAddress.LOCALHOST_IPV4); -+ -+ private CoreModuleProperties() { -+ // private -+ } -+ -+} --- -2.27.0 - diff --git a/CVE-2021-30129-2.patch b/CVE-2021-30129-2.patch deleted file mode 100644 index 8138582..0000000 --- a/CVE-2021-30129-2.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 5b5bd1dcfa0c2fc250e079e1ebcd643b51f735eb Mon Sep 17 00:00:00 2001 -From: Lyor Goldstein -Date: Fri, 26 Feb 2021 06:54:43 +0200 -Subject: [PATCH] [SSHD-1125] Added option to require immediate close of - channel in command ExitCallback invocation - ---- - .../org/apache/sshd/server/ExitCallback.java | 27 +++++++++++++++++-- - .../sshd/server/channel/ChannelSession.java | 10 +++---- - .../sshd/util/test/BogusExitCallback.java | 12 ++++++--- - .../server/subsystem/sftp/SftpSubsystem.java | 6 +++-- - 4 files changed, 43 insertions(+), 12 deletions(-) - -diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ExitCallback.java b/sshd-core/src/main/java/org/apache/sshd/server/ExitCallback.java -index dfa55be..eb1bca1 100644 ---- a/sshd-core/src/main/java/org/apache/sshd/server/ExitCallback.java -+++ b/sshd-core/src/main/java/org/apache/sshd/server/ExitCallback.java -@@ -30,7 +30,17 @@ public interface ExitCallback { - * @param exitValue the exit value - */ - default void onExit(int exitValue) { -- onExit(exitValue, ""); -+ onExit(exitValue, false); -+ } -+ -+ /** -+ * Informs the SSH server that the shell has exited -+ * -+ * @param exitValue the exit value -+ * @param closeImmediately whether to also terminate the channel immediately or do a graceful close. -+ */ -+ default void onExit(int exitValue, boolean closeImmediately) { -+ onExit(exitValue, "", closeImmediately); - } - - /** -@@ -39,5 +49,18 @@ public interface ExitCallback { - * @param exitValue the exit value - * @param exitMessage exit value description - */ -- void onExit(int exitValue, String exitMessage); -+ default void onExit(int exitValue, String exitMessage) { -+ onExit(exitValue, exitMessage, false); -+ } -+ -+ /** -+ * -+ * Informs the SSH client/server that the shell has exited -+ * -+ * @param exitValue the exit value -+ * @param exitMessage exit value description -+ * @param closeImmediately whether to also terminate the channel immediately or do a graceful close. -+ */ -+ void onExit(int exitValue, String exitMessage, boolean closeImmediately); -+ - } -diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java -index e54e0e4..484b4f0 100644 ---- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java -+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java -@@ -684,9 +684,9 @@ public class ChannelSession extends AbstractServerChannel { - tempBuffer = null; - doWriteData(buffer.array(), buffer.rpos(), buffer.available()); - } -- command.setExitCallback((exitValue, exitMessage) -> { -+ command.setExitCallback((exitValue, exitMessage, closeImmediately) -> { - try { -- closeShell(exitValue); -+ closeShell(exitValue, closeImmediately); - if (log.isDebugEnabled()) { - log.debug("onExit({}) code={} message='{}' shell closed", ChannelSession.this, exitValue, exitMessage); - } -@@ -798,9 +798,9 @@ public class ChannelSession extends AbstractServerChannel { - return env; - } - -- protected void closeShell(int exitValue) throws IOException { -+ protected void closeShell(int exitValue, boolean closeImmediately) throws IOException { - if (log.isDebugEnabled()) { -- log.debug("closeShell({}) exit code={}", this, exitValue); -+ log.debug("closeShell({}) exit code={}, immediate={}", this, exitValue, closeImmediately); - } - - if (!isClosing()) { -@@ -810,7 +810,7 @@ public class ChannelSession extends AbstractServerChannel { - sendEof(); - sendExitStatus(exitValue); - commandExitFuture.setClosed(); -- close(false); -+ close(closeImmediately); - } else { - commandExitFuture.setClosed(); - } -diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java -index a4f1ff6..9de602a 100644 ---- a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java -+++ b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java -@@ -25,21 +25,23 @@ public class BogusExitCallback implements ExitCallback { - private boolean exited; - private int exitValue; - private String exitMessage; -+ private boolean closeImmediately; - - public BogusExitCallback() { - super(); - } - - @Override -- public void onExit(int exitValue) { -- onExit(exitValue, String.valueOf(exitValue)); -+ public void onExit(int exitValue, boolean closeImmediately) { -+ onExit(exitValue, String.valueOf(exitValue), closeImmediately); - } - - @Override -- public void onExit(int exitValue, String exitMessage) { -+ public void onExit(int exitValue, String exitMessage, boolean closeImmediately) { - this.exited = true; - this.exitValue = exitValue; - this.exitMessage = exitMessage; -+ this.closeImmediately = closeImmediately; - } - - public boolean isExited() { -@@ -53,4 +55,8 @@ public class BogusExitCallback implements ExitCallback { - public String getExitMessage() { - return exitMessage; - } -+ -+ public boolean isCloseImmediately() { -+ return closeImmediately; -+ } - } -diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -index 66a0ced..c18b55e 100644 ---- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -@@ -299,6 +299,7 @@ public class SftpSubsystem - - @Override - public void run() { -+ int exitCode = 0; - try { - while (true) { - Buffer buffer = requests.take(); -@@ -318,10 +319,11 @@ public class SftpSubsystem - if (log.isDebugEnabled()) { - log.debug("run(" + session + ") caught exception details", t); - } -+ exitCode = -1; - } - } finally { - closeAllHandles(); -- callback.onExit(0); -+ callback.onExit(exitCode, exitCode != 0); - } - } - --- -2.27.0 - diff --git a/CVE-2021-30129-3.patch b/CVE-2021-30129-3.patch deleted file mode 100644 index 722ea2b..0000000 --- a/CVE-2021-30129-3.patch +++ /dev/null @@ -1,408 +0,0 @@ -From f9b2f236e6a663011b50bd7e9a41ec90e6b94831 Mon Sep 17 00:00:00 2001 -From: Lyor Goldstein -Date: Thu, 25 Feb 2021 21:05:49 +0200 -Subject: [PATCH] [SSHD-1125] Added mechanism to throttle pending write - requests in BufferedIoOutputStream - ---- - .../channel/BufferedIoOutputStream.java | 187 ++++++++++++++++-- - .../SshChannelBufferedOutputException.java | 41 ++++ - .../sshd/core/CoreModuleProperties.java | 19 ++ - .../sshd/util/test/AsyncEchoShellFactory.java | 13 +- - .../server/subsystem/sftp/SftpSubsystem.java | 3 +- - 5 files changed, 243 insertions(+), 20 deletions(-) - create mode 100644 sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java - -diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java -index 1cb75aa..c95a449 100644 ---- a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java -+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java -@@ -20,29 +20,55 @@ package org.apache.sshd.common.channel; - - import java.io.EOFException; - import java.io.IOException; -+import java.time.Duration; -+import java.util.Objects; - import java.util.Queue; - import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; - import java.util.concurrent.atomic.AtomicReference; - - import org.apache.sshd.common.Closeable; -+import org.apache.sshd.common.PropertyResolver; -+import org.apache.sshd.common.channel.exception.SshChannelBufferedOutputException; - import org.apache.sshd.common.future.SshFutureListener; - import org.apache.sshd.common.io.IoOutputStream; - import org.apache.sshd.common.io.IoWriteFuture; -+import org.apache.sshd.common.util.GenericUtils; -+import org.apache.sshd.common.util.ValidateUtils; - import org.apache.sshd.common.util.buffer.Buffer; - import org.apache.sshd.common.util.closeable.AbstractInnerCloseable; -+import org.apache.sshd.core.CoreModuleProperties; - - /** - * An {@link IoOutputStream} capable of queuing write requests - */ - public class BufferedIoOutputStream extends AbstractInnerCloseable implements IoOutputStream { -+ protected final Object id; -+ protected final int channelId; -+ protected final int maxPendingBytesCount; -+ protected final Duration maxWaitForPendingWrites; - protected final IoOutputStream out; -+ protected final AtomicInteger pendingBytesCount = new AtomicInteger(); -+ protected final AtomicLong writtenBytesCount = new AtomicLong(); - protected final Queue writes = new ConcurrentLinkedQueue<>(); - protected final AtomicReference currentWrite = new AtomicReference<>(); -- protected final Object id; -+ protected final AtomicReference pendingException = new AtomicReference<>(); - -- public BufferedIoOutputStream(Object id, IoOutputStream out) { -- this.out = out; -- this.id = id; -+ public BufferedIoOutputStream(Object id, int channelId, IoOutputStream out, PropertyResolver resolver) { -+ this(id, channelId, out, CoreModuleProperties.BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_SIZE.getRequired(resolver), -+ CoreModuleProperties.BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_WAIT.getRequired(resolver)); -+ } -+ -+ public BufferedIoOutputStream( -+ Object id, int channelId, IoOutputStream out, int maxPendingBytesCount, -+ Duration maxWaitForPendingWrites) { -+ this.id = Objects.requireNonNull(id, "No stream identifier provided"); -+ this.channelId = channelId; -+ this.out = Objects.requireNonNull(out, "No delegate output stream provided"); -+ this.maxPendingBytesCount = maxPendingBytesCount; -+ ValidateUtils.checkTrue(maxPendingBytesCount > 0, "Invalid max. pending bytes count: %d", maxPendingBytesCount); -+ this.maxWaitForPendingWrites = Objects.requireNonNull(maxWaitForPendingWrites, "No max. pending time value provided"); - } - - public Object getId() { -@@ -52,26 +78,114 @@ public class BufferedIoOutputStream extends AbstractInnerCloseable implements Io - @Override - public IoWriteFuture writePacket(Buffer buffer) throws IOException { - if (isClosing()) { -- throw new EOFException("Closed"); -+ throw new EOFException("Closed/ing - state=" + state); - } - -+ waitForAvailableWriteSpace(buffer.available()); -+ - IoWriteFutureImpl future = new IoWriteFutureImpl(getId(), buffer); - writes.add(future); - startWriting(); - return future; - } - -+ protected void waitForAvailableWriteSpace(int requiredSize) throws IOException { -+ /* -+ * NOTE: this code allows a single pending write to give this mechanism "the slip" and -+ * exit the loop "unscathed" even though there is a pending exception. However, the goal -+ * here is to avoid an OOM by having an unlimited accumulation of pending write requests -+ * due to fact that the peer is not consuming the sent data. Please note that the pending -+ * exception is "sticky" - i.e., the next write attempt will fail. This also means that if -+ * the write request that "got away" was the last one by chance and it was consumed by the -+ * peer there will be no exception thrown - which is also fine since as mentioned the goal -+ * is not to enforce a strict limit on the pending bytes size but rather on the accumulation -+ * of the pending write requests. -+ * -+ * We could have counted pending requests rather than bytes. However, we also want to avoid -+ * having a large amount of data pending consumption by the peer as well. This code strikes -+ * such a balance by allowing a single pending request to exceed the limit, but at the same -+ * time prevents too many bytes from pending by having a bunch of pending requests that while -+ * below the imposed number limit may cumulatively represent a lot of pending bytes. -+ */ -+ -+ long expireTime = System.currentTimeMillis() + maxWaitForPendingWrites.toMillis(); -+ synchronized (pendingBytesCount) { -+ for (int count = pendingBytesCount.get(); -+ /* -+ * The (count > 0) condition is put in place to allow a single pending -+ * write to exceed the maxPendingBytesCount as long as there are no -+ * other pending ones. -+ */ -+ (count > 0) -+ // Not already over the limit or about to be over it -+ && ((count + requiredSize) > maxPendingBytesCount) -+ // No pending exception signaled -+ && (pendingException.get() == null); -+ count = pendingBytesCount.get()) { -+ long remTime = expireTime - System.currentTimeMillis(); -+ if (remTime <= 0L) { -+ pendingException.compareAndSet(null, -+ new SshChannelBufferedOutputException( -+ channelId, -+ "Max. pending write timeout expired after " + writtenBytesCount + " bytes")); -+ throw pendingException.get(); -+ } -+ -+ try { -+ pendingBytesCount.wait(remTime); -+ } catch (InterruptedException e) { -+ pendingException.compareAndSet(null, -+ new SshChannelBufferedOutputException( -+ channelId, -+ "Waiting for pending writes interrupted after " + writtenBytesCount + " bytes")); -+ throw pendingException.get(); -+ } -+ } -+ -+ IOException e = pendingException.get(); -+ if (e != null) { -+ throw e; -+ } -+ -+ pendingBytesCount.addAndGet(requiredSize); -+ } -+ } -+ - protected void startWriting() throws IOException { - IoWriteFutureImpl future = writes.peek(); -+ // No more pending requests - if (future == null) { - return; - } - -+ // Don't try to write any further if pending exception signaled -+ Throwable pendingError = pendingException.get(); -+ if (pendingError != null) { -+ log.error("startWriting({})[{}] propagate to {} write requests pending error={}[{}]", -+ getId(), out, writes.size(), getClass().getSimpleName(), pendingError.getMessage()); -+ -+ IoWriteFutureImpl currentFuture = currentWrite.getAndSet(null); -+ for (IoWriteFutureImpl pendingWrite : writes) { -+ // Checking reference by design -+ if (GenericUtils.isSameReference(pendingWrite, currentFuture)) { -+ continue; // will be taken care of when its listener is eventually called -+ } -+ -+ future.setValue(pendingError); -+ } -+ -+ writes.clear(); -+ return; -+ } -+ -+ // Cannot honor this request yet since other pending one incomplete - if (!currentWrite.compareAndSet(null, future)) { - return; - } - -- out.writePacket(future.getBuffer()).addListener(new SshFutureListener() { -+ Buffer buffer = future.getBuffer(); -+ int bufferSize = buffer.available(); -+ out.writePacket(buffer).addListener(new SshFutureListener() { - @Override - public void operationComplete(IoWriteFuture f) { - if (f.isWritten()) { -@@ -79,32 +193,71 @@ public class BufferedIoOutputStream extends AbstractInnerCloseable implements Io - } else { - future.setValue(f.getException()); - } -- finishWrite(); -+ finishWrite(future, bufferSize); -+ } -+ }); -+ } -+ -+ protected void finishWrite(IoWriteFutureImpl future, int bufferSize) { -+ /* -+ * Update the pending bytes count only if successfully written, -+ * otherwise signal an error -+ */ -+ if (future.isWritten()) { -+ long writtenSize = writtenBytesCount.addAndGet(bufferSize); -+ int stillPending; -+ synchronized (pendingBytesCount) { -+ stillPending = pendingBytesCount.addAndGet(0 - bufferSize); -+ pendingBytesCount.notifyAll(); - } - -- @SuppressWarnings("synthetic-access") -- private void finishWrite() { -+ /* -+ * NOTE: since the pending exception is updated outside the synchronized block -+ * a pending write could be successfully enqueued, however this is acceptable -+ * - see comment in waitForAvailableWriteSpace -+ */ -+ if (stillPending < 0) { -+ log.error("finishWrite({})[{}] - pending byte counts underflow ({}) after {} bytes", getId(), out, stillPending, -+ writtenSize); -+ pendingException.compareAndSet(null, -+ new SshChannelBufferedOutputException(channelId, "Pending byte counts underflow")); -+ } -+ } else { -+ Throwable t = future.getException(); -+ if (t instanceof SshChannelBufferedOutputException) { -+ pendingException.compareAndSet(null, (SshChannelBufferedOutputException) t); -+ } else { -+ pendingException.compareAndSet(null, new SshChannelBufferedOutputException(channelId, t)); -+ } -+ -+ // In case someone waiting so that they can detect the exception -+ synchronized (pendingBytesCount) { -+ pendingBytesCount.notifyAll(); -+ } -+ } -+ - writes.remove(future); - currentWrite.compareAndSet(future, null); - try { - startWriting(); - } catch (IOException e) { -- log.error("finishWrite({}) failed ({}) re-start writing", out, e.getClass().getSimpleName()); -+ if (e instanceof SshChannelBufferedOutputException) { -+ pendingException.compareAndSet(null, (SshChannelBufferedOutputException) e); -+ } else { -+ pendingException.compareAndSet(null, new SshChannelBufferedOutputException(channelId, e)); -+ } -+ log.error("finishWrite({})[{}] failed ({}) re-start writing: {}", -+ getId(), out, e.getClass().getSimpleName(), e.getMessage(), e); - } - } -- }); -- } - - @Override - protected Closeable getInnerCloseable() { -- return builder() -- .when(getId(), writes) -- .close(out) -- .build(); -+ return builder().when(getId(), writes).close(out).build(); - } - - @Override - public String toString() { -- return getClass().getSimpleName() + "[" + out + "]"; -+ return getClass().getSimpleName() + "(" + getId() + ")[" + out + "]"; - } - } -diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java -new file mode 100644 -index 0000000..97e6105 ---- /dev/null -+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelBufferedOutputException.java -@@ -0,0 +1,41 @@ -+/* -+ * 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.channel.exception; -+ -+/** -+ * Used by the {@code BufferedIoOutputStream} to signal a non-recoverable error -+ * -+ * @author Apache MINA SSHD Project -+ */ -+public class SshChannelBufferedOutputException extends SshChannelException { -+ private static final long serialVersionUID = -8663890657820958046L; -+ -+ public SshChannelBufferedOutputException(int channelId, String message) { -+ this(channelId, message, null); -+ } -+ -+ public SshChannelBufferedOutputException(int channelId, Throwable cause) { -+ this(channelId, cause.getMessage(), cause); -+ } -+ -+ public SshChannelBufferedOutputException(int channelId, String message, Throwable cause) { -+ super(channelId, message, cause); -+ } -+} -diff --git a/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java b/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java -index 9e9b2d2..0d122e5 100644 ---- a/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java -+++ b/sshd-core/src/main/java/org/apache/sshd/core/CoreModuleProperties.java -@@ -24,6 +24,7 @@ import java.time.Duration; - - import org.apache.sshd.client.config.keys.ClientIdentityLoader; - import org.apache.sshd.common.Property; -+import org.apache.sshd.common.SshConstants; - import org.apache.sshd.common.channel.Channel; - import org.apache.sshd.common.session.Session; - import org.apache.sshd.common.util.OsUtils; -@@ -240,6 +241,24 @@ public final class CoreModuleProperties { - public static final Property WINDOW_TIMEOUT - = Property.duration("window-timeout", Duration.ZERO); - -+ /** -+ * Key used when creating a {@code BufferedIoOutputStream} in order to specify max. allowed unwritten pending bytes. -+ * If this value is exceeded then the code waits up to {@link #BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_WAIT} for the -+ * pending data to be written and thus make room for the new request. -+ */ -+ public static final Property BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_SIZE -+ = Property.integer("buffered-io-output-max-pending-write-size", -+ SshConstants.SSH_REQUIRED_PAYLOAD_PACKET_LENGTH_SUPPORT * 8); -+ -+ /** -+ * Key used when creating a {@code BufferedIoOutputStream} in order to specify max. wait time (msec.) for pending -+ * writes to be completed before enqueuing a new request -+ * -+ * @see #BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_SIZE -+ */ -+ public static final Property BUFFERED_IO_OUTPUT_MAX_PENDING_WRITE_WAIT -+ = Property.duration("buffered-io-output-max-pending-write-wait", Duration.ofSeconds(30L)); -+ - /** - * Key used to retrieve the value of the maximum packet size in the configuration properties map. - */ -diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java b/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java -index de9dbf4..465ff83 100644 ---- a/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java -+++ b/sshd-core/src/test/java/org/apache/sshd/util/test/AsyncEchoShellFactory.java -@@ -99,12 +99,21 @@ public class AsyncEchoShellFactory implements ShellFactory { - - @Override - public void setIoOutputStream(IoOutputStream out) { -- this.out = new BufferedIoOutputStream("STDOUT", out); -+ this.out = wrapOutputStream("SHELL-STDOUT", out); - } - - @Override - public void setIoErrorStream(IoOutputStream err) { -- this.err = new BufferedIoOutputStream("STDERR", err); -+ this.err = wrapOutputStream("SHELL-STDERR", err); -+ } -+ -+ protected BufferedIoOutputStream wrapOutputStream(String prefix, IoOutputStream stream) { -+ if (stream instanceof BufferedIoOutputStream) { -+ return (BufferedIoOutputStream) stream; -+ } -+ -+ int channelId = session.getId(); -+ return new BufferedIoOutputStream(prefix + "@" + channelId, channelId, stream, session); - } - - @Override -diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -index 66a0ced..15201ec 100644 ---- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -+++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java -@@ -256,7 +256,8 @@ public class SftpSubsystem - - @Override - public void setIoOutputStream(IoOutputStream out) { -- this.out = new BufferedIoOutputStream("sftp out buffer", out); -+ int channelId = channelSession.getId(); -+ this.out = new BufferedIoOutputStream("sftp-out@" + channelId, channelId, out, channelSession); - } - - @Override --- -2.27.0 - diff --git a/apache-sshd-2.2.0-src.tar.gz b/apache-sshd-2.2.0-src.tar.gz deleted file mode 100644 index d4fe2cf..0000000 Binary files a/apache-sshd-2.2.0-src.tar.gz and /dev/null differ diff --git a/apache-sshd-2.9.2-src.tar.gz b/apache-sshd-2.9.2-src.tar.gz new file mode 100644 index 0000000..ef94ea5 Binary files /dev/null and b/apache-sshd-2.9.2-src.tar.gz differ diff --git a/apache-sshd-javadoc.patch b/apache-sshd-javadoc.patch new file mode 100644 index 0000000..b676699 --- /dev/null +++ b/apache-sshd-javadoc.patch @@ -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 "empty" implementation of {@link PasswordIdentityProvider} that returns an empty group of passwords ++ * An "empty" 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 - key is success indicator, value is actual fingerprint, ++ * @return SimpleImmutableEntry<Boolean, String> - 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 - key is success indicator, value is actual fingerprint, ++ * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint, + * {@code null} if no key. + */ + public static SimpleImmutableEntry 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 - key is success indicator, value is actual fingerprint, ++ * @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint, + * {@code null} if no key. + */ + public static SimpleImmutableEntry 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 OpenSSH +- * key file(s) ++ * Basic support for OpenSSH key file(s) + * + * @author Apache MINA SSHD Project + */ +--- 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., "ssh-rsa", "ssh-dss" ++ * @param keyType The key type - e.g., "ssh-rsa", "ssh-dss" + * @return {@code true} if this key type is supported by the parser + */ + boolean isKeyTypeSupported(String keyType); + + /** +- * @param keyType The key type - e.g., "ssh-rsa", "ssh-dss" ++ * @param keyType The key type - e.g., "ssh-rsa", "ssh-dss" + * @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 -1 if no maximum + * @return the text with any replacements processed +- * @author Arnout J. Kuiper ajkuiper@wxs.nl +- * @author Magesh Umasankar +- * @author Bruce Atherton +- * @author Antoine Levy-Lambert ++ * ++ * author Arnout J. Kuiper ajkuiper@wxs.nl ++ * author Magesh Umasankar ++ * author Bruce Atherton ++ * author Antoine Levy-Lambert + */ + @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 < 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 < 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 "(User);" suffix ++ * Remove {@code Windows} domain and/or group prefix as well as "(User);" 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 + * RFC 4419 section 3: "Servers and clients SHOULD support +- * groups with a modulus length of k bits, where 1024 <= k <= 8192". ++ * groups with a modulus length of k bits, where 1024 <= k <= 8192". + * + * Note: this has been amended by RFC 8270 + */ +--- 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 before the actual +- * SSH protocol is executed - e.g., the PROXY +- * protocol. The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the ++ * SSH protocol is executed - e.g., the PROXY protocol. ++ * The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the + * meta-data. + * + * @author Apache MINA SSHD Project +--- 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 +- * ssh_config(5) ++ * ssh_config(5) + */ + public static final List DEFAULT_CIPHERS_PREFERENCE = Collections.unmodifiableList( + Arrays.asList( +@@ -83,7 +83,7 @@ + + /** + * The default {@link BuiltinDHFactories} setup in order of preference as specified by +- * ssh_config(5) ++ * ssh_config(5) + */ + public static final List DEFAULT_KEX_PREFERENCE = Collections.unmodifiableList( + Arrays.asList( +@@ -104,7 +104,7 @@ + + /** + * The default {@link BuiltinMacs} setup in order of preference as specified by +- * ssh_config(5) ++ * ssh_config(5) + */ + public static final List 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. + *

+ * 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. kexFlushed 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. + * + *

+- *
want-reply == true && replyHandler != null
++ *
want-reply == true && replyHandler != null
+ *
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.
+- *
want-reply == true && replyHandler == null
++ *
want-reply == true && replyHandler == null
+ *
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.
+ *
want-reply == false
+--- 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 before the actual +- * SSH protocol is executed - e.g., the PROXY +- * protocol. ++ * SSH protocol is executed - e.g., the PROXY protocol. + * + * @author Apache MINA SSHD Project + */ diff --git a/apache-sshd.spec b/apache-sshd.spec index 235d0a6..1dc32a2 100644 --- a/apache-sshd.spec +++ b/apache-sshd.spec @@ -1,15 +1,13 @@ Epoch: 1 Name: apache-sshd -Version: 2.2.0 -Release: 2 +Version: 2.9.2 +Release: 1 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: CVE-2021-30129-1.patch -Patch2: CVE-2021-30129-2.patch -Patch3: CVE-2021-30129-3.patch +Patch1: apache-sshd-javadoc.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) @@ -22,6 +20,7 @@ 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 @@ -36,10 +35,9 @@ This package provides %{name}. %setup -q %patch0 -p1 %patch1 -p1 -%patch2 -p1 -%patch3 -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 @@ -50,11 +48,13 @@ rm -rf sshd-core/src/main/java/org/apache/sshd/agent/unix %pom_disable_module sshd-cli %pom_disable_module sshd-openpgp %pom_remove_plugin :apache-rat-plugin -%pom_remove_plugin :groovy-maven-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" . %build @@ -71,6 +71,9 @@ rm -rf sshd-core/src/main/java/org/apache/sshd/agent/unix %license LICENSE.txt NOTICE.txt assembly/src/main/legal/licenses/jbcrypt.txt %changelog +* Mon Nov 21 2022 liangqifeng - 1:2.9.2-1 +- Fix CVE-2022-45047 + * Tue Aug 10 2021 yaoxin - 2.2.0-2 - Fix CVE-2021-30129