apache / mina-sshd

Apache MINA sshd is a comprehensive Java library for client- and server-side SSH.
https://mina.apache.org/sshd-project/
Apache License 2.0
902 stars 359 forks source link

HostConfigEntry resolveIdentityFilePath Identity Problem #622

Open fragaLY opened 4 weeks ago

fragaLY commented 4 weeks ago

Version

2.14.0

Bug description

During the client#connect invocation, I am facing the parsing problem that provides me with identity in format "~/.ssh/sftp.pem", but Tilda is expected to be the first token.

public class Main {

    private static final int DEFAULT_SFTP_SESSION_TIMEOUT = 1500;

    public static void main(String[] args) throws IOException {
        SshClient client = null;
        ClientSession session = null;
        try {
            client = SshClient.setUpDefaultClient();
            client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
            client.start();
            session = client.connect("user, "host", port).verify(DEFAULT_SFTP_SESSION_TIMEOUT, TimeUnit.MILLISECONDS).getSession();
            session.addPasswordIdentity("password");
            session.auth().verify(DEFAULT_SFTP_SESSION_TIMEOUT, TimeUnit.MILLISECONDS);
            System.out.println(session);
        } catch (Exception e) {
            var message = "Failed to create SSHClient Session:" + e.getMessage();
            System.out.println(message);
        } finally {
            Objects.requireNonNull(session).close();
            Objects.requireNonNull(client).close();
        }
    }
}

Actual behavior

Home tilde must be first: "~/.ssh/sftp.pem"

Expected behavior

Connection established.

Relevant log output

No response

Other information

No response

tomaswolf commented 4 weeks ago

Strange. First: since you set a password, do you want to use public key authentication with that key at all? If not, you could side-track this issue by setting a no-op HostConfigEntryResolver: client.setHostConfigEntryResolver(HostConfigEntryResolver.EMPTY);.

But that doesn't solve the underlying problem. By default, the client picks up your ~/.ssh/config. Is there is some zero-width space or other invisible character in front of the tilde in that file that we neglect to remove when reading from the file?

tomaswolf commented 4 weeks ago

Or maybe it's the quoting. If your SSH config has

IdentityFile "~/.ssh/sftp.pem"

you could replace it with just

IdentityFile ~/.ssh/sftp.pem
fragaLY commented 3 weeks ago

Hello @tomaswolf,

Thank you for your answer.

When I am using a HostConfigEntryResolver.EMPTY it skips the PK auth.

Unfortunately, now I am facing with the other problem: Failed to create SSH Client Session:No more authentication methods available

The ClentUserAuthService.class code line 331: in case of I am using a password auth approach if sets authFuture exception.

My example:


import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.config.hosts.HostConfigEntryResolver;
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.auth.UserAuthMethodFactory;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class Main {

    private static final int DEFAULT_SFTP_SESSION_TIMEOUT = 2500;

    public static void main(String[] args) throws IOException {
        SshClient client = null;
        ClientSession session = null;
        try {
            client = SshClient.setUpDefaultClient();
            client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
            client.setHostConfigEntryResolver(HostConfigEntryResolver.EMPTY);
            client.setUserAuthFactoriesNames(List.of(UserAuthMethodFactory.PASSWORD));
            client.start();
            session = client.connect("user", "host",  22).verify(DEFAULT_SFTP_SESSION_TIMEOUT, TimeUnit.MILLISECONDS).getSession();
            session.addPasswordIdentity("password");
            session.auth().verify();
            System.out.println(session);
        } catch (Exception e) {
            var message = "Failed to create SSH Client Session:" + e.getMessage();
            System.out.println(message);
        } finally {
            Objects.requireNonNull(session).close();
            Objects.requireNonNull(client).close();
        }
    }
}
fragaLY commented 3 weeks ago

I found something similar on StackOverFlow: https://stackoverflow.com/questions/79063325/no-more-authentication-methods-available-with-apache-mina-sshd

fragaLY commented 3 weeks ago

@tomaswolf

https://www.ssh.com/academy/ssh/config?hs_amp=true

If we will go back through the documentation and find that it could be quoted.

tomaswolf commented 3 weeks ago

I know that having it quoted is perfectly fine with OpenSSH. The rudimentary parser in HostConfigEntry.readHostConfigEntries(BufferedReader) is not really OpenSSH compatible. A PR to improve it (including tests) would be welcome; the parser used in JGit may serve as an inspiration.