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;

Reply via email to