19

I having a strange issue with sshj (am using sshj v0.6.0) for which I would need some help from someone. Authentication with public key works fine on some machines but doesnt work fine on other machines and I see the below error.

The only difference that I could make out was that the UNIX ID in question viz coonradt seems to have the below listed configuration setup under ~/.ssh/config only on the box on which the below errors are being triggered

Host *
    Protocol 1,2
    FallBackToRsh no
    ForwardAgent yes
    ForwardX11 yes
    PasswordAuthentication yes
    RhostsAuthentication no
    RhostsRSAAuthentication no
    RSAAuthentication yes
    NoHostAuthenticationForLocalhost yes
    StrictHostKeyChecking no
  KeepAlive yes

From the above config file I learnt that the ID in question is supposed to make use of Protocol 1,2 and I suspect that this might have something to do with my failures (I am not very sure about it, but this is just a hunch)

For all other UNIX IDs for which this works fine, I dont have any such config file.

PS : I cannot alter the config of the UNIX ID "coonradt" since this ID is being used by the central hudson servers.

Would appreciate if someone could please help me suggest as to what might be wrong here

Following is the error that I am seeing :

Oct 24, 2011 2:30:37 AM net.schmizz.sshj.DefaultConfig initCipherFactories
WARNING: Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl init
INFO: Client identity string: SSH-2.0-SSHJ_0_6_0
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl init
INFO: Server identity string: SSH-1.99-OpenSSH_4.3
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger sendKexInit
INFO: Sending SSH_MSG_KEXINIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger handle
INFO: Received SSH_MSG_KEXINIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.kex.AbstractDHG init
INFO: Sending SSH_MSG_KEXDH_INIT
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.KeyExchanger handle
INFO: Received kex followup data
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.kex.AbstractDHG next
INFO: Received SSH_MSG_KEXDH_REPLY
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl die
SEVERE: Dying because - net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
Oct 24, 2011 2:30:38 AM net.schmizz.concurrent.Promise tryRetrieve
SEVERE: <<kex done>> woke to: net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
Oct 24, 2011 2:30:38 AM net.schmizz.sshj.transport.TransportImpl setService
INFO: Setting active service to null-service
Oct 24, 2011 2:30:38 AM com.test.jaws.execution.ssh.impl.SSHJClientImpl$ExceptionHandler handleSevereCondition
SEVERE: mymachine.domain.com is not added to your /x/home/coonradt/.ssh/known_hosts file. 
Throwable occurred: net.schmizz.sshj.transport.TransportException: [HOST_KEY_NOT_VERIFIABLE] Could not verify `ssh-rsa` host key with fingerprint `ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41` for `mymachine.domain.com` on port 22
    at net.schmizz.sshj.transport.KeyExchanger.verifyHost(KeyExchanger.java:222)
    at net.schmizz.sshj.transport.KeyExchanger.handle(KeyExchanger.java:373)
    at net.schmizz.sshj.transport.TransportImpl.handle(TransportImpl.java:477)
    at net.schmizz.sshj.transport.Decoder.decode(Decoder.java:127)
    at net.schmizz.sshj.transport.Decoder.received(Decoder.java:195)
    at net.schmizz.sshj.transport.Reader.run(Reader.java:72)
Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
  • I think the issue is indeed with the coonradt user config, see the SEVERE notice: "SEVERE: mymachine.domain.com is not added to your /x/home/coonradt/.ssh/known_hosts file. ". You should probably fix this ;-) – Hiery Nomus Oct 24 '11 at 10:12
  • Hi thank you so much for the prompt reply. But can you please suggest as to what should the fix be w.r.t to the user ? Does it mean I would have to get rid of the Protocol section in the config file ? I was hoping that sshj would somehow allow me to specify the protocol version as well that can be used (Please bear with my naivety if that sounded gibberish, but as I confessed before I dont know too much on the internals of how ssh works ) – Krishnan Mahadevan Oct 24 '11 at 10:14
  • It actually has very little to do with the protocol (in fact, nothing as far as this message is concerned). What needs to happen is that the file '/x/home/coonradt/.ssh/known_hosts' should contain the fingerprint of your client in this case. I think you've stumbled upon a security measure that not every single machine can connect using that user to that server. – Hiery Nomus Oct 24 '11 at 10:19
  • Oh ok. But here is the weirdest part. The machine in question is a linux box. Our current implementation that leverages on spawning ssh.exe and scp.exe works perfectly fine. Since this is a LINUX machine, I am guessing that the home directory is going to be consistent, unlike in the windows world wherein the CYGWIN Home and the User Home needn't always be the same. That is why am wondering as to how could this happen. – Krishnan Mahadevan Oct 24 '11 at 10:23
  • @HieryNomus : I first checked if there was an entry for the machine and it was there. But strangely I saw only numbers in the file. I then checked the known_hosts file for the same machine in my ~krmahadevan/.ssh/known_hosts file and it was a bit different. Would this be the cause of the errors ? – Krishnan Mahadevan Oct 24 '11 at 11:22
  • "Since this is a LINUX machine, I am guessing that the home directory is going to be consistent, unlike in the windows world wherein the CYGWIN Home and the User Home needn't always be the same." -- The known_hosts file is read from the client machine. – shikhar Oct 24 '11 at 20:26

5 Answers5

32

You may set the SSH client to accept all keys without any verification (ignores host key verification)

SSHClient sshClient = new SSHClient();
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
...
Pranav
  • 952
  • 9
  • 20
20

How about adding a HostKeyVerifier for this machine?

sshClient.addHostKeyVerifier("ca:0b:b3:7f:53:5a:e3:bc:bf:44:63:d8:2d:26:c0:41");

The reason it doesn't happen automatically is probably because the known_hosts file isn't at $(user.home)/.ssh/known_hosts. You can also explicitly load known hosts from a specific location.

sshClient.loadKnownHosts(new File("path_to_known_hosts"));
shikhar
  • 2,432
  • 1
  • 19
  • 14
  • 1
    @Shikar : I dont think the issue has anything to do with the known_host file at all. I figured out that sshj just doesnt handle ssh v1 protocol in my limited knowledge. – Krishnan Mahadevan Oct 28 '11 at 06:01
  • 1
    @Shikar : Please take a look at https://gist.github.com/1321719 which details the problem. – Krishnan Mahadevan Oct 28 '11 at 06:01
  • @Shikar : I also forgot to tell you that the known_hosts file is available under the ~/.ssh folder and I confirmed its availability there. – Krishnan Mahadevan Oct 28 '11 at 06:04
  • 5
    Or we can just disable that verification altogether: `sshClient.addHostKeyVerifier(new PromiscuousVerifier());` – Alex F Aug 29 '16 at 18:54
9
try {
    ssh.connect(envConf.getIp(), port);
} catch (TransportException e) {
    if (e.getDisconnectReason() == DisconnectReason.HOST_KEY_NOT_VERIFIABLE) {
        String msg = e.getMessage();
        String[] split = msg.split("`");
        String vc = split[3];
        ssh = new SSHClient();
        ssh.addHostKeyVerifier(vc);
        ssh.connect(envConf.getIp(), port);
    } else {
        throw e;
    }
}
ssh.authPassword(envConf.getName(), envConf.getPw());
ssh.newSCPFileTransfer().download(envConf.getHomePath() + FilePath, toPath);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
user6089682
  • 91
  • 1
  • 1
0

For an alternative answer ensure that the hostname you are trying to connect to is exactly a match in your known_hosts file. An example mistake that I was making was trying to connect to the full URL bob.insidenetwork.pvt but my known_hosts file had only bob as an entry because when I ssh manually I'm far too lazy to type the entire URL...

Ryaminal
  • 108
  • 7
0

If the server accepts keyboard-interactive verification, you can also do this, at least with recent versions of SSHJ:

client.addHostKeyVerifier(new ConsoleKnownHostsVerifier(new File(userKnownHostsFile), System.console()) {
    @Override
    protected boolean hostKeyUnverifiableAction(String hostname, PublicKey key) {
        try {
            entries().add(new HostEntry(null, hostname, KeyType.fromKey(key), key));
            write();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return true;
    }
});

This overrides the "Are you sure you want to continue connecting (yes/no)? " prompt that the user is supposed to reply to, so that you don't need to provide any input into a console to continue, while satisfying the keyboard-interactive authentication when a host is unknown and avoiding using a PromiscuousVerifier.

You can, of course, tweak the overriding method to your heart's content to add logging, and if you want to be prompted then just use a plain ConsoleKnownHostsVerifier.

If the server doesn't accept keyboard-interactive authentication and you still don't want to use the promiscuous verifier, then you could do something similar to the above for the OpenSSHKnownHosts class; e.g.:

HostKeyVerifier hkv = new OpenSSHKnownHosts(new File("~/.ssh/known_hosts") {
    @Override
    protected boolean hostKeyUnverifiableAction(String hostname, PublicKey key) {
        return true;
    }
};
client.addHostKeyVerifier(hkv);

Inside OpenSSHKnownHosts, all the hostKeyUnverifiableAction(...) method does is return false, so change that and you're good.

quantumferret
  • 473
  • 6
  • 12