未验证 提交 7d7eaedf 编写于 作者: S Serge Rider 提交者: GitHub

Merge pull request #9829 from dbeaver/jsch-openssh-key#5845

#5845 Try to use system 'ssh-keygen'
......@@ -19,6 +19,7 @@ package org.jkiss.dbeaver.model.net.ssh;
import com.jcraft.jsch.*;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
import org.jkiss.dbeaver.model.net.ssh.SSHConstants.AuthType;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
......@@ -27,9 +28,12 @@ import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import java.io.File;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* SSH tunnel
......@@ -51,15 +55,10 @@ public class SSHImplementationJsch extends SSHImplementationAbstract {
String autoTypeString = CommonUtils.toString(configuration.getProperty(SSHConstants.PROP_AUTH_TYPE));
AuthType authType = CommonUtils.isEmpty(autoTypeString) ?
(privKeyFile == null ? AuthType.PASSWORD : AuthType.PUBLIC_KEY) :
CommonUtils.valueOf(AuthType.class, autoTypeString, AuthType.PASSWORD);
(privKeyFile == null ? AuthType.PASSWORD : AuthType.PUBLIC_KEY) :
CommonUtils.valueOf(AuthType.class, autoTypeString, AuthType.PASSWORD);
if (authType == AuthType.PUBLIC_KEY) {
if (!CommonUtils.isEmpty(configuration.getPassword())) {
jsch.addIdentity(privKeyFile.getAbsolutePath(), configuration.getPassword());
} else {
jsch.addIdentity(privKeyFile.getAbsolutePath());
}
addIdentityKey(monitor, configuration.getDataSource(), privKeyFile, configuration.getPassword());
} else if (authType == AuthType.AGENT) {
log.debug("Creating identityRepository");
IdentityRepository identityRepository = new DBeaverIdentityRepository(this, getAgentData());
......@@ -151,6 +150,75 @@ public class SSHImplementationJsch extends SSHImplementationAbstract {
}
}
private void addIdentityKey(DBRProgressMonitor monitor, DBPDataSourceContainer dataSource, File key, String password) throws IOException, JSchException {
String header;
try (BufferedReader reader = new BufferedReader(new FileReader(key))) {
header = reader.readLine();
}
/*
* This code is a workaround for JSCH because it cannot load
* newer private keys produced by ssh-keygen, so we need
* to convert it to the older format manually. This
* algorithm will fail if the 'ssh-keygen' cannot be found (#5845)
*/
if (header.equals("-----BEGIN OPENSSH PRIVATE KEY-----")) {
log.debug("Attempting to convert unsupported key");
File dir = DBWorkbench.getPlatform().getTempFolder(monitor, "openssh-pkey");
File tmp = new File(dir, dataSource.getId() + ".pem");
Files.copy(key.toPath(), tmp.toPath(), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
Process process = new ProcessBuilder()
.command(
"ssh-keygen",
"-p",
"-m", "PEM",
"-f", tmp.getAbsolutePath(),
"-q",
"-N", '"' + (CommonUtils.isEmpty(password) ? "" : password) + '"')
.start();
try {
if (!process.waitFor(5000, TimeUnit.MILLISECONDS)) {
process.destroyForcibly();
}
int status = process.exitValue();
if (status != 0) {
String message;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
message = reader.lines().collect(Collectors.joining("\n"));
}
throw new IOException("Specified private key cannot be converted:\n" + message);
}
addIdentityKey0(tmp, password);
} catch (InterruptedException e) {
throw new IOException(e);
} finally {
if (!tmp.delete()) {
log.debug("Failed to delete private key file");
}
}
} else {
addIdentityKey0(key, password);
}
}
private void addIdentityKey0(File key, String password) throws JSchException {
if (!CommonUtils.isEmpty(password)) {
jsch.addIdentity(key.getAbsolutePath(), password);
} else {
jsch.addIdentity(key.getAbsolutePath());
}
}
private class UIUserInfo implements UserInfo, UIKeyboardInteractive {
DBWHandlerConfiguration configuration;
......@@ -191,7 +259,7 @@ public class SSHImplementationJsch extends SSHImplementationAbstract {
@Override
public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
log.debug("JSCH keyboard interactive auth");
return new String[] { configuration.getPassword() } ;
return new String[]{ configuration.getPassword() };
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册