0

I'm trying to connect to a sftp server, which I connect to via commands using sftp -oHostKeyAlgorithms=+ssh-dss user@host. However, when I try to connect via my java-spring application, using apache vfs, I get the following exception:

ERROR] 20/06/2023 11:50:13.333 [http-nio-8080-exec-1]  o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: org.apache.commons.vfs2.FileSystemException: Could not connect to SFTP server at "sftp://user:***@host/".] with root cause
com.jcraft.jsch.JSchException: Algorithm negotiation fail

My file download method looks like this:

public void downloadFile(final String originFilePath, final String destinationFilePath) throws IOException {
        try (final StandardFileSystemManager manager = new StandardFileSystemManager()) {
            manager.init();
            final FileObject remoteFile = manager.resolveFile(getConnectionWithPath(originFilePath), createDefaultOptions());
            manager.resolveFile(destinationFilePath).copyFrom(remoteFile, Selectors.SELECT_SELF);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

The getConnectionWithPath(originFilePath) looks like this (the getX() methods retrieve the value from my properties file):

public String getConnectionWithPath(final String remoteFilePath) {
        return "sftp://" + getUser() + ":" + getPassword() + "@" + getIp() + "/" + remoteFilePath;
    }

And finally, my createDefaultOptions() method:

public static FileSystemOptions createDefaultOptions() throws FileSystemException {
        FileSystemOptions opts = new FileSystemOptions();

        SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);
        SftpFileSystemConfigBuilder.getInstance().setKeyExchangeAlgorithm(opts, "ssh-dss");
        SftpFileSystemConfigBuilder.getInstance().setDisableDetectExecChannel(opts, true);

        return opts;
    }

I'm using jsch 0.1.55 and apache vfs 2.9.0

After trying many approaches, I ended up using just jsch to create the connection and download the files I need, using the following methods:

public void downloadFile(String originFilePath, String destinationFilePath) throws IOException {
        try {
            final Session session = createSessionAndConnect();
            ChannelSftp sftpChannel = getJSCHConnectionChannel(session);

            sftpChannel.get(originFilePath, destinationFilePath);

            closeJSCHConnectionChannel(sftpChannel, session);
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
    }
private Session createSessionAndConnect() throws JSchException {
        JSch jsch = new JSch();
        Session session = null;

        session = jsch.getSession(getUser(), getIp(), 22);
        session.setConfig("StrictHostKeyChecking", "no"); // Is this fine?
        session.setPassword(getPassword());
        session.connect();

        return session;
    }
private ChannelSftp getJSCHConnectionChannel(Session session) throws JSchException {
        Channel channel = session.openChannel("sftp");
        channel.connect();
        return (ChannelSftp) channel;
    }
private void closeJSCHConnectionChannel(final ChannelSftp sftpChannel, final Session session) {
        sftpChannel.exit();
        session.disconnect();
    }
StzEZ
  • 21
  • 4
  • Setting keyexchange algorithm to ssh-dss is nonsense because **ssh-dss is not a keyexchange algorithm**; _no_ connection using your code can ever succeed. ssh-dss is a _signature_ algorithm, in this case used for the host, or as OpenSSH says 'HostkeyAlgorithm'; Jsch calls it `server_host_key` and vfs/sftp doesn't appear to have a way to configure it, but you shouldn't need to because jsch 0.1.55 default includes it. (OpenSSH dropped it from default in 7.0, which is why you need an option on commandline `sftp` -- if the server is actually using it; have you confirmed that?) – dave_thompson_085 Jun 20 '23 at 10:58
  • Yes, the server is using it as far as I know. I tried with the default configuration without success, thus adding the line you mentioned. I'm considering using jsch directly, which works fine, but needs more lines of code. – StzEZ Jun 20 '23 at 11:21
  • There are dozens of recent questions here about *"Algorithm negotiation fail"* problems with JSch already. What research did you do? – Martin Prikryl Jun 20 '23 at 11:47
  • @MartinPrikryl That's what I've seen, but as I said all I could find was about jsch, not apache vfs – StzEZ Jun 20 '23 at 15:21
  • Can you get a log showing the problem? Per [the source](https://github.com/apache/commons-vfs/blob/master/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java#L53) vfs hooks up Jsch logging to commons-logging, so you should be able to just enable logging on that class. – dave_thompson_085 Jun 21 '23 at 02:35
  • Ok, but have you realized that you likely cannot use original JSch, as it is outdated? Did try testing JSch directly, and its clones that are more up-to-date? – Martin Prikryl Jun 21 '23 at 08:24
  • @MartinPrikryl We try to have as few dependencies as possible, hence the use of the original jsch, as it's needed anyway for apache vfs to work, is that a problem? It seems to work fine – StzEZ Jun 21 '23 at 13:28
  • *"Seems to work fine"*??? Doesn't seem to me. – Martin Prikryl Jun 21 '23 at 13:55
  • @MartinPrikryl Why not? I'm getting all the files I need using it – StzEZ Jun 21 '23 at 14:07
  • I do not see you mentioning anywhere, that direct use of JSCh works for you. If it does, post your JSch code, JSch log file and JSch log file from within vfs, if possible. – Martin Prikryl Jun 21 '23 at 14:28
  • @MartinPrikryl _"I'm considering using jsch directly, which works fine, but needs more lines of code."_ I commented that in an earlier comment, maybe I wasn't clear enough. Right now, using just jsch, everything works as expected, however using vfs reduces the amount of code. Added my current code at the end of the question – StzEZ Jun 21 '23 at 14:34

1 Answers1

0

Given that I couldn't find a better approach, the cose that worked for me is as follows:

I ended up using just jsch to create the connection and download the files I need, using the following methods:

public void downloadFile(String originFilePath, String destinationFilePath) throws IOException {
        try {
            final Session session = createSessionAndConnect();
            ChannelSftp sftpChannel = getJSCHConnectionChannel(session);

            sftpChannel.get(originFilePath, destinationFilePath);

            closeJSCHConnectionChannel(sftpChannel, session);
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
    }
private Session createSessionAndConnect() throws JSchException {
        JSch jsch = new JSch();
        Session session = null;

        session = jsch.getSession(getUser(), getIp(), 22);
        session.setConfig("StrictHostKeyChecking", "no"); // Is this fine?
        session.setPassword(getPassword());
        session.connect();

        return session;
    }
private ChannelSftp getJSCHConnectionChannel(Session session) throws JSchException {
        Channel channel = session.openChannel("sftp");
        channel.connect();
        return (ChannelSftp) channel;
    }
private void closeJSCHConnectionChannel(final ChannelSftp sftpChannel, final Session session) {
        sftpChannel.exit();
        session.disconnect();
    }
StzEZ
  • 21
  • 4