This is an automated email from the ASF dual-hosted git repository. twolf pushed a commit to branch dev_3.0 in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit ccb211d4cc71adf763c031ae9563bbb8bff78f41 Author: Thomas Wolf <tw...@apache.org> AuthorDate: Thu Apr 24 00:08:04 2025 +0200 Session creation: lazy initialize ClientUserAuthService This service gets created when the session is created. At that time the properties may not be set yet on the session, so the constructor cannot read them. Read them later when the service is started. Arguably creating the service when the session is created is too early, it would be sufficient to create it once the SERVICE_REQUEST message arrives. But that would be a more risky change. --- .../java/org/apache/sshd/client/SshClient.java | 25 ++++++++++--- .../sshd/client/session/ClientUserAuthService.java | 41 +++++++++++----------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java index 54d85a853..5778bd426 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java @@ -23,12 +23,14 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketTimeoutException; import java.net.URI; +import java.net.URISyntaxException; import java.nio.channels.UnsupportedAddressTypeException; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyPair; +import java.text.MessageFormat; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -82,6 +84,7 @@ import org.apache.sshd.common.Factory; import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.ServiceFactory; import org.apache.sshd.common.SshConstants; +import org.apache.sshd.common.SshException; import org.apache.sshd.common.channel.ChannelFactory; import org.apache.sshd.common.config.keys.FilePasswordProvider; import org.apache.sshd.common.config.keys.FilePasswordProviderManager; @@ -629,7 +632,12 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa } } else { proxySession.close(true); - connectFuture.setException(f3.getException()); + // Record at which proxy we could not log in + SshException ex = new SshException(SshConstants.SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, + MessageFormat.format("Cannot log in at {0}:{1}", jump.getHost(), + Integer.toString(jump.getPort())), + f3.getException()); + connectFuture.setException(ex); } }); } catch (IOException e) { @@ -722,17 +730,26 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa if (GenericUtils.isEmpty(proxyJump)) { return jumps; } - String[] hops = GenericUtils.split(proxyJump, ','); + String trimmed = proxyJump.trim(); + if ("none".equals(trimmed)) { + return jumps; + } + String[] hops = GenericUtils.split(trimmed, ','); for (String hop : hops) { String h = hop.trim(); if (h.isEmpty()) { throw new IllegalArgumentException("Empty proxy jump in list: " + proxyJump); } URI uri = URI.create(h.contains("://") ? h : "ssh://" + h); - if (GenericUtils.isNotEmpty(uri.getScheme()) && !"ssh".equals(uri.getScheme())) { - throw new IllegalArgumentException("Unsupported scheme for proxy jump: " + hop); + if (!"ssh".equals(uri.getScheme())) { + throw new IllegalArgumentException("Invalid proxy jump: " + hop, + new URISyntaxException(hop, "Scheme must be 'ssh', was '" + uri.getScheme() + '\'')); } String host = uri.getHost(); + if (GenericUtils.isEmpty(host) || !GenericUtils.isEmpty(uri.getPath())) { + throw new IllegalArgumentException("Invalid proxy jump: " + hop, + new URISyntaxException(hop, "Must have a host and no path")); + } int port = uri.getPort(); String userInfo = uri.getUserInfo(); HostConfigEntry entry = resolveHost(userInfo, host, port, context, null); 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 ffcfe5b30..140a6fbac 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 @@ -82,6 +82,27 @@ public class ClientUserAuthService extends AbstractCloseable implements Service, clientSession.getUserAuthFactories(), "No user auth factories for %s", s); clientMethods = new ArrayList<>(); + clientSession.resetAuthTimeout(); + } + + @Override + public ClientSession getSession() { + return getClientSession(); + } + + @Override + public ClientSession getClientSession() { + return clientSession; + } + + @Override + public Map<String, Object> getProperties() { + return properties; + } + + @Override + public void start() { + ClientSession s = getClientSession(); String prefs = CoreModuleProperties.PREFERRED_AUTHS.getOrNull(s); boolean debugEnabled = log.isDebugEnabled(); if (GenericUtils.isEmpty(prefs)) { @@ -109,26 +130,6 @@ public class ClientUserAuthService extends AbstractCloseable implements Service, log.debug("ClientUserAuthService({}) client methods: {}", s, clientMethods); } - clientSession.resetAuthTimeout(); - } - - @Override - public ClientSession getSession() { - return getClientSession(); - } - - @Override - public ClientSession getClientSession() { - return clientSession; - } - - @Override - public Map<String, Object> getProperties() { - return properties; - } - - @Override - public void start() { Runnable initial; synchronized (initLock) { started = true;