undisp
undisp

Reputation: 721

Getting UnknownHostKey when connecting to remote server with JSch

I'm trying to connect to a remote server in Java via JSch, but I'm getting an error.

I have this code:

public static void myCode() {
    String command = "ls /home";
    String userName = "username";
    String password = "pass";
    String connectionIP = "XXX.XXX.XXX.XXX";
    int port = 0000; // example value
    SSHManager instance = new SSHManager(userName, password, connectionIP, "", port);
    String errorMessage = instance.connect();

    if (errorMessage != null) {
        System.out.println(errorMessage);
    }

    String result = instance.sendCommand(command);
    instance.close();
}

SSHManager class:

/* 
 * SSHManager
 * 
 * @author cabbott
 * @version 1.0
 */

import com.jcraft.jsch.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SSHManager {

    private static final Logger LOGGER
            = Logger.getLogger(SSHManager.class.getName());
    private JSch jschSSHChannel;
    private String strUserName;
    private String strConnectionIP;
    private int intConnectionPort;
    private String strPassword;
    private Session sesConnection;
    private int intTimeOut;

    private void doCommonConstructorActions(String userName,
            String password, String connectionIP, String knownHostsFileName) {
        jschSSHChannel = new JSch();

        try {
            jschSSHChannel.setKnownHosts(knownHostsFileName);
        } catch (JSchException jschX) {
            logError(jschX.getMessage());
        }

        strUserName = userName;
        strPassword = password;
        strConnectionIP = connectionIP;
    }

    public SSHManager(String userName, String password,
            String connectionIP, String knownHostsFileName) {
        doCommonConstructorActions(userName, password,
                connectionIP, knownHostsFileName);
        intConnectionPort = 22;
        intTimeOut = 60000;
    }

    public SSHManager(String userName, String password, String connectionIP,
            String knownHostsFileName, int connectionPort) {
        doCommonConstructorActions(userName, password, connectionIP,
                knownHostsFileName);
        intConnectionPort = connectionPort;
        intTimeOut = 60000;
    }

    public SSHManager(String userName, String password, String connectionIP,
            String knownHostsFileName, int connectionPort, int timeOutMilliseconds) {
        doCommonConstructorActions(userName, password, connectionIP,
                knownHostsFileName);
        intConnectionPort = connectionPort;
        intTimeOut = timeOutMilliseconds;
    }

    public String connect() {
        String errorMessage = null;

        try {
            sesConnection = jschSSHChannel.getSession(strUserName,
                    strConnectionIP, intConnectionPort);
            sesConnection.setPassword(strPassword);
        // UNCOMMENT THIS FOR TESTING PURPOSES, BUT DO NOT USE IN PRODUCTION
            // sesConnection.setConfig("StrictHostKeyChecking", "no");
            sesConnection.connect(intTimeOut);
        } catch (JSchException jschX) {
            errorMessage = jschX.getMessage();
        }

        return errorMessage;
    }

    private String logError(String errorMessage) {
        if (errorMessage != null) {
            LOGGER.log(Level.SEVERE, "{0}:{1} - {2}",
                    new Object[]{strConnectionIP, intConnectionPort, errorMessage});
        }

        return errorMessage;
    }

    private String logWarning(String warnMessage) {
        if (warnMessage != null) {
            LOGGER.log(Level.WARNING, "{0}:{1} - {2}",
                    new Object[]{strConnectionIP, intConnectionPort, warnMessage});
        }

        return warnMessage;
    }

    public String sendCommand(String command) {
        StringBuilder outputBuffer = new StringBuilder();

        try {
            Channel channel = sesConnection.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            InputStream commandOutput = channel.getInputStream();
            channel.connect();
            int readByte = commandOutput.read();

            while (readByte != 0xffffffff) {
                outputBuffer.append((char) readByte);
                readByte = commandOutput.read();
            }

            channel.disconnect();
        } catch (IOException ioX) {
            logWarning(ioX.getMessage());
            return null;
        } catch (JSchException jschX) {
            logWarning(jschX.getMessage());
            return null;
        }

        return outputBuffer.toString();
    }

    public void close() {
        sesConnection.disconnect();
    }

}

When I run it, I get this error:

Jul 31, 2015 2:56:44 PM javaapplication2.SSHManager logError
SEVERE: null:0 - java.io.FileNotFoundException
UnknownHostKey: XXX.XXX.XXX.XXX. RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
Jul 31, 2015 2:56:45 PM javaapplication2.SSHManager logWarning
WARNING: XXX.XXX.XXX.XXX:0.000 - session is down

I found this answer:
https://stackoverflow.com/a/2003460/2699664

After reading it I decided to deleted the ~/.ssh/known_hosts and then logged in the server via ssh in the terminal. It told me that the known hosts file was updated but the same error occurs with this code.

Another thing that I find weird is the fact that the last line of the error says that I inserted the port 0.000 when I inserted 0000.

Does anyone know where could be the error?

Upvotes: 0

Views: 1593

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202088

By default the JSch should able to resolve known hostkeys from OpenSSH known_hosts file that you set up using ssh.

But as you explicitly call JSch.setKnownHosts with an empty path (hence the FileNotFoundException), you break it (hence the UnknownHostKey).

Upvotes: 1

Related Questions