Skip to content

Commit

Permalink
[JENKINS-60812] Failed known_hosts verification for non-standard ssh …
Browse files Browse the repository at this point in the history
…port (#174)
  • Loading branch information
kuisathaverat authored Jan 31, 2020
1 parent 5662f1c commit e6e2cb9
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,21 @@
*/
package hudson.plugins.sshslaves.verifiers;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import hudson.slaves.ComputerLauncher;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;

import com.trilead.ssh2.KnownHosts;

import hudson.Extension;
import hudson.model.TaskListener;
import hudson.plugins.sshslaves.Messages;
import hudson.plugins.sshslaves.SSHLauncher;
import hudson.slaves.ComputerLauncher;
import hudson.slaves.SlaveComputer;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

/**
* A verifier that reads host keys from the Jenkins users' SSH known_hosts file.
Expand All @@ -55,64 +52,76 @@ public class KnownHostsFileKeyVerificationStrategy extends SshHostKeyVerificatio
private static final String KNOWN_HOSTS_FILE_PATH = StringUtils.defaultIfBlank(System.getProperty(KNOWN_HOSTS_PROPERTY), KNOWN_HOSTS_DEFAULT);
private static final File KNOWN_HOSTS_FILE = new File(KNOWN_HOSTS_FILE_PATH);

@DataBoundConstructor
public KnownHostsFileKeyVerificationStrategy() {
super();
@DataBoundConstructor
public KnownHostsFileKeyVerificationStrategy() {
super();
}

@Override
public boolean verify(SlaveComputer computer, HostKey hostKey, TaskListener listener) throws Exception {
ComputerLauncher launcher = computer.getLauncher();
if (!(launcher instanceof SSHLauncher)) {
return false;
}

@Override
public boolean verify(SlaveComputer computer, HostKey hostKey, TaskListener listener) throws Exception {
ComputerLauncher launcher = computer.getLauncher();
if (!(launcher instanceof SSHLauncher)) {
return false;
}

if (!KNOWN_HOSTS_FILE.exists()) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_NoKnownHostsFile(KNOWN_HOSTS_FILE.getAbsolutePath()));
return false;
}

KnownHosts knownHosts = new KnownHosts(KNOWN_HOSTS_FILE);
int result = knownHosts.verifyHostkey(((SSHLauncher)launcher).getHost(), hostKey.getAlgorithm(), hostKey.getKey());

if (KnownHosts.HOSTKEY_IS_OK == result) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_KeyTrusted(SSHLauncher.getTimestamp()));
return true;
} else if (KnownHosts.HOSTKEY_IS_NEW == result) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_NewKeyNotTrusted(SSHLauncher.getTimestamp()));
return false;
} else {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_ChangedKeyNotTrusted(SSHLauncher.getTimestamp()));
return false;
}


if (!KNOWN_HOSTS_FILE.exists()) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_NoKnownHostsFile(KNOWN_HOSTS_FILE.getAbsolutePath()));
return false;
}

@Override
public String[] getPreferredKeyAlgorithms(SlaveComputer computer) throws IOException {
ComputerLauncher launcher = computer.getLauncher();
SSHLauncher sshLauncher = (SSHLauncher) launcher;
String host = sshLauncher.getHost();
String hostPort = host + ":" + sshLauncher.getPort();

if (!(launcher instanceof SSHLauncher) || !KNOWN_HOSTS_FILE.exists()) {
return super.getPreferredKeyAlgorithms(computer);
}
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_SearchingFor(host, KNOWN_HOSTS_FILE));
int resultHost = verify(host, hostKey.getAlgorithm(), hostKey.getKey());

KnownHosts knownHosts = new KnownHosts(KNOWN_HOSTS_FILE);
return knownHosts.getPreferredServerHostkeyAlgorithmOrder(((SSHLauncher) launcher).getHost());
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_SearchingFor(hostPort, KNOWN_HOSTS_FILE));
int resultHostPort = verify(hostPort, hostKey.getAlgorithm(), hostKey.getKey());

if (KnownHosts.HOSTKEY_IS_OK == resultHost || KnownHosts.HOSTKEY_IS_OK == resultHostPort) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_KeyTrusted(SSHLauncher.getTimestamp()));
return true;
} else if (KnownHosts.HOSTKEY_IS_NEW == resultHost && KnownHosts.HOSTKEY_IS_NEW == resultHostPort) {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_NewKeyNotTrusted(SSHLauncher.getTimestamp()));
return false;
} else {
listener.getLogger().println(Messages.KnownHostsFileHostKeyVerifier_ChangedKeyNotTrusted(SSHLauncher.getTimestamp()));
return false;
}

@Restricted(NoExternalUse.class)
public File getKnownHostsFile(){
return KNOWN_HOSTS_FILE;
}

private int verify(String host, String algorithm, byte[] key) throws IOException {
KnownHosts knownHosts = new KnownHosts(KNOWN_HOSTS_FILE);
return knownHosts.verifyHostkey(host, algorithm, key);
}

@Override
public String[] getPreferredKeyAlgorithms(SlaveComputer computer) throws IOException {
ComputerLauncher launcher = computer.getLauncher();

if (!(launcher instanceof SSHLauncher) || !KNOWN_HOSTS_FILE.exists()) {
return super.getPreferredKeyAlgorithms(computer);
}

@Extension
public static class KnownHostsFileKeyVerificationStrategyDescriptor extends SshHostKeyVerificationStrategyDescriptor {

@Override
public String getDisplayName() {
return Messages.KnownHostsFileHostKeyVerifier_DisplayName();
}


KnownHosts knownHosts = new KnownHosts(KNOWN_HOSTS_FILE);
return knownHosts.getPreferredServerHostkeyAlgorithmOrder(((SSHLauncher) launcher).getHost());
}

@Restricted(NoExternalUse.class)
public File getKnownHostsFile() {
return KNOWN_HOSTS_FILE;
}

@Extension
public static class KnownHostsFileKeyVerificationStrategyDescriptor extends SshHostKeyVerificationStrategyDescriptor {

@Override
public String getDisplayName() {
return Messages.KnownHostsFileHostKeyVerifier_DisplayName();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ KnownHostsFileHostKeyVerifier.NewKeyNotTrusted={0} [SSH] WARNING: No entry curre
KnownHostsFileHostKeyVerifier.ChangedKeyNotTrusted={0} [SSH] The SSH key presented by the remote host does not match the key saved in the Known Hosts file against this host. Connections to this host will be denied until the two keys match.
KnownHostsFileHostKeyVerifier.KeyTrusted={0} [SSH] SSH host key matches key in Known Hosts file. Connection will be allowed.
KnownHostsFileHostKeyVerifier.NoKnownHostsFile={0} [SSH] No Known Hosts file was found at {0}. Please ensure one is created at this path and that Jenkins can read it.
KnownHostsFileHostKeyVerifier.SearchingFor=Searching for {0} in {1}
MissingVerificationStrategyAdministrativeMonitor.DisplayName=Missing Verification Strategy Monitor

0 comments on commit e6e2cb9

Please sign in to comment.