This is an automated email from the ASF dual-hosted git repository. lgoldstein pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit 32f9eb6943dd8abc19a23dfd70fd60e8d3f558e2 Author: Lyor Goldstein <lgoldst...@apache.org> AuthorDate: Thu Oct 17 13:50:49 2019 +0300 [SSHD-842] Updated hierarchy of ServerSessionHolder(s) --- .../sshd/client/session/ClientUserAuthService.java | 21 ++++++++------- .../main/java/org/apache/sshd/common/Service.java | 5 ++-- .../java/org/apache/sshd/server/auth/UserAuth.java | 1 - .../sshd/server/channel/AbstractServerChannel.java | 7 ----- .../apache/sshd/server/channel/ServerChannel.java | 6 ++++- .../server/command/AbstractCommandSupport.java | 31 +++++++++++++++------- .../server/kex/AbstractDHServerKeyExchange.java | 12 ++++++--- .../apache/sshd/server/shell/InvertedShell.java | 15 ++++++++++- .../org/apache/sshd/server/shell/ProcessShell.java | 23 +++++++++------- .../server/shell/InvertedShellWrapperTest.java | 28 ++++++++++++++++--- .../apache/sshd/util/test/BogusInvertedShell.java | 4 +-- .../subsystem/sftp/SftpSubsystemEnvironment.java | 9 ++++++- 12 files changed, 108 insertions(+), 54 deletions(-) diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java index cccbc87..5c00c6a 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java @@ -41,7 +41,6 @@ import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; import org.apache.sshd.common.auth.UserAuthMethodFactory; import org.apache.sshd.common.session.Session; -import org.apache.sshd.common.session.SessionHolder; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -52,10 +51,7 @@ import org.apache.sshd.common.util.closeable.AbstractCloseable; * * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public class ClientUserAuthService - extends AbstractCloseable - implements Service, SessionHolder<ClientSession>, ClientSessionHolder { - +public class ClientUserAuthService extends AbstractCloseable implements Service, ClientSessionHolder { /** * The AuthFuture that is being used by the current auth request. This encodes the state. * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating. @@ -144,7 +140,8 @@ public class ClientUserAuthService log.debug("auth({})[{}] request new authentication", session, service); } } else { - currentFuture.setException(new InterruptedIOException("New authentication started before previous completed")); + currentFuture.setException( + new InterruptedIOException("New authentication started before previous completed")); } } @@ -240,7 +237,8 @@ public class ClientUserAuthService session.setAuthenticated(); ((ClientSessionImpl) session).switchToNextService(); - AuthFuture authFuture = Objects.requireNonNull(authFutureHolder.get(), "No current future"); + AuthFuture authFuture = + Objects.requireNonNull(authFutureHolder.get(), "No current future"); // Will wake up anyone sitting in waitFor authFuture.setAuthed(true); return; @@ -270,7 +268,8 @@ public class ClientUserAuthService } if (userAuth == null) { - throw new IllegalStateException("Received unknown packet: " + SshConstants.getCommandMessageName(cmd)); + throw new IllegalStateException( + "Received unknown packet: " + SshConstants.getCommandMessageName(cmd)); } if (log.isDebugEnabled()) { @@ -328,9 +327,11 @@ public class ClientUserAuthService } // also wake up anyone sitting in waitFor - AuthFuture authFuture = Objects.requireNonNull(authFutureHolder.get(), "No current future"); + AuthFuture authFuture = + Objects.requireNonNull(authFutureHolder.get(), "No current future"); authFuture.setException(new SshException( - SshConstants.SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, "No more authentication methods available")); + SshConstants.SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, + "No more authentication methods available")); return; } diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Service.java b/sshd-core/src/main/java/org/apache/sshd/common/Service.java index 69426e9..2ebc41c 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/Service.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/Service.java @@ -19,6 +19,7 @@ package org.apache.sshd.common; import org.apache.sshd.common.session.Session; +import org.apache.sshd.common.session.SessionHolder; import org.apache.sshd.common.util.buffer.Buffer; /** @@ -27,9 +28,7 @@ import org.apache.sshd.common.util.buffer.Buffer; * * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public interface Service extends PropertyResolver, Closeable { - Session getSession(); - +public interface Service extends SessionHolder<Session>, PropertyResolver, Closeable { @Override default PropertyResolver getParentPropertyResolver() { return getSession(); diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuth.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuth.java index d26da38..21a92ab 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuth.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/UserAuth.java @@ -30,7 +30,6 @@ import org.apache.sshd.server.session.ServerSessionHolder; * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ public interface UserAuth extends ServerSessionHolder, UserAuthInstance<ServerSession>, UsernameHolder { - /** * Try to authenticate the user. This methods should return a non {@code null} * value indicating if the authentication succeeded. If the authentication is diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java index aa42934..250e818 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java @@ -36,7 +36,6 @@ import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.threads.CloseableExecutorService; -import org.apache.sshd.server.session.ServerSession; /** * TODO Add javadoc @@ -44,7 +43,6 @@ import org.apache.sshd.server.session.ServerSession; * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ public abstract class AbstractServerChannel extends AbstractChannel implements ServerChannel { - protected final AtomicBoolean exitStatusSent = new AtomicBoolean(false); protected AbstractServerChannel(CloseableExecutorService executor) { @@ -58,11 +56,6 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S } @Override - public ServerSession getServerSession() { - return (ServerSession) getSession(); - } - - @Override public OpenFuture open(int recipient, long rwSize, long packetSize, Buffer buffer) { setRecipient(recipient); diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ServerChannel.java index 5dc73de..b3e75c4 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ServerChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ServerChannel.java @@ -20,11 +20,15 @@ package org.apache.sshd.server.channel; import org.apache.sshd.common.channel.Channel; +import org.apache.sshd.server.session.ServerSession; import org.apache.sshd.server.session.ServerSessionHolder; /** * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ public interface ServerChannel extends Channel, ServerSessionHolder { - // Marker interface + @Override + default ServerSession getServerSession() { + return (ServerSession) getSession(); + } } diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/AbstractCommandSupport.java b/sshd-core/src/main/java/org/apache/sshd/server/command/AbstractCommandSupport.java index 67a636a..03d1e3f 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/command/AbstractCommandSupport.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/command/AbstractCommandSupport.java @@ -47,7 +47,7 @@ import org.apache.sshd.server.session.ServerSessionHolder; public abstract class AbstractCommandSupport extends AbstractLoggingBean implements Command, Runnable, ExecutorServiceCarrier, SessionAware, - SessionHolder<Session>, ServerSessionHolder { + SessionHolder<ServerSession>, ServerSessionHolder { protected final String command; protected InputStream in; protected OutputStream out; @@ -55,7 +55,7 @@ public abstract class AbstractCommandSupport protected ExitCallback callback; protected Environment environment; protected Future<?> cmdFuture; - protected Thread cmdRunner; + protected volatile Thread cmdRunner; protected CloseableExecutorService executorService; protected boolean cbCalled; protected ServerSession serverSession; @@ -78,7 +78,7 @@ public abstract class AbstractCommandSupport } @Override - public Session getSession() { + public ServerSession getSession() { return getServerSession(); } @@ -145,13 +145,19 @@ public abstract class AbstractCommandSupport public void start(ChannelSession channel, Environment env) throws IOException { environment = env; try { + if (log.isDebugEnabled()) { + log.debug("start({}) starting runner for command={}", channel, command); + } + CloseableExecutorService executors = getExecutorService(); cmdFuture = executors.submit(() -> { cmdRunner = Thread.currentThread(); this.run(); }); } catch (RuntimeException e) { // e.g., RejectedExecutionException - log.error("Failed (" + e.getClass().getSimpleName() + ") to start command=" + command + ": " + e.getMessage(), e); + log.error("start(" + channel + ")" + + " Failed (" + e.getClass().getSimpleName() + ")" + + " to start command=" + command + ": " + e.getMessage(), e); throw new IOException(e); } } @@ -160,11 +166,13 @@ public abstract class AbstractCommandSupport public void destroy(ChannelSession channel) throws Exception { // if thread has not completed, cancel it boolean debugEnabled = log.isDebugEnabled(); - if ((cmdFuture != null) && (!cmdFuture.isDone()) && (cmdRunner != Thread.currentThread())) { + if ((cmdFuture != null) + && (!cmdFuture.isDone()) + && (cmdRunner != Thread.currentThread())) { boolean result = cmdFuture.cancel(true); // TODO consider waiting some reasonable (?) amount of time for cancellation if (debugEnabled) { - log.debug("destroy() - cancel pending future=" + result); + log.debug("destroy({})[{}] - cancel pending future={}", channel, this, result); } } @@ -174,7 +182,8 @@ public abstract class AbstractCommandSupport if ((executors != null) && (!executors.isShutdown())) { Collection<Runnable> runners = executors.shutdownNow(); if (debugEnabled) { - log.debug("destroy() - shutdown executor service - runners count=" + runners.size()); + log.debug("destroy({})[{}] - shutdown executor service - runners count={}", + channel, this, runners.size()); } } this.executorService = null; @@ -185,10 +194,11 @@ public abstract class AbstractCommandSupport } protected void onExit(int exitValue, String exitMessage) { + Session session = getSession(); if (cbCalled) { if (log.isTraceEnabled()) { - log.trace("onExit({}) ignore exitValue={}, message={} - already called", - this, exitValue, exitMessage); + log.trace("onExit({})[{}] ignore exitValue={}, message={} - already called", + session, this, exitValue, exitMessage); } return; } @@ -196,7 +206,8 @@ public abstract class AbstractCommandSupport ExitCallback cb = getExitCallback(); try { if (log.isDebugEnabled()) { - log.debug("onExit({}) exiting - value={}, message={}", this, exitValue, exitMessage); + log.debug("onExit({})[{}] exiting - value={}, message={}", + session, this, exitValue, exitMessage); } cb.onExit(exitValue, exitMessage); } finally { diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java index 7c11ec5..c8a796e 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java @@ -19,6 +19,7 @@ package org.apache.sshd.server.kex; +import java.security.KeyPair; import java.security.PublicKey; import java.util.Objects; @@ -31,9 +32,12 @@ import org.apache.sshd.server.session.ServerSessionHolder; /** * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange implements ServerSessionHolder { +public abstract class AbstractDHServerKeyExchange + extends AbstractDHKeyExchange + implements ServerSessionHolder { protected AbstractDHServerKeyExchange(Session s) { - super(ValidateUtils.checkInstanceOf(s, ServerSession.class, "Using a client side KeyExchange on a server: %s", s)); + super(ValidateUtils.checkInstanceOf(s, ServerSession.class, + "Using a client side KeyExchange on a server: %s", s)); } @Override @@ -44,6 +48,8 @@ public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange @Override public PublicKey getServerKey() { ServerSession session = getServerSession(); - return Objects.requireNonNull(session.getHostKey(), "No server key pair available").getPublic(); + KeyPair kpHost = Objects.requireNonNull( + session.getHostKey(), "No server key pair available"); + return kpHost.getPublic(); } } diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java b/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java index 0377afa..ade5e69 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShell.java @@ -21,9 +21,12 @@ package org.apache.sshd.server.shell; import java.io.InputStream; import java.io.OutputStream; +import org.apache.sshd.common.session.SessionHolder; import org.apache.sshd.server.SessionAware; import org.apache.sshd.server.channel.ChannelSession; import org.apache.sshd.server.command.CommandLifecycle; +import org.apache.sshd.server.session.ServerSession; +import org.apache.sshd.server.session.ServerSessionHolder; /** * This shell have inverted streams, such as the one obtained when launching a @@ -33,7 +36,17 @@ import org.apache.sshd.server.command.CommandLifecycle; * * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public interface InvertedShell extends CommandLifecycle, SessionAware { +public interface InvertedShell + extends SessionHolder<ServerSession>, + ServerSessionHolder, + CommandLifecycle, + SessionAware { + + @Override + default ServerSession getSession() { + return getServerSession(); + } + /** * @return The {@link ChannelSession} instance through which * the shell was created - may be {@code null} if shell not started yet diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java b/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java index a86eeb8..6b62cc1 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java @@ -38,14 +38,13 @@ import org.apache.sshd.server.Environment; import org.apache.sshd.server.channel.ChannelSession; import org.apache.sshd.server.channel.PuttyRequestHandler; import org.apache.sshd.server.session.ServerSession; -import org.apache.sshd.server.session.ServerSessionHolder; /** * Bridges the I/O streams between the SSH command and the process that executes it * * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public class ProcessShell extends AbstractLoggingBean implements InvertedShell, ServerSessionHolder { +public class ProcessShell extends AbstractLoggingBean implements InvertedShell { private final List<String> command; private String cmdValue; private ServerSession session; @@ -65,7 +64,8 @@ public class ProcessShell extends AbstractLoggingBean implements InvertedShell, public ProcessShell(Collection<String> command) { // we copy the original list so as not to change it - this.command = new ArrayList<>(ValidateUtils.checkNotNullAndNotEmpty(command, "No process shell command(s)")); + this.command = new ArrayList<>( + ValidateUtils.checkNotNullAndNotEmpty(command, "No process shell command(s)")); this.cmdValue = GenericUtils.join(command, ' '); } @@ -105,16 +105,17 @@ public class ProcessShell extends AbstractLoggingBean implements InvertedShell, Map<String, String> procEnv = builder.environment(); procEnv.putAll(varsMap); } catch (Exception e) { - log.warn("start() - Failed ({}) to set environment for command={}: {}", - e.getClass().getSimpleName(), cmdValue, e.getMessage()); + log.warn("start({}) - Failed ({}) to set environment for command={}: {}", + channel, e.getClass().getSimpleName(), cmdValue, e.getMessage()); if (log.isDebugEnabled()) { - log.debug("start(" + cmdValue + ") failure details", e); + log.debug("start(" + channel + ")[" + cmdValue + "] failure details", e); } } } if (log.isDebugEnabled()) { - log.debug("Starting shell with command: '{}' and env: {}", builder.command(), builder.environment()); + log.debug("start({}): command='{}', env={}", + channel, builder.command(), builder.environment()); } process = builder.start(); @@ -177,7 +178,7 @@ public class ProcessShell extends AbstractLoggingBean implements InvertedShell, boolean debugEnabled = log.isDebugEnabled(); if (process != null) { if (debugEnabled) { - log.debug("destroy({}) Destroy process for {}", channel, cmdValue); + log.debug("destroy({}) Destroy process for '{}'", channel, cmdValue); } process.destroy(); } @@ -186,14 +187,16 @@ public class ProcessShell extends AbstractLoggingBean implements InvertedShell, IoUtils.closeQuietly(getInputStream(), getOutputStream(), getErrorStream()); if (e != null) { if (debugEnabled) { - log.debug(e.getClass().getSimpleName() + " while destroy streams of '" + this + "': " + e.getMessage()); + log.debug("destroy({}) {} while destroy streams of '{}': {}", + channel, e.getClass().getSimpleName(), this, e.getMessage()); } if (log.isTraceEnabled()) { Throwable[] suppressed = e.getSuppressed(); if (GenericUtils.length(suppressed) > 0) { for (Throwable t : suppressed) { - log.trace("Suppressed " + t.getClass().getSimpleName() + ") while destroy streams of '" + this + "': " + t.getMessage()); + log.trace("destroy({}) Suppressed {} while destroy streams of '{}': {}", + channel, t.getClass().getSimpleName(), this, t.getMessage()); } } } diff --git a/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java b/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java index 7e6aaac..fca8c99 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java @@ -79,14 +79,20 @@ public class InvertedShellWrapperTest extends BaseTestSupport { @Test // see SSHD-570 public void testExceptionWhilePumpStreams() throws Exception { - final BogusInvertedShell bogusShell = newShell("out", "err"); + BogusInvertedShell bogusShell = newShell("out", "err"); bogusShell.setAlive(false); final int destroyedExitValue = 7365; + @SuppressWarnings("checkstyle:anoninnerlength") InvertedShell shell = new InvertedShell() { private boolean destroyed; @Override + public ServerSession getServerSession() { + return bogusShell.getServerSession(); + } + + @Override public ChannelSession getChannelSession() { return bogusShell.getChannelSession(); } @@ -188,7 +194,9 @@ public class InvertedShellWrapperTest extends BaseTestSupport { InputStream shellErr = newDelayedInputStream(Short.SIZE, errorContent); ByteArrayOutputStream stderr = new ByteArrayOutputStream(errorContent.length() + Byte.SIZE)) { + @SuppressWarnings("checkstyle:anoninnerlength") InvertedShell shell = new InvertedShell() { + private ServerSession session; private ChannelSession channel; @Override @@ -197,13 +205,23 @@ public class InvertedShellWrapperTest extends BaseTestSupport { } @Override + public ServerSession getServerSession() { + if (session != null) { + return session; + } + + ChannelSession channel = getChannelSession(); + return (channel == null) ? null : channel.getServerSession(); + } + + @Override public ChannelSession getChannelSession() { return channel; } @Override public void setSession(ServerSession session) { - // ignored + this.session = session; } @Override @@ -286,8 +304,10 @@ public class InvertedShellWrapperTest extends BaseTestSupport { private static BogusInvertedShell newShell(String contentOut, String contentErr) { ByteArrayOutputStream in = new ByteArrayOutputStream(20); - ByteArrayInputStream out = new ByteArrayInputStream(contentOut.getBytes(StandardCharsets.UTF_8)); - ByteArrayInputStream err = new ByteArrayInputStream(contentErr.getBytes(StandardCharsets.UTF_8)); + ByteArrayInputStream out = + new ByteArrayInputStream(contentOut.getBytes(StandardCharsets.UTF_8)); + ByteArrayInputStream err = + new ByteArrayInputStream(contentErr.getBytes(StandardCharsets.UTF_8)); return new BogusInvertedShell(in, out, err); } } diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusInvertedShell.java b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusInvertedShell.java index 6670529..ce5ccdc 100644 --- a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusInvertedShell.java +++ b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusInvertedShell.java @@ -28,11 +28,9 @@ import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.server.Environment; import org.apache.sshd.server.channel.ChannelSession; import org.apache.sshd.server.session.ServerSession; -import org.apache.sshd.server.session.ServerSessionHolder; import org.apache.sshd.server.shell.InvertedShell; -public class BogusInvertedShell implements InvertedShell, ServerSessionHolder { - +public class BogusInvertedShell implements InvertedShell { private final OutputStream in; private final InputStream out; private final InputStream err; diff --git a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemEnvironment.java b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemEnvironment.java index a7a12b1..cebe9cf 100644 --- a/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemEnvironment.java +++ b/sshd-sftp/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystemEnvironment.java @@ -23,14 +23,16 @@ import java.nio.file.Path; import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.apache.sshd.common.session.SessionHolder; import org.apache.sshd.common.subsystem.sftp.SftpConstants; import org.apache.sshd.server.config.SshServerConfigFileReader; +import org.apache.sshd.server.session.ServerSession; import org.apache.sshd.server.session.ServerSessionHolder; /** * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> */ -public interface SftpSubsystemEnvironment extends ServerSessionHolder { +public interface SftpSubsystemEnvironment extends SessionHolder<ServerSession>, ServerSessionHolder { /** * Force the use of a given sftp version */ @@ -44,6 +46,11 @@ public interface SftpSubsystemEnvironment extends ServerSessionHolder { .mapToObj(Integer::toString) .collect(Collectors.joining(",")); + @Override + default ServerSession getSession() { + return getServerSession(); + } + /** * @return The negotiated version */