I'm trying to set up a simple SSH client that verifies server's public key via known hosts file, using Apache Mina SSHD. I've pieced together below pesudo-code that works - well, it would work, if I knew how to make the client wait for server hostkey verification to complete.
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.file.*;
import java.security.PublicKey;
import java.util.concurrent.TimeUnit;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.config.hosts.KnownHostEntry;
import org.apache.sshd.client.future.*;
import org.apache.sshd.client.keyverifier.*;
import org.apache.sshd.client.session.ClientSession;
public class SshdTest {
public static void main(String[] args) throws IOException {
Path knownHostsPath = Paths.get(System.getProperty("user.home"), ".ssh", "known_hosts");
SshClient ssh = SshClient.setUpDefaultClient();
KnownHostsServerKeyVerifier verifier = new DefaultKnownHostsServerKeyVerifier(new ServerKeyVerifier() {
@Override
public boolean verifyServerKey(ClientSession cs, SocketAddress sa, PublicKey pk) {
return true; // ask user to verify unknown public key
}
}, true, knownHostsPath);
verifier.setModifiedServerKeyAcceptor(new ModifiedServerKeyAcceptor() {
@Override
public boolean acceptModifiedServerKey(ClientSession cs, SocketAddress sa, KnownHostEntry khe, PublicKey expected, PublicKey actual) throws Exception {
return true; // ask user to verify public key change
}
});
ssh.setServerKeyVerifier(verifier);
ssh.start();
String host = "localhost";
String username = "user";
int port = 22;
String password = "password";
ConnectFuture cf = ssh.connect(username, host, port).verify(5L, TimeUnit.SECONDS);
cf.await();
// wait for server hostkey verification to complete and check ok?
try (
ClientSession session = cf.getSession()) {
session.addPasswordIdentity(password);
AuthFuture auth = session.auth();
auth.await(5L, TimeUnit.SECONDS);
// check ok and do the work
}
ssh.stop();
}
}
I expected cf.await()
line to encompass both the connection and hostkey verification process, but it doesn't, which means user is asked for both password and hostkey verification at the same time or in some undefined order if the code stays as is.
How do I make the client wait for server hostkey verification to complete before attempting anything else, such as user authentication? Also, how do I check if the verification was successful?